get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 76168,
    "url": "https://patches.dpdk.org/api/patches/76168/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20200831045958.5589-1-xiaoyun.li@intel.com/",
    "project": {
        "id": 1,
        "url": "https://patches.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": "<20200831045958.5589-1-xiaoyun.li@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20200831045958.5589-1-xiaoyun.li@intel.com",
    "date": "2020-08-31T04:59:58",
    "name": "raw/ntb: add Icelake support for Intel NTB",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "e77348e0142bfa583ab8c7de9e9ef396d26216ff",
    "submitter": {
        "id": 798,
        "url": "https://patches.dpdk.org/api/people/798/?format=api",
        "name": "Li, Xiaoyun",
        "email": "xiaoyun.li@intel.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20200831045958.5589-1-xiaoyun.li@intel.com/mbox/",
    "series": [
        {
            "id": 11852,
            "url": "https://patches.dpdk.org/api/series/11852/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=11852",
            "date": "2020-08-31T04:59:58",
            "name": "raw/ntb: add Icelake support for Intel NTB",
            "version": 1,
            "mbox": "https://patches.dpdk.org/series/11852/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/76168/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/76168/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 F2D02A04AB;\n\tMon, 31 Aug 2020 07:11:18 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id DF5C6137D;\n\tMon, 31 Aug 2020 07:11:17 +0200 (CEST)",
            "from mga14.intel.com (mga14.intel.com [192.55.52.115])\n by dpdk.org (Postfix) with ESMTP id E7E18255\n for <dev@dpdk.org>; Mon, 31 Aug 2020 07:11:15 +0200 (CEST)",
            "from fmsmga005.fm.intel.com ([10.253.24.32])\n by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 30 Aug 2020 22:11:14 -0700",
            "from dpdk-xiaoyun3.sh.intel.com ([10.67.118.175])\n by fmsmga005.fm.intel.com with ESMTP; 30 Aug 2020 22:11:13 -0700"
        ],
        "IronPort-SDR": [
            "\n MhMvk4x1jrc4eigNI4cCiN7Em/IsCd37/HJsKoUpW8a17D0qhSOWiUWDxQvU1Y16De7IODo4B3\n a0S8NffWcYnw==",
            "\n APk32ZlWzUPhlbTxwXMrgH0+2BMsWsORvRL/AfiIcx7KvsY2twaxvgEzX+7xy4WjwkXcmk2D0s\n 7/PbriuTduig=="
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6000,8403,9729\"; a=\"156171939\"",
            "E=Sophos;i=\"5.76,374,1592895600\"; d=\"scan'208\";a=\"156171939\"",
            "E=Sophos;i=\"5.76,374,1592895600\"; d=\"scan'208\";a=\"501729798\""
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "From": "Xiaoyun Li <xiaoyun.li@intel.com>",
        "To": "jingjing.wu@intel.com",
        "Cc": "dev@dpdk.org, omkar.maslekar@intel.com, Xiaoyun Li <xiaoyun.li@intel.com>",
        "Date": "Mon, 31 Aug 2020 12:59:58 +0800",
        "Message-Id": "<20200831045958.5589-1-xiaoyun.li@intel.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "Subject": "[dpdk-dev] [PATCH] raw/ntb: add Icelake support for Intel NTB",
        "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": "Add NTB device support (4th generation) for Intel Icelake platform.\n\nSigned-off-by: Xiaoyun Li <xiaoyun.li@intel.com>\n---\n doc/guides/rawdevs/ntb.rst             |  11 +-\n doc/guides/rel_notes/release_20_11.rst |   3 +\n drivers/raw/ntb/ntb.c                  |   2 +\n drivers/raw/ntb/ntb.h                  |   1 +\n drivers/raw/ntb/ntb_hw_intel.c         | 236 ++++++++++++++++++++++---\n drivers/raw/ntb/ntb_hw_intel.h         |  28 ++-\n usertools/dpdk-devbind.py              |   4 +-\n 7 files changed, 246 insertions(+), 39 deletions(-)",
    "diff": "diff --git a/doc/guides/rawdevs/ntb.rst b/doc/guides/rawdevs/ntb.rst\nindex aa7d80964..f3556113c 100644\n--- a/doc/guides/rawdevs/ntb.rst\n+++ b/doc/guides/rawdevs/ntb.rst\n@@ -14,16 +14,17 @@ allocation for the peer to access and read/write allocated memory from peer.\n Also, the PMD allows to use doorbell registers to notify the peer and share\n some information by using scratchpad registers.\n \n-BIOS setting on Intel Skylake\n------------------------------\n+BIOS setting on Intel Xeon\n+--------------------------\n \n Intel Non-transparent Bridge needs special BIOS setting. Since the PMD only\n supports Intel Skylake platform, introduce BIOS setting here. The referencce\n is https://www.intel.com/content/dam/support/us/en/documents/server-products/Intel_Xeon_Processor_Scalable_Family_BIOS_User_Guide.pdf\n \n - Set the needed PCIe port as NTB to NTB mode on both hosts.\n-- Enable NTB bars and set bar size of bar 23 and bar 45 as 12-29 (2K-512M)\n-  on both hosts. Note that bar size on both hosts should be the same.\n+- Enable NTB bars and set bar size of bar 23 and bar 45 as 12-29 (4K-512M)\n+  on both hosts (for Icelake, bar size can be set as 12-51, namely 4K-128PB).\n+  Note that bar size on both hosts should be the same.\n - Disable split bars for both hosts.\n - Set crosslink control override as DSD/USP on one host, USD/DSP on\n   another host.\n@@ -151,4 +152,4 @@ like the following:\n Limitation\n ----------\n \n-- This PMD only supports Intel Skylake platform.\n+- This PMD only supports Intel Skylake and Icelake platforms.\ndiff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst\nindex df227a177..d13782459 100644\n--- a/doc/guides/rel_notes/release_20_11.rst\n+++ b/doc/guides/rel_notes/release_20_11.rst\n@@ -55,6 +55,9 @@ New Features\n      Also, make sure to start the actual text at the margin.\n      =======================================================\n \n+* **Added Icelake (Gen4) support for Intel NTB.**\n+\n+  Added NTB device support (4th generation) for Intel Icelake platform.\n \n Removed Items\n -------------\ndiff --git a/drivers/raw/ntb/ntb.c b/drivers/raw/ntb/ntb.c\nindex e40412bb7..3b59f9a44 100644\n--- a/drivers/raw/ntb/ntb.c\n+++ b/drivers/raw/ntb/ntb.c\n@@ -25,6 +25,7 @@\n \n static const struct rte_pci_id pci_id_ntb_map[] = {\n \t{ RTE_PCI_DEVICE(NTB_INTEL_VENDOR_ID, NTB_INTEL_DEV_ID_B2B_SKX) },\n+\t{ RTE_PCI_DEVICE(NTB_INTEL_VENDOR_ID, NTB_INTEL_DEV_ID_B2B_ICX) },\n \t{ .vendor_id = 0, /* sentinel */ },\n };\n \n@@ -1333,6 +1334,7 @@ ntb_init_hw(struct rte_rawdev *dev, struct rte_pci_device *pci_dev)\n \n \tswitch (pci_dev->id.device_id) {\n \tcase NTB_INTEL_DEV_ID_B2B_SKX:\n+\tcase NTB_INTEL_DEV_ID_B2B_ICX:\n \t\thw->ntb_ops = &intel_ntb_ops;\n \t\tbreak;\n \tdefault:\ndiff --git a/drivers/raw/ntb/ntb.h b/drivers/raw/ntb/ntb.h\nindex a561c42d1..cdf7667d5 100644\n--- a/drivers/raw/ntb/ntb.h\n+++ b/drivers/raw/ntb/ntb.h\n@@ -18,6 +18,7 @@ extern int ntb_logtype;\n \n /* Device IDs */\n #define NTB_INTEL_DEV_ID_B2B_SKX    0x201C\n+#define NTB_INTEL_DEV_ID_B2B_ICX    0x347E\n \n /* Reserved to app to use. */\n #define NTB_SPAD_USER               \"spad_user_\"\ndiff --git a/drivers/raw/ntb/ntb_hw_intel.c b/drivers/raw/ntb/ntb_hw_intel.c\nindex e7f8667cd..76670c96b 100644\n--- a/drivers/raw/ntb/ntb_hw_intel.c\n+++ b/drivers/raw/ntb/ntb_hw_intel.c\n@@ -25,17 +25,29 @@ static enum xeon_ntb_bar intel_ntb_bar[] = {\n \tXEON_NTB_BAR45,\n };\n \n-static int\n-intel_ntb_dev_init(const struct rte_rawdev *dev)\n+static inline int\n+is_gen3_ntb(const struct ntb_hw *hw)\n {\n-\tstruct ntb_hw *hw = dev->dev_private;\n-\tuint8_t reg_val, bar;\n-\tint ret, i;\n+\tif (hw->pci_dev->id.device_id == NTB_INTEL_DEV_ID_B2B_SKX)\n+\t\treturn 1;\n \n-\tif (hw == NULL) {\n-\t\tNTB_LOG(ERR, \"Invalid device.\");\n-\t\treturn -EINVAL;\n-\t}\n+\treturn 0;\n+}\n+\n+static inline int\n+is_gen4_ntb(const struct ntb_hw *hw)\n+{\n+\tif (hw->pci_dev->id.device_id == NTB_INTEL_DEV_ID_B2B_ICX)\n+\t\treturn 1;\n+\n+\treturn 0;\n+}\n+\n+static int\n+intel_ntb3_check_ppd(struct ntb_hw *hw)\n+{\n+\tuint8_t reg_val;\n+\tint ret;\n \n \tret = rte_pci_read_config(hw->pci_dev, &reg_val,\n \t\t\t\t  sizeof(reg_val), XEON_PPD_OFFSET);\n@@ -71,8 +83,73 @@ intel_ntb_dev_init(const struct rte_rawdev *dev)\n \t\treturn -EINVAL;\n \t}\n \n+\treturn 0;\n+}\n+\n+static int\n+intel_ntb4_check_ppd(struct ntb_hw *hw)\n+{\n+\tuint32_t reg_val;\n+\n+\treg_val = rte_read32(hw->hw_addr + XEON_GEN4_PPD1_OFFSET);\n+\n+\t/* Check connection topo type. Only support B2B. */\n+\tswitch (reg_val & XEON_GEN4_PPD_CONN_MASK) {\n+\tcase XEON_GEN4_PPD_CONN_B2B:\n+\t\tNTB_LOG(INFO, \"Topo B2B (back to back) is using.\");\n+\t\tbreak;\n+\tdefault:\n+\t\tNTB_LOG(ERR, \"Not supported conn topo. Please use B2B.\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* Check device type. */\n+\tif (reg_val & XEON_GEN4_PPD_DEV_DSD) {\n+\t\tNTB_LOG(INFO, \"DSD, Downstream Device.\");\n+\t\thw->topo = NTB_TOPO_B2B_DSD;\n+\t} else {\n+\t\tNTB_LOG(INFO, \"USD, Upstream device.\");\n+\t\thw->topo = NTB_TOPO_B2B_USD;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+intel_ntb_dev_init(const struct rte_rawdev *dev)\n+{\n+\tstruct ntb_hw *hw = dev->dev_private;\n+\tuint16_t link_ctrl;\n+\tvoid *reg_addr;\n+\tuint8_t bar;\n+\tint ret, i;\n+\n+\tif (hw == NULL) {\n+\t\tNTB_LOG(ERR, \"Invalid device.\");\n+\t\treturn -EINVAL;\n+\t}\n+\n \thw->hw_addr = (char *)hw->pci_dev->mem_resource[0].addr;\n \n+\tif (is_gen3_ntb(hw)) {\n+\t\tret = intel_ntb3_check_ppd(hw);\n+\t} else if (is_gen4_ntb(hw)) {\n+\t\t/* PPD is in MMIO but not config space for NTB Gen4 */\n+\t\tret = intel_ntb4_check_ppd(hw);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t\t/* init link setup */\n+\t\treg_addr = hw->hw_addr + XEON_GEN4_LINK_CTRL_OFFSET;\n+\t\tlink_ctrl = rte_read16(reg_addr);\n+\t\tlink_ctrl |= XEON_GEN4_LINK_CTRL_LINK_DIS;\n+\t\trte_write16(link_ctrl, reg_addr);\n+\t} else {\n+\t\treturn -ENOTSUP;\n+\t}\n+\n+\tif (ret)\n+\t\treturn ret;\n+\n \thw->mw_cnt = XEON_MW_COUNT;\n \thw->db_cnt = XEON_DB_COUNT;\n \thw->spad_cnt = XEON_SPAD_COUNT;\n@@ -149,15 +226,28 @@ intel_ntb_mw_set_trans(const struct rte_rawdev *dev, int mw_idx,\n \trte_write64(base, xlat_addr);\n \trte_write64(limit, limit_addr);\n \n-\t/* Setup the external point so that remote can access. */\n-\txlat_off = XEON_EMBAR1_OFFSET + 8 * mw_idx;\n-\txlat_addr = hw->hw_addr + xlat_off;\n-\tlimit_off = XEON_EMBAR1XLMT_OFFSET + mw_idx * XEON_BAR_INTERVAL_OFFSET;\n-\tlimit_addr = hw->hw_addr + limit_off;\n-\tbase = rte_read64(xlat_addr);\n-\tbase &= ~0xf;\n-\tlimit = base + size;\n-\trte_write64(limit, limit_addr);\n+\tif (is_gen3_ntb(hw)) {\n+\t\t/* Setup the external point so that remote can access. */\n+\t\txlat_off = XEON_EMBAR1_OFFSET + 8 * mw_idx;\n+\t\txlat_addr = hw->hw_addr + xlat_off;\n+\t\tlimit_off = XEON_EMBAR1XLMT_OFFSET +\n+\t\t\t    mw_idx * XEON_BAR_INTERVAL_OFFSET;\n+\t\tlimit_addr = hw->hw_addr + limit_off;\n+\t\tbase = rte_read64(xlat_addr);\n+\t\tbase &= ~0xf;\n+\t\tlimit = base + size;\n+\t\trte_write64(limit, limit_addr);\n+\t} else if (is_gen4_ntb(hw)) {\n+\t\t/* Set translate base address index register */\n+\t\txlat_off = XEON_GEN4_IM1XBASEIDX_OFFSET +\n+\t\t\t   mw_idx * XEON_GEN4_XBASEIDX_INTERVAL;\n+\t\txlat_addr = hw->hw_addr + xlat_off;\n+\t\trte_write16(rte_log2_u64(size), xlat_addr);\n+\t} else {\n+\t\trte_write64(base, limit_addr);\n+\t\trte_write64(0, xlat_addr);\n+\t\treturn -ENOTSUP;\n+\t}\n \n \treturn 0;\n }\n@@ -187,7 +277,7 @@ static int\n intel_ntb_get_link_status(const struct rte_rawdev *dev)\n {\n \tstruct ntb_hw *hw = dev->dev_private;\n-\tuint16_t reg_val;\n+\tuint16_t reg_val, reg_off;\n \tint ret;\n \n \tif (hw == NULL) {\n@@ -195,11 +285,19 @@ intel_ntb_get_link_status(const struct rte_rawdev *dev)\n \t\treturn -EINVAL;\n \t}\n \n-\tret = rte_pci_read_config(hw->pci_dev, &reg_val,\n-\t\t\t\t  sizeof(reg_val), XEON_LINK_STATUS_OFFSET);\n-\tif (ret < 0) {\n-\t\tNTB_LOG(ERR, \"Unable to get link status.\");\n-\t\treturn -EIO;\n+\tif (is_gen3_ntb(hw)) {\n+\t\treg_off = XEON_GEN3_LINK_STATUS_OFFSET;\n+\t\tret = rte_pci_read_config(hw->pci_dev, &reg_val,\n+\t\t\t\t\t  sizeof(reg_val), reg_off);\n+\t\tif (ret < 0) {\n+\t\t\tNTB_LOG(ERR, \"Unable to get link status.\");\n+\t\t\treturn -EIO;\n+\t\t}\n+\t} else if (is_gen4_ntb(hw)) {\n+\t\treg_off = XEON_GEN4_LINK_STATUS_OFFSET;\n+\t\treg_val = rte_read16(hw->hw_addr + reg_off);\n+\t} else {\n+\t\treturn -ENOTSUP;\n \t}\n \n \thw->link_status = NTB_LNK_STA_ACTIVE(reg_val);\n@@ -216,9 +314,8 @@ intel_ntb_get_link_status(const struct rte_rawdev *dev)\n }\n \n static int\n-intel_ntb_set_link(const struct rte_rawdev *dev, bool up)\n+intel_ntb_gen3_set_link(const struct ntb_hw *hw, bool up)\n {\n-\tstruct ntb_hw *hw = dev->dev_private;\n \tuint32_t ntb_ctrl, reg_off;\n \tvoid *reg_addr;\n \n@@ -241,6 +338,65 @@ intel_ntb_set_link(const struct rte_rawdev *dev, bool up)\n \treturn 0;\n }\n \n+static int\n+intel_ntb_gen4_set_link(const struct ntb_hw *hw, bool up)\n+{\n+\tuint32_t ntb_ctrl, ppd0;\n+\tuint16_t link_ctrl;\n+\tvoid *reg_addr;\n+\n+\tif (up) {\n+\t\treg_addr = hw->hw_addr + XEON_NTBCNTL_OFFSET;\n+\t\tntb_ctrl = NTB_CTL_P2S_BAR2_SNOOP | NTB_CTL_S2P_BAR2_SNOOP;\n+\t\tntb_ctrl |= NTB_CTL_P2S_BAR4_SNOOP | NTB_CTL_S2P_BAR4_SNOOP;\n+\t\trte_write32(ntb_ctrl, reg_addr);\n+\n+\t\treg_addr = hw->hw_addr + XEON_GEN4_LINK_CTRL_OFFSET;\n+\t\tlink_ctrl = rte_read16(reg_addr);\n+\t\tlink_ctrl &= ~XEON_GEN4_LINK_CTRL_LINK_DIS;\n+\t\trte_write16(link_ctrl, reg_addr);\n+\n+\t\t/* start link training */\n+\t\treg_addr = hw->hw_addr + XEON_GEN4_PPD0_OFFSET;\n+\t\tppd0 = rte_read32(reg_addr);\n+\t\tppd0 |= XEON_GEN4_PPD_LINKTRN;\n+\t\trte_write32(ppd0, reg_addr);\n+\n+\t\t/* make sure link training has started */\n+\t\tppd0 = rte_read32(reg_addr);\n+\t\tif (!(ppd0 & XEON_GEN4_PPD_LINKTRN)) {\n+\t\t\tNTB_LOG(ERR, \"Link is not training.\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t} else {\n+\t\treg_addr = hw->hw_addr + XEON_NTBCNTL_OFFSET;\n+\t\tntb_ctrl = rte_read32(reg_addr);\n+\t\tntb_ctrl &= ~(NTB_CTL_P2S_BAR2_SNOOP | NTB_CTL_S2P_BAR2_SNOOP);\n+\t\tntb_ctrl &= ~(NTB_CTL_P2S_BAR4_SNOOP | NTB_CTL_S2P_BAR4_SNOOP);\n+\t\trte_write32(ntb_ctrl, reg_addr);\n+\n+\t\treg_addr = hw->hw_addr + XEON_GEN4_LINK_CTRL_OFFSET;\n+\t\tlink_ctrl = rte_read16(reg_addr);\n+\t\tlink_ctrl |= XEON_GEN4_LINK_CTRL_LINK_DIS;\n+\t\trte_write16(link_ctrl, reg_addr);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+intel_ntb_set_link(const struct rte_rawdev *dev, bool up)\n+{\n+\tstruct ntb_hw *hw = dev->dev_private;\n+\n+\tif (is_gen3_ntb(hw))\n+\t\treturn intel_ntb_gen3_set_link(hw, up);\n+\telse if (is_gen4_ntb(hw))\n+\t\treturn intel_ntb_gen4_set_link(hw, up);\n+\telse\n+\t\treturn -ENOTSUP;\n+}\n+\n static uint32_t\n intel_ntb_spad_read(const struct rte_rawdev *dev, int spad, bool peer)\n {\n@@ -254,7 +410,14 @@ intel_ntb_spad_read(const struct rte_rawdev *dev, int spad, bool peer)\n \t}\n \n \t/* When peer is true, read peer spad reg */\n-\treg_off = peer ? XEON_B2B_SPAD_OFFSET : XEON_IM_SPAD_OFFSET;\n+\tif (is_gen3_ntb(hw))\n+\t\treg_off = peer ? XEON_GEN3_B2B_SPAD_OFFSET :\n+\t\t\t\tXEON_IM_SPAD_OFFSET;\n+\telse if (is_gen4_ntb(hw))\n+\t\treg_off = peer ? XEON_GEN4_B2B_SPAD_OFFSET :\n+\t\t\t\tXEON_IM_SPAD_OFFSET;\n+\telse\n+\t\treturn -ENOTSUP;\n \treg_addr = hw->hw_addr + reg_off + (spad << 2);\n \tspad_v = rte_read32(reg_addr);\n \n@@ -275,7 +438,14 @@ intel_ntb_spad_write(const struct rte_rawdev *dev, int spad,\n \t}\n \n \t/* When peer is true, write peer spad reg */\n-\treg_off = peer ? XEON_B2B_SPAD_OFFSET : XEON_IM_SPAD_OFFSET;\n+\tif (is_gen3_ntb(hw))\n+\t\treg_off = peer ? XEON_GEN3_B2B_SPAD_OFFSET :\n+\t\t\t\tXEON_IM_SPAD_OFFSET;\n+\telse if (is_gen4_ntb(hw))\n+\t\treg_off = peer ? XEON_GEN4_B2B_SPAD_OFFSET :\n+\t\t\t\tXEON_IM_SPAD_OFFSET;\n+\telse\n+\t\treturn -ENOTSUP;\n \treg_addr = hw->hw_addr + reg_off + (spad << 2);\n \n \trte_write32(spad_v, reg_addr);\n@@ -308,6 +478,9 @@ intel_ntb_db_clear(const struct rte_rawdev *dev, uint64_t db_bits)\n \tdb_off = XEON_IM_INT_STATUS_OFFSET;\n \tdb_addr = hw->hw_addr + db_off;\n \n+\tif (is_gen4_ntb(hw))\n+\t\trte_write16(XEON_GEN4_SLOTSTS_DLLSCS,\n+\t\t\t    hw->hw_addr + XEON_GEN4_SLOTSTS);\n \trte_write64(db_bits, db_addr);\n \n \treturn 0;\n@@ -365,7 +538,12 @@ intel_ntb_vector_bind(const struct rte_rawdev *dev, uint8_t intr, uint8_t msix)\n \t}\n \n \t/* Bind intr source to msix vector */\n-\treg_off = XEON_INTVEC_OFFSET;\n+\tif (is_gen3_ntb(hw))\n+\t\treg_off = XEON_GEN3_INTVEC_OFFSET;\n+\telse if (is_gen4_ntb(hw))\n+\t\treg_off = XEON_GEN4_INTVEC_OFFSET;\n+\telse\n+\t\treturn -ENOTSUP;\n \treg_addr = hw->hw_addr + reg_off + intr;\n \n \trte_write8(msix, reg_addr);\ndiff --git a/drivers/raw/ntb/ntb_hw_intel.h b/drivers/raw/ntb/ntb_hw_intel.h\nindex 4d1e64504..604f7aa7a 100644\n--- a/drivers/raw/ntb/ntb_hw_intel.h\n+++ b/drivers/raw/ntb/ntb_hw_intel.h\n@@ -22,7 +22,7 @@\n #define NTB_LNK_STA_SPEED(x)\t\t((x) & NTB_LNK_STA_SPEED_MASK)\n #define NTB_LNK_STA_WIDTH(x)\t\t(((x) & NTB_LNK_STA_WIDTH_MASK) >> 4)\n \n-/* Intel Skylake Xeon hardware */\n+/* Intel Xeon hardware */\n #define XEON_IMBAR1SZ_OFFSET\t\t0x00d0\n #define XEON_IMBAR2SZ_OFFSET\t\t0x00d1\n #define XEON_EMBAR1SZ_OFFSET\t\t0x00d2\n@@ -31,7 +31,13 @@\n #define XEON_DEVSTS_OFFSET\t\t0x009a\n #define XEON_UNCERRSTS_OFFSET\t\t0x014c\n #define XEON_CORERRSTS_OFFSET\t\t0x0158\n-#define XEON_LINK_STATUS_OFFSET\t\t0x01a2\n+#define XEON_GEN3_LINK_STATUS_OFFSET\t0x01a2\n+/* Link status and PPD are in MMIO but not config space for Gen4 NTB */\n+#define XEON_GEN4_PPD0_OFFSET\t\t0xb0d4\n+#define XEON_GEN4_PPD1_OFFSET\t\t0xb4c0\n+#define XEON_GEN4_LINK_CTRL_OFFSET\t0xb050\n+#define XEON_GEN4_LINK_STATUS_OFFSET\t0xb052\n+#define XEON_GEN4_LINK_CTRL_LINK_DIS\t0x0010\n \n #define XEON_NTBCNTL_OFFSET\t\t0x0000\n #define XEON_BAR_INTERVAL_OFFSET\t0x0010\n@@ -39,13 +45,18 @@\n #define XEON_IMBAR1XLMT_OFFSET\t\t0x0018\t\t/* SBAR2LMT */\n #define XEON_IMBAR2XBASE_OFFSET\t\t0x0020\t\t/* SBAR4XLAT */\n #define XEON_IMBAR2XLMT_OFFSET\t\t0x0028\t\t/* SBAR4LMT */\n+#define XEON_GEN4_XBASEIDX_INTERVAL\t0x0002\n+#define XEON_GEN4_IM1XBASEIDX_OFFSET\t0x0074\n+#define XEON_GEN4_IM2XBASEIDX_OFFSET\t0x0076\n #define XEON_IM_INT_STATUS_OFFSET\t0x0040\n #define XEON_IM_INT_DISABLE_OFFSET\t0x0048\n #define XEON_IM_SPAD_OFFSET\t\t0x0080\t\t/* SPAD */\n+#define XEON_GEN3_B2B_SPAD_OFFSET\t0x0180\t\t/* GEN3 B2B SPAD */\n+#define XEON_GEN4_B2B_SPAD_OFFSET\t0x8080\t\t/* GEN4 B2B SPAD */\n #define XEON_USMEMMISS_OFFSET\t\t0x0070\n-#define XEON_INTVEC_OFFSET\t\t0x00d0\n+#define XEON_GEN3_INTVEC_OFFSET\t\t0x00d0\n+#define XEON_GEN4_INTVEC_OFFSET\t\t0x0050\n #define XEON_IM_DOORBELL_OFFSET\t\t0x0100\t\t/* SDOORBELL0 */\n-#define XEON_B2B_SPAD_OFFSET\t\t0x0180\t\t/* B2B SPAD */\n #define XEON_EMBAR0XBASE_OFFSET\t\t0x4008\t\t/* B2B_XLAT */\n #define XEON_EMBAR1XBASE_OFFSET\t\t0x4010\t\t/* PBAR2XLAT */\n #define XEON_EMBAR1XLMT_OFFSET\t\t0x4018\t\t/* PBAR2LMT */\n@@ -60,6 +71,7 @@\n #define XEON_EMBAR1_OFFSET\t\t0x4518\t\t/* SBAR23BASE */\n #define XEON_EMBAR2_OFFSET\t\t0x4520\t\t/* SBAR45BASE */\n \n+\n #define XEON_PPD_OFFSET\t\t\t0x00d4\n #define XEON_PPD_CONN_MASK\t\t0x03\n #define XEON_PPD_CONN_TRANSPARENT\t0x00\n@@ -70,6 +82,14 @@\n #define XEON_PPD_DEV_DSD\t\t0x10\n #define XEON_PPD_SPLIT_BAR_MASK\t\t0x40\n \n+#define XEON_GEN4_PPD_CONN_MASK\t\t0x0300\n+#define XEON_GEN4_PPD_CONN_B2B\t\t0x0200\n+#define XEON_GEN4_PPD_DEV_MASK\t\t0x1000\n+#define XEON_GEN4_PPD_DEV_DSD\t\t0x1000\n+#define XEON_GEN4_PPD_DEV_USD\t\t0x0000\n+#define XEON_GEN4_PPD_LINKTRN\t\t0x0008\n+#define XEON_GEN4_SLOTSTS\t\t0xb05a\n+#define XEON_GEN4_SLOTSTS_DLLSCS\t0x100\n \n #define XEON_MW_COUNT\t\t\t2\n \ndiff --git a/usertools/dpdk-devbind.py b/usertools/dpdk-devbind.py\nindex 86b6b53c4..081c3bc92 100755\n--- a/usertools/dpdk-devbind.py\n+++ b/usertools/dpdk-devbind.py\n@@ -53,6 +53,8 @@\n               'SVendor': None, 'SDevice': None}\n intel_ntb_skx = {'Class': '06', 'Vendor': '8086', 'Device': '201c',\n               'SVendor': None, 'SDevice': None}\n+intel_ntb_icx = {'Class': '06', 'Vendor': '8086', 'Device': '347e',\n+              'SVendor': None, 'SDevice': None}\n \n network_devices = [network_class, cavium_pkx, avp_vnic, ifpga_class]\n baseband_devices = [acceleration_class]\n@@ -60,7 +62,7 @@\n eventdev_devices = [cavium_sso, cavium_tim, octeontx2_sso]\n mempool_devices = [cavium_fpa, octeontx2_npa]\n compress_devices = [cavium_zip]\n-misc_devices = [intel_ioat_bdw, intel_ioat_skx, intel_ioat_icx, intel_ntb_skx, octeontx2_dma]\n+misc_devices = [intel_ioat_bdw, intel_ioat_skx, intel_ioat_icx, intel_ntb_skx, intel_ntb_icx, octeontx2_dma]\n \n # global dict ethernet devices present. Dictionary indexed by PCI address.\n # Each device within this is itself a dictionary of device properties\n",
    "prefixes": []
}