Date: Thu, 15 Oct 2015 23:46:07 +0000 (UTC) From: "Conrad E. Meyer" <cem@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r289397 - head/sys/dev/ntb/ntb_hw Message-ID: <201510152346.t9FNk7Pa090301@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: cem Date: Thu Oct 15 23:46:07 2015 New Revision: 289397 URL: https://svnweb.freebsd.org/changeset/base/289397 Log: NTB: MFV ab760a0c: Add split BAR support for Haswell On the Haswell platform, a split BAR option to allow creation of 2 32bit BARs (4 and 5) from the 64bit BAR 4. Adding support for this new option. Authored by: Dave Jiang Obtained from: Linux (Dual BSD/GPL driver) Sponsored by: EMC / Isilon Storage Division Modified: head/sys/dev/ntb/ntb_hw/ntb_hw.c head/sys/dev/ntb/ntb_hw/ntb_hw.h head/sys/dev/ntb/ntb_hw/ntb_regs.h Modified: head/sys/dev/ntb/ntb_hw/ntb_hw.c ============================================================================== --- head/sys/dev/ntb/ntb_hw/ntb_hw.c Thu Oct 15 23:45:43 2015 (r289396) +++ head/sys/dev/ntb/ntb_hw/ntb_hw.c Thu Oct 15 23:46:07 2015 (r289397) @@ -62,7 +62,8 @@ __FBSDID("$FreeBSD$"); #define NTB_CONFIG_BAR 0 #define NTB_B2B_BAR_1 1 #define NTB_B2B_BAR_2 2 -#define NTB_MAX_BARS 3 +#define NTB_B2B_BAR_3 3 +#define NTB_MAX_BARS 4 #define NTB_MW_TO_BAR(mw) ((mw) + 1) #define MAX_MSIX_INTERRUPTS MAX(XEON_MAX_DB_BITS, SOC_MAX_DB_BITS) @@ -85,7 +86,7 @@ struct ntb_hw_info { uint32_t device_id; const char *desc; enum ntb_device_type type; - uint64_t features; + uint32_t features; }; struct ntb_pci_bar_info { @@ -142,6 +143,7 @@ struct ntb_softc { uint32_t rdb; uint32_t bar2_xlat; uint32_t bar4_xlat; + uint32_t bar5_xlat; uint32_t spad_remote; uint32_t spad_local; uint32_t lnk_cntl; @@ -186,9 +188,11 @@ bus_space_write_8(bus_space_tag_t tag, b #define ntb_reg_read(SIZE, offset) ntb_bar_read(SIZE, NTB_CONFIG_BAR, offset) #define ntb_reg_write(SIZE, offset, val) \ ntb_bar_write(SIZE, NTB_CONFIG_BAR, offset, val) -#define ntb_mw_read(SIZE, offset) ntb_bar_read(SIZE, NTB_B2B_BAR_2, offset) +#define ntb_mw_read(SIZE, offset) \ + ntb_bar_read(SIZE, NTB_MW_TO_BAR(ntb->limits.max_mw), offset) #define ntb_mw_write(SIZE, offset, val) \ - ntb_bar_write(SIZE, NTB_B2B_BAR_2, offset, val) + ntb_bar_write(SIZE, NTB_MW_TO_BAR(ntb->limits.max_mw), \ + offset, val) typedef int (*bar_map_strategy)(struct ntb_softc *ntb, struct ntb_pci_bar_info *bar); @@ -221,6 +225,7 @@ static void unmask_ldb_interrupt(struct static int ntb_create_callbacks(struct ntb_softc *ntb, uint32_t num_vectors); static void ntb_free_callbacks(struct ntb_softc *ntb); static struct ntb_hw_info *ntb_get_device_info(uint32_t device_id); +static void ntb_detect_max_mw(struct ntb_softc *ntb); static int ntb_detect_xeon(struct ntb_softc *ntb); static int ntb_detect_soc(struct ntb_softc *ntb); static int ntb_setup_xeon(struct ntb_softc *ntb); @@ -323,7 +328,7 @@ ntb_attach(device_t device) if (error) goto out; - ntb->limits.max_mw = NTB_MAX_NUM_MW; + ntb_detect_max_mw(ntb); error = ntb_map_pci_bars(ntb); if (error) @@ -357,6 +362,12 @@ ntb_detach(device_t device) if (ntb->type == NTB_XEON) ntb_teardown_xeon(ntb); ntb_teardown_interrupts(ntb); + + /* + * Redetect total MWs so we unmap properly -- in case we lowered the + * maximum to work around Xeon errata. + */ + ntb_detect_max_mw(ntb); ntb_unmap_pci_bar(ntb); return (0); @@ -379,12 +390,22 @@ ntb_map_pci_bars(struct ntb_softc *ntb) return (rc); ntb->bar_info[NTB_B2B_BAR_2].pci_resource_id = PCIR_BAR(4); - if (HAS_FEATURE(NTB_REGS_THRU_MW)) + if (HAS_FEATURE(NTB_REGS_THRU_MW) && !HAS_FEATURE(NTB_SPLIT_BAR)) rc = map_pci_bar(ntb, map_mmr_bar, &ntb->bar_info[NTB_B2B_BAR_2]); else rc = map_pci_bar(ntb, map_memory_window_bar, &ntb->bar_info[NTB_B2B_BAR_2]); + if (!HAS_FEATURE(NTB_SPLIT_BAR)) + return (rc); + + ntb->bar_info[NTB_B2B_BAR_3].pci_resource_id = PCIR_BAR(5); + if (HAS_FEATURE(NTB_REGS_THRU_MW)) + rc = map_pci_bar(ntb, map_mmr_bar, + &ntb->bar_info[NTB_B2B_BAR_3]); + else + rc = map_pci_bar(ntb, map_memory_window_bar, + &ntb->bar_info[NTB_B2B_BAR_3]); return (rc); } @@ -484,7 +505,7 @@ ntb_unmap_pci_bar(struct ntb_softc *ntb) struct ntb_pci_bar_info *current_bar; int i; - for (i = 0; i< NTB_MAX_BARS; i++) { + for (i = 0; i < NTB_MAX_BARS; i++) { current_bar = &ntb->bar_info[i]; if (current_bar->pci_resource != NULL) bus_release_resource(ntb->device, SYS_RES_MEMORY, @@ -906,6 +927,21 @@ ntb_teardown_xeon(struct ntb_softc *ntb) ntb_hw_link_down(ntb); } +static void +ntb_detect_max_mw(struct ntb_softc *ntb) +{ + + if (ntb->type == NTB_SOC) { + ntb->limits.max_mw = SOC_MAX_MW; + return; + } + + if (HAS_FEATURE(NTB_SPLIT_BAR)) + ntb->limits.max_mw = XEON_HSXSPLIT_MAX_MW; + else + ntb->limits.max_mw = XEON_SNB_MAX_MW; +} + static int ntb_detect_xeon(struct ntb_softc *ntb) { @@ -919,6 +955,9 @@ ntb_detect_xeon(struct ntb_softc *ntb) else ntb->dev_type = NTB_DEV_DSD; + if ((ppd & XEON_PPD_SPLIT_BAR) != 0) + ntb->features |= NTB_SPLIT_BAR; + conn_type = ppd & XEON_PPD_CONN_TYPE; switch (conn_type) { case NTB_CONN_B2B: @@ -968,6 +1007,8 @@ ntb_setup_xeon(struct ntb_softc *ntb) ntb->reg_ofs.spad_local = XEON_SPAD_OFFSET; ntb->reg_ofs.bar2_xlat = XEON_SBAR2XLAT_OFFSET; ntb->reg_ofs.bar4_xlat = XEON_SBAR4XLAT_OFFSET; + if (HAS_FEATURE(NTB_SPLIT_BAR)) + ntb->reg_ofs.bar5_xlat = XEON_SBAR5XLAT_OFFSET; switch (ntb->conn_type) { case NTB_CONN_B2B: @@ -1013,22 +1054,24 @@ ntb_setup_xeon(struct ntb_softc *ntb) * write the limit registers first just in case. */ if (HAS_FEATURE(NTB_REGS_THRU_MW)) { - /* Reserve the last MW for mapping remote spad */ - ntb->limits.max_mw--; /* * Set the Limit register to 4k, the minimum size, to prevent * an illegal access. + * + * XXX: Should this be PBAR5LMT / get_mw_size(, max_mw - 1)? */ ntb_reg_write(8, XEON_PBAR4LMT_OFFSET, ntb_get_mw_size(ntb, 1) + 0x1000); + /* Reserve the last MW for mapping remote spad */ + ntb->limits.max_mw--; } else /* * Disable the limit register, just in case it is set to - * something silly. + * something silly. A 64-bit write will also clear PBAR5LMT in + * split-bar mode, and this is desired. */ ntb_reg_write(8, XEON_PBAR4LMT_OFFSET, 0); - ntb->reg_ofs.lnk_cntl = XEON_NTBCNTL_OFFSET; ntb->reg_ofs.lnk_stat = XEON_LINK_STATUS_OFFSET; ntb->reg_ofs.spci_cmd = XEON_PCICMD_OFFSET; @@ -1112,15 +1155,15 @@ configure_soc_secondary_side_bars(struct { if (ntb->dev_type == NTB_DEV_USD) { - ntb_reg_write(8, SOC_PBAR2XLAT_OFFSET, PBAR2XLAT_USD_ADDR); - ntb_reg_write(8, SOC_PBAR4XLAT_OFFSET, PBAR4XLAT_USD_ADDR); + ntb_reg_write(8, SOC_PBAR2XLAT_OFFSET, MBAR23_DSD_ADDR); + ntb_reg_write(8, SOC_PBAR4XLAT_OFFSET, MBAR4_DSD_ADDR); ntb_reg_write(8, SOC_MBAR23_OFFSET, MBAR23_USD_ADDR); - ntb_reg_write(8, SOC_MBAR45_OFFSET, MBAR45_USD_ADDR); + ntb_reg_write(8, SOC_MBAR45_OFFSET, MBAR4_USD_ADDR); } else { - ntb_reg_write(8, SOC_PBAR2XLAT_OFFSET, PBAR2XLAT_DSD_ADDR); - ntb_reg_write(8, SOC_PBAR4XLAT_OFFSET, PBAR4XLAT_DSD_ADDR); + ntb_reg_write(8, SOC_PBAR2XLAT_OFFSET, MBAR23_USD_ADDR); + ntb_reg_write(8, SOC_PBAR4XLAT_OFFSET, MBAR4_USD_ADDR); ntb_reg_write(8, SOC_MBAR23_OFFSET, MBAR23_DSD_ADDR); - ntb_reg_write(8, SOC_MBAR45_OFFSET, MBAR45_DSD_ADDR); + ntb_reg_write(8, SOC_MBAR45_OFFSET, MBAR4_DSD_ADDR); } } @@ -1129,13 +1172,19 @@ configure_xeon_secondary_side_bars(struc { if (ntb->dev_type == NTB_DEV_USD) { - ntb_reg_write(8, XEON_PBAR2XLAT_OFFSET, PBAR2XLAT_USD_ADDR); + ntb_reg_write(8, XEON_PBAR2XLAT_OFFSET, MBAR23_DSD_ADDR); if (HAS_FEATURE(NTB_REGS_THRU_MW)) ntb_reg_write(8, XEON_PBAR4XLAT_OFFSET, MBAR01_DSD_ADDR); else { - ntb_reg_write(8, XEON_PBAR4XLAT_OFFSET, - PBAR4XLAT_USD_ADDR); + if (HAS_FEATURE(NTB_SPLIT_BAR)) { + ntb_reg_write(4, XEON_PBAR4XLAT_OFFSET, + MBAR4_DSD_ADDR); + ntb_reg_write(4, XEON_PBAR5XLAT_OFFSET, + MBAR5_DSD_ADDR); + } else + ntb_reg_write(8, XEON_PBAR4XLAT_OFFSET, + MBAR4_DSD_ADDR); /* * B2B_XLAT_OFFSET is a 64-bit register but can only be * written 32 bits at a time. @@ -1147,15 +1196,25 @@ configure_xeon_secondary_side_bars(struc } ntb_reg_write(8, XEON_SBAR0BASE_OFFSET, MBAR01_USD_ADDR); ntb_reg_write(8, XEON_SBAR2BASE_OFFSET, MBAR23_USD_ADDR); - ntb_reg_write(8, XEON_SBAR4BASE_OFFSET, MBAR45_USD_ADDR); + if (HAS_FEATURE(NTB_SPLIT_BAR)) { + ntb_reg_write(4, XEON_SBAR4BASE_OFFSET, MBAR4_USD_ADDR); + ntb_reg_write(4, XEON_SBAR5BASE_OFFSET, MBAR5_USD_ADDR); + } else + ntb_reg_write(8, XEON_SBAR4BASE_OFFSET, MBAR4_USD_ADDR); } else { - ntb_reg_write(8, XEON_PBAR2XLAT_OFFSET, PBAR2XLAT_DSD_ADDR); + ntb_reg_write(8, XEON_PBAR2XLAT_OFFSET, MBAR23_USD_ADDR); if (HAS_FEATURE(NTB_REGS_THRU_MW)) ntb_reg_write(8, XEON_PBAR4XLAT_OFFSET, MBAR01_USD_ADDR); else { - ntb_reg_write(8, XEON_PBAR4XLAT_OFFSET, - PBAR4XLAT_DSD_ADDR); + if (HAS_FEATURE(NTB_SPLIT_BAR)) { + ntb_reg_write(4, XEON_PBAR4XLAT_OFFSET, + MBAR4_USD_ADDR); + ntb_reg_write(4, XEON_PBAR5XLAT_OFFSET, + MBAR5_USD_ADDR); + } else + ntb_reg_write(8, XEON_PBAR4XLAT_OFFSET, + MBAR4_USD_ADDR); /* * B2B_XLAT_OFFSET is a 64-bit register but can only be * written 32 bits at a time. @@ -1167,7 +1226,14 @@ configure_xeon_secondary_side_bars(struc } ntb_reg_write(8, XEON_SBAR0BASE_OFFSET, MBAR01_DSD_ADDR); ntb_reg_write(8, XEON_SBAR2BASE_OFFSET, MBAR23_DSD_ADDR); - ntb_reg_write(8, XEON_SBAR4BASE_OFFSET, MBAR45_DSD_ADDR); + if (HAS_FEATURE(NTB_SPLIT_BAR)) { + ntb_reg_write(4, XEON_SBAR4BASE_OFFSET, + MBAR4_DSD_ADDR); + ntb_reg_write(4, XEON_SBAR5BASE_OFFSET, + MBAR5_DSD_ADDR); + } else + ntb_reg_write(8, XEON_SBAR4BASE_OFFSET, + MBAR4_DSD_ADDR); } } @@ -1288,7 +1354,9 @@ ntb_hw_link_up(struct ntb_softc *ntb) cntl = ntb_reg_read(4, ntb->reg_ofs.lnk_cntl); cntl &= ~(NTB_CNTL_LINK_DISABLE | NTB_CNTL_CFG_LOCK); cntl |= NTB_CNTL_P2S_BAR23_SNOOP | NTB_CNTL_S2P_BAR23_SNOOP; - cntl |= NTB_CNTL_P2S_BAR45_SNOOP | NTB_CNTL_S2P_BAR45_SNOOP; + cntl |= NTB_CNTL_P2S_BAR4_SNOOP | NTB_CNTL_S2P_BAR4_SNOOP; + if (HAS_FEATURE(NTB_SPLIT_BAR)) + cntl |= NTB_CNTL_P2S_BAR5_SNOOP | NTB_CNTL_S2P_BAR5_SNOOP; ntb_reg_write(4, ntb->reg_ofs.lnk_cntl, cntl); } @@ -1304,7 +1372,9 @@ ntb_hw_link_down(struct ntb_softc *ntb) cntl = ntb_reg_read(4, ntb->reg_ofs.lnk_cntl); cntl &= ~(NTB_CNTL_P2S_BAR23_SNOOP | NTB_CNTL_S2P_BAR23_SNOOP); - cntl &= ~(NTB_CNTL_P2S_BAR45_SNOOP | NTB_CNTL_S2P_BAR45_SNOOP); + cntl &= ~(NTB_CNTL_P2S_BAR4_SNOOP | NTB_CNTL_S2P_BAR4_SNOOP); + if (HAS_FEATURE(NTB_SPLIT_BAR)) + cntl &= ~(NTB_CNTL_P2S_BAR5_SNOOP | NTB_CNTL_S2P_BAR5_SNOOP); cntl |= NTB_CNTL_LINK_DISABLE | NTB_CNTL_CFG_LOCK; ntb_reg_write(4, ntb->reg_ofs.lnk_cntl, cntl); } @@ -1753,7 +1823,13 @@ ntb_set_mw_addr(struct ntb_softc *ntb, u ntb_reg_write(8, ntb->reg_ofs.bar2_xlat, addr); break; case NTB_B2B_BAR_2: - ntb_reg_write(8, ntb->reg_ofs.bar4_xlat, addr); + if (HAS_FEATURE(NTB_SPLIT_BAR)) + ntb_reg_write(4, ntb->reg_ofs.bar4_xlat, addr); + else + ntb_reg_write(8, ntb->reg_ofs.bar4_xlat, addr); + break; + case NTB_B2B_BAR_3: + ntb_reg_write(4, ntb->reg_ofs.bar5_xlat, addr); break; } } Modified: head/sys/dev/ntb/ntb_hw/ntb_hw.h ============================================================================== --- head/sys/dev/ntb/ntb_hw/ntb_hw.h Thu Oct 15 23:45:43 2015 (r289396) +++ head/sys/dev/ntb/ntb_hw/ntb_hw.h Thu Oct 15 23:46:07 2015 (r289397) @@ -31,7 +31,7 @@ struct ntb_softc; -#define NTB_MAX_NUM_MW 2 +#define NTB_MAX_NUM_MW 3 enum ntb_link_event { NTB_LINK_DOWN = 0, @@ -78,11 +78,14 @@ void ntb_ring_doorbell(struct ntb_softc bool ntb_query_link_status(struct ntb_softc *ntb); device_t ntb_get_device(struct ntb_softc *ntb); +/* Hardware owns the low 32 bits of features. */ #define NTB_BAR_SIZE_4K (1 << 0) /* REGS_THRU_MW is the equivalent of Linux's NTB_HWERR_SDOORBELL_LOCKUP */ #define NTB_REGS_THRU_MW (1 << 1) #define NTB_SB01BASE_LOCKUP (1 << 2) #define NTB_B2BDOORBELL_BIT14 (1 << 3) +/* Software/configuration owns the top 32 bits. */ +#define NTB_SPLIT_BAR (1ull << 32) bool ntb_has_feature(struct ntb_softc *, uint64_t); #endif /* _NTB_HW_H_ */ Modified: head/sys/dev/ntb/ntb_hw/ntb_regs.h ============================================================================== --- head/sys/dev/ntb/ntb_hw/ntb_regs.h Thu Oct 15 23:45:43 2015 (r289396) +++ head/sys/dev/ntb/ntb_hw/ntb_regs.h Thu Oct 15 23:46:07 2015 (r289397) @@ -34,6 +34,8 @@ #define NTB_LINK_WIDTH_MASK 0x03f0 #define XEON_MSIX_CNT 4 +#define XEON_SNB_MAX_MW 2 +#define XEON_HSXSPLIT_MAX_MW 3 #define XEON_MAX_SPADS 16 #define XEON_MAX_COMPAT_SPADS 16 /* Reserve the uppermost bit for link interrupt */ @@ -50,15 +52,20 @@ #define XEON_PBAR2LMT_OFFSET 0x0000 #define XEON_PBAR4LMT_OFFSET 0x0008 +#define XEON_PBAR5LMT_OFFSET 0x000c #define XEON_PBAR2XLAT_OFFSET 0x0010 #define XEON_PBAR4XLAT_OFFSET 0x0018 +#define XEON_PBAR5XLAT_OFFSET 0x001c #define XEON_SBAR2LMT_OFFSET 0x0020 #define XEON_SBAR4LMT_OFFSET 0x0028 +#define XEON_SBAR5LMT_OFFSET 0x002c #define XEON_SBAR2XLAT_OFFSET 0x0030 #define XEON_SBAR4XLAT_OFFSET 0x0038 +#define XEON_SBAR5XLAT_OFFSET 0x003c #define XEON_SBAR0BASE_OFFSET 0x0040 #define XEON_SBAR2BASE_OFFSET 0x0048 #define XEON_SBAR4BASE_OFFSET 0x0050 +#define XEON_SBAR5BASE_OFFSET 0x0054 #define XEON_NTBCNTL_OFFSET 0x0058 #define XEON_SBDF_OFFSET 0x005c #define XEON_PDOORBELL_OFFSET 0x0060 @@ -75,6 +82,7 @@ #define XEON_B2B_XLAT_OFFSETU 0x0148 #define SOC_MSIX_CNT 34 +#define SOC_MAX_MW 2 #define SOC_MAX_SPADS 16 #define SOC_MAX_DB_BITS 34 #define SOC_DB_BITS_PER_VEC 1 @@ -111,17 +119,19 @@ #define SOC_LTSSMSTATEJMP_OFFSET (SOC_IP_BASE + 0x3040) #define SOC_IBSTERRRCRVSTS0_OFFSET (SOC_IP_BASE + 0x3324) -#define SOC_DESKEWSTS_DBERR (1 << 15) +#define SOC_DESKEWSTS_DBERR (1 << 15) #define SOC_LTSSMERRSTS0_UNEXPECTEDEI (1 << 20) #define SOC_LTSSMSTATEJMP_FORCEDETECT (1 << 2) -#define SOC_IBIST_ERR_OFLOW 0x7fff7fff +#define SOC_IBIST_ERR_OFLOW 0x7fff7fff #define NTB_CNTL_CFG_LOCK (1 << 0) #define NTB_CNTL_LINK_DISABLE (1 << 1) #define NTB_CNTL_S2P_BAR23_SNOOP (1 << 2) #define NTB_CNTL_P2S_BAR23_SNOOP (1 << 4) -#define NTB_CNTL_S2P_BAR45_SNOOP (1 << 6) -#define NTB_CNTL_P2S_BAR45_SNOOP (1 << 8) +#define NTB_CNTL_S2P_BAR4_SNOOP (1 << 6) +#define NTB_CNTL_P2S_BAR4_SNOOP (1 << 8) +#define NTB_CNTL_S2P_BAR5_SNOOP (1 << 12) +#define NTB_CNTL_P2S_BAR5_SNOOP (1 << 14) #define SOC_CNTL_LINK_DOWN (1 << 16) #define XEON_PBAR23SZ_OFFSET 0x00d0 @@ -129,6 +139,7 @@ #define NTB_PPD_OFFSET 0x00d4 #define XEON_PPD_CONN_TYPE 0x0003 #define XEON_PPD_DEV_TYPE 0x0010 +#define XEON_PPD_SPLIT_BAR 0x0040 #define SOC_PPD_INIT_LINK 0x0008 #define SOC_PPD_CONN_TYPE 0x0300 #define SOC_PPD_DEV_TYPE 0x1000 @@ -140,16 +151,15 @@ #define NTB_DEV_DSD 1 #define NTB_DEV_USD 0 -#define PBAR2XLAT_USD_ADDR 0x0000004000000000ull -#define PBAR4XLAT_USD_ADDR 0x0000008000000000ull -#define MBAR01_USD_ADDR 0x000000210000000cull -#define MBAR23_USD_ADDR 0x000000410000000cull -#define MBAR45_USD_ADDR 0x000000810000000cull -#define PBAR2XLAT_DSD_ADDR 0x0000004100000000ull -#define PBAR4XLAT_DSD_ADDR 0x0000008100000000ull -#define MBAR01_DSD_ADDR 0x000000200000000cull -#define MBAR23_DSD_ADDR 0x000000400000000cull -#define MBAR45_DSD_ADDR 0x000000800000000cull +/* All addresses are in low 32-bit space so 32-bit BARs can function */ +#define MBAR01_USD_ADDR 0x2100000cull +#define MBAR23_USD_ADDR 0x4100000cull +#define MBAR4_USD_ADDR 0x8100000cull +#define MBAR5_USD_ADDR 0xa100000cull +#define MBAR01_DSD_ADDR 0x2000000cull +#define MBAR23_DSD_ADDR 0x4000000cull +#define MBAR4_DSD_ADDR 0x8000000cull +#define MBAR5_DSD_ADDR 0xa000000cull /* XEON Shadowed MMIO Space */ #define XEON_SHADOW_PDOORBELL_OFFSET 0x60
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201510152346.t9FNk7Pa090301>