Add NTB device support (4th generation) for Intel Icelake platform. Signed-off-by: Xiaoyun Li <xiaoyun.li@intel.com> --- doc/guides/rawdevs/ntb.rst | 11 +- doc/guides/rel_notes/release_20_11.rst | 3 + drivers/raw/ntb/ntb.c | 2 + drivers/raw/ntb/ntb.h | 1 + drivers/raw/ntb/ntb_hw_intel.c | 236 ++++++++++++++++++++++--- drivers/raw/ntb/ntb_hw_intel.h | 28 ++- usertools/dpdk-devbind.py | 4 +- 7 files changed, 246 insertions(+), 39 deletions(-) diff --git a/doc/guides/rawdevs/ntb.rst b/doc/guides/rawdevs/ntb.rst index aa7d80964..f3556113c 100644 --- a/doc/guides/rawdevs/ntb.rst +++ b/doc/guides/rawdevs/ntb.rst @@ -14,16 +14,17 @@ allocation for the peer to access and read/write allocated memory from peer. Also, the PMD allows to use doorbell registers to notify the peer and share some information by using scratchpad registers. -BIOS setting on Intel Skylake ------------------------------ +BIOS setting on Intel Xeon +-------------------------- Intel Non-transparent Bridge needs special BIOS setting. Since the PMD only supports Intel Skylake platform, introduce BIOS setting here. The referencce is https://www.intel.com/content/dam/support/us/en/documents/server-products/Intel_Xeon_Processor_Scalable_Family_BIOS_User_Guide.pdf - Set the needed PCIe port as NTB to NTB mode on both hosts. -- Enable NTB bars and set bar size of bar 23 and bar 45 as 12-29 (2K-512M) - on both hosts. Note that bar size on both hosts should be the same. +- Enable NTB bars and set bar size of bar 23 and bar 45 as 12-29 (4K-512M) + on both hosts (for Icelake, bar size can be set as 12-51, namely 4K-128PB). + Note that bar size on both hosts should be the same. - Disable split bars for both hosts. - Set crosslink control override as DSD/USP on one host, USD/DSP on another host. @@ -151,4 +152,4 @@ like the following: Limitation ---------- -- This PMD only supports Intel Skylake platform. +- This PMD only supports Intel Skylake and Icelake platforms. diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst index df227a177..d13782459 100644 --- a/doc/guides/rel_notes/release_20_11.rst +++ b/doc/guides/rel_notes/release_20_11.rst @@ -55,6 +55,9 @@ New Features Also, make sure to start the actual text at the margin. ======================================================= +* **Added Icelake (Gen4) support for Intel NTB.** + + Added NTB device support (4th generation) for Intel Icelake platform. Removed Items ------------- diff --git a/drivers/raw/ntb/ntb.c b/drivers/raw/ntb/ntb.c index e40412bb7..3b59f9a44 100644 --- a/drivers/raw/ntb/ntb.c +++ b/drivers/raw/ntb/ntb.c @@ -25,6 +25,7 @@ static const struct rte_pci_id pci_id_ntb_map[] = { { RTE_PCI_DEVICE(NTB_INTEL_VENDOR_ID, NTB_INTEL_DEV_ID_B2B_SKX) }, + { RTE_PCI_DEVICE(NTB_INTEL_VENDOR_ID, NTB_INTEL_DEV_ID_B2B_ICX) }, { .vendor_id = 0, /* sentinel */ }, }; @@ -1333,6 +1334,7 @@ ntb_init_hw(struct rte_rawdev *dev, struct rte_pci_device *pci_dev) switch (pci_dev->id.device_id) { case NTB_INTEL_DEV_ID_B2B_SKX: + case NTB_INTEL_DEV_ID_B2B_ICX: hw->ntb_ops = &intel_ntb_ops; break; default: diff --git a/drivers/raw/ntb/ntb.h b/drivers/raw/ntb/ntb.h index a561c42d1..cdf7667d5 100644 --- a/drivers/raw/ntb/ntb.h +++ b/drivers/raw/ntb/ntb.h @@ -18,6 +18,7 @@ extern int ntb_logtype; /* Device IDs */ #define NTB_INTEL_DEV_ID_B2B_SKX 0x201C +#define NTB_INTEL_DEV_ID_B2B_ICX 0x347E /* Reserved to app to use. */ #define NTB_SPAD_USER "spad_user_" diff --git a/drivers/raw/ntb/ntb_hw_intel.c b/drivers/raw/ntb/ntb_hw_intel.c index e7f8667cd..76670c96b 100644 --- a/drivers/raw/ntb/ntb_hw_intel.c +++ b/drivers/raw/ntb/ntb_hw_intel.c @@ -25,17 +25,29 @@ static enum xeon_ntb_bar intel_ntb_bar[] = { XEON_NTB_BAR45, }; -static int -intel_ntb_dev_init(const struct rte_rawdev *dev) +static inline int +is_gen3_ntb(const struct ntb_hw *hw) { - struct ntb_hw *hw = dev->dev_private; - uint8_t reg_val, bar; - int ret, i; + if (hw->pci_dev->id.device_id == NTB_INTEL_DEV_ID_B2B_SKX) + return 1; - if (hw == NULL) { - NTB_LOG(ERR, "Invalid device."); - return -EINVAL; - } + return 0; +} + +static inline int +is_gen4_ntb(const struct ntb_hw *hw) +{ + if (hw->pci_dev->id.device_id == NTB_INTEL_DEV_ID_B2B_ICX) + return 1; + + return 0; +} + +static int +intel_ntb3_check_ppd(struct ntb_hw *hw) +{ + uint8_t reg_val; + int ret; ret = rte_pci_read_config(hw->pci_dev, ®_val, sizeof(reg_val), XEON_PPD_OFFSET); @@ -71,8 +83,73 @@ intel_ntb_dev_init(const struct rte_rawdev *dev) return -EINVAL; } + return 0; +} + +static int +intel_ntb4_check_ppd(struct ntb_hw *hw) +{ + uint32_t reg_val; + + reg_val = rte_read32(hw->hw_addr + XEON_GEN4_PPD1_OFFSET); + + /* Check connection topo type. Only support B2B. */ + switch (reg_val & XEON_GEN4_PPD_CONN_MASK) { + case XEON_GEN4_PPD_CONN_B2B: + NTB_LOG(INFO, "Topo B2B (back to back) is using."); + break; + default: + NTB_LOG(ERR, "Not supported conn topo. Please use B2B."); + return -EINVAL; + } + + /* Check device type. */ + if (reg_val & XEON_GEN4_PPD_DEV_DSD) { + NTB_LOG(INFO, "DSD, Downstream Device."); + hw->topo = NTB_TOPO_B2B_DSD; + } else { + NTB_LOG(INFO, "USD, Upstream device."); + hw->topo = NTB_TOPO_B2B_USD; + } + + return 0; +} + +static int +intel_ntb_dev_init(const struct rte_rawdev *dev) +{ + struct ntb_hw *hw = dev->dev_private; + uint16_t link_ctrl; + void *reg_addr; + uint8_t bar; + int ret, i; + + if (hw == NULL) { + NTB_LOG(ERR, "Invalid device."); + return -EINVAL; + } + hw->hw_addr = (char *)hw->pci_dev->mem_resource[0].addr; + if (is_gen3_ntb(hw)) { + ret = intel_ntb3_check_ppd(hw); + } else if (is_gen4_ntb(hw)) { + /* PPD is in MMIO but not config space for NTB Gen4 */ + ret = intel_ntb4_check_ppd(hw); + if (ret) + return ret; + /* init link setup */ + reg_addr = hw->hw_addr + XEON_GEN4_LINK_CTRL_OFFSET; + link_ctrl = rte_read16(reg_addr); + link_ctrl |= XEON_GEN4_LINK_CTRL_LINK_DIS; + rte_write16(link_ctrl, reg_addr); + } else { + return -ENOTSUP; + } + + if (ret) + return ret; + hw->mw_cnt = XEON_MW_COUNT; hw->db_cnt = XEON_DB_COUNT; hw->spad_cnt = XEON_SPAD_COUNT; @@ -149,15 +226,28 @@ intel_ntb_mw_set_trans(const struct rte_rawdev *dev, int mw_idx, rte_write64(base, xlat_addr); rte_write64(limit, limit_addr); - /* Setup the external point so that remote can access. */ - xlat_off = XEON_EMBAR1_OFFSET + 8 * mw_idx; - xlat_addr = hw->hw_addr + xlat_off; - limit_off = XEON_EMBAR1XLMT_OFFSET + mw_idx * XEON_BAR_INTERVAL_OFFSET; - limit_addr = hw->hw_addr + limit_off; - base = rte_read64(xlat_addr); - base &= ~0xf; - limit = base + size; - rte_write64(limit, limit_addr); + if (is_gen3_ntb(hw)) { + /* Setup the external point so that remote can access. */ + xlat_off = XEON_EMBAR1_OFFSET + 8 * mw_idx; + xlat_addr = hw->hw_addr + xlat_off; + limit_off = XEON_EMBAR1XLMT_OFFSET + + mw_idx * XEON_BAR_INTERVAL_OFFSET; + limit_addr = hw->hw_addr + limit_off; + base = rte_read64(xlat_addr); + base &= ~0xf; + limit = base + size; + rte_write64(limit, limit_addr); + } else if (is_gen4_ntb(hw)) { + /* Set translate base address index register */ + xlat_off = XEON_GEN4_IM1XBASEIDX_OFFSET + + mw_idx * XEON_GEN4_XBASEIDX_INTERVAL; + xlat_addr = hw->hw_addr + xlat_off; + rte_write16(rte_log2_u64(size), xlat_addr); + } else { + rte_write64(base, limit_addr); + rte_write64(0, xlat_addr); + return -ENOTSUP; + } return 0; } @@ -187,7 +277,7 @@ static int intel_ntb_get_link_status(const struct rte_rawdev *dev) { struct ntb_hw *hw = dev->dev_private; - uint16_t reg_val; + uint16_t reg_val, reg_off; int ret; if (hw == NULL) { @@ -195,11 +285,19 @@ intel_ntb_get_link_status(const struct rte_rawdev *dev) return -EINVAL; } - ret = rte_pci_read_config(hw->pci_dev, ®_val, - sizeof(reg_val), XEON_LINK_STATUS_OFFSET); - if (ret < 0) { - NTB_LOG(ERR, "Unable to get link status."); - return -EIO; + if (is_gen3_ntb(hw)) { + reg_off = XEON_GEN3_LINK_STATUS_OFFSET; + ret = rte_pci_read_config(hw->pci_dev, ®_val, + sizeof(reg_val), reg_off); + if (ret < 0) { + NTB_LOG(ERR, "Unable to get link status."); + return -EIO; + } + } else if (is_gen4_ntb(hw)) { + reg_off = XEON_GEN4_LINK_STATUS_OFFSET; + reg_val = rte_read16(hw->hw_addr + reg_off); + } else { + return -ENOTSUP; } hw->link_status = NTB_LNK_STA_ACTIVE(reg_val); @@ -216,9 +314,8 @@ intel_ntb_get_link_status(const struct rte_rawdev *dev) } static int -intel_ntb_set_link(const struct rte_rawdev *dev, bool up) +intel_ntb_gen3_set_link(const struct ntb_hw *hw, bool up) { - struct ntb_hw *hw = dev->dev_private; uint32_t ntb_ctrl, reg_off; void *reg_addr; @@ -241,6 +338,65 @@ intel_ntb_set_link(const struct rte_rawdev *dev, bool up) return 0; } +static int +intel_ntb_gen4_set_link(const struct ntb_hw *hw, bool up) +{ + uint32_t ntb_ctrl, ppd0; + uint16_t link_ctrl; + void *reg_addr; + + if (up) { + reg_addr = hw->hw_addr + XEON_NTBCNTL_OFFSET; + ntb_ctrl = NTB_CTL_P2S_BAR2_SNOOP | NTB_CTL_S2P_BAR2_SNOOP; + ntb_ctrl |= NTB_CTL_P2S_BAR4_SNOOP | NTB_CTL_S2P_BAR4_SNOOP; + rte_write32(ntb_ctrl, reg_addr); + + reg_addr = hw->hw_addr + XEON_GEN4_LINK_CTRL_OFFSET; + link_ctrl = rte_read16(reg_addr); + link_ctrl &= ~XEON_GEN4_LINK_CTRL_LINK_DIS; + rte_write16(link_ctrl, reg_addr); + + /* start link training */ + reg_addr = hw->hw_addr + XEON_GEN4_PPD0_OFFSET; + ppd0 = rte_read32(reg_addr); + ppd0 |= XEON_GEN4_PPD_LINKTRN; + rte_write32(ppd0, reg_addr); + + /* make sure link training has started */ + ppd0 = rte_read32(reg_addr); + if (!(ppd0 & XEON_GEN4_PPD_LINKTRN)) { + NTB_LOG(ERR, "Link is not training."); + return -EINVAL; + } + } else { + reg_addr = hw->hw_addr + XEON_NTBCNTL_OFFSET; + ntb_ctrl = rte_read32(reg_addr); + ntb_ctrl &= ~(NTB_CTL_P2S_BAR2_SNOOP | NTB_CTL_S2P_BAR2_SNOOP); + ntb_ctrl &= ~(NTB_CTL_P2S_BAR4_SNOOP | NTB_CTL_S2P_BAR4_SNOOP); + rte_write32(ntb_ctrl, reg_addr); + + reg_addr = hw->hw_addr + XEON_GEN4_LINK_CTRL_OFFSET; + link_ctrl = rte_read16(reg_addr); + link_ctrl |= XEON_GEN4_LINK_CTRL_LINK_DIS; + rte_write16(link_ctrl, reg_addr); + } + + return 0; +} + +static int +intel_ntb_set_link(const struct rte_rawdev *dev, bool up) +{ + struct ntb_hw *hw = dev->dev_private; + + if (is_gen3_ntb(hw)) + return intel_ntb_gen3_set_link(hw, up); + else if (is_gen4_ntb(hw)) + return intel_ntb_gen4_set_link(hw, up); + else + return -ENOTSUP; +} + static uint32_t intel_ntb_spad_read(const struct rte_rawdev *dev, int spad, bool peer) { @@ -254,7 +410,14 @@ intel_ntb_spad_read(const struct rte_rawdev *dev, int spad, bool peer) } /* When peer is true, read peer spad reg */ - reg_off = peer ? XEON_B2B_SPAD_OFFSET : XEON_IM_SPAD_OFFSET; + if (is_gen3_ntb(hw)) + reg_off = peer ? XEON_GEN3_B2B_SPAD_OFFSET : + XEON_IM_SPAD_OFFSET; + else if (is_gen4_ntb(hw)) + reg_off = peer ? XEON_GEN4_B2B_SPAD_OFFSET : + XEON_IM_SPAD_OFFSET; + else + return -ENOTSUP; reg_addr = hw->hw_addr + reg_off + (spad << 2); spad_v = rte_read32(reg_addr); @@ -275,7 +438,14 @@ intel_ntb_spad_write(const struct rte_rawdev *dev, int spad, } /* When peer is true, write peer spad reg */ - reg_off = peer ? XEON_B2B_SPAD_OFFSET : XEON_IM_SPAD_OFFSET; + if (is_gen3_ntb(hw)) + reg_off = peer ? XEON_GEN3_B2B_SPAD_OFFSET : + XEON_IM_SPAD_OFFSET; + else if (is_gen4_ntb(hw)) + reg_off = peer ? XEON_GEN4_B2B_SPAD_OFFSET : + XEON_IM_SPAD_OFFSET; + else + return -ENOTSUP; reg_addr = hw->hw_addr + reg_off + (spad << 2); rte_write32(spad_v, reg_addr); @@ -308,6 +478,9 @@ intel_ntb_db_clear(const struct rte_rawdev *dev, uint64_t db_bits) db_off = XEON_IM_INT_STATUS_OFFSET; db_addr = hw->hw_addr + db_off; + if (is_gen4_ntb(hw)) + rte_write16(XEON_GEN4_SLOTSTS_DLLSCS, + hw->hw_addr + XEON_GEN4_SLOTSTS); rte_write64(db_bits, db_addr); return 0; @@ -365,7 +538,12 @@ intel_ntb_vector_bind(const struct rte_rawdev *dev, uint8_t intr, uint8_t msix) } /* Bind intr source to msix vector */ - reg_off = XEON_INTVEC_OFFSET; + if (is_gen3_ntb(hw)) + reg_off = XEON_GEN3_INTVEC_OFFSET; + else if (is_gen4_ntb(hw)) + reg_off = XEON_GEN4_INTVEC_OFFSET; + else + return -ENOTSUP; reg_addr = hw->hw_addr + reg_off + intr; rte_write8(msix, reg_addr); diff --git a/drivers/raw/ntb/ntb_hw_intel.h b/drivers/raw/ntb/ntb_hw_intel.h index 4d1e64504..604f7aa7a 100644 --- a/drivers/raw/ntb/ntb_hw_intel.h +++ b/drivers/raw/ntb/ntb_hw_intel.h @@ -22,7 +22,7 @@ #define NTB_LNK_STA_SPEED(x) ((x) & NTB_LNK_STA_SPEED_MASK) #define NTB_LNK_STA_WIDTH(x) (((x) & NTB_LNK_STA_WIDTH_MASK) >> 4) -/* Intel Skylake Xeon hardware */ +/* Intel Xeon hardware */ #define XEON_IMBAR1SZ_OFFSET 0x00d0 #define XEON_IMBAR2SZ_OFFSET 0x00d1 #define XEON_EMBAR1SZ_OFFSET 0x00d2 @@ -31,7 +31,13 @@ #define XEON_DEVSTS_OFFSET 0x009a #define XEON_UNCERRSTS_OFFSET 0x014c #define XEON_CORERRSTS_OFFSET 0x0158 -#define XEON_LINK_STATUS_OFFSET 0x01a2 +#define XEON_GEN3_LINK_STATUS_OFFSET 0x01a2 +/* Link status and PPD are in MMIO but not config space for Gen4 NTB */ +#define XEON_GEN4_PPD0_OFFSET 0xb0d4 +#define XEON_GEN4_PPD1_OFFSET 0xb4c0 +#define XEON_GEN4_LINK_CTRL_OFFSET 0xb050 +#define XEON_GEN4_LINK_STATUS_OFFSET 0xb052 +#define XEON_GEN4_LINK_CTRL_LINK_DIS 0x0010 #define XEON_NTBCNTL_OFFSET 0x0000 #define XEON_BAR_INTERVAL_OFFSET 0x0010 @@ -39,13 +45,18 @@ #define XEON_IMBAR1XLMT_OFFSET 0x0018 /* SBAR2LMT */ #define XEON_IMBAR2XBASE_OFFSET 0x0020 /* SBAR4XLAT */ #define XEON_IMBAR2XLMT_OFFSET 0x0028 /* SBAR4LMT */ +#define XEON_GEN4_XBASEIDX_INTERVAL 0x0002 +#define XEON_GEN4_IM1XBASEIDX_OFFSET 0x0074 +#define XEON_GEN4_IM2XBASEIDX_OFFSET 0x0076 #define XEON_IM_INT_STATUS_OFFSET 0x0040 #define XEON_IM_INT_DISABLE_OFFSET 0x0048 #define XEON_IM_SPAD_OFFSET 0x0080 /* SPAD */ +#define XEON_GEN3_B2B_SPAD_OFFSET 0x0180 /* GEN3 B2B SPAD */ +#define XEON_GEN4_B2B_SPAD_OFFSET 0x8080 /* GEN4 B2B SPAD */ #define XEON_USMEMMISS_OFFSET 0x0070 -#define XEON_INTVEC_OFFSET 0x00d0 +#define XEON_GEN3_INTVEC_OFFSET 0x00d0 +#define XEON_GEN4_INTVEC_OFFSET 0x0050 #define XEON_IM_DOORBELL_OFFSET 0x0100 /* SDOORBELL0 */ -#define XEON_B2B_SPAD_OFFSET 0x0180 /* B2B SPAD */ #define XEON_EMBAR0XBASE_OFFSET 0x4008 /* B2B_XLAT */ #define XEON_EMBAR1XBASE_OFFSET 0x4010 /* PBAR2XLAT */ #define XEON_EMBAR1XLMT_OFFSET 0x4018 /* PBAR2LMT */ @@ -60,6 +71,7 @@ #define XEON_EMBAR1_OFFSET 0x4518 /* SBAR23BASE */ #define XEON_EMBAR2_OFFSET 0x4520 /* SBAR45BASE */ + #define XEON_PPD_OFFSET 0x00d4 #define XEON_PPD_CONN_MASK 0x03 #define XEON_PPD_CONN_TRANSPARENT 0x00 @@ -70,6 +82,14 @@ #define XEON_PPD_DEV_DSD 0x10 #define XEON_PPD_SPLIT_BAR_MASK 0x40 +#define XEON_GEN4_PPD_CONN_MASK 0x0300 +#define XEON_GEN4_PPD_CONN_B2B 0x0200 +#define XEON_GEN4_PPD_DEV_MASK 0x1000 +#define XEON_GEN4_PPD_DEV_DSD 0x1000 +#define XEON_GEN4_PPD_DEV_USD 0x0000 +#define XEON_GEN4_PPD_LINKTRN 0x0008 +#define XEON_GEN4_SLOTSTS 0xb05a +#define XEON_GEN4_SLOTSTS_DLLSCS 0x100 #define XEON_MW_COUNT 2 diff --git a/usertools/dpdk-devbind.py b/usertools/dpdk-devbind.py index 86b6b53c4..081c3bc92 100755 --- a/usertools/dpdk-devbind.py +++ b/usertools/dpdk-devbind.py @@ -53,6 +53,8 @@ 'SVendor': None, 'SDevice': None} intel_ntb_skx = {'Class': '06', 'Vendor': '8086', 'Device': '201c', 'SVendor': None, 'SDevice': None} +intel_ntb_icx = {'Class': '06', 'Vendor': '8086', 'Device': '347e', + 'SVendor': None, 'SDevice': None} network_devices = [network_class, cavium_pkx, avp_vnic, ifpga_class] baseband_devices = [acceleration_class] @@ -60,7 +62,7 @@ eventdev_devices = [cavium_sso, cavium_tim, octeontx2_sso] mempool_devices = [cavium_fpa, octeontx2_npa] compress_devices = [cavium_zip] -misc_devices = [intel_ioat_bdw, intel_ioat_skx, intel_ioat_icx, intel_ntb_skx, octeontx2_dma] +misc_devices = [intel_ioat_bdw, intel_ioat_skx, intel_ioat_icx, intel_ntb_skx, intel_ntb_icx, octeontx2_dma] # global dict ethernet devices present. Dictionary indexed by PCI address. # Each device within this is itself a dictionary of device properties -- 2.17.1
Add NTB device support (4th generation) for Intel Icelake platform. Signed-off-by: Xiaoyun Li <xiaoyun.li@intel.com> --- doc/guides/rawdevs/ntb.rst | 16 +- doc/guides/rel_notes/release_20_11.rst | 3 + drivers/raw/ntb/ntb.c | 5 + drivers/raw/ntb/ntb.h | 1 + drivers/raw/ntb/ntb_hw_intel.c | 229 +++++++++++++++++++++---- drivers/raw/ntb/ntb_hw_intel.h | 28 ++- usertools/dpdk-devbind.py | 4 +- 7 files changed, 244 insertions(+), 42 deletions(-) diff --git a/doc/guides/rawdevs/ntb.rst b/doc/guides/rawdevs/ntb.rst index aa7d80964..0f04d3e24 100644 --- a/doc/guides/rawdevs/ntb.rst +++ b/doc/guides/rawdevs/ntb.rst @@ -14,16 +14,16 @@ allocation for the peer to access and read/write allocated memory from peer. Also, the PMD allows to use doorbell registers to notify the peer and share some information by using scratchpad registers. -BIOS setting on Intel Skylake ------------------------------ +BIOS setting on Intel Xeon +-------------------------- -Intel Non-transparent Bridge needs special BIOS setting. Since the PMD only -supports Intel Skylake platform, introduce BIOS setting here. The referencce -is https://www.intel.com/content/dam/support/us/en/documents/server-products/Intel_Xeon_Processor_Scalable_Family_BIOS_User_Guide.pdf +Intel Non-transparent Bridge needs special BIOS setting. The referencce for +Skylake is https://www.intel.com/content/dam/support/us/en/documents/server-products/Intel_Xeon_Processor_Scalable_Family_BIOS_User_Guide.pdf - Set the needed PCIe port as NTB to NTB mode on both hosts. -- Enable NTB bars and set bar size of bar 23 and bar 45 as 12-29 (2K-512M) - on both hosts. Note that bar size on both hosts should be the same. +- Enable NTB bars and set bar size of bar 23 and bar 45 as 12-29 (4K-512M) + on both hosts (for Icelake, bar size can be set as 12-51, namely 4K-128PB). + Note that bar size on both hosts should be the same. - Disable split bars for both hosts. - Set crosslink control override as DSD/USP on one host, USD/DSP on another host. @@ -151,4 +151,4 @@ like the following: Limitation ---------- -- This PMD only supports Intel Skylake platform. +- This PMD only supports Intel Skylake and Icelake platforms. diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst index df227a177..d13782459 100644 --- a/doc/guides/rel_notes/release_20_11.rst +++ b/doc/guides/rel_notes/release_20_11.rst @@ -55,6 +55,9 @@ New Features Also, make sure to start the actual text at the margin. ======================================================= +* **Added Icelake (Gen4) support for Intel NTB.** + + Added NTB device support (4th generation) for Intel Icelake platform. Removed Items ------------- diff --git a/drivers/raw/ntb/ntb.c b/drivers/raw/ntb/ntb.c index e40412bb7..e29acecef 100644 --- a/drivers/raw/ntb/ntb.c +++ b/drivers/raw/ntb/ntb.c @@ -25,6 +25,7 @@ static const struct rte_pci_id pci_id_ntb_map[] = { { RTE_PCI_DEVICE(NTB_INTEL_VENDOR_ID, NTB_INTEL_DEV_ID_B2B_SKX) }, + { RTE_PCI_DEVICE(NTB_INTEL_VENDOR_ID, NTB_INTEL_DEV_ID_B2B_ICX) }, { .vendor_id = 0, /* sentinel */ }, }; @@ -244,6 +245,9 @@ ntb_dev_intr_handler(void *param) hw->peer_dev_up = 0; return; } + + /* Clear other received doorbells. */ + (*hw->ntb_ops->db_clear)(dev, db_bits); } static void @@ -1333,6 +1337,7 @@ ntb_init_hw(struct rte_rawdev *dev, struct rte_pci_device *pci_dev) switch (pci_dev->id.device_id) { case NTB_INTEL_DEV_ID_B2B_SKX: + case NTB_INTEL_DEV_ID_B2B_ICX: hw->ntb_ops = &intel_ntb_ops; break; default: diff --git a/drivers/raw/ntb/ntb.h b/drivers/raw/ntb/ntb.h index a561c42d1..cdf7667d5 100644 --- a/drivers/raw/ntb/ntb.h +++ b/drivers/raw/ntb/ntb.h @@ -18,6 +18,7 @@ extern int ntb_logtype; /* Device IDs */ #define NTB_INTEL_DEV_ID_B2B_SKX 0x201C +#define NTB_INTEL_DEV_ID_B2B_ICX 0x347E /* Reserved to app to use. */ #define NTB_SPAD_USER "spad_user_" diff --git a/drivers/raw/ntb/ntb_hw_intel.c b/drivers/raw/ntb/ntb_hw_intel.c index e7f8667cd..cadceef51 100644 --- a/drivers/raw/ntb/ntb_hw_intel.c +++ b/drivers/raw/ntb/ntb_hw_intel.c @@ -25,17 +25,29 @@ static enum xeon_ntb_bar intel_ntb_bar[] = { XEON_NTB_BAR45, }; -static int -intel_ntb_dev_init(const struct rte_rawdev *dev) +static inline int +is_gen3_ntb(const struct ntb_hw *hw) { - struct ntb_hw *hw = dev->dev_private; - uint8_t reg_val, bar; - int ret, i; + if (hw->pci_dev->id.device_id == NTB_INTEL_DEV_ID_B2B_SKX) + return 1; - if (hw == NULL) { - NTB_LOG(ERR, "Invalid device."); - return -EINVAL; - } + return 0; +} + +static inline int +is_gen4_ntb(const struct ntb_hw *hw) +{ + if (hw->pci_dev->id.device_id == NTB_INTEL_DEV_ID_B2B_ICX) + return 1; + + return 0; +} + +static int +intel_ntb3_check_ppd(struct ntb_hw *hw) +{ + uint8_t reg_val; + int ret; ret = rte_pci_read_config(hw->pci_dev, ®_val, sizeof(reg_val), XEON_PPD_OFFSET); @@ -71,8 +83,66 @@ intel_ntb_dev_init(const struct rte_rawdev *dev) return -EINVAL; } + return 0; +} + +static int +intel_ntb4_check_ppd(struct ntb_hw *hw) +{ + uint32_t reg_val; + + reg_val = rte_read32(hw->hw_addr + XEON_GEN4_PPD1_OFFSET); + + /* Check connection topo type. Only support B2B. */ + switch (reg_val & XEON_GEN4_PPD_CONN_MASK) { + case XEON_GEN4_PPD_CONN_B2B: + NTB_LOG(INFO, "Topo B2B (back to back) is using."); + break; + default: + NTB_LOG(ERR, "Not supported conn topo. Please use B2B."); + return -EINVAL; + } + + /* Check device type. */ + if (reg_val & XEON_GEN4_PPD_DEV_DSD) { + NTB_LOG(INFO, "DSD, Downstream Device."); + hw->topo = NTB_TOPO_B2B_DSD; + } else { + NTB_LOG(INFO, "USD, Upstream device."); + hw->topo = NTB_TOPO_B2B_USD; + } + + return 0; +} + +static int +intel_ntb_dev_init(const struct rte_rawdev *dev) +{ + struct ntb_hw *hw = dev->dev_private; + uint8_t bar; + int ret, i; + + if (hw == NULL) { + NTB_LOG(ERR, "Invalid device."); + return -EINVAL; + } + hw->hw_addr = (char *)hw->pci_dev->mem_resource[0].addr; + if (is_gen3_ntb(hw)) { + ret = intel_ntb3_check_ppd(hw); + } else if (is_gen4_ntb(hw)) { + /* PPD is in MMIO but not config space for NTB Gen4 */ + ret = intel_ntb4_check_ppd(hw); + if (ret) + return ret; + } else { + return -ENOTSUP; + } + + if (ret) + return ret; + hw->mw_cnt = XEON_MW_COUNT; hw->db_cnt = XEON_DB_COUNT; hw->spad_cnt = XEON_SPAD_COUNT; @@ -149,15 +219,28 @@ intel_ntb_mw_set_trans(const struct rte_rawdev *dev, int mw_idx, rte_write64(base, xlat_addr); rte_write64(limit, limit_addr); - /* Setup the external point so that remote can access. */ - xlat_off = XEON_EMBAR1_OFFSET + 8 * mw_idx; - xlat_addr = hw->hw_addr + xlat_off; - limit_off = XEON_EMBAR1XLMT_OFFSET + mw_idx * XEON_BAR_INTERVAL_OFFSET; - limit_addr = hw->hw_addr + limit_off; - base = rte_read64(xlat_addr); - base &= ~0xf; - limit = base + size; - rte_write64(limit, limit_addr); + if (is_gen3_ntb(hw)) { + /* Setup the external point so that remote can access. */ + xlat_off = XEON_EMBAR1_OFFSET + 8 * mw_idx; + xlat_addr = hw->hw_addr + xlat_off; + limit_off = XEON_EMBAR1XLMT_OFFSET + + mw_idx * XEON_BAR_INTERVAL_OFFSET; + limit_addr = hw->hw_addr + limit_off; + base = rte_read64(xlat_addr); + base &= ~0xf; + limit = base + size; + rte_write64(limit, limit_addr); + } else if (is_gen4_ntb(hw)) { + /* Set translate base address index register */ + xlat_off = XEON_GEN4_IM1XBASEIDX_OFFSET + + mw_idx * XEON_GEN4_XBASEIDX_INTERVAL; + xlat_addr = hw->hw_addr + xlat_off; + rte_write16(rte_log2_u64(size), xlat_addr); + } else { + rte_write64(base, limit_addr); + rte_write64(0, xlat_addr); + return -ENOTSUP; + } return 0; } @@ -187,7 +270,7 @@ static int intel_ntb_get_link_status(const struct rte_rawdev *dev) { struct ntb_hw *hw = dev->dev_private; - uint16_t reg_val; + uint16_t reg_val, reg_off; int ret; if (hw == NULL) { @@ -195,11 +278,19 @@ intel_ntb_get_link_status(const struct rte_rawdev *dev) return -EINVAL; } - ret = rte_pci_read_config(hw->pci_dev, ®_val, - sizeof(reg_val), XEON_LINK_STATUS_OFFSET); - if (ret < 0) { - NTB_LOG(ERR, "Unable to get link status."); - return -EIO; + if (is_gen3_ntb(hw)) { + reg_off = XEON_GEN3_LINK_STATUS_OFFSET; + ret = rte_pci_read_config(hw->pci_dev, ®_val, + sizeof(reg_val), reg_off); + if (ret < 0) { + NTB_LOG(ERR, "Unable to get link status."); + return -EIO; + } + } else if (is_gen4_ntb(hw)) { + reg_off = XEON_GEN4_LINK_STATUS_OFFSET; + reg_val = rte_read16(hw->hw_addr + reg_off); + } else { + return -ENOTSUP; } hw->link_status = NTB_LNK_STA_ACTIVE(reg_val); @@ -216,9 +307,8 @@ intel_ntb_get_link_status(const struct rte_rawdev *dev) } static int -intel_ntb_set_link(const struct rte_rawdev *dev, bool up) +intel_ntb_gen3_set_link(const struct ntb_hw *hw, bool up) { - struct ntb_hw *hw = dev->dev_private; uint32_t ntb_ctrl, reg_off; void *reg_addr; @@ -241,6 +331,65 @@ intel_ntb_set_link(const struct rte_rawdev *dev, bool up) return 0; } +static int +intel_ntb_gen4_set_link(const struct ntb_hw *hw, bool up) +{ + uint32_t ntb_ctrl, ppd0; + uint16_t link_ctrl; + void *reg_addr; + + if (up) { + reg_addr = hw->hw_addr + XEON_NTBCNTL_OFFSET; + ntb_ctrl = NTB_CTL_P2S_BAR2_SNOOP | NTB_CTL_S2P_BAR2_SNOOP; + ntb_ctrl |= NTB_CTL_P2S_BAR4_SNOOP | NTB_CTL_S2P_BAR4_SNOOP; + rte_write32(ntb_ctrl, reg_addr); + + reg_addr = hw->hw_addr + XEON_GEN4_LINK_CTRL_OFFSET; + link_ctrl = rte_read16(reg_addr); + link_ctrl &= ~XEON_GEN4_LINK_CTRL_LINK_DIS; + rte_write16(link_ctrl, reg_addr); + + /* start link training */ + reg_addr = hw->hw_addr + XEON_GEN4_PPD0_OFFSET; + ppd0 = rte_read32(reg_addr); + ppd0 |= XEON_GEN4_PPD_LINKTRN; + rte_write32(ppd0, reg_addr); + + /* make sure link training has started */ + ppd0 = rte_read32(reg_addr); + if (!(ppd0 & XEON_GEN4_PPD_LINKTRN)) { + NTB_LOG(ERR, "Link is not training."); + return -EINVAL; + } + } else { + reg_addr = hw->hw_addr + XEON_NTBCNTL_OFFSET; + ntb_ctrl = rte_read32(reg_addr); + ntb_ctrl &= ~(NTB_CTL_P2S_BAR2_SNOOP | NTB_CTL_S2P_BAR2_SNOOP); + ntb_ctrl &= ~(NTB_CTL_P2S_BAR4_SNOOP | NTB_CTL_S2P_BAR4_SNOOP); + rte_write32(ntb_ctrl, reg_addr); + + reg_addr = hw->hw_addr + XEON_GEN4_LINK_CTRL_OFFSET; + link_ctrl = rte_read16(reg_addr); + link_ctrl |= XEON_GEN4_LINK_CTRL_LINK_DIS; + rte_write16(link_ctrl, reg_addr); + } + + return 0; +} + +static int +intel_ntb_set_link(const struct rte_rawdev *dev, bool up) +{ + struct ntb_hw *hw = dev->dev_private; + + if (is_gen3_ntb(hw)) + return intel_ntb_gen3_set_link(hw, up); + else if (is_gen4_ntb(hw)) + return intel_ntb_gen4_set_link(hw, up); + else + return -ENOTSUP; +} + static uint32_t intel_ntb_spad_read(const struct rte_rawdev *dev, int spad, bool peer) { @@ -254,7 +403,14 @@ intel_ntb_spad_read(const struct rte_rawdev *dev, int spad, bool peer) } /* When peer is true, read peer spad reg */ - reg_off = peer ? XEON_B2B_SPAD_OFFSET : XEON_IM_SPAD_OFFSET; + if (is_gen3_ntb(hw)) + reg_off = peer ? XEON_GEN3_B2B_SPAD_OFFSET : + XEON_IM_SPAD_OFFSET; + else if (is_gen4_ntb(hw)) + reg_off = peer ? XEON_GEN4_B2B_SPAD_OFFSET : + XEON_IM_SPAD_OFFSET; + else + return -ENOTSUP; reg_addr = hw->hw_addr + reg_off + (spad << 2); spad_v = rte_read32(reg_addr); @@ -275,7 +431,14 @@ intel_ntb_spad_write(const struct rte_rawdev *dev, int spad, } /* When peer is true, write peer spad reg */ - reg_off = peer ? XEON_B2B_SPAD_OFFSET : XEON_IM_SPAD_OFFSET; + if (is_gen3_ntb(hw)) + reg_off = peer ? XEON_GEN3_B2B_SPAD_OFFSET : + XEON_IM_SPAD_OFFSET; + else if (is_gen4_ntb(hw)) + reg_off = peer ? XEON_GEN4_B2B_SPAD_OFFSET : + XEON_IM_SPAD_OFFSET; + else + return -ENOTSUP; reg_addr = hw->hw_addr + reg_off + (spad << 2); rte_write32(spad_v, reg_addr); @@ -308,6 +471,9 @@ intel_ntb_db_clear(const struct rte_rawdev *dev, uint64_t db_bits) db_off = XEON_IM_INT_STATUS_OFFSET; db_addr = hw->hw_addr + db_off; + if (is_gen4_ntb(hw)) + rte_write16(XEON_GEN4_SLOTSTS_DLLSCS, + hw->hw_addr + XEON_GEN4_SLOTSTS); rte_write64(db_bits, db_addr); return 0; @@ -365,7 +531,12 @@ intel_ntb_vector_bind(const struct rte_rawdev *dev, uint8_t intr, uint8_t msix) } /* Bind intr source to msix vector */ - reg_off = XEON_INTVEC_OFFSET; + if (is_gen3_ntb(hw)) + reg_off = XEON_GEN3_INTVEC_OFFSET; + else if (is_gen4_ntb(hw)) + reg_off = XEON_GEN4_INTVEC_OFFSET; + else + return -ENOTSUP; reg_addr = hw->hw_addr + reg_off + intr; rte_write8(msix, reg_addr); diff --git a/drivers/raw/ntb/ntb_hw_intel.h b/drivers/raw/ntb/ntb_hw_intel.h index 4d1e64504..604f7aa7a 100644 --- a/drivers/raw/ntb/ntb_hw_intel.h +++ b/drivers/raw/ntb/ntb_hw_intel.h @@ -22,7 +22,7 @@ #define NTB_LNK_STA_SPEED(x) ((x) & NTB_LNK_STA_SPEED_MASK) #define NTB_LNK_STA_WIDTH(x) (((x) & NTB_LNK_STA_WIDTH_MASK) >> 4) -/* Intel Skylake Xeon hardware */ +/* Intel Xeon hardware */ #define XEON_IMBAR1SZ_OFFSET 0x00d0 #define XEON_IMBAR2SZ_OFFSET 0x00d1 #define XEON_EMBAR1SZ_OFFSET 0x00d2 @@ -31,7 +31,13 @@ #define XEON_DEVSTS_OFFSET 0x009a #define XEON_UNCERRSTS_OFFSET 0x014c #define XEON_CORERRSTS_OFFSET 0x0158 -#define XEON_LINK_STATUS_OFFSET 0x01a2 +#define XEON_GEN3_LINK_STATUS_OFFSET 0x01a2 +/* Link status and PPD are in MMIO but not config space for Gen4 NTB */ +#define XEON_GEN4_PPD0_OFFSET 0xb0d4 +#define XEON_GEN4_PPD1_OFFSET 0xb4c0 +#define XEON_GEN4_LINK_CTRL_OFFSET 0xb050 +#define XEON_GEN4_LINK_STATUS_OFFSET 0xb052 +#define XEON_GEN4_LINK_CTRL_LINK_DIS 0x0010 #define XEON_NTBCNTL_OFFSET 0x0000 #define XEON_BAR_INTERVAL_OFFSET 0x0010 @@ -39,13 +45,18 @@ #define XEON_IMBAR1XLMT_OFFSET 0x0018 /* SBAR2LMT */ #define XEON_IMBAR2XBASE_OFFSET 0x0020 /* SBAR4XLAT */ #define XEON_IMBAR2XLMT_OFFSET 0x0028 /* SBAR4LMT */ +#define XEON_GEN4_XBASEIDX_INTERVAL 0x0002 +#define XEON_GEN4_IM1XBASEIDX_OFFSET 0x0074 +#define XEON_GEN4_IM2XBASEIDX_OFFSET 0x0076 #define XEON_IM_INT_STATUS_OFFSET 0x0040 #define XEON_IM_INT_DISABLE_OFFSET 0x0048 #define XEON_IM_SPAD_OFFSET 0x0080 /* SPAD */ +#define XEON_GEN3_B2B_SPAD_OFFSET 0x0180 /* GEN3 B2B SPAD */ +#define XEON_GEN4_B2B_SPAD_OFFSET 0x8080 /* GEN4 B2B SPAD */ #define XEON_USMEMMISS_OFFSET 0x0070 -#define XEON_INTVEC_OFFSET 0x00d0 +#define XEON_GEN3_INTVEC_OFFSET 0x00d0 +#define XEON_GEN4_INTVEC_OFFSET 0x0050 #define XEON_IM_DOORBELL_OFFSET 0x0100 /* SDOORBELL0 */ -#define XEON_B2B_SPAD_OFFSET 0x0180 /* B2B SPAD */ #define XEON_EMBAR0XBASE_OFFSET 0x4008 /* B2B_XLAT */ #define XEON_EMBAR1XBASE_OFFSET 0x4010 /* PBAR2XLAT */ #define XEON_EMBAR1XLMT_OFFSET 0x4018 /* PBAR2LMT */ @@ -60,6 +71,7 @@ #define XEON_EMBAR1_OFFSET 0x4518 /* SBAR23BASE */ #define XEON_EMBAR2_OFFSET 0x4520 /* SBAR45BASE */ + #define XEON_PPD_OFFSET 0x00d4 #define XEON_PPD_CONN_MASK 0x03 #define XEON_PPD_CONN_TRANSPARENT 0x00 @@ -70,6 +82,14 @@ #define XEON_PPD_DEV_DSD 0x10 #define XEON_PPD_SPLIT_BAR_MASK 0x40 +#define XEON_GEN4_PPD_CONN_MASK 0x0300 +#define XEON_GEN4_PPD_CONN_B2B 0x0200 +#define XEON_GEN4_PPD_DEV_MASK 0x1000 +#define XEON_GEN4_PPD_DEV_DSD 0x1000 +#define XEON_GEN4_PPD_DEV_USD 0x0000 +#define XEON_GEN4_PPD_LINKTRN 0x0008 +#define XEON_GEN4_SLOTSTS 0xb05a +#define XEON_GEN4_SLOTSTS_DLLSCS 0x100 #define XEON_MW_COUNT 2 diff --git a/usertools/dpdk-devbind.py b/usertools/dpdk-devbind.py index 86b6b53c4..081c3bc92 100755 --- a/usertools/dpdk-devbind.py +++ b/usertools/dpdk-devbind.py @@ -53,6 +53,8 @@ 'SVendor': None, 'SDevice': None} intel_ntb_skx = {'Class': '06', 'Vendor': '8086', 'Device': '201c', 'SVendor': None, 'SDevice': None} +intel_ntb_icx = {'Class': '06', 'Vendor': '8086', 'Device': '347e', + 'SVendor': None, 'SDevice': None} network_devices = [network_class, cavium_pkx, avp_vnic, ifpga_class] baseband_devices = [acceleration_class] @@ -60,7 +62,7 @@ eventdev_devices = [cavium_sso, cavium_tim, octeontx2_sso] mempool_devices = [cavium_fpa, octeontx2_npa] compress_devices = [cavium_zip] -misc_devices = [intel_ioat_bdw, intel_ioat_skx, intel_ioat_icx, intel_ntb_skx, octeontx2_dma] +misc_devices = [intel_ioat_bdw, intel_ioat_skx, intel_ioat_icx, intel_ntb_skx, intel_ntb_icx, octeontx2_dma] # global dict ethernet devices present. Dictionary indexed by PCI address. # Each device within this is itself a dictionary of device properties -- 2.17.1
Add NTB device support (4th generation) for Intel Icelake platform. Signed-off-by: Xiaoyun Li <xiaoyun.li@intel.com> --- v3: * Removed a blank line. * Added change doc for v2. v2: * Corrected and polished the doc. * Fixed a link setup issue. --- doc/guides/rawdevs/ntb.rst | 16 +- doc/guides/rel_notes/release_20_11.rst | 3 + drivers/raw/ntb/ntb.c | 5 + drivers/raw/ntb/ntb.h | 1 + drivers/raw/ntb/ntb_hw_intel.c | 229 +++++++++++++++++++++---- drivers/raw/ntb/ntb_hw_intel.h | 27 ++- usertools/dpdk-devbind.py | 4 +- 7 files changed, 243 insertions(+), 42 deletions(-) diff --git a/doc/guides/rawdevs/ntb.rst b/doc/guides/rawdevs/ntb.rst index aa7d80964..0f04d3e24 100644 --- a/doc/guides/rawdevs/ntb.rst +++ b/doc/guides/rawdevs/ntb.rst @@ -14,16 +14,16 @@ allocation for the peer to access and read/write allocated memory from peer. Also, the PMD allows to use doorbell registers to notify the peer and share some information by using scratchpad registers. -BIOS setting on Intel Skylake ------------------------------ +BIOS setting on Intel Xeon +-------------------------- -Intel Non-transparent Bridge needs special BIOS setting. Since the PMD only -supports Intel Skylake platform, introduce BIOS setting here. The referencce -is https://www.intel.com/content/dam/support/us/en/documents/server-products/Intel_Xeon_Processor_Scalable_Family_BIOS_User_Guide.pdf +Intel Non-transparent Bridge needs special BIOS setting. The referencce for +Skylake is https://www.intel.com/content/dam/support/us/en/documents/server-products/Intel_Xeon_Processor_Scalable_Family_BIOS_User_Guide.pdf - Set the needed PCIe port as NTB to NTB mode on both hosts. -- Enable NTB bars and set bar size of bar 23 and bar 45 as 12-29 (2K-512M) - on both hosts. Note that bar size on both hosts should be the same. +- Enable NTB bars and set bar size of bar 23 and bar 45 as 12-29 (4K-512M) + on both hosts (for Icelake, bar size can be set as 12-51, namely 4K-128PB). + Note that bar size on both hosts should be the same. - Disable split bars for both hosts. - Set crosslink control override as DSD/USP on one host, USD/DSP on another host. @@ -151,4 +151,4 @@ like the following: Limitation ---------- -- This PMD only supports Intel Skylake platform. +- This PMD only supports Intel Skylake and Icelake platforms. diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst index df227a177..d13782459 100644 --- a/doc/guides/rel_notes/release_20_11.rst +++ b/doc/guides/rel_notes/release_20_11.rst @@ -55,6 +55,9 @@ New Features Also, make sure to start the actual text at the margin. ======================================================= +* **Added Icelake (Gen4) support for Intel NTB.** + + Added NTB device support (4th generation) for Intel Icelake platform. Removed Items ------------- diff --git a/drivers/raw/ntb/ntb.c b/drivers/raw/ntb/ntb.c index e40412bb7..e29acecef 100644 --- a/drivers/raw/ntb/ntb.c +++ b/drivers/raw/ntb/ntb.c @@ -25,6 +25,7 @@ static const struct rte_pci_id pci_id_ntb_map[] = { { RTE_PCI_DEVICE(NTB_INTEL_VENDOR_ID, NTB_INTEL_DEV_ID_B2B_SKX) }, + { RTE_PCI_DEVICE(NTB_INTEL_VENDOR_ID, NTB_INTEL_DEV_ID_B2B_ICX) }, { .vendor_id = 0, /* sentinel */ }, }; @@ -244,6 +245,9 @@ ntb_dev_intr_handler(void *param) hw->peer_dev_up = 0; return; } + + /* Clear other received doorbells. */ + (*hw->ntb_ops->db_clear)(dev, db_bits); } static void @@ -1333,6 +1337,7 @@ ntb_init_hw(struct rte_rawdev *dev, struct rte_pci_device *pci_dev) switch (pci_dev->id.device_id) { case NTB_INTEL_DEV_ID_B2B_SKX: + case NTB_INTEL_DEV_ID_B2B_ICX: hw->ntb_ops = &intel_ntb_ops; break; default: diff --git a/drivers/raw/ntb/ntb.h b/drivers/raw/ntb/ntb.h index a561c42d1..cdf7667d5 100644 --- a/drivers/raw/ntb/ntb.h +++ b/drivers/raw/ntb/ntb.h @@ -18,6 +18,7 @@ extern int ntb_logtype; /* Device IDs */ #define NTB_INTEL_DEV_ID_B2B_SKX 0x201C +#define NTB_INTEL_DEV_ID_B2B_ICX 0x347E /* Reserved to app to use. */ #define NTB_SPAD_USER "spad_user_" diff --git a/drivers/raw/ntb/ntb_hw_intel.c b/drivers/raw/ntb/ntb_hw_intel.c index e7f8667cd..cadceef51 100644 --- a/drivers/raw/ntb/ntb_hw_intel.c +++ b/drivers/raw/ntb/ntb_hw_intel.c @@ -25,17 +25,29 @@ static enum xeon_ntb_bar intel_ntb_bar[] = { XEON_NTB_BAR45, }; -static int -intel_ntb_dev_init(const struct rte_rawdev *dev) +static inline int +is_gen3_ntb(const struct ntb_hw *hw) { - struct ntb_hw *hw = dev->dev_private; - uint8_t reg_val, bar; - int ret, i; + if (hw->pci_dev->id.device_id == NTB_INTEL_DEV_ID_B2B_SKX) + return 1; - if (hw == NULL) { - NTB_LOG(ERR, "Invalid device."); - return -EINVAL; - } + return 0; +} + +static inline int +is_gen4_ntb(const struct ntb_hw *hw) +{ + if (hw->pci_dev->id.device_id == NTB_INTEL_DEV_ID_B2B_ICX) + return 1; + + return 0; +} + +static int +intel_ntb3_check_ppd(struct ntb_hw *hw) +{ + uint8_t reg_val; + int ret; ret = rte_pci_read_config(hw->pci_dev, ®_val, sizeof(reg_val), XEON_PPD_OFFSET); @@ -71,8 +83,66 @@ intel_ntb_dev_init(const struct rte_rawdev *dev) return -EINVAL; } + return 0; +} + +static int +intel_ntb4_check_ppd(struct ntb_hw *hw) +{ + uint32_t reg_val; + + reg_val = rte_read32(hw->hw_addr + XEON_GEN4_PPD1_OFFSET); + + /* Check connection topo type. Only support B2B. */ + switch (reg_val & XEON_GEN4_PPD_CONN_MASK) { + case XEON_GEN4_PPD_CONN_B2B: + NTB_LOG(INFO, "Topo B2B (back to back) is using."); + break; + default: + NTB_LOG(ERR, "Not supported conn topo. Please use B2B."); + return -EINVAL; + } + + /* Check device type. */ + if (reg_val & XEON_GEN4_PPD_DEV_DSD) { + NTB_LOG(INFO, "DSD, Downstream Device."); + hw->topo = NTB_TOPO_B2B_DSD; + } else { + NTB_LOG(INFO, "USD, Upstream device."); + hw->topo = NTB_TOPO_B2B_USD; + } + + return 0; +} + +static int +intel_ntb_dev_init(const struct rte_rawdev *dev) +{ + struct ntb_hw *hw = dev->dev_private; + uint8_t bar; + int ret, i; + + if (hw == NULL) { + NTB_LOG(ERR, "Invalid device."); + return -EINVAL; + } + hw->hw_addr = (char *)hw->pci_dev->mem_resource[0].addr; + if (is_gen3_ntb(hw)) { + ret = intel_ntb3_check_ppd(hw); + } else if (is_gen4_ntb(hw)) { + /* PPD is in MMIO but not config space for NTB Gen4 */ + ret = intel_ntb4_check_ppd(hw); + if (ret) + return ret; + } else { + return -ENOTSUP; + } + + if (ret) + return ret; + hw->mw_cnt = XEON_MW_COUNT; hw->db_cnt = XEON_DB_COUNT; hw->spad_cnt = XEON_SPAD_COUNT; @@ -149,15 +219,28 @@ intel_ntb_mw_set_trans(const struct rte_rawdev *dev, int mw_idx, rte_write64(base, xlat_addr); rte_write64(limit, limit_addr); - /* Setup the external point so that remote can access. */ - xlat_off = XEON_EMBAR1_OFFSET + 8 * mw_idx; - xlat_addr = hw->hw_addr + xlat_off; - limit_off = XEON_EMBAR1XLMT_OFFSET + mw_idx * XEON_BAR_INTERVAL_OFFSET; - limit_addr = hw->hw_addr + limit_off; - base = rte_read64(xlat_addr); - base &= ~0xf; - limit = base + size; - rte_write64(limit, limit_addr); + if (is_gen3_ntb(hw)) { + /* Setup the external point so that remote can access. */ + xlat_off = XEON_EMBAR1_OFFSET + 8 * mw_idx; + xlat_addr = hw->hw_addr + xlat_off; + limit_off = XEON_EMBAR1XLMT_OFFSET + + mw_idx * XEON_BAR_INTERVAL_OFFSET; + limit_addr = hw->hw_addr + limit_off; + base = rte_read64(xlat_addr); + base &= ~0xf; + limit = base + size; + rte_write64(limit, limit_addr); + } else if (is_gen4_ntb(hw)) { + /* Set translate base address index register */ + xlat_off = XEON_GEN4_IM1XBASEIDX_OFFSET + + mw_idx * XEON_GEN4_XBASEIDX_INTERVAL; + xlat_addr = hw->hw_addr + xlat_off; + rte_write16(rte_log2_u64(size), xlat_addr); + } else { + rte_write64(base, limit_addr); + rte_write64(0, xlat_addr); + return -ENOTSUP; + } return 0; } @@ -187,7 +270,7 @@ static int intel_ntb_get_link_status(const struct rte_rawdev *dev) { struct ntb_hw *hw = dev->dev_private; - uint16_t reg_val; + uint16_t reg_val, reg_off; int ret; if (hw == NULL) { @@ -195,11 +278,19 @@ intel_ntb_get_link_status(const struct rte_rawdev *dev) return -EINVAL; } - ret = rte_pci_read_config(hw->pci_dev, ®_val, - sizeof(reg_val), XEON_LINK_STATUS_OFFSET); - if (ret < 0) { - NTB_LOG(ERR, "Unable to get link status."); - return -EIO; + if (is_gen3_ntb(hw)) { + reg_off = XEON_GEN3_LINK_STATUS_OFFSET; + ret = rte_pci_read_config(hw->pci_dev, ®_val, + sizeof(reg_val), reg_off); + if (ret < 0) { + NTB_LOG(ERR, "Unable to get link status."); + return -EIO; + } + } else if (is_gen4_ntb(hw)) { + reg_off = XEON_GEN4_LINK_STATUS_OFFSET; + reg_val = rte_read16(hw->hw_addr + reg_off); + } else { + return -ENOTSUP; } hw->link_status = NTB_LNK_STA_ACTIVE(reg_val); @@ -216,9 +307,8 @@ intel_ntb_get_link_status(const struct rte_rawdev *dev) } static int -intel_ntb_set_link(const struct rte_rawdev *dev, bool up) +intel_ntb_gen3_set_link(const struct ntb_hw *hw, bool up) { - struct ntb_hw *hw = dev->dev_private; uint32_t ntb_ctrl, reg_off; void *reg_addr; @@ -241,6 +331,65 @@ intel_ntb_set_link(const struct rte_rawdev *dev, bool up) return 0; } +static int +intel_ntb_gen4_set_link(const struct ntb_hw *hw, bool up) +{ + uint32_t ntb_ctrl, ppd0; + uint16_t link_ctrl; + void *reg_addr; + + if (up) { + reg_addr = hw->hw_addr + XEON_NTBCNTL_OFFSET; + ntb_ctrl = NTB_CTL_P2S_BAR2_SNOOP | NTB_CTL_S2P_BAR2_SNOOP; + ntb_ctrl |= NTB_CTL_P2S_BAR4_SNOOP | NTB_CTL_S2P_BAR4_SNOOP; + rte_write32(ntb_ctrl, reg_addr); + + reg_addr = hw->hw_addr + XEON_GEN4_LINK_CTRL_OFFSET; + link_ctrl = rte_read16(reg_addr); + link_ctrl &= ~XEON_GEN4_LINK_CTRL_LINK_DIS; + rte_write16(link_ctrl, reg_addr); + + /* start link training */ + reg_addr = hw->hw_addr + XEON_GEN4_PPD0_OFFSET; + ppd0 = rte_read32(reg_addr); + ppd0 |= XEON_GEN4_PPD_LINKTRN; + rte_write32(ppd0, reg_addr); + + /* make sure link training has started */ + ppd0 = rte_read32(reg_addr); + if (!(ppd0 & XEON_GEN4_PPD_LINKTRN)) { + NTB_LOG(ERR, "Link is not training."); + return -EINVAL; + } + } else { + reg_addr = hw->hw_addr + XEON_NTBCNTL_OFFSET; + ntb_ctrl = rte_read32(reg_addr); + ntb_ctrl &= ~(NTB_CTL_P2S_BAR2_SNOOP | NTB_CTL_S2P_BAR2_SNOOP); + ntb_ctrl &= ~(NTB_CTL_P2S_BAR4_SNOOP | NTB_CTL_S2P_BAR4_SNOOP); + rte_write32(ntb_ctrl, reg_addr); + + reg_addr = hw->hw_addr + XEON_GEN4_LINK_CTRL_OFFSET; + link_ctrl = rte_read16(reg_addr); + link_ctrl |= XEON_GEN4_LINK_CTRL_LINK_DIS; + rte_write16(link_ctrl, reg_addr); + } + + return 0; +} + +static int +intel_ntb_set_link(const struct rte_rawdev *dev, bool up) +{ + struct ntb_hw *hw = dev->dev_private; + + if (is_gen3_ntb(hw)) + return intel_ntb_gen3_set_link(hw, up); + else if (is_gen4_ntb(hw)) + return intel_ntb_gen4_set_link(hw, up); + else + return -ENOTSUP; +} + static uint32_t intel_ntb_spad_read(const struct rte_rawdev *dev, int spad, bool peer) { @@ -254,7 +403,14 @@ intel_ntb_spad_read(const struct rte_rawdev *dev, int spad, bool peer) } /* When peer is true, read peer spad reg */ - reg_off = peer ? XEON_B2B_SPAD_OFFSET : XEON_IM_SPAD_OFFSET; + if (is_gen3_ntb(hw)) + reg_off = peer ? XEON_GEN3_B2B_SPAD_OFFSET : + XEON_IM_SPAD_OFFSET; + else if (is_gen4_ntb(hw)) + reg_off = peer ? XEON_GEN4_B2B_SPAD_OFFSET : + XEON_IM_SPAD_OFFSET; + else + return -ENOTSUP; reg_addr = hw->hw_addr + reg_off + (spad << 2); spad_v = rte_read32(reg_addr); @@ -275,7 +431,14 @@ intel_ntb_spad_write(const struct rte_rawdev *dev, int spad, } /* When peer is true, write peer spad reg */ - reg_off = peer ? XEON_B2B_SPAD_OFFSET : XEON_IM_SPAD_OFFSET; + if (is_gen3_ntb(hw)) + reg_off = peer ? XEON_GEN3_B2B_SPAD_OFFSET : + XEON_IM_SPAD_OFFSET; + else if (is_gen4_ntb(hw)) + reg_off = peer ? XEON_GEN4_B2B_SPAD_OFFSET : + XEON_IM_SPAD_OFFSET; + else + return -ENOTSUP; reg_addr = hw->hw_addr + reg_off + (spad << 2); rte_write32(spad_v, reg_addr); @@ -308,6 +471,9 @@ intel_ntb_db_clear(const struct rte_rawdev *dev, uint64_t db_bits) db_off = XEON_IM_INT_STATUS_OFFSET; db_addr = hw->hw_addr + db_off; + if (is_gen4_ntb(hw)) + rte_write16(XEON_GEN4_SLOTSTS_DLLSCS, + hw->hw_addr + XEON_GEN4_SLOTSTS); rte_write64(db_bits, db_addr); return 0; @@ -365,7 +531,12 @@ intel_ntb_vector_bind(const struct rte_rawdev *dev, uint8_t intr, uint8_t msix) } /* Bind intr source to msix vector */ - reg_off = XEON_INTVEC_OFFSET; + if (is_gen3_ntb(hw)) + reg_off = XEON_GEN3_INTVEC_OFFSET; + else if (is_gen4_ntb(hw)) + reg_off = XEON_GEN4_INTVEC_OFFSET; + else + return -ENOTSUP; reg_addr = hw->hw_addr + reg_off + intr; rte_write8(msix, reg_addr); diff --git a/drivers/raw/ntb/ntb_hw_intel.h b/drivers/raw/ntb/ntb_hw_intel.h index 4d1e64504..c61a2a8a6 100644 --- a/drivers/raw/ntb/ntb_hw_intel.h +++ b/drivers/raw/ntb/ntb_hw_intel.h @@ -22,7 +22,7 @@ #define NTB_LNK_STA_SPEED(x) ((x) & NTB_LNK_STA_SPEED_MASK) #define NTB_LNK_STA_WIDTH(x) (((x) & NTB_LNK_STA_WIDTH_MASK) >> 4) -/* Intel Skylake Xeon hardware */ +/* Intel Xeon hardware */ #define XEON_IMBAR1SZ_OFFSET 0x00d0 #define XEON_IMBAR2SZ_OFFSET 0x00d1 #define XEON_EMBAR1SZ_OFFSET 0x00d2 @@ -31,7 +31,13 @@ #define XEON_DEVSTS_OFFSET 0x009a #define XEON_UNCERRSTS_OFFSET 0x014c #define XEON_CORERRSTS_OFFSET 0x0158 -#define XEON_LINK_STATUS_OFFSET 0x01a2 +#define XEON_GEN3_LINK_STATUS_OFFSET 0x01a2 +/* Link status and PPD are in MMIO but not config space for Gen4 NTB */ +#define XEON_GEN4_PPD0_OFFSET 0xb0d4 +#define XEON_GEN4_PPD1_OFFSET 0xb4c0 +#define XEON_GEN4_LINK_CTRL_OFFSET 0xb050 +#define XEON_GEN4_LINK_STATUS_OFFSET 0xb052 +#define XEON_GEN4_LINK_CTRL_LINK_DIS 0x0010 #define XEON_NTBCNTL_OFFSET 0x0000 #define XEON_BAR_INTERVAL_OFFSET 0x0010 @@ -39,13 +45,18 @@ #define XEON_IMBAR1XLMT_OFFSET 0x0018 /* SBAR2LMT */ #define XEON_IMBAR2XBASE_OFFSET 0x0020 /* SBAR4XLAT */ #define XEON_IMBAR2XLMT_OFFSET 0x0028 /* SBAR4LMT */ +#define XEON_GEN4_XBASEIDX_INTERVAL 0x0002 +#define XEON_GEN4_IM1XBASEIDX_OFFSET 0x0074 +#define XEON_GEN4_IM2XBASEIDX_OFFSET 0x0076 #define XEON_IM_INT_STATUS_OFFSET 0x0040 #define XEON_IM_INT_DISABLE_OFFSET 0x0048 #define XEON_IM_SPAD_OFFSET 0x0080 /* SPAD */ +#define XEON_GEN3_B2B_SPAD_OFFSET 0x0180 /* GEN3 B2B SPAD */ +#define XEON_GEN4_B2B_SPAD_OFFSET 0x8080 /* GEN4 B2B SPAD */ #define XEON_USMEMMISS_OFFSET 0x0070 -#define XEON_INTVEC_OFFSET 0x00d0 +#define XEON_GEN3_INTVEC_OFFSET 0x00d0 +#define XEON_GEN4_INTVEC_OFFSET 0x0050 #define XEON_IM_DOORBELL_OFFSET 0x0100 /* SDOORBELL0 */ -#define XEON_B2B_SPAD_OFFSET 0x0180 /* B2B SPAD */ #define XEON_EMBAR0XBASE_OFFSET 0x4008 /* B2B_XLAT */ #define XEON_EMBAR1XBASE_OFFSET 0x4010 /* PBAR2XLAT */ #define XEON_EMBAR1XLMT_OFFSET 0x4018 /* PBAR2LMT */ @@ -70,6 +81,14 @@ #define XEON_PPD_DEV_DSD 0x10 #define XEON_PPD_SPLIT_BAR_MASK 0x40 +#define XEON_GEN4_PPD_CONN_MASK 0x0300 +#define XEON_GEN4_PPD_CONN_B2B 0x0200 +#define XEON_GEN4_PPD_DEV_MASK 0x1000 +#define XEON_GEN4_PPD_DEV_DSD 0x1000 +#define XEON_GEN4_PPD_DEV_USD 0x0000 +#define XEON_GEN4_PPD_LINKTRN 0x0008 +#define XEON_GEN4_SLOTSTS 0xb05a +#define XEON_GEN4_SLOTSTS_DLLSCS 0x100 #define XEON_MW_COUNT 2 diff --git a/usertools/dpdk-devbind.py b/usertools/dpdk-devbind.py index 86b6b53c4..081c3bc92 100755 --- a/usertools/dpdk-devbind.py +++ b/usertools/dpdk-devbind.py @@ -53,6 +53,8 @@ 'SVendor': None, 'SDevice': None} intel_ntb_skx = {'Class': '06', 'Vendor': '8086', 'Device': '201c', 'SVendor': None, 'SDevice': None} +intel_ntb_icx = {'Class': '06', 'Vendor': '8086', 'Device': '347e', + 'SVendor': None, 'SDevice': None} network_devices = [network_class, cavium_pkx, avp_vnic, ifpga_class] baseband_devices = [acceleration_class] @@ -60,7 +62,7 @@ eventdev_devices = [cavium_sso, cavium_tim, octeontx2_sso] mempool_devices = [cavium_fpa, octeontx2_npa] compress_devices = [cavium_zip] -misc_devices = [intel_ioat_bdw, intel_ioat_skx, intel_ioat_icx, intel_ntb_skx, octeontx2_dma] +misc_devices = [intel_ioat_bdw, intel_ioat_skx, intel_ioat_icx, intel_ntb_skx, intel_ntb_icx, octeontx2_dma] # global dict ethernet devices present. Dictionary indexed by PCI address. # Each device within this is itself a dictionary of device properties -- 2.17.1
> + > +static int > +intel_ntb_dev_init(const struct rte_rawdev *dev) { > + struct ntb_hw *hw = dev->dev_private; > + uint8_t bar; > + int ret, i; > + > + if (hw == NULL) { > + NTB_LOG(ERR, "Invalid device."); > + return -EINVAL; > + } > + > hw->hw_addr = (char *)hw->pci_dev->mem_resource[0].addr; > > + if (is_gen3_ntb(hw)) { > + ret = intel_ntb3_check_ppd(hw); > + } else if (is_gen4_ntb(hw)) { > + /* PPD is in MMIO but not config space for NTB Gen4 */ > + ret = intel_ntb4_check_ppd(hw); > + if (ret) > + return ret; Above two lines are not necessary. > + } else { > + return -ENOTSUP; > + } > + > + if (ret) > + return ret; > + > hw->mw_cnt = XEON_MW_COUNT; > hw->db_cnt = XEON_DB_COUNT; > hw->spad_cnt = XEON_SPAD_COUNT; > @@ -149,15 +219,28 @@ intel_ntb_mw_set_trans(const struct rte_rawdev > *dev, int mw_idx, > rte_write64(base, xlat_addr); > rte_write64(limit, limit_addr); > > - /* Setup the external point so that remote can access. */ > - xlat_off = XEON_EMBAR1_OFFSET + 8 * mw_idx; > - xlat_addr = hw->hw_addr + xlat_off; > - limit_off = XEON_EMBAR1XLMT_OFFSET + mw_idx * > XEON_BAR_INTERVAL_OFFSET; > - limit_addr = hw->hw_addr + limit_off; > - base = rte_read64(xlat_addr); > - base &= ~0xf; > - limit = base + size; > - rte_write64(limit, limit_addr); > + if (is_gen3_ntb(hw)) { > + /* Setup the external point so that remote can access. */ > + xlat_off = XEON_EMBAR1_OFFSET + 8 * mw_idx; > + xlat_addr = hw->hw_addr + xlat_off; > + limit_off = XEON_EMBAR1XLMT_OFFSET + > + mw_idx * XEON_BAR_INTERVAL_OFFSET; > + limit_addr = hw->hw_addr + limit_off; > + base = rte_read64(xlat_addr); > + base &= ~0xf; > + limit = base + size; > + rte_write64(limit, limit_addr); > + } else if (is_gen4_ntb(hw)) { Can we use a variable in struct to indicate it's gen4 or gen3 after init instead of check it every time? > + /* Set translate base address index register */ > + xlat_off = XEON_GEN4_IM1XBASEIDX_OFFSET + > + mw_idx * XEON_GEN4_XBASEIDX_INTERVAL; > + xlat_addr = hw->hw_addr + xlat_off; > + rte_write16(rte_log2_u64(size), xlat_addr); > + } else { > + rte_write64(base, limit_addr); > + rte_write64(0, xlat_addr); > + return -ENOTSUP; > + } Is the else branch necessary? As if neither gen3 or gen4, the init would fail. Would be better to print an ERR instead of just return NO support. > > return 0; > }
Hi > -----Original Message----- > From: Wu, Jingjing <jingjing.wu@intel.com> > Sent: Monday, September 7, 2020 16:35 > To: Li, Xiaoyun <xiaoyun.li@intel.com> > Cc: dev@dpdk.org; Maslekar, Omkar <omkar.maslekar@intel.com> > Subject: RE: [PATCH v3] raw/ntb: add Icelake support for Intel NTB > > > + > > +static int > > +intel_ntb_dev_init(const struct rte_rawdev *dev) { > > + struct ntb_hw *hw = dev->dev_private; > > + uint8_t bar; > > + int ret, i; > > + > > + if (hw == NULL) { > > + NTB_LOG(ERR, "Invalid device."); > > + return -EINVAL; > > + } > > + > > hw->hw_addr = (char *)hw->pci_dev->mem_resource[0].addr; > > > > + if (is_gen3_ntb(hw)) { > > + ret = intel_ntb3_check_ppd(hw); > > + } else if (is_gen4_ntb(hw)) { > > + /* PPD is in MMIO but not config space for NTB Gen4 */ > > + ret = intel_ntb4_check_ppd(hw); > > + if (ret) > > + return ret; > Above two lines are not necessary. OK. > > + } else { > > + return -ENOTSUP; > > + } > > + > > + if (ret) > > + return ret; > > + > > hw->mw_cnt = XEON_MW_COUNT; > > hw->db_cnt = XEON_DB_COUNT; > > hw->spad_cnt = XEON_SPAD_COUNT; > > @@ -149,15 +219,28 @@ intel_ntb_mw_set_trans(const struct rte_rawdev > > *dev, int mw_idx, > > rte_write64(base, xlat_addr); > > rte_write64(limit, limit_addr); > > > > - /* Setup the external point so that remote can access. */ > > - xlat_off = XEON_EMBAR1_OFFSET + 8 * mw_idx; > > - xlat_addr = hw->hw_addr + xlat_off; > > - limit_off = XEON_EMBAR1XLMT_OFFSET + mw_idx * > > XEON_BAR_INTERVAL_OFFSET; > > - limit_addr = hw->hw_addr + limit_off; > > - base = rte_read64(xlat_addr); > > - base &= ~0xf; > > - limit = base + size; > > - rte_write64(limit, limit_addr); > > + if (is_gen3_ntb(hw)) { > > + /* Setup the external point so that remote can access. */ > > + xlat_off = XEON_EMBAR1_OFFSET + 8 * mw_idx; > > + xlat_addr = hw->hw_addr + xlat_off; > > + limit_off = XEON_EMBAR1XLMT_OFFSET + > > + mw_idx * XEON_BAR_INTERVAL_OFFSET; > > + limit_addr = hw->hw_addr + limit_off; > > + base = rte_read64(xlat_addr); > > + base &= ~0xf; > > + limit = base + size; > > + rte_write64(limit, limit_addr); > > + } else if (is_gen4_ntb(hw)) { > Can we use a variable in struct to indicate it's gen4 or gen3 after init instead of > check it every time? What's the difference? It comes from the value in hw->pci_dev->id.device_id. Checking it in this way is trying to make it easier to extend it for gen2 ntb in the future. It's not either gen3 or gen4. I don't think it makes sense to have a bool value to indicate it's gen3 or gen4. > > > + /* Set translate base address index register */ > > + xlat_off = XEON_GEN4_IM1XBASEIDX_OFFSET + > > + mw_idx * XEON_GEN4_XBASEIDX_INTERVAL; > > + xlat_addr = hw->hw_addr + xlat_off; > > + rte_write16(rte_log2_u64(size), xlat_addr); > > + } else { > > + rte_write64(base, limit_addr); > > + rte_write64(0, xlat_addr); > > + return -ENOTSUP; > > + } > Is the else branch necessary? As if neither gen3 or gen4, the init would fail. > Would be better to print an ERR instead of just return NO support. I don't think so. Yes. It will fail in init. Returning err is to stop other following actions like in intel_ntb_vector_bind() since it should be stopped. And I'd like to keep them in one coding style. As to the print, I think that can be upper layer's job to check the value and print err. Choosing ENOTSUP is because that in init, if it's not supported hw, it will return -ENOTSUP err. > > > > return 0; > > } >
> > > - rte_write64(limit, limit_addr); > > > + if (is_gen3_ntb(hw)) { > > > + /* Setup the external point so that remote can access. */ > > > + xlat_off = XEON_EMBAR1_OFFSET + 8 * mw_idx; > > > + xlat_addr = hw->hw_addr + xlat_off; > > > + limit_off = XEON_EMBAR1XLMT_OFFSET + > > > + mw_idx * XEON_BAR_INTERVAL_OFFSET; > > > + limit_addr = hw->hw_addr + limit_off; > > > + base = rte_read64(xlat_addr); > > > + base &= ~0xf; > > > + limit = base + size; > > > + rte_write64(limit, limit_addr); > > > + } else if (is_gen4_ntb(hw)) { > > Can we use a variable in struct to indicate it's gen4 or gen3 after init instead of > > check it every time? > > What's the difference? It comes from the value in hw->pci_dev->id.device_id. > Checking it in this way is trying to make it easier to extend it for gen2 ntb in the future. > It's not either gen3 or gen4. > I don't think it makes sense to have a bool value to indicate it's gen3 or gen4. Understand, as the inline function is very simple, it looks OK. > > > > > > + /* Set translate base address index register */ > > > + xlat_off = XEON_GEN4_IM1XBASEIDX_OFFSET + > > > + mw_idx * XEON_GEN4_XBASEIDX_INTERVAL; > > > + xlat_addr = hw->hw_addr + xlat_off; > > > + rte_write16(rte_log2_u64(size), xlat_addr); > > > + } else { > > > + rte_write64(base, limit_addr); > > > + rte_write64(0, xlat_addr); > > > + return -ENOTSUP; > > > + } > > Is the else branch necessary? As if neither gen3 or gen4, the init would fail. > > Would be better to print an ERR instead of just return NO support. > > I don't think so. > Yes. It will fail in init. Returning err is to stop other following actions like in > intel_ntb_vector_bind() since it should be stopped. > And I'd like to keep them in one coding style. As to the print, I think that can be upper > layer's job to check the value and print err. > Choosing ENOTSUP is because that in init, if it's not supported hw, it will return - > ENOTSUP err. > I cannot say what you did is incorrect. But try to think it like this way: according current API design, ntb raw device is allocated when driver probe, if init fails, raw device would be free. How the ops be called? > > > > > > return 0; > > > } > >
Hi > -----Original Message----- > From: Wu, Jingjing <jingjing.wu@intel.com> > Sent: Tuesday, September 8, 2020 00:16 > To: Li, Xiaoyun <xiaoyun.li@intel.com> > Cc: dev@dpdk.org; Maslekar, Omkar <omkar.maslekar@intel.com> > Subject: RE: [PATCH v3] raw/ntb: add Icelake support for Intel NTB > > > > > - rte_write64(limit, limit_addr); > > > > + if (is_gen3_ntb(hw)) { > > > > + /* Setup the external point so that remote can access. */ > > > > + xlat_off = XEON_EMBAR1_OFFSET + 8 * mw_idx; > > > > + xlat_addr = hw->hw_addr + xlat_off; > > > > + limit_off = XEON_EMBAR1XLMT_OFFSET + > > > > + mw_idx * XEON_BAR_INTERVAL_OFFSET; > > > > + limit_addr = hw->hw_addr + limit_off; > > > > + base = rte_read64(xlat_addr); > > > > + base &= ~0xf; > > > > + limit = base + size; > > > > + rte_write64(limit, limit_addr); > > > > + } else if (is_gen4_ntb(hw)) { > > > Can we use a variable in struct to indicate it's gen4 or gen3 after > > > init instead of check it every time? > > > > What's the difference? It comes from the value in hw->pci_dev->id.device_id. > > Checking it in this way is trying to make it easier to extend it for gen2 ntb in the > future. > > It's not either gen3 or gen4. > > I don't think it makes sense to have a bool value to indicate it's gen3 or gen4. > > Understand, as the inline function is very simple, it looks OK. > > > > > > > > > + /* Set translate base address index register */ > > > > + xlat_off = XEON_GEN4_IM1XBASEIDX_OFFSET + > > > > + mw_idx * XEON_GEN4_XBASEIDX_INTERVAL; > > > > + xlat_addr = hw->hw_addr + xlat_off; > > > > + rte_write16(rte_log2_u64(size), xlat_addr); > > > > + } else { > > > > + rte_write64(base, limit_addr); > > > > + rte_write64(0, xlat_addr); > > > > + return -ENOTSUP; > > > > + } > > > Is the else branch necessary? As if neither gen3 or gen4, the init would fail. > > > Would be better to print an ERR instead of just return NO support. > > > > I don't think so. > > Yes. It will fail in init. Returning err is to stop other following > > actions like in > > intel_ntb_vector_bind() since it should be stopped. > > And I'd like to keep them in one coding style. As to the print, I > > think that can be upper layer's job to check the value and print err. > > Choosing ENOTSUP is because that in init, if it's not supported hw, it > > will return - ENOTSUP err. > > > I cannot say what you did is incorrect. But try to think it like this way: according > current API design, ntb raw device is allocated when driver probe, if init fails, > raw device would be free. How the ops be called? I'll add a err print later. > > > > > > > > > return 0; > > > > } > > >
Add NTB device support (4th generation) for Intel Ice Lake platform. Signed-off-by: Xiaoyun Li <xiaoyun.li@intel.com> --- v4: * Removed unnecessary return. * Added more print log. * Replaced "Icelake" with "Ice Lake". v3: * Removed a blank line. * Added change doc for v2. v2: * Corrected and polished the doc. * Fixed a link setup issue. --- doc/guides/rawdevs/ntb.rst | 16 +- doc/guides/rel_notes/release_20_11.rst | 3 + drivers/raw/ntb/ntb.c | 5 + drivers/raw/ntb/ntb.h | 1 + drivers/raw/ntb/ntb_hw_intel.c | 241 ++++++++++++++++++++++--- drivers/raw/ntb/ntb_hw_intel.h | 27 ++- usertools/dpdk-devbind.py | 4 +- 7 files changed, 255 insertions(+), 42 deletions(-) diff --git a/doc/guides/rawdevs/ntb.rst b/doc/guides/rawdevs/ntb.rst index aa7d80964..39e4d65f8 100644 --- a/doc/guides/rawdevs/ntb.rst +++ b/doc/guides/rawdevs/ntb.rst @@ -14,16 +14,16 @@ allocation for the peer to access and read/write allocated memory from peer. Also, the PMD allows to use doorbell registers to notify the peer and share some information by using scratchpad registers. -BIOS setting on Intel Skylake ------------------------------ +BIOS setting on Intel Xeon +-------------------------- -Intel Non-transparent Bridge needs special BIOS setting. Since the PMD only -supports Intel Skylake platform, introduce BIOS setting here. The referencce -is https://www.intel.com/content/dam/support/us/en/documents/server-products/Intel_Xeon_Processor_Scalable_Family_BIOS_User_Guide.pdf +Intel Non-transparent Bridge needs special BIOS setting. The referencce for +Skylake is https://www.intel.com/content/dam/support/us/en/documents/server-products/Intel_Xeon_Processor_Scalable_Family_BIOS_User_Guide.pdf - Set the needed PCIe port as NTB to NTB mode on both hosts. -- Enable NTB bars and set bar size of bar 23 and bar 45 as 12-29 (2K-512M) - on both hosts. Note that bar size on both hosts should be the same. +- Enable NTB bars and set bar size of bar 23 and bar 45 as 12-29 (4K-512M) + on both hosts (for Ice Lake, bar size can be set as 12-51, namely 4K-128PB). + Note that bar size on both hosts should be the same. - Disable split bars for both hosts. - Set crosslink control override as DSD/USP on one host, USD/DSP on another host. @@ -151,4 +151,4 @@ like the following: Limitation ---------- -- This PMD only supports Intel Skylake platform. +- This PMD only supports Intel Skylake and Ice Lake platforms. diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst index df227a177..db9ebc4e7 100644 --- a/doc/guides/rel_notes/release_20_11.rst +++ b/doc/guides/rel_notes/release_20_11.rst @@ -55,6 +55,9 @@ New Features Also, make sure to start the actual text at the margin. ======================================================= +* **Added Ice Lake (Gen4) support for Intel NTB.** + + Added NTB device support (4th generation) for Intel Ice Lake platform. Removed Items ------------- diff --git a/drivers/raw/ntb/ntb.c b/drivers/raw/ntb/ntb.c index e40412bb7..e29acecef 100644 --- a/drivers/raw/ntb/ntb.c +++ b/drivers/raw/ntb/ntb.c @@ -25,6 +25,7 @@ static const struct rte_pci_id pci_id_ntb_map[] = { { RTE_PCI_DEVICE(NTB_INTEL_VENDOR_ID, NTB_INTEL_DEV_ID_B2B_SKX) }, + { RTE_PCI_DEVICE(NTB_INTEL_VENDOR_ID, NTB_INTEL_DEV_ID_B2B_ICX) }, { .vendor_id = 0, /* sentinel */ }, }; @@ -244,6 +245,9 @@ ntb_dev_intr_handler(void *param) hw->peer_dev_up = 0; return; } + + /* Clear other received doorbells. */ + (*hw->ntb_ops->db_clear)(dev, db_bits); } static void @@ -1333,6 +1337,7 @@ ntb_init_hw(struct rte_rawdev *dev, struct rte_pci_device *pci_dev) switch (pci_dev->id.device_id) { case NTB_INTEL_DEV_ID_B2B_SKX: + case NTB_INTEL_DEV_ID_B2B_ICX: hw->ntb_ops = &intel_ntb_ops; break; default: diff --git a/drivers/raw/ntb/ntb.h b/drivers/raw/ntb/ntb.h index a561c42d1..cdf7667d5 100644 --- a/drivers/raw/ntb/ntb.h +++ b/drivers/raw/ntb/ntb.h @@ -18,6 +18,7 @@ extern int ntb_logtype; /* Device IDs */ #define NTB_INTEL_DEV_ID_B2B_SKX 0x201C +#define NTB_INTEL_DEV_ID_B2B_ICX 0x347E /* Reserved to app to use. */ #define NTB_SPAD_USER "spad_user_" diff --git a/drivers/raw/ntb/ntb_hw_intel.c b/drivers/raw/ntb/ntb_hw_intel.c index e7f8667cd..4427e1145 100644 --- a/drivers/raw/ntb/ntb_hw_intel.c +++ b/drivers/raw/ntb/ntb_hw_intel.c @@ -25,17 +25,29 @@ static enum xeon_ntb_bar intel_ntb_bar[] = { XEON_NTB_BAR45, }; -static int -intel_ntb_dev_init(const struct rte_rawdev *dev) +static inline int +is_gen3_ntb(const struct ntb_hw *hw) { - struct ntb_hw *hw = dev->dev_private; - uint8_t reg_val, bar; - int ret, i; + if (hw->pci_dev->id.device_id == NTB_INTEL_DEV_ID_B2B_SKX) + return 1; - if (hw == NULL) { - NTB_LOG(ERR, "Invalid device."); - return -EINVAL; - } + return 0; +} + +static inline int +is_gen4_ntb(const struct ntb_hw *hw) +{ + if (hw->pci_dev->id.device_id == NTB_INTEL_DEV_ID_B2B_ICX) + return 1; + + return 0; +} + +static int +intel_ntb3_check_ppd(struct ntb_hw *hw) +{ + uint8_t reg_val; + int ret; ret = rte_pci_read_config(hw->pci_dev, ®_val, sizeof(reg_val), XEON_PPD_OFFSET); @@ -71,8 +83,65 @@ intel_ntb_dev_init(const struct rte_rawdev *dev) return -EINVAL; } + return 0; +} + +static int +intel_ntb4_check_ppd(struct ntb_hw *hw) +{ + uint32_t reg_val; + + reg_val = rte_read32(hw->hw_addr + XEON_GEN4_PPD1_OFFSET); + + /* Check connection topo type. Only support B2B. */ + switch (reg_val & XEON_GEN4_PPD_CONN_MASK) { + case XEON_GEN4_PPD_CONN_B2B: + NTB_LOG(INFO, "Topo B2B (back to back) is using."); + break; + default: + NTB_LOG(ERR, "Not supported conn topo. Please use B2B."); + return -EINVAL; + } + + /* Check device type. */ + if (reg_val & XEON_GEN4_PPD_DEV_DSD) { + NTB_LOG(INFO, "DSD, Downstream Device."); + hw->topo = NTB_TOPO_B2B_DSD; + } else { + NTB_LOG(INFO, "USD, Upstream device."); + hw->topo = NTB_TOPO_B2B_USD; + } + + return 0; +} + +static int +intel_ntb_dev_init(const struct rte_rawdev *dev) +{ + struct ntb_hw *hw = dev->dev_private; + uint8_t bar; + int ret, i; + + if (hw == NULL) { + NTB_LOG(ERR, "Invalid device."); + return -EINVAL; + } + hw->hw_addr = (char *)hw->pci_dev->mem_resource[0].addr; + if (is_gen3_ntb(hw)) + ret = intel_ntb3_check_ppd(hw); + else if (is_gen4_ntb(hw)) + /* PPD is in MMIO but not config space for NTB Gen4 */ + ret = intel_ntb4_check_ppd(hw); + else { + NTB_LOG(ERR, "Cannot init device for unsupported device."); + return -ENOTSUP; + } + + if (ret) + return ret; + hw->mw_cnt = XEON_MW_COUNT; hw->db_cnt = XEON_DB_COUNT; hw->spad_cnt = XEON_SPAD_COUNT; @@ -149,15 +218,29 @@ intel_ntb_mw_set_trans(const struct rte_rawdev *dev, int mw_idx, rte_write64(base, xlat_addr); rte_write64(limit, limit_addr); - /* Setup the external point so that remote can access. */ - xlat_off = XEON_EMBAR1_OFFSET + 8 * mw_idx; - xlat_addr = hw->hw_addr + xlat_off; - limit_off = XEON_EMBAR1XLMT_OFFSET + mw_idx * XEON_BAR_INTERVAL_OFFSET; - limit_addr = hw->hw_addr + limit_off; - base = rte_read64(xlat_addr); - base &= ~0xf; - limit = base + size; - rte_write64(limit, limit_addr); + if (is_gen3_ntb(hw)) { + /* Setup the external point so that remote can access. */ + xlat_off = XEON_EMBAR1_OFFSET + 8 * mw_idx; + xlat_addr = hw->hw_addr + xlat_off; + limit_off = XEON_EMBAR1XLMT_OFFSET + + mw_idx * XEON_BAR_INTERVAL_OFFSET; + limit_addr = hw->hw_addr + limit_off; + base = rte_read64(xlat_addr); + base &= ~0xf; + limit = base + size; + rte_write64(limit, limit_addr); + } else if (is_gen4_ntb(hw)) { + /* Set translate base address index register */ + xlat_off = XEON_GEN4_IM1XBASEIDX_OFFSET + + mw_idx * XEON_GEN4_XBASEIDX_INTERVAL; + xlat_addr = hw->hw_addr + xlat_off; + rte_write16(rte_log2_u64(size), xlat_addr); + } else { + NTB_LOG(ERR, "Cannot set translation of memory windows for unsupported device."); + rte_write64(base, limit_addr); + rte_write64(0, xlat_addr); + return -ENOTSUP; + } return 0; } @@ -187,7 +270,7 @@ static int intel_ntb_get_link_status(const struct rte_rawdev *dev) { struct ntb_hw *hw = dev->dev_private; - uint16_t reg_val; + uint16_t reg_val, reg_off; int ret; if (hw == NULL) { @@ -195,11 +278,20 @@ intel_ntb_get_link_status(const struct rte_rawdev *dev) return -EINVAL; } - ret = rte_pci_read_config(hw->pci_dev, ®_val, - sizeof(reg_val), XEON_LINK_STATUS_OFFSET); - if (ret < 0) { - NTB_LOG(ERR, "Unable to get link status."); - return -EIO; + if (is_gen3_ntb(hw)) { + reg_off = XEON_GEN3_LINK_STATUS_OFFSET; + ret = rte_pci_read_config(hw->pci_dev, ®_val, + sizeof(reg_val), reg_off); + if (ret < 0) { + NTB_LOG(ERR, "Unable to get link status."); + return -EIO; + } + } else if (is_gen4_ntb(hw)) { + reg_off = XEON_GEN4_LINK_STATUS_OFFSET; + reg_val = rte_read16(hw->hw_addr + reg_off); + } else { + NTB_LOG(ERR, "Cannot get link status for unsupported device."); + return -ENOTSUP; } hw->link_status = NTB_LNK_STA_ACTIVE(reg_val); @@ -216,9 +308,8 @@ intel_ntb_get_link_status(const struct rte_rawdev *dev) } static int -intel_ntb_set_link(const struct rte_rawdev *dev, bool up) +intel_ntb_gen3_set_link(const struct ntb_hw *hw, bool up) { - struct ntb_hw *hw = dev->dev_private; uint32_t ntb_ctrl, reg_off; void *reg_addr; @@ -241,6 +332,70 @@ intel_ntb_set_link(const struct rte_rawdev *dev, bool up) return 0; } +static int +intel_ntb_gen4_set_link(const struct ntb_hw *hw, bool up) +{ + uint32_t ntb_ctrl, ppd0; + uint16_t link_ctrl; + void *reg_addr; + + if (up) { + reg_addr = hw->hw_addr + XEON_NTBCNTL_OFFSET; + ntb_ctrl = NTB_CTL_P2S_BAR2_SNOOP | NTB_CTL_S2P_BAR2_SNOOP; + ntb_ctrl |= NTB_CTL_P2S_BAR4_SNOOP | NTB_CTL_S2P_BAR4_SNOOP; + rte_write32(ntb_ctrl, reg_addr); + + reg_addr = hw->hw_addr + XEON_GEN4_LINK_CTRL_OFFSET; + link_ctrl = rte_read16(reg_addr); + link_ctrl &= ~XEON_GEN4_LINK_CTRL_LINK_DIS; + rte_write16(link_ctrl, reg_addr); + + /* start link training */ + reg_addr = hw->hw_addr + XEON_GEN4_PPD0_OFFSET; + ppd0 = rte_read32(reg_addr); + ppd0 |= XEON_GEN4_PPD_LINKTRN; + rte_write32(ppd0, reg_addr); + + /* make sure link training has started */ + ppd0 = rte_read32(reg_addr); + if (!(ppd0 & XEON_GEN4_PPD_LINKTRN)) { + NTB_LOG(ERR, "Link is not training."); + return -EINVAL; + } + } else { + reg_addr = hw->hw_addr + XEON_NTBCNTL_OFFSET; + ntb_ctrl = rte_read32(reg_addr); + ntb_ctrl &= ~(NTB_CTL_P2S_BAR2_SNOOP | NTB_CTL_S2P_BAR2_SNOOP); + ntb_ctrl &= ~(NTB_CTL_P2S_BAR4_SNOOP | NTB_CTL_S2P_BAR4_SNOOP); + rte_write32(ntb_ctrl, reg_addr); + + reg_addr = hw->hw_addr + XEON_GEN4_LINK_CTRL_OFFSET; + link_ctrl = rte_read16(reg_addr); + link_ctrl |= XEON_GEN4_LINK_CTRL_LINK_DIS; + rte_write16(link_ctrl, reg_addr); + } + + return 0; +} + +static int +intel_ntb_set_link(const struct rte_rawdev *dev, bool up) +{ + struct ntb_hw *hw = dev->dev_private; + int ret = 0; + + if (is_gen3_ntb(hw)) + ret = intel_ntb_gen3_set_link(hw, up); + else if (is_gen4_ntb(hw)) + ret = intel_ntb_gen4_set_link(hw, up); + else { + NTB_LOG(ERR, "Cannot set link for unsupported device."); + ret = -ENOTSUP; + } + + return ret; +} + static uint32_t intel_ntb_spad_read(const struct rte_rawdev *dev, int spad, bool peer) { @@ -254,7 +409,16 @@ intel_ntb_spad_read(const struct rte_rawdev *dev, int spad, bool peer) } /* When peer is true, read peer spad reg */ - reg_off = peer ? XEON_B2B_SPAD_OFFSET : XEON_IM_SPAD_OFFSET; + if (is_gen3_ntb(hw)) + reg_off = peer ? XEON_GEN3_B2B_SPAD_OFFSET : + XEON_IM_SPAD_OFFSET; + else if (is_gen4_ntb(hw)) + reg_off = peer ? XEON_GEN4_B2B_SPAD_OFFSET : + XEON_IM_SPAD_OFFSET; + else { + NTB_LOG(ERR, "Cannot read spad for unsupported device."); + return -ENOTSUP; + } reg_addr = hw->hw_addr + reg_off + (spad << 2); spad_v = rte_read32(reg_addr); @@ -275,7 +439,16 @@ intel_ntb_spad_write(const struct rte_rawdev *dev, int spad, } /* When peer is true, write peer spad reg */ - reg_off = peer ? XEON_B2B_SPAD_OFFSET : XEON_IM_SPAD_OFFSET; + if (is_gen3_ntb(hw)) + reg_off = peer ? XEON_GEN3_B2B_SPAD_OFFSET : + XEON_IM_SPAD_OFFSET; + else if (is_gen4_ntb(hw)) + reg_off = peer ? XEON_GEN4_B2B_SPAD_OFFSET : + XEON_IM_SPAD_OFFSET; + else { + NTB_LOG(ERR, "Cannot write spad for unsupported device."); + return -ENOTSUP; + } reg_addr = hw->hw_addr + reg_off + (spad << 2); rte_write32(spad_v, reg_addr); @@ -308,6 +481,9 @@ intel_ntb_db_clear(const struct rte_rawdev *dev, uint64_t db_bits) db_off = XEON_IM_INT_STATUS_OFFSET; db_addr = hw->hw_addr + db_off; + if (is_gen4_ntb(hw)) + rte_write16(XEON_GEN4_SLOTSTS_DLLSCS, + hw->hw_addr + XEON_GEN4_SLOTSTS); rte_write64(db_bits, db_addr); return 0; @@ -365,7 +541,14 @@ intel_ntb_vector_bind(const struct rte_rawdev *dev, uint8_t intr, uint8_t msix) } /* Bind intr source to msix vector */ - reg_off = XEON_INTVEC_OFFSET; + if (is_gen3_ntb(hw)) + reg_off = XEON_GEN3_INTVEC_OFFSET; + else if (is_gen4_ntb(hw)) + reg_off = XEON_GEN4_INTVEC_OFFSET; + else { + NTB_LOG(ERR, "Cannot bind vectors for unsupported device."); + return -ENOTSUP; + } reg_addr = hw->hw_addr + reg_off + intr; rte_write8(msix, reg_addr); diff --git a/drivers/raw/ntb/ntb_hw_intel.h b/drivers/raw/ntb/ntb_hw_intel.h index 4d1e64504..c61a2a8a6 100644 --- a/drivers/raw/ntb/ntb_hw_intel.h +++ b/drivers/raw/ntb/ntb_hw_intel.h @@ -22,7 +22,7 @@ #define NTB_LNK_STA_SPEED(x) ((x) & NTB_LNK_STA_SPEED_MASK) #define NTB_LNK_STA_WIDTH(x) (((x) & NTB_LNK_STA_WIDTH_MASK) >> 4) -/* Intel Skylake Xeon hardware */ +/* Intel Xeon hardware */ #define XEON_IMBAR1SZ_OFFSET 0x00d0 #define XEON_IMBAR2SZ_OFFSET 0x00d1 #define XEON_EMBAR1SZ_OFFSET 0x00d2 @@ -31,7 +31,13 @@ #define XEON_DEVSTS_OFFSET 0x009a #define XEON_UNCERRSTS_OFFSET 0x014c #define XEON_CORERRSTS_OFFSET 0x0158 -#define XEON_LINK_STATUS_OFFSET 0x01a2 +#define XEON_GEN3_LINK_STATUS_OFFSET 0x01a2 +/* Link status and PPD are in MMIO but not config space for Gen4 NTB */ +#define XEON_GEN4_PPD0_OFFSET 0xb0d4 +#define XEON_GEN4_PPD1_OFFSET 0xb4c0 +#define XEON_GEN4_LINK_CTRL_OFFSET 0xb050 +#define XEON_GEN4_LINK_STATUS_OFFSET 0xb052 +#define XEON_GEN4_LINK_CTRL_LINK_DIS 0x0010 #define XEON_NTBCNTL_OFFSET 0x0000 #define XEON_BAR_INTERVAL_OFFSET 0x0010 @@ -39,13 +45,18 @@ #define XEON_IMBAR1XLMT_OFFSET 0x0018 /* SBAR2LMT */ #define XEON_IMBAR2XBASE_OFFSET 0x0020 /* SBAR4XLAT */ #define XEON_IMBAR2XLMT_OFFSET 0x0028 /* SBAR4LMT */ +#define XEON_GEN4_XBASEIDX_INTERVAL 0x0002 +#define XEON_GEN4_IM1XBASEIDX_OFFSET 0x0074 +#define XEON_GEN4_IM2XBASEIDX_OFFSET 0x0076 #define XEON_IM_INT_STATUS_OFFSET 0x0040 #define XEON_IM_INT_DISABLE_OFFSET 0x0048 #define XEON_IM_SPAD_OFFSET 0x0080 /* SPAD */ +#define XEON_GEN3_B2B_SPAD_OFFSET 0x0180 /* GEN3 B2B SPAD */ +#define XEON_GEN4_B2B_SPAD_OFFSET 0x8080 /* GEN4 B2B SPAD */ #define XEON_USMEMMISS_OFFSET 0x0070 -#define XEON_INTVEC_OFFSET 0x00d0 +#define XEON_GEN3_INTVEC_OFFSET 0x00d0 +#define XEON_GEN4_INTVEC_OFFSET 0x0050 #define XEON_IM_DOORBELL_OFFSET 0x0100 /* SDOORBELL0 */ -#define XEON_B2B_SPAD_OFFSET 0x0180 /* B2B SPAD */ #define XEON_EMBAR0XBASE_OFFSET 0x4008 /* B2B_XLAT */ #define XEON_EMBAR1XBASE_OFFSET 0x4010 /* PBAR2XLAT */ #define XEON_EMBAR1XLMT_OFFSET 0x4018 /* PBAR2LMT */ @@ -70,6 +81,14 @@ #define XEON_PPD_DEV_DSD 0x10 #define XEON_PPD_SPLIT_BAR_MASK 0x40 +#define XEON_GEN4_PPD_CONN_MASK 0x0300 +#define XEON_GEN4_PPD_CONN_B2B 0x0200 +#define XEON_GEN4_PPD_DEV_MASK 0x1000 +#define XEON_GEN4_PPD_DEV_DSD 0x1000 +#define XEON_GEN4_PPD_DEV_USD 0x0000 +#define XEON_GEN4_PPD_LINKTRN 0x0008 +#define XEON_GEN4_SLOTSTS 0xb05a +#define XEON_GEN4_SLOTSTS_DLLSCS 0x100 #define XEON_MW_COUNT 2 diff --git a/usertools/dpdk-devbind.py b/usertools/dpdk-devbind.py index 86b6b53c4..081c3bc92 100755 --- a/usertools/dpdk-devbind.py +++ b/usertools/dpdk-devbind.py @@ -53,6 +53,8 @@ 'SVendor': None, 'SDevice': None} intel_ntb_skx = {'Class': '06', 'Vendor': '8086', 'Device': '201c', 'SVendor': None, 'SDevice': None} +intel_ntb_icx = {'Class': '06', 'Vendor': '8086', 'Device': '347e', + 'SVendor': None, 'SDevice': None} network_devices = [network_class, cavium_pkx, avp_vnic, ifpga_class] baseband_devices = [acceleration_class] @@ -60,7 +62,7 @@ eventdev_devices = [cavium_sso, cavium_tim, octeontx2_sso] mempool_devices = [cavium_fpa, octeontx2_npa] compress_devices = [cavium_zip] -misc_devices = [intel_ioat_bdw, intel_ioat_skx, intel_ioat_icx, intel_ntb_skx, octeontx2_dma] +misc_devices = [intel_ioat_bdw, intel_ioat_skx, intel_ioat_icx, intel_ntb_skx, intel_ntb_icx, octeontx2_dma] # global dict ethernet devices present. Dictionary indexed by PCI address. # Each device within this is itself a dictionary of device properties -- 2.17.1
> -----Original Message-----
> From: Li, Xiaoyun <xiaoyun.li@intel.com>
> Sent: Tuesday, September 8, 2020 11:28 AM
> To: Wu, Jingjing <jingjing.wu@intel.com>
> Cc: dev@dpdk.org; Maslekar, Omkar <omkar.maslekar@intel.com>; Li,
> Xiaoyun <xiaoyun.li@intel.com>
> Subject: [PATCH v4] raw/ntb: add Ice Lake support for Intel NTB
>
> Add NTB device support (4th generation) for Intel Ice Lake platform.
>
> Signed-off-by: Xiaoyun Li <xiaoyun.li@intel.com>
Acked-by: Jingjing Wu <jingjing.wu@intel.com>
> > Add NTB device support (4th generation) for Intel Ice Lake platform.
> >
> > Signed-off-by: Xiaoyun Li <xiaoyun.li@intel.com>
> Acked-by: Jingjing Wu <jingjing.wu@intel.com>
Applied, thanks