Date: Thu, 10 Mar 2016 06:15:32 +0000 (UTC) From: Navdeep Parhar <np@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r296603 - in head/sys/dev/cxgbe: . common Message-ID: <201603100615.u2A6FWE5031172@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: np Date: Thu Mar 10 06:15:31 2016 New Revision: 296603 URL: https://svnweb.freebsd.org/changeset/base/296603 Log: cxgbe(4): Add general purpose routines that offer safe access to the chip's memory windows. Convert existing users of these windows to the new routines. Modified: head/sys/dev/cxgbe/adapter.h head/sys/dev/cxgbe/common/common.h head/sys/dev/cxgbe/t4_main.c Modified: head/sys/dev/cxgbe/adapter.h ============================================================================== --- head/sys/dev/cxgbe/adapter.h Thu Mar 10 05:45:24 2016 (r296602) +++ head/sys/dev/cxgbe/adapter.h Thu Mar 10 06:15:31 2016 (r296603) @@ -438,6 +438,29 @@ struct hw_buf_info { }; enum { + NUM_MEMWIN = 3, + + MEMWIN0_APERTURE = 2048, + MEMWIN0_BASE = 0x1b800, + + MEMWIN1_APERTURE = 32768, + MEMWIN1_BASE = 0x28000, + + MEMWIN2_APERTURE_T4 = 65536, + MEMWIN2_BASE_T4 = 0x30000, + + MEMWIN2_APERTURE_T5 = 128 * 1024, + MEMWIN2_BASE_T5 = 0x60000, +}; + +struct memwin { + struct rwlock mw_lock __aligned(CACHE_LINE_SIZE); + uint32_t mw_base; /* constant after setup_memwin */ + uint32_t mw_aperture; /* ditto */ + uint32_t mw_curpos; /* protected by mw_lock */ +}; + +enum { FL_STARVING = (1 << 0), /* on the adapter's list of starving fl's */ FL_DOOMED = (1 << 1), /* about to be destroyed */ FL_BUF_PACKING = (1 << 2), /* buffer packing enabled */ @@ -806,6 +829,8 @@ struct adapter { struct mtx reg_lock; /* for indirect register access */ + struct memwin memwin[NUM_MEMWIN]; /* memory windows */ + an_handler_t an_handler __aligned(CACHE_LINE_SIZE); fw_msg_handler_t fw_msg_handler[7]; /* NUM_FW6_TYPES */ cpl_handler_t cpl_handler[0xef]; /* NUM_CPL_CMDS */ Modified: head/sys/dev/cxgbe/common/common.h ============================================================================== --- head/sys/dev/cxgbe/common/common.h Thu Mar 10 05:45:24 2016 (r296602) +++ head/sys/dev/cxgbe/common/common.h Thu Mar 10 06:15:31 2016 (r296603) @@ -52,20 +52,6 @@ enum { enum { MEM_EDC0, MEM_EDC1, MEM_MC, MEM_MC0 = MEM_MC, MEM_MC1 }; -enum { - MEMWIN0_APERTURE = 2048, - MEMWIN0_BASE = 0x1b800, - - MEMWIN1_APERTURE = 32768, - MEMWIN1_BASE = 0x28000, - - MEMWIN2_APERTURE_T4 = 65536, - MEMWIN2_BASE_T4 = 0x30000, - - MEMWIN2_APERTURE_T5 = 128 * 1024, - MEMWIN2_BASE_T5 = 0x60000, -}; - enum dev_master { MASTER_CANT, MASTER_MAY, MASTER_MUST }; enum dev_state { DEV_STATE_UNINIT, DEV_STATE_INIT, DEV_STATE_ERR }; @@ -76,11 +62,6 @@ enum { PAUSE_AUTONEG = 1 << 2 }; -struct memwin { - uint32_t base; - uint32_t aperture; -}; - struct port_stats { u64 tx_octets; /* total # of octets in good frames */ u64 tx_frames; /* all good frames */ Modified: head/sys/dev/cxgbe/t4_main.c ============================================================================== --- head/sys/dev/cxgbe/t4_main.c Thu Mar 10 05:45:24 2016 (r296602) +++ head/sys/dev/cxgbe/t4_main.c Thu Mar 10 06:15:31 2016 (r296603) @@ -399,12 +399,16 @@ struct filter_entry { static int map_bars_0_and_4(struct adapter *); static int map_bar_2(struct adapter *); static void setup_memwin(struct adapter *); +static void position_memwin(struct adapter *, int, uint32_t); +static int rw_via_memwin(struct adapter *, int, uint32_t, uint32_t *, int, int); +static inline int read_via_memwin(struct adapter *, int, uint32_t, uint32_t *, + int); +static inline int write_via_memwin(struct adapter *, int, uint32_t, + const uint32_t *, int); static int validate_mem_range(struct adapter *, uint32_t, int); static int fwmtype_to_hwmtype(int); static int validate_mt_off_len(struct adapter *, int, uint32_t, int, uint32_t *); -static void memwin_info(struct adapter *, int, uint32_t *, uint32_t *); -static uint32_t position_memwin(struct adapter *, int, uint32_t); static int cfg_itype_and_nqueues(struct adapter *, int, int, int, struct intrs_and_queues *); static int prep_firmware(struct adapter *); @@ -1164,6 +1168,13 @@ t4_detach(device_t dev) if (mtx_initialized(&sc->reg_lock)) mtx_destroy(&sc->reg_lock); + for (i = 0; i < NUM_MEMWIN; i++) { + struct memwin *mw = &sc->memwin[i]; + + if (rw_initialized(&mw->mw_lock)) + rw_destroy(&mw->mw_lock); + } + bzero(sc, sizeof(*sc)); return (0); @@ -1965,13 +1976,18 @@ map_bar_2(struct adapter *sc) return (0); } -static const struct memwin t4_memwin[] = { +struct memwin_init { + uint32_t base; + uint32_t aperture; +}; + +static const struct memwin_init t4_memwin[NUM_MEMWIN] = { { MEMWIN0_BASE, MEMWIN0_APERTURE }, { MEMWIN1_BASE, MEMWIN1_APERTURE }, { MEMWIN2_BASE_T4, MEMWIN2_APERTURE_T4 } }; -static const struct memwin t5_memwin[] = { +static const struct memwin_init t5_memwin[NUM_MEMWIN] = { { MEMWIN0_BASE, MEMWIN0_APERTURE }, { MEMWIN1_BASE, MEMWIN1_APERTURE }, { MEMWIN2_BASE_T5, MEMWIN2_APERTURE_T5 }, @@ -1980,8 +1996,9 @@ static const struct memwin t5_memwin[] = static void setup_memwin(struct adapter *sc) { - const struct memwin *mw; - int i, n; + const struct memwin_init *mw_init; + struct memwin *mw; + int i; uint32_t bar0; if (is_t4(sc)) { @@ -1995,27 +2012,125 @@ setup_memwin(struct adapter *sc) bar0 = t4_hw_pci_read_cfg4(sc, PCIR_BAR(0)); bar0 &= (uint32_t) PCIM_BAR_MEM_BASE; - mw = &t4_memwin[0]; - n = nitems(t4_memwin); + mw_init = &t4_memwin[0]; } else { - /* T5 uses the relative offset inside the PCIe BAR */ + /* T5+ use the relative offset inside the PCIe BAR */ bar0 = 0; - mw = &t5_memwin[0]; - n = nitems(t5_memwin); + mw_init = &t5_memwin[0]; } - for (i = 0; i < n; i++, mw++) { + for (i = 0, mw = &sc->memwin[0]; i < NUM_MEMWIN; i++, mw_init++, mw++) { + rw_init(&mw->mw_lock, "memory window access"); + mw->mw_base = mw_init->base; + mw->mw_aperture = mw_init->aperture; + mw->mw_curpos = 0; t4_write_reg(sc, PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_BASE_WIN, i), - (mw->base + bar0) | V_BIR(0) | - V_WINDOW(ilog2(mw->aperture) - 10)); + (mw->mw_base + bar0) | V_BIR(0) | + V_WINDOW(ilog2(mw->mw_aperture) - 10)); + rw_wlock(&mw->mw_lock); + position_memwin(sc, i, 0); + rw_wunlock(&mw->mw_lock); } /* flush */ t4_read_reg(sc, PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_BASE_WIN, 2)); } +/* + * Positions the memory window at the given address in the card's address space. + * There are some alignment requirements and the actual position may be at an + * address prior to the requested address. mw->mw_curpos always has the actual + * position of the window. + */ +static void +position_memwin(struct adapter *sc, int idx, uint32_t addr) +{ + struct memwin *mw; + uint32_t pf; + uint32_t reg; + + MPASS(idx >= 0 && idx < NUM_MEMWIN); + mw = &sc->memwin[idx]; + rw_assert(&mw->mw_lock, RA_WLOCKED); + + if (is_t4(sc)) { + pf = 0; + mw->mw_curpos = addr & ~0xf; /* start must be 16B aligned */ + } else { + pf = V_PFNUM(sc->pf); + mw->mw_curpos = addr & ~0x7f; /* start must be 128B aligned */ + } + reg = PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_OFFSET, idx); + t4_write_reg(sc, reg, mw->mw_curpos | pf); + t4_read_reg(sc, reg); /* flush */ +} + +static int +rw_via_memwin(struct adapter *sc, int idx, uint32_t addr, uint32_t *val, + int len, int rw) +{ + struct memwin *mw; + uint32_t mw_end, v; + + MPASS(idx >= 0 && idx < NUM_MEMWIN); + + /* Memory can only be accessed in naturally aligned 4 byte units */ + if (addr & 3 || len & 3 || len <= 0) + return (EINVAL); + + mw = &sc->memwin[idx]; + while (len > 0) { + rw_rlock(&mw->mw_lock); + mw_end = mw->mw_curpos + mw->mw_aperture; + if (addr >= mw_end || addr + len <= mw->mw_curpos) { + /* Will need to reposition the window */ + if (!rw_try_upgrade(&mw->mw_lock)) { + rw_runlock(&mw->mw_lock); + rw_wlock(&mw->mw_lock); + } + rw_assert(&mw->mw_lock, RA_WLOCKED); + position_memwin(sc, idx, addr); + rw_downgrade(&mw->mw_lock); + mw_end = mw->mw_curpos + mw->mw_aperture; + } + rw_assert(&mw->mw_lock, RA_RLOCKED); + while (addr < mw_end && len > 0) { + if (rw == 0) { + v = t4_read_reg(sc, mw->mw_base + addr - + mw->mw_curpos); + *val++ = le32toh(v); + } else { + v = *val++; + t4_write_reg(sc, mw->mw_base + addr - + mw->mw_curpos, htole32(v));; + } + addr += 4; + len -= 4; + } + rw_runlock(&mw->mw_lock); + } + + return (0); +} + +static inline int +read_via_memwin(struct adapter *sc, int idx, uint32_t addr, uint32_t *val, + int len) +{ + + return (rw_via_memwin(sc, idx, addr, val, len, 0)); +} + +static inline int +write_via_memwin(struct adapter *sc, int idx, uint32_t addr, + const uint32_t *val, int len) +{ + + return (rw_via_memwin(sc, idx, addr, (void *)(uintptr_t)val, len, 1)); +} + static int t4_range_cmp(const void *a, const void *b) { @@ -2217,58 +2332,6 @@ validate_mt_off_len(struct adapter *sc, return (validate_mem_range(sc, *addr, len)); } -static void -memwin_info(struct adapter *sc, int win, uint32_t *base, uint32_t *aperture) -{ - const struct memwin *mw; - - if (is_t4(sc)) { - KASSERT(win >= 0 && win < nitems(t4_memwin), - ("%s: incorrect memwin# (%d)", __func__, win)); - mw = &t4_memwin[win]; - } else { - KASSERT(win >= 0 && win < nitems(t5_memwin), - ("%s: incorrect memwin# (%d)", __func__, win)); - mw = &t5_memwin[win]; - } - - if (base != NULL) - *base = mw->base; - if (aperture != NULL) - *aperture = mw->aperture; -} - -/* - * Positions the memory window such that it can be used to access the specified - * address in the chip's address space. The return value is the offset of addr - * from the start of the window. - */ -static uint32_t -position_memwin(struct adapter *sc, int n, uint32_t addr) -{ - uint32_t start, pf; - uint32_t reg; - - KASSERT(n >= 0 && n <= 3, - ("%s: invalid window %d.", __func__, n)); - KASSERT((addr & 3) == 0, - ("%s: addr (0x%x) is not at a 4B boundary.", __func__, addr)); - - if (is_t4(sc)) { - pf = 0; - start = addr & ~0xf; /* start must be 16B aligned */ - } else { - pf = V_PFNUM(sc->pf); - start = addr & ~0x7f; /* start must be 128B aligned */ - } - reg = PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_OFFSET, n); - - t4_write_reg(sc, reg, start | pf); - t4_read_reg(sc, reg); - - return (addr - start); -} - static int cfg_itype_and_nqueues(struct adapter *sc, int n10g, int n1g, int num_vis, struct intrs_and_queues *iaq) @@ -2869,9 +2932,9 @@ partition_resources(struct adapter *sc, } if (strncmp(sc->cfg_file, FLASH_CF, sizeof(sc->cfg_file)) != 0) { - u_int cflen, i, n; + u_int cflen; const uint32_t *cfdata; - uint32_t param, val, addr, off, mw_base, mw_aperture; + uint32_t param, val, addr; KASSERT(cfg != NULL || default_cfg != NULL, ("%s: no config to upload", __func__)); @@ -2921,16 +2984,7 @@ partition_resources(struct adapter *sc, __func__, mtype, moff, cflen, rc); goto use_config_on_flash; } - - memwin_info(sc, 2, &mw_base, &mw_aperture); - while (cflen) { - off = position_memwin(sc, 2, addr); - n = min(cflen, mw_aperture - off); - for (i = 0; i < n; i += 4) - t4_write_reg(sc, mw_base + off + i, *cfdata++); - cflen -= n; - addr += n; - } + write_via_memwin(sc, 2, addr, cfdata, cflen); } else { use_config_on_flash: mtype = FW_MEMTYPE_FLASH; @@ -7486,22 +7540,22 @@ done: static inline uint64_t get_filter_hits(struct adapter *sc, uint32_t fid) { - uint32_t mw_base, off, tcb_base = t4_read_reg(sc, A_TP_CMM_TCB_BASE); - uint64_t hits; + uint32_t tcb_addr; - memwin_info(sc, 0, &mw_base, NULL); + tcb_addr = t4_read_reg(sc, A_TP_CMM_TCB_BASE) + + (fid + sc->tids.ftid_base) * TCB_SIZE; - off = position_memwin(sc, 0, - tcb_base + (fid + sc->tids.ftid_base) * TCB_SIZE); if (is_t4(sc)) { - hits = t4_read_reg64(sc, mw_base + off + 16); - hits = be64toh(hits); + uint64_t hits; + + read_via_memwin(sc, 0, tcb_addr + 16, (uint32_t *)&hits, 8); + return (be64toh(hits)); } else { - hits = t4_read_reg(sc, mw_base + off + 24); - hits = be32toh(hits); - } + uint32_t hits; - return (hits); + read_via_memwin(sc, 0, tcb_addr + 24, &hits, 4); + return (be32toh(hits)); + } } static int @@ -7975,12 +8029,12 @@ done: return (rc); } +#define MAX_READ_BUF_SIZE (128 * 1024) static int read_card_mem(struct adapter *sc, int win, struct t4_mem_range *mr) { - uint32_t addr, off, remaining, i, n; - uint32_t *buf, *b; - uint32_t mw_base, mw_aperture; + uint32_t addr, remaining, n; + uint32_t *buf; int rc; uint8_t *dst; @@ -7988,25 +8042,19 @@ read_card_mem(struct adapter *sc, int wi if (rc != 0) return (rc); - memwin_info(sc, win, &mw_base, &mw_aperture); - buf = b = malloc(min(mr->len, mw_aperture), M_CXGBE, M_WAITOK); + buf = malloc(min(mr->len, MAX_READ_BUF_SIZE), M_CXGBE, M_WAITOK); addr = mr->addr; remaining = mr->len; dst = (void *)mr->data; while (remaining) { - off = position_memwin(sc, win, addr); - - /* number of bytes that we'll copy in the inner loop */ - n = min(remaining, mw_aperture - off); - for (i = 0; i < n; i += 4) - *b++ = t4_read_reg(sc, mw_base + off + i); + n = min(remaining, MAX_READ_BUF_SIZE); + read_via_memwin(sc, 2, addr, buf, n); rc = copyout(buf, dst, n); if (rc != 0) break; - b = buf; dst += n; remaining -= n; addr += n; @@ -8015,6 +8063,7 @@ read_card_mem(struct adapter *sc, int wi free(buf, M_CXGBE); return (rc); } +#undef MAX_READ_BUF_SIZE static int read_i2c(struct adapter *sc, struct t4_i2c_data *i2cd)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201603100615.u2A6FWE5031172>