diff options
author | Bill Taylor <Bill.Taylor@Sun.COM> | 2010-03-22 13:54:46 -0700 |
---|---|---|
committer | Bill Taylor <Bill.Taylor@Sun.COM> | 2010-03-22 13:54:46 -0700 |
commit | c7facc54c4abed9e554ff80225311e6b7048d3c9 (patch) | |
tree | c846e4ebb88c5255b23292f5f61bb21b6a8345c8 | |
parent | b6611e3b41e720b79f165a90cc0ffa574819d2e8 (diff) | |
download | illumos-gate-c7facc54c4abed9e554ff80225311e6b7048d3c9.tar.gz |
6932984 IBTF and HCA drivers need to more completely support FMR and ibt_map_mem_area()
27 files changed, 654 insertions, 2417 deletions
diff --git a/usr/src/uts/common/io/ib/adapters/hermon/hermon.c b/usr/src/uts/common/io/ib/adapters/hermon/hermon.c index 3fd3224b49..cfe77cdb35 100644 --- a/usr/src/uts/common/io/ib/adapters/hermon/hermon.c +++ b/usr/src/uts/common/io/ib/adapters/hermon/hermon.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -880,6 +880,10 @@ hermon_dma_alloc(hermon_state_t *state, hermon_dma_info_t *dma_info, int status; hermon_dma_attr_init(state, &dma_attr); +#ifdef __sparc + if (state->hs_cfg_profile->cp_iommu_bypass == HERMON_BINDMEM_BYPASS) + dma_attr.dma_attr_flags = DDI_DMA_FORCE_PHYSICAL; +#endif /* Allocate a DMA handle */ status = ddi_dma_alloc_handle(state->hs_dip, &dma_attr, DDI_DMA_SLEEP, diff --git a/usr/src/uts/common/io/ib/adapters/hermon/hermon_cfg.c b/usr/src/uts/common/io/ib/adapters/hermon/hermon_cfg.c index b32ce7705c..64bfac0fe2 100644 --- a/usr/src/uts/common/io/ib/adapters/hermon/hermon_cfg.c +++ b/usr/src/uts/common/io/ib/adapters/hermon/hermon_cfg.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -242,6 +242,20 @@ hermon_cfg_profile_init_phase1(hermon_state_t *state) return (DDI_FAILURE); } + /* + * Set IOMMU bypass or not. Ensure consistency of flags with + * architecture type. + */ +#ifdef __sparc + if (hermon_iommu_bypass == 1) { + hermon_check_iommu_bypass(state, cp); + } else { + cp->cp_iommu_bypass = HERMON_BINDMEM_NORMAL; + } +#else + cp->cp_iommu_bypass = HERMON_BINDMEM_NORMAL; +#endif + /* Attach the configuration profile to Hermon softstate */ state->hs_cfg_profile = cp; @@ -352,20 +366,6 @@ hermon_cfg_profile_init_phase2(hermon_state_t *state) /* Determine WQE sizes from requested max SGLs */ hermon_cfg_wqe_sizes(state, cp); - /* - * Set IOMMU bypass or not. Ensure consistency of flags with - * architecture type. - */ -#ifdef __sparc - if (hermon_iommu_bypass == 1) { - hermon_check_iommu_bypass(state, cp); - } else { - cp->cp_iommu_bypass = HERMON_BINDMEM_NORMAL; - } -#else - cp->cp_iommu_bypass = HERMON_BINDMEM_NORMAL; -#endif - /* Set whether to use MSIs or not */ cp->cp_use_msi_if_avail = hermon_use_msi_if_avail; diff --git a/usr/src/uts/common/io/ib/adapters/hermon/hermon_ci.c b/usr/src/uts/common/io/ib/adapters/hermon/hermon_ci.c index b5284feba2..6f32f36a45 100644 --- a/usr/src/uts/common/io/ib/adapters/hermon/hermon_ci.c +++ b/usr/src/uts/common/io/ib/adapters/hermon/hermon_ci.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -42,6 +42,9 @@ #include <sys/ib/adapters/hermon/hermon.h> +extern uint32_t hermon_kernel_data_ro; +extern uint32_t hermon_user_data_ro; + /* HCA and port related operations */ static ibt_status_t hermon_ci_query_hca_ports(ibc_hca_hdl_t, uint8_t, ibt_hca_portinfo_t *); @@ -173,8 +176,7 @@ static ibt_status_t hermon_ci_post_srq(ibc_hca_hdl_t, ibc_srq_hdl_t, /* Address translation */ static ibt_status_t hermon_ci_map_mem_area(ibc_hca_hdl_t, ibt_va_attr_t *, - void *, uint_t, ibt_phys_buf_t *, uint_t *, size_t *, ib_memlen_t *, - ibc_ma_hdl_t *); + void *, uint_t, ibt_reg_req_t *, ibc_ma_hdl_t *); static ibt_status_t hermon_ci_unmap_mem_area(ibc_hca_hdl_t, ibc_ma_hdl_t); static ibt_status_t hermon_ci_map_mem_iov(ibc_hca_hdl_t, ibt_iov_attr_t *, ibt_all_wr_t *, ibc_mi_hdl_t *); @@ -2300,61 +2302,339 @@ hermon_ci_post_srq(ibc_hca_hdl_t hca, ibc_srq_hdl_t srq, } /* Address translation */ + +struct ibc_ma_s { + int h_ma_addr_list_len; + void *h_ma_addr_list; + ddi_dma_handle_t h_ma_dmahdl; + ddi_dma_handle_t h_ma_list_hdl; + ddi_acc_handle_t h_ma_list_acc_hdl; + size_t h_ma_real_len; + caddr_t h_ma_kaddr; + ibt_phys_addr_t h_ma_list_cookie; +}; + +static ibt_status_t +hermon_map_mem_area_fmr(ibc_hca_hdl_t hca, ibt_va_attr_t *va_attrs, + uint_t list_len, ibt_pmr_attr_t *pmr, ibc_ma_hdl_t *ma_hdl_p) +{ + int status; + ibt_status_t ibt_status; + ibc_ma_hdl_t ma_hdl; + ib_memlen_t len; + ddi_dma_attr_t dma_attr; + uint_t cookie_cnt; + ddi_dma_cookie_t dmacookie; + hermon_state_t *state; + uint64_t *kaddr; + uint64_t addr, endaddr, pagesize; + int i, kmflag; + int (*callback)(caddr_t); + + if ((va_attrs->va_flags & IBT_VA_BUF) == 0) { + return (IBT_NOT_SUPPORTED); /* XXX - not yet implemented */ + } + + state = (hermon_state_t *)hca; + hermon_dma_attr_init(state, &dma_attr); + if (va_attrs->va_flags & IBT_VA_NOSLEEP) { + kmflag = KM_NOSLEEP; + callback = DDI_DMA_DONTWAIT; + } else { + kmflag = KM_SLEEP; + callback = DDI_DMA_SLEEP; + } + + ma_hdl = kmem_zalloc(sizeof (*ma_hdl), kmflag); + if (ma_hdl == NULL) { + return (IBT_INSUFF_RESOURCE); + } +#ifdef __sparc + if (state->hs_cfg_profile->cp_iommu_bypass == HERMON_BINDMEM_BYPASS) + dma_attr.dma_attr_flags = DDI_DMA_FORCE_PHYSICAL; + + if (hermon_kernel_data_ro == HERMON_RO_ENABLED) + dma_attr.dma_attr_flags |= DDI_DMA_RELAXED_ORDERING; +#endif + + _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ma_hdl)) + status = ddi_dma_alloc_handle(state->hs_dip, &dma_attr, + callback, NULL, &ma_hdl->h_ma_dmahdl); + if (status != DDI_SUCCESS) { + kmem_free(ma_hdl, sizeof (*ma_hdl)); + return (IBT_INSUFF_RESOURCE); + } + status = ddi_dma_buf_bind_handle(ma_hdl->h_ma_dmahdl, + va_attrs->va_buf, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, + callback, NULL, &dmacookie, &cookie_cnt); + if (status != DDI_DMA_MAPPED) { + status = ibc_get_ci_failure(0); + goto marea_fail3; + } + + ma_hdl->h_ma_real_len = list_len * sizeof (ibt_phys_addr_t); + ma_hdl->h_ma_kaddr = kmem_zalloc(ma_hdl->h_ma_real_len, kmflag); + if (ma_hdl->h_ma_kaddr == NULL) { + ibt_status = IBT_INSUFF_RESOURCE; + goto marea_fail4; + } + + i = 0; + len = 0; + pagesize = PAGESIZE; + kaddr = (uint64_t *)(void *)ma_hdl->h_ma_kaddr; + while (cookie_cnt-- > 0) { + addr = dmacookie.dmac_laddress; + len += dmacookie.dmac_size; + endaddr = addr + (dmacookie.dmac_size - 1); + addr = addr & ~(pagesize - 1); + while (addr <= endaddr) { + if (i >= list_len) { + status = IBT_PBL_TOO_SMALL; + goto marea_fail5; + } + kaddr[i] = htonll(addr | HERMON_MTT_ENTRY_PRESENT); + i++; + addr += pagesize; + if (addr == 0) { + static int do_once = 1; + _NOTE(SCHEME_PROTECTS_DATA("safe sharing", + do_once)) + if (do_once) { + do_once = 0; + cmn_err(CE_NOTE, "probable error in " + "dma_cookie address: map_mem_area"); + } + break; + } + } + if (cookie_cnt != 0) + ddi_dma_nextcookie(ma_hdl->h_ma_dmahdl, &dmacookie); + } + + _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*pmr)) + pmr->pmr_addr_list = (ibt_phys_addr_t *)(void *)ma_hdl->h_ma_kaddr; + pmr->pmr_iova = va_attrs->va_vaddr; + pmr->pmr_len = len; + pmr->pmr_offset = va_attrs->va_vaddr & PAGEOFFSET; + pmr->pmr_buf_sz = PAGESHIFT; /* PRM says "Page Sice", but... */ + pmr->pmr_num_buf = i; + pmr->pmr_ma = ma_hdl; + + *ma_hdl_p = ma_hdl; + return (IBT_SUCCESS); + +marea_fail5: + kmem_free(ma_hdl->h_ma_kaddr, ma_hdl->h_ma_real_len); +marea_fail4: + status = ddi_dma_unbind_handle(ma_hdl->h_ma_dmahdl); +marea_fail3: + ddi_dma_free_handle(&ma_hdl->h_ma_dmahdl); + kmem_free(ma_hdl, sizeof (*ma_hdl)); + *ma_hdl_p = NULL; + return (ibt_status); +} + /* * hermon_ci_map_mem_area() * Context: Can be called from interrupt or base context. + * + * Creates the memory mapping suitable for a subsequent posting of an + * FRWR work request. All the info about the memory area for the + * FRWR work request (wr member of "union ibt_reg_req_u") is filled + * such that the client only needs to point wr.rc.rcwr.reg_pmr to it, + * and then fill in the additional information only it knows. + * + * Alternatively, creates the memory mapping for FMR. */ /* ARGSUSED */ static ibt_status_t hermon_ci_map_mem_area(ibc_hca_hdl_t hca, ibt_va_attr_t *va_attrs, - void *ibtl_reserved, uint_t list_len, ibt_phys_buf_t *paddr_list_p, - uint_t *ret_num_paddr_p, size_t *paddr_buf_sz_p, - ib_memlen_t *paddr_offset_p, ibc_ma_hdl_t *ibc_ma_hdl_p) + void *ibtl_reserved, uint_t list_len, ibt_reg_req_t *reg_req, + ibc_ma_hdl_t *ma_hdl_p) { - hermon_state_t *state; - uint_t cookiecnt; + ibt_status_t ibt_status; int status; + ibc_ma_hdl_t ma_hdl; + ibt_wr_reg_pmr_t *pmr; + ib_memlen_t len; + ddi_dma_attr_t dma_attr; + ddi_dma_handle_t khdl; + uint_t cookie_cnt; + ddi_dma_cookie_t dmacookie, kcookie; + hermon_state_t *state; + uint64_t *kaddr; + uint64_t addr, endaddr, pagesize, kcookie_paddr; + int i, j, kmflag; + int (*callback)(caddr_t); - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*paddr_list_p)) - - /* Check for valid HCA handle */ - if (hca == NULL) { - return (IBT_HCA_HDL_INVALID); + if (va_attrs->va_flags & (IBT_VA_FMR | IBT_VA_REG_FN)) { + /* delegate FMR and Physical Register to other function */ + return (hermon_map_mem_area_fmr(hca, va_attrs, list_len, + ®_req->fn_arg, ma_hdl_p)); } - if ((va_attrs->va_flags & IBT_VA_BUF) && (va_attrs->va_buf == NULL)) { - return (IBT_INVALID_PARAM); - } + /* FRWR */ state = (hermon_state_t *)hca; + hermon_dma_attr_init(state, &dma_attr); +#ifdef __sparc + if (state->hs_cfg_profile->cp_iommu_bypass == HERMON_BINDMEM_BYPASS) + dma_attr.dma_attr_flags = DDI_DMA_FORCE_PHYSICAL; + + if (hermon_kernel_data_ro == HERMON_RO_ENABLED) + dma_attr.dma_attr_flags |= DDI_DMA_RELAXED_ORDERING; +#endif + if (va_attrs->va_flags & IBT_VA_NOSLEEP) { + kmflag = KM_NOSLEEP; + callback = DDI_DMA_DONTWAIT; + } else { + kmflag = KM_SLEEP; + callback = DDI_DMA_SLEEP; + } - /* - * Based on the length of the buffer and the paddr_list passed in, - * retrieve DMA cookies for the virtual to physical address - * translation. - */ - status = hermon_get_dma_cookies(state, paddr_list_p, va_attrs, - list_len, &cookiecnt, ibc_ma_hdl_p); - if (status != DDI_SUCCESS) { - return (status); + ma_hdl = kmem_zalloc(sizeof (*ma_hdl), kmflag); + if (ma_hdl == NULL) { + return (IBT_INSUFF_RESOURCE); } + _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ma_hdl)) + status = ddi_dma_alloc_handle(state->hs_dip, &dma_attr, + callback, NULL, &ma_hdl->h_ma_dmahdl); + if (status != DDI_SUCCESS) { + kmem_free(ma_hdl, sizeof (*ma_hdl)); + ibt_status = IBT_INSUFF_RESOURCE; + goto marea_fail0; + } + dma_attr.dma_attr_align = 64; /* as per PRM */ + status = ddi_dma_alloc_handle(state->hs_dip, &dma_attr, + callback, NULL, &ma_hdl->h_ma_list_hdl); + if (status != DDI_SUCCESS) { + ibt_status = IBT_INSUFF_RESOURCE; + goto marea_fail1; + } /* - * Split the cookies returned from 'hermon_get_dma_cookies() above. We - * also pass in the size of the cookies we would like. - * Note: for now, we only support PAGESIZE cookies. + * Entries in the list in the last slot on each page cannot be used, + * so 1 extra ibt_phys_addr_t is allocated per page. We add 1 more + * to deal with the possibility of a less than 1 page allocation + * across a page boundary. */ - status = hermon_split_dma_cookies(state, paddr_list_p, paddr_offset_p, - list_len, &cookiecnt, PAGESIZE); + status = ddi_dma_mem_alloc(ma_hdl->h_ma_list_hdl, (list_len + 1 + + list_len / (HERMON_PAGESIZE / sizeof (ibt_phys_addr_t))) * + sizeof (ibt_phys_addr_t), + &state->hs_reg_accattr, DDI_DMA_CONSISTENT, callback, NULL, + &ma_hdl->h_ma_kaddr, &ma_hdl->h_ma_real_len, + &ma_hdl->h_ma_list_acc_hdl); if (status != DDI_SUCCESS) { - return (status); + ibt_status = IBT_INSUFF_RESOURCE; + goto marea_fail2; + } + status = ddi_dma_addr_bind_handle(ma_hdl->h_ma_list_hdl, NULL, + ma_hdl->h_ma_kaddr, ma_hdl->h_ma_real_len, DDI_DMA_RDWR | + DDI_DMA_CONSISTENT, callback, NULL, + &kcookie, &cookie_cnt); + if (status != DDI_SUCCESS) { + ibt_status = IBT_INSUFF_RESOURCE; + goto marea_fail3; + } + if ((kcookie.dmac_laddress & 0x3f) != 0) { + cmn_err(CE_NOTE, "64-byte alignment assumption wrong"); + ibt_status = ibc_get_ci_failure(0); + goto marea_fail4; + } + ma_hdl->h_ma_list_cookie.p_laddr = kcookie.dmac_laddress; + + if (va_attrs->va_flags & IBT_VA_BUF) { + status = ddi_dma_buf_bind_handle(ma_hdl->h_ma_dmahdl, + va_attrs->va_buf, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, + callback, NULL, &dmacookie, &cookie_cnt); + } else { + status = ddi_dma_addr_bind_handle(ma_hdl->h_ma_dmahdl, + va_attrs->va_as, (caddr_t)(uintptr_t)va_attrs->va_vaddr, + va_attrs->va_len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, + callback, NULL, &dmacookie, &cookie_cnt); + } + if (status != DDI_DMA_MAPPED) { + ibt_status = ibc_get_ci_failure(0); + goto marea_fail4; + } + i = 0; /* count the number of pbl entries */ + j = 0; /* count the number of links to next HERMON_PAGE */ + len = 0; + pagesize = PAGESIZE; + kaddr = (uint64_t *)(void *)ma_hdl->h_ma_kaddr; + kcookie_paddr = kcookie.dmac_laddress + HERMON_PAGEMASK; + khdl = ma_hdl->h_ma_list_hdl; + while (cookie_cnt-- > 0) { + addr = dmacookie.dmac_laddress; + len += dmacookie.dmac_size; + endaddr = addr + (dmacookie.dmac_size - 1); + addr = addr & ~(pagesize - 1); + while (addr <= endaddr) { + if (i >= list_len) { + ibt_status = IBT_PBL_TOO_SMALL; + goto marea_fail5; + } + /* Deal with last entry on page. */ + if (!((uintptr_t)&kaddr[i+j+1] & HERMON_PAGEOFFSET)) { + if (kcookie.dmac_size > HERMON_PAGESIZE) { + kcookie_paddr += HERMON_PAGESIZE; + kcookie.dmac_size -= HERMON_PAGESIZE; + } else { + ddi_dma_nextcookie(khdl, &kcookie); + kcookie_paddr = kcookie.dmac_laddress; + } + kaddr[i+j] = htonll(kcookie_paddr); + j++; + } + kaddr[i+j] = htonll(addr | HERMON_MTT_ENTRY_PRESENT); + i++; + addr += pagesize; + if (addr == 0) { + static int do_once = 1; + _NOTE(SCHEME_PROTECTS_DATA("safe sharing", + do_once)) + if (do_once) { + do_once = 0; + cmn_err(CE_NOTE, "probable error in " + "dma_cookie address: map_mem_area"); + } + break; + } + } + if (cookie_cnt != 0) + ddi_dma_nextcookie(ma_hdl->h_ma_dmahdl, &dmacookie); } - /* Setup return values */ - *ret_num_paddr_p = cookiecnt; - *paddr_buf_sz_p = PAGESIZE; + pmr = ®_req->wr; + _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*pmr)) + pmr->pmr_len = len; + pmr->pmr_offset = va_attrs->va_vaddr & PAGEOFFSET; + pmr->pmr_buf_sz = PAGESHIFT; /* PRM says "Page Size", but... */ + pmr->pmr_num_buf = i; + pmr->pmr_addr_list = &ma_hdl->h_ma_list_cookie; + *ma_hdl_p = ma_hdl; return (IBT_SUCCESS); + +marea_fail5: + status = ddi_dma_unbind_handle(ma_hdl->h_ma_dmahdl); + if (status != DDI_SUCCESS) + HERMON_WARNING(state, "failed to unbind DMA mapping"); +marea_fail4: + status = ddi_dma_unbind_handle(ma_hdl->h_ma_list_hdl); + if (status != DDI_SUCCESS) + HERMON_WARNING(state, "failed to unbind DMA mapping"); +marea_fail3: + ddi_dma_mem_free(&ma_hdl->h_ma_list_acc_hdl); +marea_fail2: + ddi_dma_free_handle(&ma_hdl->h_ma_list_hdl); +marea_fail1: + ddi_dma_free_handle(&ma_hdl->h_ma_dmahdl); +marea_fail0: + kmem_free(ma_hdl, sizeof (*ma_hdl)); + *ma_hdl_p = NULL; + return (ibt_status); } /* @@ -2366,16 +2646,27 @@ hermon_ci_map_mem_area(ibc_hca_hdl_t hca, ibt_va_attr_t *va_attrs, static ibt_status_t hermon_ci_unmap_mem_area(ibc_hca_hdl_t hca, ibc_ma_hdl_t ma_hdl) { - int status = DDI_SUCCESS; + int status; + hermon_state_t *state; if (ma_hdl == NULL) { - return (IBT_MI_HDL_INVALID); + return (IBT_MA_HDL_INVALID); } - - status = hermon_free_dma_cookies(ma_hdl); - if (status != DDI_SUCCESS) { - return (ibc_get_ci_failure(0)); + state = (hermon_state_t *)hca; + if (ma_hdl->h_ma_list_hdl != NULL) { + status = ddi_dma_unbind_handle(ma_hdl->h_ma_list_hdl); + if (status != DDI_SUCCESS) + HERMON_WARNING(state, "failed to unbind DMA mapping"); + ddi_dma_mem_free(&ma_hdl->h_ma_list_acc_hdl); + ddi_dma_free_handle(&ma_hdl->h_ma_list_hdl); + } else { + kmem_free(ma_hdl->h_ma_kaddr, ma_hdl->h_ma_real_len); } + status = ddi_dma_unbind_handle(ma_hdl->h_ma_dmahdl); + if (status != DDI_SUCCESS) + HERMON_WARNING(state, "failed to unbind DMA mapping"); + ddi_dma_free_handle(&ma_hdl->h_ma_dmahdl); + kmem_free(ma_hdl, sizeof (*ma_hdl)); return (IBT_SUCCESS); } @@ -2424,6 +2715,13 @@ hermon_ci_map_mem_iov(ibc_hca_hdl_t hca, ibt_iov_attr_t *iov_attr, state = (hermon_state_t *)hca; hermon_dma_attr_init(state, &dma_attr); +#ifdef __sparc + if (state->hs_cfg_profile->cp_iommu_bypass == HERMON_BINDMEM_BYPASS) + dma_attr.dma_attr_flags = DDI_DMA_FORCE_PHYSICAL; + + if (hermon_kernel_data_ro == HERMON_RO_ENABLED) + dma_attr.dma_attr_flags |= DDI_DMA_RELAXED_ORDERING; +#endif nds = 0; max_nds = iov_attr->iov_wr_nds; @@ -2461,7 +2759,7 @@ hermon_ci_map_mem_iov(ibc_hca_hdl_t hca, ibt_iov_attr_t *iov_attr, return (ibc_get_ci_failure(0)); } while (cookie_cnt-- > 0) { - if (nds >= max_nds) { + if (nds > max_nds) { status = ddi_dma_unbind_handle(dmahdl); if (status != DDI_SUCCESS) HERMON_WARNING(state, "failed to " @@ -2517,7 +2815,7 @@ hermon_ci_map_mem_iov(ibc_hca_hdl_t hca, ibt_iov_attr_t *iov_attr, ibt_status = ibc_get_ci_failure(0); goto fail1; } - if (nds + cookie_cnt >= max_nds) { + if (nds + cookie_cnt > max_nds) { ibt_status = IBT_SGL_TOO_SMALL; goto fail2; } @@ -2594,7 +2892,7 @@ hermon_ci_unmap_mem_iov(ibc_hca_hdl_t hca, ibc_mi_hdl_t mi_hdl) /* ARGSUSED */ static ibt_status_t hermon_ci_alloc_lkey(ibc_hca_hdl_t hca, ibc_pd_hdl_t pd, - ibt_lkey_flags_t flags, uint_t phys_buf_list_sz, ibc_mr_hdl_t *mr_p, + ibt_lkey_flags_t flags, uint_t list_sz, ibc_mr_hdl_t *mr_p, ibt_pmr_desc_t *mem_desc_p) { return (IBT_NOT_SUPPORTED); diff --git a/usr/src/uts/common/io/ib/adapters/hermon/hermon_cq.c b/usr/src/uts/common/io/ib/adapters/hermon/hermon_cq.c index 4f24984712..cab3c11b26 100644 --- a/usr/src/uts/common/io/ib/adapters/hermon/hermon_cq.c +++ b/usr/src/uts/common/io/ib/adapters/hermon/hermon_cq.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1473,6 +1473,11 @@ hermon_cq_errcqe_consume(hermon_state_t *state, hermon_cqhdl_t cq, */ imm_eth_pkey_cred = HERMON_CQE_ERROR_SYNDROME_GET(cq, cqe); status = imm_eth_pkey_cred; + if (status != HERMON_CQE_WR_FLUSHED_ERR) + IBTF_DPRINTF_L2("errcqe", "cqe %p indx %x status 0x%x " + "vendor syndrome %x", cqe, HERMON_CQE_WQECNTR_GET(cq, cqe), + status, ((uint8_t *)cqe)[26]); + switch (status) { case HERMON_CQE_LOC_LEN_ERR: HERMON_FMANOTE(state, HERMON_FMA_LOCLEN); diff --git a/usr/src/uts/common/io/ib/adapters/hermon/hermon_event.c b/usr/src/uts/common/io/ib/adapters/hermon/hermon_event.c index bb09315a16..55a06879dd 100644 --- a/usr/src/uts/common/io/ib/adapters/hermon/hermon_event.c +++ b/usr/src/uts/common/io/ib/adapters/hermon/hermon_event.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1123,6 +1123,7 @@ hermon_eq_demux(hermon_state_t *state, hermon_eqhdl_t eq, case HERMON_EVT_LOCAL_ACC_VIO_WQ_ERROR: HERMON_FMANOTE(state, HERMON_FMA_LOCACEQ); + IBTF_DPRINTF_L2("async", HERMON_FMA_LOCACEQ); status = hermon_local_acc_vio_wq_err_handler(state, eq, eqe); break; case HERMON_EVT_SEND_QUEUE_DRAINED: diff --git a/usr/src/uts/common/io/ib/adapters/hermon/hermon_misc.c b/usr/src/uts/common/io/ib/adapters/hermon/hermon_misc.c index bf24763985..d6be098f5e 100644 --- a/usr/src/uts/common/io/ib/adapters/hermon/hermon_misc.c +++ b/usr/src/uts/common/io/ib/adapters/hermon/hermon_misc.c @@ -47,6 +47,7 @@ #include <sys/ib/adapters/hermon/hermon.h> extern uint32_t hermon_kernel_data_ro; +extern int hermon_rdma_debug; /* used for helping uniquify fmr pool taskq name */ static uint_t hermon_debug_fmrpool_cnt = 0x00000000; @@ -102,6 +103,10 @@ hermon_dbr_new_user_page(hermon_state_t *state, uint_t index, PAGESIZE, B_WRITE, 0, 0, NULL, DDI_UMEM_SLEEP); hermon_dma_attr_init(state, &dma_attr); +#ifdef __sparc + if (state->hs_cfg_profile->cp_iommu_bypass == HERMON_BINDMEM_BYPASS) + dma_attr.dma_attr_flags = DDI_DMA_FORCE_PHYSICAL; +#endif status = ddi_dma_alloc_handle(state->hs_dip, &dma_attr, DDI_DMA_SLEEP, NULL, &pagep->upg_dmahdl); if (status != DDI_SUCCESS) { @@ -287,6 +292,10 @@ hermon_dbr_page_alloc(hermon_state_t *state, hermon_dbr_info_t **dinfo) hermon_dma_attr_init(state, &dma_attr); dma_attr.dma_attr_align = PAGESIZE; dma_attr.dma_attr_sgllen = 1; /* make sure only one cookie */ +#ifdef __sparc + if (state->hs_cfg_profile->cp_iommu_bypass == HERMON_BINDMEM_BYPASS) + dma_attr.dma_attr_flags = DDI_DMA_FORCE_PHYSICAL; +#endif status = ddi_dma_alloc_handle(state->hs_dip, &dma_attr, DDI_DMA_SLEEP, NULL, &dma_hdl); @@ -2395,7 +2404,6 @@ hermon_queue_alloc(hermon_state_t *state, hermon_qalloc_info_t *qa_info, ddi_dma_attr_t dma_attr; int (*callback)(caddr_t); uint64_t realsize, alloc_mask; - uint_t type; int flag, status; _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*qa_info)) @@ -2411,10 +2419,11 @@ hermon_queue_alloc(hermon_state_t *state, hermon_qalloc_info_t *qa_info, */ hermon_dma_attr_init(state, &dma_attr); dma_attr.dma_attr_align = qa_info->qa_bind_align; - type = state->hs_cfg_profile->cp_iommu_bypass; - if (type == HERMON_BINDMEM_BYPASS) { +#ifdef __sparc + if (state->hs_cfg_profile->cp_iommu_bypass == HERMON_BINDMEM_BYPASS) { dma_attr.dma_attr_flags = DDI_DMA_FORCE_PHYSICAL; } +#endif /* Allocate a DMA handle */ status = ddi_dma_alloc_handle(state->hs_dip, &dma_attr, callback, NULL, @@ -2504,7 +2513,7 @@ hermon_queue_alloc(hermon_state_t *state, hermon_qalloc_info_t *qa_info, * passed to the HW */ qa_info->qa_pgoffs = (uint_t)((uintptr_t) - qa_info->qa_buf_aligned & HERMON_PAGEMASK); + qa_info->qa_buf_aligned & HERMON_PAGEOFFSET); return (DDI_SUCCESS); } @@ -2539,7 +2548,7 @@ hermon_queue_free(hermon_qalloc_info_t *qa_info) } /* - * hermon_destroy_fmr_pool() + * hermon_create_fmr_pool() * Create a pool of FMRs. * Context: Can be called from kernel context only. */ @@ -2746,6 +2755,16 @@ hermon_register_physical_fmr(hermon_state_t *state, hermon_fmrhdl_t fmrpool, (void) memcpy(mem_desc_p, &fmr->fmr_desc, sizeof (ibt_pmr_desc_t)); *mr = (hermon_mrhdl_t)fmr->fmr; + _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*(fmr->fmr))) + _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS( + *(fmr->fmr->mr_mptrsrcp))) + if (hermon_rdma_debug & 0x4) + IBTF_DPRINTF_L2("fmr", " reg cache: mr %p " + "index %x", fmr->fmr, + fmr->fmr->mr_mptrsrcp->hr_indx); + _NOTE(NOW_VISIBLE_TO_OTHER_THREADS( + *(fmr->fmr->mr_mptrsrcp))) + _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*(fmr->fmr))) mutex_exit(&fmrpool->fmr_cachelock); mutex_exit(&fmrpool->fmr_lock); return (DDI_SUCCESS); @@ -2757,6 +2776,7 @@ hermon_register_physical_fmr(hermon_state_t *state, hermon_fmrhdl_t fmrpool, /* grab next free entry */ fmr = fmrpool->fmr_free_list; if (fmr == NULL) { + IBTF_DPRINTF_L2("fmr", "WARNING: no free fmr resource"); mutex_exit(&fmrpool->fmr_cachelock); mutex_exit(&fmrpool->fmr_lock); return (IBT_INSUFF_RESOURCE); @@ -2772,6 +2792,11 @@ hermon_register_physical_fmr(hermon_state_t *state, hermon_fmrhdl_t fmrpool, mutex_exit(&fmrpool->fmr_lock); return (status); } + _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*fmr->fmr)) + if (hermon_rdma_debug & 0x4) + IBTF_DPRINTF_L2("fmr", " reg: mr %p key %x", + fmr->fmr, fmr->fmr->mr_rkey); + _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*fmr->fmr)) fmr->fmr_refcnt = 1; fmr->fmr_remaps++; @@ -2828,10 +2853,20 @@ hermon_deregister_fmr(hermon_state_t *state, hermon_mrhdl_t mr) if (fmr->fmr_remaps < state->hs_cfg_profile->cp_fmr_max_remaps) { /* add to free list */ + _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*(fmr->fmr))) + if (hermon_rdma_debug & 0x4) + IBTF_DPRINTF_L2("fmr", "dereg: mr %p key %x", + fmr->fmr, fmr->fmr->mr_rkey); + _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*(fmr->fmr))) fmr->fmr_next = fmrpool->fmr_free_list; fmrpool->fmr_free_list = fmr; } else { /* add to dirty list */ + _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*(fmr->fmr))) + if (hermon_rdma_debug & 0x4) + IBTF_DPRINTF_L2("fmr", "dirty: mr %p key %x", + fmr->fmr, fmr->fmr->mr_rkey); + _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*(fmr->fmr))) fmr->fmr_next = fmrpool->fmr_dirty_list; fmrpool->fmr_dirty_list = fmr; fmrpool->fmr_dirty_len++; @@ -3006,309 +3041,3 @@ hermon_fmr_cache_fini(hermon_fmrhdl_t fmr) /* Destroy the lock used for FMR cache */ mutex_destroy(&fmr->fmr_cachelock); } - -/* - * hermon_get_dma_cookies() - * Return DMA cookies in the pre-allocated paddr_list_p based on the length - * needed. - * Context: Can be called from interrupt or base context. - */ -int -hermon_get_dma_cookies(hermon_state_t *state, ibt_phys_buf_t *paddr_list_p, - ibt_va_attr_t *va_attrs, uint_t list_len, uint_t *cookiecnt, - ibc_ma_hdl_t *ibc_ma_hdl_p) -{ - ddi_dma_handle_t dma_hdl; - ddi_dma_attr_t dma_attr; - ddi_dma_cookie_t dmacookie; - int (*callback)(caddr_t); - int status; - int i; - - /* Set the callback flag appropriately */ - callback = (va_attrs->va_flags & IBT_VA_NOSLEEP) ? DDI_DMA_DONTWAIT : - DDI_DMA_SLEEP; - if ((callback == DDI_DMA_SLEEP) && - (HERMON_SLEEP != HERMON_SLEEPFLAG_FOR_CONTEXT())) { - return (IBT_INVALID_PARAM); - } - - /* - * Initialize many of the default DMA attributes and allocate the DMA - * handle. Then, if we're bypassing the IOMMU, set the - * DDI_DMA_FORCE_PHYSICAL flag. - */ - hermon_dma_attr_init(state, &dma_attr); - -#ifdef __x86 - /* - * On x86 we can specify a maximum segment length for our returned - * cookies. - */ - if (va_attrs->va_flags & IBT_VA_FMR) { - dma_attr.dma_attr_seg = PAGESIZE - 1; - } -#endif - - /* - * Check to see if the RO flag is set, and if so, - * set that bit in the attr structure as well. - * - * NOTE 1: This function is ONLY called by consumers, and only for - * data buffers - */ - if (hermon_kernel_data_ro == HERMON_RO_ENABLED) { - dma_attr.dma_attr_flags |= DDI_DMA_RELAXED_ORDERING; - } - - status = ddi_dma_alloc_handle(state->hs_dip, &dma_attr, - callback, NULL, &dma_hdl); - if (status != DDI_SUCCESS) { - switch (status) { - case DDI_DMA_NORESOURCES: - return (IBT_INSUFF_RESOURCE); - case DDI_DMA_BADATTR: - default: - return (ibc_get_ci_failure(0)); - } - } - - /* - * Now bind the handle with the correct DMA attributes. - */ - if (va_attrs->va_flags & IBT_VA_BUF) { - status = ddi_dma_buf_bind_handle(dma_hdl, va_attrs->va_buf, - DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, - NULL, &dmacookie, cookiecnt); - } else { - status = ddi_dma_addr_bind_handle(dma_hdl, NULL, - (caddr_t)(uintptr_t)va_attrs->va_vaddr, va_attrs->va_len, - DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, - NULL, &dmacookie, cookiecnt); - } - if (status != DDI_SUCCESS) { - ddi_dma_free_handle(&dma_hdl); - - switch (status) { - case DDI_DMA_NORESOURCES: - return (IBT_INSUFF_RESOURCE); - case DDI_DMA_TOOBIG: - return (IBT_INVALID_PARAM); - case DDI_DMA_PARTIAL_MAP: - case DDI_DMA_INUSE: - case DDI_DMA_NOMAPPING: - default: - return (ibc_get_ci_failure(0)); - } - } - - /* - * Verify our physical buffer list (PBL) is large enough to handle the - * number of cookies that were returned. - */ - if (*cookiecnt > list_len) { - (void) ddi_dma_unbind_handle(dma_hdl); - ddi_dma_free_handle(&dma_hdl); - return (IBT_PBL_TOO_SMALL); - } - - /* - * We store the cookies returned by the DDI into our own PBL. This - * sets the cookies up for later processing (for example, if we want to - * split up the cookies into smaller chunks). We use the laddr and - * size fields in each cookie to create each individual entry (PBE). - */ - - /* - * Store first cookie info first - */ - paddr_list_p[0].p_laddr = dmacookie.dmac_laddress; - paddr_list_p[0].p_size = dmacookie.dmac_size; - - /* - * Loop through each cookie, storing each cookie into our physical - * buffer list. - */ - for (i = 1; i < *cookiecnt; i++) { - ddi_dma_nextcookie(dma_hdl, &dmacookie); - - paddr_list_p[i].p_laddr = dmacookie.dmac_laddress; - paddr_list_p[i].p_size = dmacookie.dmac_size; - } - - /* return handle */ - *ibc_ma_hdl_p = (ibc_ma_hdl_t)dma_hdl; - return (DDI_SUCCESS); -} - -/* - * hermon_split_dma_cookies() - * Split up cookies passed in from paddr_list_p, returning the new list in the - * same buffers, based on the pagesize to split the cookies into. - * Context: Can be called from interrupt or base context. - */ -/* ARGSUSED */ -int -hermon_split_dma_cookies(hermon_state_t *state, ibt_phys_buf_t *paddr_list, - ib_memlen_t *paddr_offset, uint_t list_len, uint_t *cookiecnt, - uint_t pagesize) -{ - uint64_t pageoffset; - uint64_t pagemask; - uint_t pageshift; - uint_t current_cookiecnt; - uint_t cookies_needed; - uint64_t last_size, extra_cookie; - int i_increment; - int i, k; - int status; - - /* Setup pagesize calculations */ - pageoffset = pagesize - 1; - pagemask = (~pageoffset); - pageshift = highbit(pagesize) - 1; - - /* - * Setup first cookie offset based on pagesize requested. - */ - *paddr_offset = paddr_list[0].p_laddr & pageoffset; - paddr_list[0].p_laddr &= pagemask; - - /* Save away the current number of cookies that are passed in */ - current_cookiecnt = *cookiecnt; - - /* Perform splitting up of current cookies into pagesize blocks */ - for (i = 0; i < current_cookiecnt; i += i_increment) { - /* - * If the cookie is smaller than pagesize, or already is - * pagesize, then we are already within our limits, so we skip - * it. - */ - if (paddr_list[i].p_size <= pagesize) { - i_increment = 1; - continue; - } - - /* - * If this is our first cookie, then we have to deal with the - * offset that may be present in the first address. So add - * that to our size, to calculate potential change to the last - * cookie's size. - * - * Also, calculate the number of cookies that we'll need to - * split up this block into. - */ - if (i == 0) { - last_size = (paddr_list[i].p_size + *paddr_offset) & - pageoffset; - cookies_needed = (paddr_list[i].p_size + - *paddr_offset) >> pageshift; - } else { - last_size = 0; - cookies_needed = paddr_list[i].p_size >> pageshift; - } - - /* - * If our size is not a multiple of pagesize, we need one more - * cookie. - */ - if (last_size) { - extra_cookie = 1; - } else { - extra_cookie = 0; - } - - /* - * Split cookie into pagesize chunks, shifting list of cookies - * down, using more cookie slots in the PBL if necessary. - */ - status = hermon_dma_cookie_shift(paddr_list, i, list_len, - current_cookiecnt - i, cookies_needed + extra_cookie); - if (status != 0) { - return (status); - } - - /* - * If the very first cookie, we must take possible offset into - * account. - */ - if (i == 0) { - paddr_list[i].p_size = pagesize - *paddr_offset; - } else { - paddr_list[i].p_size = pagesize; - } - - /* - * We have shifted the existing cookies down the PBL, now fill - * in the blank entries by splitting up our current block. - */ - for (k = 1; k < cookies_needed; k++) { - paddr_list[i + k].p_laddr = - paddr_list[i + k - 1].p_laddr + pagesize; - paddr_list[i + k].p_size = pagesize; - } - - /* If we have one extra cookie (of less than pagesize...) */ - if (extra_cookie) { - paddr_list[i + k].p_laddr = - paddr_list[i + k - 1].p_laddr + pagesize; - paddr_list[i + k].p_size = (size_t)last_size; - } - - /* Increment cookiecnt appropriately based on cookies used */ - i_increment = cookies_needed + extra_cookie; - current_cookiecnt += i_increment - 1; - } - - /* Update to new cookie count */ - *cookiecnt = current_cookiecnt; - return (DDI_SUCCESS); -} - -/* - * hermon_dma_cookie_shift() - * Context: Can be called from interrupt or base context. - */ -int -hermon_dma_cookie_shift(ibt_phys_buf_t *paddr_list, int start, int end, - int cookiecnt, int num_shift) -{ - int shift_start; - int i; - - /* Calculating starting point in the PBL list */ - shift_start = start + cookiecnt - 1; - - /* Check if we're at the end of our PBL list */ - if ((shift_start + num_shift - 1) >= end) { - return (IBT_PBL_TOO_SMALL); - } - - for (i = shift_start; i > start; i--) { - paddr_list[i + num_shift - 1] = paddr_list[i]; - } - - return (DDI_SUCCESS); -} - - -/* - * hermon_free_dma_cookies() - * Context: Can be called from interrupt or base context. - */ -int -hermon_free_dma_cookies(ibc_ma_hdl_t ma_hdl) -{ - ddi_dma_handle_t dma_hdl; - int status; - - dma_hdl = (ddi_dma_handle_t)ma_hdl; - - status = ddi_dma_unbind_handle(dma_hdl); - if (status != DDI_SUCCESS) { - return (ibc_get_ci_failure(0)); - } - ddi_dma_free_handle(&dma_hdl); - - return (DDI_SUCCESS); -} diff --git a/usr/src/uts/common/io/ib/adapters/hermon/hermon_mr.c b/usr/src/uts/common/io/ib/adapters/hermon/hermon_mr.c index 7b136ed470..409d9176d6 100644 --- a/usr/src/uts/common/io/ib/adapters/hermon/hermon_mr.c +++ b/usr/src/uts/common/io/ib/adapters/hermon/hermon_mr.c @@ -47,14 +47,18 @@ extern uint32_t hermon_kernel_data_ro; extern uint32_t hermon_user_data_ro; +extern int hermon_rdma_debug; /* * Used by hermon_mr_keycalc() below to fill in the "unconstrained" portion * of Hermon memory keys (LKeys and RKeys) */ static uint_t hermon_memkey_cnt = 0x00; -#define HERMON_MEMKEY_SHIFT 24 -#define HERMON_MPT_SW_OWNERSHIP 0xF +#define HERMON_MEMKEY_SHIFT 24 + +/* initial state of an MPT */ +#define HERMON_MPT_SW_OWNERSHIP 0xF /* memory regions */ +#define HERMON_MPT_FREE 0x3 /* allocate lkey */ static int hermon_mr_common_reg(hermon_state_t *state, hermon_pdhdl_t pd, hermon_bind_info_t *bind, hermon_mrhdl_t *mrhdl, hermon_mr_options_t *op, @@ -73,8 +77,8 @@ static void hermon_mr_mem_unbind(hermon_state_t *state, hermon_bind_info_t *bind); static int hermon_mr_fast_mtt_write(hermon_state_t *state, hermon_rsrc_t *mtt, hermon_bind_info_t *bind, uint32_t mtt_pgsize_bits); -static int hermon_mr_fast_mtt_write_fmr(hermon_rsrc_t *mtt, - ibt_pmr_attr_t *mem_pattr, uint32_t mtt_pgsize_bits); +static int hermon_mr_fast_mtt_write_fmr(hermon_state_t *state, + hermon_rsrc_t *mtt, ibt_pmr_attr_t *mem_pattr, uint32_t mtt_pgsize_bits); static uint_t hermon_mtt_refcnt_inc(hermon_rsrc_t *rsrc); static uint_t hermon_mtt_refcnt_dec(hermon_rsrc_t *rsrc); @@ -252,12 +256,7 @@ hermon_mr_register_shared(hermon_state_t *state, hermon_mrhdl_t mrhdl, * if no remote access is required, then the RKey value is not filled * in. Otherwise both Rkey and LKey are given the same value. */ - mr->mr_lkey = hermon_mr_keycalc(mpt->hr_indx); - if ((mr->mr_accflag & IBT_MR_REMOTE_READ) || - (mr->mr_accflag & IBT_MR_REMOTE_WRITE) || - (mr->mr_accflag & IBT_MR_REMOTE_ATOMIC)) { - mr->mr_rkey = mr->mr_lkey; - } + mr->mr_rkey = mr->mr_lkey = hermon_mr_keycalc(mpt->hr_indx); /* Grab the MR lock for the current memory region */ mutex_enter(&mrhdl->mr_lock); @@ -446,13 +445,17 @@ hermon_mr_alloc_fmr(hermon_state_t *state, hermon_pdhdl_t pd, hermon_fmrhdl_t fmr_pool, hermon_mrhdl_t *mrhdl) { hermon_rsrc_t *mpt, *mtt, *rsrc; - hermon_hw_dmpt_t mpt_entry; + hermon_hw_dmpt_t mpt_entry; hermon_mrhdl_t mr; hermon_bind_info_t bind; uint64_t mtt_addr; uint64_t nummtt; uint_t sleep, mtt_pgsize_bits; int status; + offset_t i; + hermon_icm_table_t *icm_table; + hermon_dma_info_t *dma_info; + uint32_t index1, index2, rindx; /* * Check the sleep flag. Ensure that it is consistent with the @@ -521,12 +524,8 @@ hermon_mr_alloc_fmr(hermon_state_t *state, hermon_pdhdl_t pd, * if no remote access is required, then the RKey value is not filled * in. Otherwise both Rkey and LKey are given the same value. */ - mr->mr_lkey = hermon_mr_keycalc(mpt->hr_indx); - if ((mr->mr_accflag & IBT_MR_REMOTE_READ) || - (mr->mr_accflag & IBT_MR_REMOTE_WRITE) || - (mr->mr_accflag & IBT_MR_REMOTE_ATOMIC)) { - mr->mr_rkey = mr->mr_lkey; - } + mr->mr_fmr_key = 1; /* ready for the next reload */ + mr->mr_rkey = mr->mr_lkey = mpt->hr_indx; /* * Determine number of pages spanned. This routine uses the @@ -571,6 +570,8 @@ hermon_mr_alloc_fmr(hermon_state_t *state, hermon_pdhdl_t pd, mpt_entry.entity_sz = mr->mr_logmttpgsz; mtt_addr = (mtt->hr_indx << HERMON_MTT_SIZE_SHIFT); + mpt_entry.fast_reg_en = 1; + mpt_entry.mtt_size = (uint_t)nummtt; mpt_entry.mtt_addr_h = mtt_addr >> 32; mpt_entry.mtt_addr_l = mtt_addr >> 3; mpt_entry.mem_key = mr->mr_lkey; @@ -608,14 +609,24 @@ hermon_mr_alloc_fmr(hermon_state_t *state, hermon_pdhdl_t pd, */ mr->mr_mptrsrcp = mpt; mr->mr_mttrsrcp = mtt; + mr->mr_mpt_type = HERMON_MPT_DMPT; mr->mr_pdhdl = pd; mr->mr_rsrcp = rsrc; mr->mr_is_fmr = 1; mr->mr_lkey = hermon_mr_key_swap(mr->mr_lkey); mr->mr_rkey = hermon_mr_key_swap(mr->mr_rkey); + mr->mr_mttaddr = mtt_addr; (void) memcpy(&mr->mr_bindinfo, &bind, sizeof (hermon_bind_info_t)); + /* initialize hr_addr for use during register/deregister/invalidate */ + icm_table = &state->hs_icm[HERMON_DMPT]; + rindx = mpt->hr_indx; + hermon_index(index1, index2, rindx, icm_table, i); + dma_info = icm_table->icm_dma[index1] + index2; + _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mpt)) + mpt->hr_addr = (void *)((uintptr_t)(dma_info->vaddr + i * mpt->hr_len)); + *mrhdl = mr; return (DDI_SUCCESS); @@ -635,6 +646,7 @@ fmralloc_fail: return (status); } + /* * hermon_mr_register_physical_fmr() * Context: Can be called from interrupt or base context. @@ -647,21 +659,24 @@ hermon_mr_register_physical_fmr(hermon_state_t *state, hermon_rsrc_t *mpt; uint64_t *mpt_table; int status; + uint32_t key; mutex_enter(&mr->mr_lock); mpt = mr->mr_mptrsrcp; mpt_table = (uint64_t *)mpt->hr_addr; /* Write MPT status to SW bit */ - ddi_put8(mpt->hr_acchdl, (uint8_t *)&mpt_table[0], 0xF); + *(uint8_t *)mpt_table = 0xF0; + + membar_producer(); /* * Write the mapped addresses into the MTT entries. FMR needs to do * this a little differently, so we call the fmr specific fast mtt * write here. */ - status = hermon_mr_fast_mtt_write_fmr(mr->mr_mttrsrcp, mem_pattr_p, - mr->mr_logmttpgsz); + status = hermon_mr_fast_mtt_write_fmr(state, mr->mr_mttrsrcp, + mem_pattr_p, mr->mr_logmttpgsz); if (status != DDI_SUCCESS) { mutex_exit(&mr->mr_lock); status = ibc_get_ci_failure(0); @@ -677,27 +692,25 @@ hermon_mr_register_physical_fmr(hermon_state_t *state, * if no remote access is required, then the RKey value is not filled * in. Otherwise both Rkey and LKey are given the same value. */ - mr->mr_lkey = hermon_mr_keycalc(mpt->hr_indx); - if ((mr->mr_accflag & IBT_MR_REMOTE_READ) || - (mr->mr_accflag & IBT_MR_REMOTE_WRITE) || - (mr->mr_accflag & IBT_MR_REMOTE_ATOMIC)) { - mr->mr_rkey = mr->mr_lkey; - } + key = mpt->hr_indx | (mr->mr_fmr_key++ << HERMON_MEMKEY_SHIFT); + mr->mr_lkey = mr->mr_rkey = hermon_mr_key_swap(key); /* write mem key value */ - ddi_put32(mpt->hr_acchdl, (uint32_t *)&mpt_table[1], mr->mr_lkey); + *(uint32_t *)&mpt_table[1] = htonl(key); /* write length value */ - ddi_put64(mpt->hr_acchdl, &mpt_table[3], mem_pattr_p->pmr_len); + mpt_table[3] = htonll(mem_pattr_p->pmr_len); /* write start addr value */ - ddi_put64(mpt->hr_acchdl, &mpt_table[2], mem_pattr_p->pmr_iova); + mpt_table[2] = htonll(mem_pattr_p->pmr_iova); /* write lkey value */ - ddi_put32(mpt->hr_acchdl, (uint32_t *)&mpt_table[4], mr->mr_lkey); + *(uint32_t *)&mpt_table[4] = htonl(key); + + membar_producer(); /* Write MPT status to HW bit */ - ddi_put8(mpt->hr_acchdl, (uint8_t *)&mpt_table[0], 0x0); + *(uint8_t *)mpt_table = 0x00; /* Fill in return parameters */ mem_desc_p->pmd_lkey = mr->mr_lkey; @@ -719,7 +732,7 @@ fmr_reg_fail1: * software. The memory tables may be corrupt, so we leave the region * unregistered. */ - return (DDI_FAILURE); + return (status); } @@ -784,6 +797,9 @@ hermon_mr_deregister(hermon_state_t *state, hermon_mrhdl_t *mrhdl, uint_t level, if ((mr->mr_is_umem) && (mr->mr_umemcookie == NULL)) { goto mrdereg_finish_cleanup; } + if (hermon_rdma_debug & 0x4) + IBTF_DPRINTF_L2("mr", "dereg: mr %p key %x", + mr, mr->mr_rkey); /* * We must drop the "mr_lock" here to ensure that both SLEEP and @@ -972,16 +988,20 @@ hermon_mr_invalidate_fmr(hermon_state_t *state, hermon_mrhdl_t mr) mpt_table = (uint64_t *)mpt->hr_addr; /* Write MPT status to SW bit */ - ddi_put8(mpt->hr_acchdl, (uint8_t *)&mpt_table[0], 0xF); + *(uint8_t *)&mpt_table[0] = 0xF0; + + membar_producer(); /* invalidate mem key value */ - ddi_put32(mpt->hr_acchdl, (uint32_t *)&mpt_table[1], 0); + *(uint32_t *)&mpt_table[1] = 0; /* invalidate lkey value */ - ddi_put32(mpt->hr_acchdl, (uint32_t *)&mpt_table[4], 0); + *(uint32_t *)&mpt_table[4] = 0; + + membar_producer(); /* Write MPT status to HW bit */ - ddi_put8(mpt->hr_acchdl, (uint8_t *)&mpt_table[0], 0x0); + *(uint8_t *)&mpt_table[0] = 0x00; mutex_exit(&mr->mr_lock); @@ -1004,7 +1024,8 @@ hermon_mr_deregister_fmr(hermon_state_t *state, hermon_mrhdl_t mr) mpt_table = (uint64_t *)mpt->hr_addr; /* Write MPT status to SW bit */ - ddi_put8(mpt->hr_acchdl, (uint8_t *)&mpt_table[0], 0xF); + *(uint8_t *)&mpt_table[0] = 0xF0; + mutex_exit(&mr->mr_lock); return (DDI_SUCCESS); @@ -1020,6 +1041,10 @@ int hermon_mr_query(hermon_state_t *state, hermon_mrhdl_t mr, ibt_mr_query_attr_t *attr) { + int status; + hermon_hw_dmpt_t mpt_entry; + uint32_t lkey; + _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*attr)) mutex_enter(&mr->mr_lock); @@ -1034,9 +1059,38 @@ hermon_mr_query(hermon_state_t *state, hermon_mrhdl_t mr, return (IBT_MR_HDL_INVALID); } + status = hermon_cmn_query_cmd_post(state, QUERY_MPT, 0, + mr->mr_lkey >> 8, &mpt_entry, sizeof (hermon_hw_dmpt_t), + HERMON_NOSLEEP); + if (status != HERMON_CMD_SUCCESS) { + cmn_err(CE_CONT, "Hermon: QUERY_MPT failed: status %x", status); + mutex_exit(&mr->mr_lock); + return (ibc_get_ci_failure(0)); + } + + /* Update the mr sw struct from the hw struct. */ + lkey = mpt_entry.mem_key; + mr->mr_lkey = mr->mr_rkey = (lkey >> 8) | (lkey << 24); + mr->mr_bindinfo.bi_addr = mpt_entry.start_addr; + mr->mr_bindinfo.bi_len = mpt_entry.reg_win_len; + mr->mr_accflag = (mr->mr_accflag & IBT_MR_RO_DISABLED) | + (mpt_entry.lw ? IBT_MR_LOCAL_WRITE : 0) | + (mpt_entry.rr ? IBT_MR_REMOTE_READ : 0) | + (mpt_entry.rw ? IBT_MR_REMOTE_WRITE : 0) | + (mpt_entry.atomic ? IBT_MR_REMOTE_ATOMIC : 0) | + (mpt_entry.en_bind ? IBT_MR_WINDOW_BIND : 0); + mr->mr_mttaddr = ((uint64_t)mpt_entry.mtt_addr_h << 32) | + (mpt_entry.mtt_addr_l << 3); + mr->mr_logmttpgsz = mpt_entry.entity_sz; + /* Fill in the queried attributes */ + attr->mr_lkey_state = + (mpt_entry.status == HERMON_MPT_FREE) ? IBT_KEY_FREE : + (mpt_entry.status == HERMON_MPT_SW_OWNERSHIP) ? IBT_KEY_INVALID : + IBT_KEY_VALID; + attr->mr_phys_buf_list_sz = mpt_entry.mtt_size; attr->mr_attr_flags = mr->mr_accflag; - attr->mr_pd = (ibt_pd_hdl_t)mr->mr_pdhdl; + attr->mr_pd = (ibt_pd_hdl_t)mr->mr_pdhdl; /* Fill in the "local" attributes */ attr->mr_lkey = (ibt_lkey_t)mr->mr_lkey; @@ -1591,13 +1645,7 @@ hermon_mr_common_reg(hermon_state_t *state, hermon_pdhdl_t pd, * in. Otherwise both Rkey and LKey are given the same value. */ if (mpt) - mr->mr_lkey = hermon_mr_keycalc(mpt->hr_indx); - - if ((mr->mr_accflag & IBT_MR_REMOTE_READ) || - (mr->mr_accflag & IBT_MR_REMOTE_WRITE) || - (mr->mr_accflag & IBT_MR_REMOTE_ATOMIC)) { - mr->mr_rkey = mr->mr_lkey; - } + mr->mr_rkey = mr->mr_lkey = hermon_mr_keycalc(mpt->hr_indx); /* * Determine if the memory is from userland and pin the pages @@ -1750,6 +1798,9 @@ hermon_mr_common_reg(hermon_state_t *state, hermon_pdhdl_t pd, status = ibc_get_ci_failure(0); goto mrcommon_fail7; } + if (hermon_rdma_debug & 0x4) + IBTF_DPRINTF_L2("mr", " reg: mr %p key %x", + mr, hermon_mr_key_swap(mr->mr_rkey)); no_passown: /* @@ -2919,64 +2970,36 @@ hermon_mr_fast_mtt_write(hermon_state_t *state, hermon_rsrc_t *mtt, * hermon_mr_fast_mtt_write_fmr() * Context: Can be called from interrupt or base context. */ +/* ARGSUSED */ static int -hermon_mr_fast_mtt_write_fmr(hermon_rsrc_t *mtt, ibt_pmr_attr_t *mem_pattr, - uint32_t mtt_pgsize_bits) +hermon_mr_fast_mtt_write_fmr(hermon_state_t *state, hermon_rsrc_t *mtt, + ibt_pmr_attr_t *mem_pattr, uint32_t mtt_pgsize_bits) { + hermon_icm_table_t *icm_table; + hermon_dma_info_t *dma_info; + uint32_t index1, index2, rindx; uint64_t *mtt_table; - ibt_phys_addr_t *buf; - uint64_t mtt_entry; - uint64_t addr, first_addr, endaddr; - uint64_t pagesize; - int i; + offset_t i, j; + uint_t per_span; - /* Calculate page size from the suggested value passed in */ - pagesize = ((uint64_t)1 << mtt_pgsize_bits); + icm_table = &state->hs_icm[HERMON_MTT]; + rindx = mtt->hr_indx; + hermon_index(index1, index2, rindx, icm_table, i); + per_span = icm_table->span; + dma_info = icm_table->icm_dma[index1] + index2; + mtt_table = (uint64_t *)(uintptr_t)dma_info->vaddr; /* - * Walk the "addr list" and fill in the MTT table entries + * Fill in the MTT table entries */ - mtt_table = (uint64_t *)mtt->hr_addr; - for (i = 0; i < mem_pattr->pmr_num_buf; i++) { - buf = &mem_pattr->pmr_addr_list[i]; - - /* - * For first cookie, use the offset field to determine where - * the buffer starts. The end addr is then calculated with the - * offset in mind. - */ - if (i == 0) { - first_addr = addr = buf->p_laddr + - mem_pattr->pmr_offset; - endaddr = addr + (mem_pattr->pmr_buf_sz - 1) - - mem_pattr->pmr_offset; - /* - * For last cookie, determine end addr based on starting - * address and size of the total buffer - */ - } else if (i == mem_pattr->pmr_num_buf - 1) { - addr = buf->p_laddr; - endaddr = addr + (first_addr + mem_pattr->pmr_len & - (mem_pattr->pmr_buf_sz - 1)); - /* - * For the middle cookies case, start and end addr are - * straightforward. Just use the laddr, and the size, as all - * middle cookies are a set size. - */ - } else { - addr = buf->p_laddr; - endaddr = addr + (mem_pattr->pmr_buf_sz - 1); - } - - addr = addr & ~((uint64_t)pagesize - 1); - while (addr <= endaddr) { - /* - * Fill in the mapped addresses (calculated above) and - * set HERMON_MTT_ENTRY_PRESENT flag for each MTT entry. - */ - mtt_entry = addr | HERMON_MTT_ENTRY_PRESENT; - mtt_table[i] = htonll(mtt_entry); - addr += pagesize; + for (j = 0; j < mem_pattr->pmr_num_buf; j++) { + mtt_table[i] = mem_pattr->pmr_addr_list[j].p_laddr; + i++; + rindx++; + if (i == per_span) { + hermon_index(index1, index2, rindx, icm_table, i); + dma_info = icm_table->icm_dma[index1] + index2; + mtt_table = (uint64_t *)(uintptr_t)dma_info->vaddr; } } diff --git a/usr/src/uts/common/io/ib/adapters/hermon/hermon_rsrc.c b/usr/src/uts/common/io/ib/adapters/hermon/hermon_rsrc.c index 45d10850c8..53ff4cba38 100644 --- a/usr/src/uts/common/io/ib/adapters/hermon/hermon_rsrc.c +++ b/usr/src/uts/common/io/ib/adapters/hermon/hermon_rsrc.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -212,6 +212,11 @@ hermon_rsrc_alloc(hermon_state_t *state, hermon_rsrc_type_t rsrc, uint_t num, break; case HERMON_QPC: + /* Allocate "num" contiguous/aligned QPCs for RSS */ + status = hermon_rsrc_hw_entry_alloc(rsrc_pool, num, num, + 0, sleepflag, tmp_rsrc_hdl); + break; + case HERMON_CQC: case HERMON_SRQC: case HERMON_EQC: @@ -942,8 +947,6 @@ hermon_rsrc_init_phase2(hermon_state_t *state) case HERMON_SRQHDL: state->hs_srqhdl = hdl_info.swi_table_ptr; break; - case HERMON_MRHDL: - break; default: break; } @@ -1386,8 +1389,9 @@ hermon_rsrc_hw_entries_init(hermon_state_t *state, /* Set this pool's rsrc_start from the initial ICM allocation */ if (rsrc_pool->rsrc_start == 0) { - rsrc_pool->rsrc_start = (void *)(uintptr_t) - state->hs_icm[rsrc_pool->rsrc_type].icm_dma[0][0].vaddr; + + /* use a ROUND value that works on both 32 and 64-bit kernels */ + rsrc_pool->rsrc_start = (void *)(uintptr_t)0x10000000; if (hermon_rsrc_verbose) { IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entries_init:" @@ -1749,6 +1753,7 @@ hermon_rsrc_hw_entry_alloc(hermon_rsrc_pool_info_t *pool_info, uint_t num, if (status != DDI_SUCCESS) { return (DDI_FAILURE); } + hdl->hr_addr = NULL; } return (DDI_SUCCESS); diff --git a/usr/src/uts/common/io/ib/adapters/hermon/hermon_srq.c b/usr/src/uts/common/io/ib/adapters/hermon/hermon_srq.c index 0ea6d9ea48..596cd2e31b 100644 --- a/usr/src/uts/common/io/ib/adapters/hermon/hermon_srq.c +++ b/usr/src/uts/common/io/ib/adapters/hermon/hermon_srq.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -718,7 +718,7 @@ hermon_srq_modify(hermon_state_t *state, hermon_srqhdl_t srq, uint_t size, srq_desc_off = (uint64_t)(uintptr_t)new_srqinfo.qa_buf_aligned - (uint64_t)bind.bi_addr; srq_pgoffs = (uint_t) - ((uintptr_t)new_srqinfo.qa_buf_aligned & HERMON_PAGEMASK); + ((uintptr_t)new_srqinfo.qa_buf_aligned & HERMON_PAGEOFFSET); /* * Fill in the MPT entry. This is the final step before passing diff --git a/usr/src/uts/common/io/ib/adapters/hermon/hermon_wr.c b/usr/src/uts/common/io/ib/adapters/hermon/hermon_wr.c index 7dadb76b41..010becef26 100644 --- a/usr/src/uts/common/io/ib/adapters/hermon/hermon_wr.c +++ b/usr/src/uts/common/io/ib/adapters/hermon/hermon_wr.c @@ -63,6 +63,15 @@ static void hermon_cq_workq_remove(hermon_cqhdl_t cq, static ibt_wr_ds_t null_sgl = { 0, 0x00000100, 0 }; +/* + * Add ability to try to debug RDMA_READ/RDMA_WRITE failures. + * + * 0x1 - print rkey used during post_send + * 0x2 - print sgls used during post_send + * 0x4 - print FMR comings and goings + */ +int hermon_rdma_debug = 0x0; + static int hermon_post_send_ud(hermon_state_t *state, hermon_qphdl_t qp, ibt_send_wr_t *wr, uint_t num_wr, uint_t *num_posted) @@ -310,6 +319,10 @@ hermon_post_send_rc(hermon_state_t *state, hermon_qphdl_t qp, uint32_t *wqe_start; int sectperwqe; uint_t posted_cnt = 0; + int print_rdma; + int rlen; + uint32_t rkey; + uint64_t raddr; /* initialize the FMA retry loop */ hermon_pio_init(fm_loop_cnt, fm_status, fm_test_num); @@ -317,9 +330,6 @@ hermon_post_send_rc(hermon_state_t *state, hermon_qphdl_t qp, ASSERT(MUTEX_HELD(&qp->qp_sq_lock)); _NOTE(LOCK_RELEASED_AS_SIDE_EFFECT(&qp->qp_sq_lock)) - /* make sure we see any update of wq_head */ - membar_consumer(); - /* Save away some initial QP state */ wq = qp->qp_sq_wqhdr; qsize_msk = wq->wq_mask; @@ -331,6 +341,9 @@ hermon_post_send_rc(hermon_state_t *state, hermon_qphdl_t qp, status = DDI_SUCCESS; post_next: + print_rdma = 0; + rlen = 0; + /* * Check for "queue full" condition. If the queue * is already full, then no more WQEs can be posted. @@ -397,6 +410,12 @@ post_next: */ HERMON_WQE_BUILD_REMADDR(qp, rc, &wr->wr.rc.rcwr.rdma); + if (hermon_rdma_debug) { + print_rdma = hermon_rdma_debug; + rkey = wr->wr.rc.rcwr.rdma.rdma_rkey; + raddr = wr->wr.rc.rcwr.rdma.rdma_raddr; + } + /* Update "ds" for filling in Data Segments (below) */ ds = (hermon_hw_wqe_sgl_t *)((uintptr_t)rc + sizeof (hermon_hw_snd_wqe_remaddr_t)); @@ -490,6 +509,10 @@ post_next: if (sgl[i].ds_len == 0) { continue; } + rlen += sgl[i].ds_len; + if (print_rdma & 0x2) + IBTF_DPRINTF_L2("rdma", "post: [%d]: laddr %llx " + "llen %x", i, sgl[i].ds_va, sgl[i].ds_len); /* * Fill in the Data Segment(s) for the current WQE, using the @@ -500,6 +523,11 @@ post_next: HERMON_WQE_BUILD_DATA_SEG_SEND(&ds[last_ds], &sgl[i]); } + if (print_rdma & 0x1) { + IBTF_DPRINTF_L2("rdma", "post: indx %x rkey %x raddr %llx " + "total len %x", tail, rkey, raddr, rlen); + } + fence = (wr->wr_flags & IBT_WR_SEND_FENCE) ? 1 : 0; signaled_dbd = ((qp->qp_sq_sigtype == HERMON_QP_SQ_ALL_SIGNALED) || @@ -634,11 +662,21 @@ hermon_post_send(hermon_state_t *state, hermon_qphdl_t qp, goto post_many; /* Use these optimized functions most of the time */ - if (qp->qp_serv_type == HERMON_QP_UD) + if (qp->qp_serv_type == HERMON_QP_UD) { + if (wr->wr_trans != IBT_UD_SRV) { + mutex_exit(&qp->qp_sq_lock); + return (IBT_QP_SRV_TYPE_INVALID); + } return (hermon_post_send_ud(state, qp, wr, num_wr, num_posted)); + } - if (qp->qp_serv_type == HERMON_QP_RC) + if (qp->qp_serv_type == HERMON_QP_RC) { + if (wr->wr_trans != IBT_RC_SRV) { + mutex_exit(&qp->qp_sq_lock); + return (IBT_QP_SRV_TYPE_INVALID); + } return (hermon_post_send_rc(state, qp, wr, num_wr, num_posted)); + } if (qp->qp_serv_type == HERMON_QP_UC) goto post_many; @@ -649,9 +687,6 @@ hermon_post_send(hermon_state_t *state, hermon_qphdl_t qp, post_many: /* general loop for non-optimized posting */ - /* Grab the lock for the WRID list */ - membar_consumer(); - /* Save away some initial QP state */ wq = qp->qp_sq_wqhdr; qsize_msk = wq->wq_mask; diff --git a/usr/src/uts/common/io/ib/adapters/tavor/tavor.c b/usr/src/uts/common/io/ib/adapters/tavor/tavor.c index 9c29ddb581..51b15cbb1c 100644 --- a/usr/src/uts/common/io/ib/adapters/tavor/tavor.c +++ b/usr/src/uts/common/io/ib/adapters/tavor/tavor.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1852,9 +1852,6 @@ tavor_soft_state_init(tavor_state_t *state) if (state->ts_cfg_profile->cp_srq_enable) { caps |= IBT_HCA_SRQ | IBT_HCA_RESIZE_SRQ; } - if (state->ts_cfg_profile->cp_fmr_enable) { - caps |= IBT_HCA_FMR; - } caps |= (IBT_HCA_AH_PORT_CHECK | IBT_HCA_SQD_SQD_PORT | IBT_HCA_SI_GUID | IBT_HCA_RNR_NAK | IBT_HCA_CURRENT_QP_STATE | IBT_HCA_PORT_UP | IBT_HCA_SQD_STATE); diff --git a/usr/src/uts/common/io/ib/adapters/tavor/tavor_cfg.c b/usr/src/uts/common/io/ib/adapters/tavor/tavor_cfg.c index fcc5a14c50..35735ebc8b 100644 --- a/usr/src/uts/common/io/ib/adapters/tavor/tavor_cfg.c +++ b/usr/src/uts/common/io/ib/adapters/tavor/tavor_cfg.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -58,9 +58,6 @@ uint32_t tavor_log_max_cq_sz = TAVOR_CQ_SZ_SHIFT; /* Select to enable SRQ or not; NOTE: 0 for disabled, 1 for enabled */ uint32_t tavor_srq_enable = 1; -/* Select to enable FMR or not; NOTE: 0 for disabled, 1 for enabled */ -uint32_t tavor_fmr_enable = 1; - /* Number of supported SRQs and their maximum size */ uint32_t tavor_log_num_srq = TAVOR_NUM_SRQ_SHIFT_128; uint32_t tavor_log_max_srq_sz = TAVOR_SRQ_SZ_SHIFT; @@ -91,14 +88,6 @@ uint32_t tavor_log_max_mrw_sz = TAVOR_MAX_MEM_MPT_SHIFT_128; uint32_t tavor_log_num_mttseg = TAVOR_NUM_MTTSEG_SHIFT; /* - * Number of remaps allowed for FMR before a sync is required. This value - * determines how many times we can fmr_deregister() before the underlying fmr - * framework places the region to wait for an MTT_SYNC operation, cleaning up - * the old mappings. - */ -uint32_t tavor_fmr_num_remaps = TAVOR_FMR_MAX_REMAPS; - -/* * Number of supported Tavor mailboxes ("In" and "Out") and their maximum * sizes, respectively */ @@ -295,8 +284,8 @@ tavor_cfg_profile_init_phase1(tavor_state_t *state) cp->cp_max_out_splt_trans = tavor_max_out_splt_trans; cp->cp_max_mem_rd_byte_cnt = tavor_max_mem_rd_byte_cnt; cp->cp_srq_enable = tavor_srq_enable; - cp->cp_fmr_enable = tavor_fmr_enable; - cp->cp_fmr_max_remaps = tavor_fmr_num_remaps; + cp->cp_fmr_enable = 0; + cp->cp_fmr_max_remaps = 0; /* * Although most of the configuration is enabled in "phase2" of the diff --git a/usr/src/uts/common/io/ib/adapters/tavor/tavor_ci.c b/usr/src/uts/common/io/ib/adapters/tavor/tavor_ci.c index f981ca2c2b..c8174a7bdd 100644 --- a/usr/src/uts/common/io/ib/adapters/tavor/tavor_ci.c +++ b/usr/src/uts/common/io/ib/adapters/tavor/tavor_ci.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -173,8 +173,7 @@ static ibt_status_t tavor_ci_post_srq(ibc_hca_hdl_t, ibc_srq_hdl_t, /* Address translation */ static ibt_status_t tavor_ci_map_mem_area(ibc_hca_hdl_t, ibt_va_attr_t *, - void *, uint_t, ibt_phys_buf_t *, uint_t *, size_t *, ib_memlen_t *, - ibc_ma_hdl_t *); + void *, uint_t, ibt_reg_req_t *, ibc_ma_hdl_t *); static ibt_status_t tavor_ci_unmap_mem_area(ibc_hca_hdl_t, ibc_ma_hdl_t); static ibt_status_t tavor_ci_map_mem_iov(ibc_hca_hdl_t, ibt_iov_attr_t *, ibt_all_wr_t *, ibc_mi_hdl_t *); @@ -2971,68 +2970,10 @@ tavor_ci_post_srq(ibc_hca_hdl_t hca, ibc_srq_hdl_t srq, /* ARGSUSED */ static ibt_status_t tavor_ci_map_mem_area(ibc_hca_hdl_t hca, ibt_va_attr_t *va_attrs, - void *ibtl_reserved, uint_t list_len, ibt_phys_buf_t *paddr_list_p, - uint_t *ret_num_paddr_p, size_t *paddr_buf_sz_p, - ib_memlen_t *paddr_offset_p, ibc_ma_hdl_t *ibc_ma_hdl_p) + void *ibtl_reserved, uint_t list_len, ibt_reg_req_t *reg_req, + ibc_ma_hdl_t *ibc_ma_hdl_p) { - tavor_state_t *state; - uint_t cookiecnt; - int status; - - TAVOR_TNF_ENTER(tavor_ci_map_mem_area); - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*paddr_list_p)) - - /* Check for valid HCA handle */ - if (hca == NULL) { - TNF_PROBE_0(tavor_ci_map_mem_area_fail, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_ci_map_mem_area); - return (IBT_HCA_HDL_INVALID); - } - - if ((va_attrs->va_flags & IBT_VA_BUF) && (va_attrs->va_buf == NULL)) { - TNF_PROBE_0(tavor_ci_map_mem_area_fail, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_ci_map_mem_area); - return (IBT_INVALID_PARAM); - } - - state = (tavor_state_t *)hca; - - /* - * Based on the length of the buffer and the paddr_list passed in, - * retrieve DMA cookies for the virtual to physical address - * translation. - */ - status = tavor_get_dma_cookies(state, paddr_list_p, va_attrs, - list_len, &cookiecnt, ibc_ma_hdl_p); - if (status != DDI_SUCCESS) { - TNF_PROBE_1(tavor_ci_map_mem_area, TAVOR_TNF_ERROR, "", - tnf_uint, status, status); - TAVOR_TNF_EXIT(tavor_ci_map_mem_area); - return (status); - } - - /* - * Split the cookies returned from 'tavor_get_dma_cookies() above. We - * also pass in the size of the cookies we would like. - * Note: for now, we only support PAGESIZE cookies. - */ - status = tavor_split_dma_cookies(state, paddr_list_p, paddr_offset_p, - list_len, &cookiecnt, PAGESIZE); - if (status != DDI_SUCCESS) { - TNF_PROBE_1(tavor_ci_map_mem_area, TAVOR_TNF_ERROR, "", - tnf_uint, status, status); - TAVOR_TNF_EXIT(tavor_ci_map_mem_area); - return (status); - } - - /* Setup return values */ - *ret_num_paddr_p = cookiecnt; - *paddr_buf_sz_p = PAGESIZE; - - TAVOR_TNF_EXIT(tavor_ci_map_mem_area); - return (IBT_SUCCESS); + return (IBT_NOT_SUPPORTED); } /* @@ -3044,27 +2985,7 @@ tavor_ci_map_mem_area(ibc_hca_hdl_t hca, ibt_va_attr_t *va_attrs, static ibt_status_t tavor_ci_unmap_mem_area(ibc_hca_hdl_t hca, ibc_ma_hdl_t ma_hdl) { - int status; - - TAVOR_TNF_ENTER(tavor_ci_unmap_mem_area); - - if (ma_hdl == NULL) { - TNF_PROBE_0(tavor_ci_unmap_mem_area_invalid_mahdl_fail, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_ci_unmap_mem_area); - return (IBT_MA_HDL_INVALID); - } - - status = tavor_free_dma_cookies(ma_hdl); - if (status != DDI_SUCCESS) { - TNF_PROBE_0(tavor_ci_unmap_mem_area_free_dma_fail, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_ci_unmap_mem_area); - return (ibc_get_ci_failure(0)); - } - - TAVOR_TNF_EXIT(tavor_ci_unmap_mem_area); - return (IBT_SUCCESS); + return (IBT_NOT_SUPPORTED); } /* ARGSUSED */ @@ -3132,72 +3053,12 @@ tavor_ci_reregister_physical_mr(ibc_hca_hdl_t hca, ibc_mr_hdl_t mr, * Creates a pool of memory regions suitable for FMR registration * Context: Can be called from base context only */ +/* ARGSUSED */ static ibt_status_t tavor_ci_create_fmr_pool(ibc_hca_hdl_t hca, ibc_pd_hdl_t pd, ibt_fmr_pool_attr_t *params, ibc_fmr_pool_hdl_t *fmr_pool_p) { - tavor_state_t *state; - tavor_pdhdl_t pdhdl; - tavor_fmrhdl_t fmrpoolhdl; - int status; - - TAVOR_TNF_ENTER(tavor_ci_create_fmr_pool); - - /* Check for valid HCA handle */ - if (hca == NULL) { - TNF_PROBE_0(tavor_ci_create_fmr_pool_invhca_fail, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_ci_create_fmr_pool); - return (IBT_HCA_HDL_INVALID); - } - - state = (tavor_state_t *)hca; - - /* Check if FMR is even supported */ - if (state->ts_cfg_profile->cp_fmr_enable == 0) { - TNF_PROBE_0(tavor_ci_create_fmr_pool_not_supported_fail, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_ci_create_fmr_pool); - return (IBT_HCA_FMR_NOT_SUPPORTED); - } - - /* Check for valid PD handle pointer */ - if (pd == NULL) { - TNF_PROBE_0(tavor_ci_create_fmr_invpdhdl_fail, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_ci_create_fmr_pool); - return (IBT_PD_HDL_INVALID); - } - - pdhdl = (tavor_pdhdl_t)pd; - - /* - * Validate the access flags. Both Remote Write and Remote Atomic - * require the Local Write flag to be set - */ - if (((params->fmr_flags & IBT_MR_ENABLE_REMOTE_WRITE) || - (params->fmr_flags & IBT_MR_ENABLE_REMOTE_ATOMIC)) && - !(params->fmr_flags & IBT_MR_ENABLE_LOCAL_WRITE)) { - TNF_PROBE_0(tavor_ci_create_fmr_pool_inv_accflags_fail, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_ci_create_fmr_pool); - return (IBT_MR_ACCESS_REQ_INVALID); - } - - status = tavor_create_fmr_pool(state, pdhdl, params, &fmrpoolhdl); - if (status != DDI_SUCCESS) { - TNF_PROBE_1(tavor_ci_create_fmr_pool, TAVOR_TNF_ERROR, "", - tnf_uint, status, status); - TAVOR_TNF_EXIT(tavor_ci_create_fmr_pool); - return (status); - } - - /* Set fmr_pool from tavor handle */ - *fmr_pool_p = (ibc_fmr_pool_hdl_t)fmrpoolhdl; - - TAVOR_TNF_EXIT(tavor_ci_create_fmr_pool); - - return (IBT_SUCCESS); + return (IBT_NOT_SUPPORTED); } /* @@ -3205,45 +3066,11 @@ tavor_ci_create_fmr_pool(ibc_hca_hdl_t hca, ibc_pd_hdl_t pd, * Free all resources associated with an FMR pool. * Context: Can be called from base context only. */ +/* ARGSUSED */ static ibt_status_t tavor_ci_destroy_fmr_pool(ibc_hca_hdl_t hca, ibc_fmr_pool_hdl_t fmr_pool) { - tavor_state_t *state; - tavor_fmrhdl_t fmrpoolhdl; - int status; - - TAVOR_TNF_ENTER(tavor_ci_destroy_fmr_pool); - - /* Check for valid HCA handle */ - if (hca == NULL) { - TNF_PROBE_0(tavor_ci_destroy_fmr_pool_invhca_fail, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_ci_create_fmr_pool); - return (IBT_HCA_HDL_INVALID); - } - - state = (tavor_state_t *)hca; - - /* Check for valid FMR Pool handle */ - if (fmr_pool == NULL) { - TNF_PROBE_0(tavor_ci_destroy_fmr_pool_invfmr_pool_fail, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_ci_destroy_fmr_pool); - return (IBT_FMR_POOL_HDL_INVALID); - } - - fmrpoolhdl = (tavor_fmrhdl_t)fmr_pool; - - status = tavor_destroy_fmr_pool(state, fmrpoolhdl); - if (status != DDI_SUCCESS) { - TNF_PROBE_1(tavor_ci_destroy_fmr_pool, TAVOR_TNF_ERROR, "", - tnf_uint, status, status); - TAVOR_TNF_EXIT(tavor_ci_destroy_fmr_pool); - return (status); - } - - TAVOR_TNF_EXIT(tavor_ci_destroy_fmr_pool); - return (IBT_SUCCESS); + return (IBT_NOT_SUPPORTED); } /* @@ -3251,45 +3078,11 @@ tavor_ci_destroy_fmr_pool(ibc_hca_hdl_t hca, ibc_fmr_pool_hdl_t fmr_pool) * Force a flush of the memory tables, cleaning up used FMR resources. * Context: Can be called from interrupt or base context. */ +/* ARGSUSED */ static ibt_status_t tavor_ci_flush_fmr_pool(ibc_hca_hdl_t hca, ibc_fmr_pool_hdl_t fmr_pool) { - tavor_state_t *state; - tavor_fmrhdl_t fmrpoolhdl; - int status; - - TAVOR_TNF_ENTER(tavor_ci_flush_fmr_pool); - - /* Check for valid HCA handle */ - if (hca == NULL) { - TNF_PROBE_0(tavor_ci_flush_fmr_pool_invhca_fail, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_ci_flush_fmr_pool); - return (IBT_HCA_HDL_INVALID); - } - - state = (tavor_state_t *)hca; - - /* Check for valid FMR Pool handle */ - if (fmr_pool == NULL) { - TNF_PROBE_0(tavor_ci_flush_fmr_pool_invhca_fail, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_ci_flush_fmr_pool); - return (IBT_FMR_POOL_HDL_INVALID); - } - - fmrpoolhdl = (tavor_fmrhdl_t)fmr_pool; - - status = tavor_flush_fmr_pool(state, fmrpoolhdl); - if (status != DDI_SUCCESS) { - TNF_PROBE_1(tavor_ci_flush_fmr_pool, TAVOR_TNF_ERROR, "", - tnf_uint, status, status); - TAVOR_TNF_EXIT(tavor_ci_flush_fmr_pool); - return (status); - } - - TAVOR_TNF_EXIT(tavor_ci_flush_fmr_pool); - return (IBT_SUCCESS); + return (IBT_NOT_SUPPORTED); } /* @@ -3304,66 +3097,7 @@ tavor_ci_register_physical_fmr(ibc_hca_hdl_t hca, ibc_fmr_pool_hdl_t fmr_pool, ibt_pmr_attr_t *mem_pattr, void *ibtl_reserved, ibc_mr_hdl_t *mr_p, ibt_pmr_desc_t *mem_desc_p) { - tavor_state_t *state; - tavor_mrhdl_t mrhdl; - tavor_fmrhdl_t fmrpoolhdl; - int status; - - TAVOR_TNF_ENTER(tavor_ci_register_physical_fmr); - - ASSERT(mem_pattr != NULL); - ASSERT(mr_p != NULL); - ASSERT(mem_desc_p != NULL); - - /* Check for valid HCA handle */ - if (hca == NULL) { - TNF_PROBE_0(tavor_ci_register_physical_fmr_invhca_fail, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_ci_register_physical_fmr); - return (IBT_HCA_HDL_INVALID); - } - - /* Grab the Tavor softstate pointer */ - state = (tavor_state_t *)hca; - - /* Check for valid FMR Pool handle */ - if (fmr_pool == NULL) { - TNF_PROBE_0(tavor_ci_register_physical_fmr_invhca_fail, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_ci_register_physical_fmr); - return (IBT_FMR_POOL_HDL_INVALID); - } - - fmrpoolhdl = (tavor_fmrhdl_t)fmr_pool; - - status = tavor_register_physical_fmr(state, fmrpoolhdl, mem_pattr, - &mrhdl, mem_desc_p); - if (status != DDI_SUCCESS) { - TNF_PROBE_1(tavor_ci_register_physical_fmr_reg_fail, - TAVOR_TNF_ERROR, "", tnf_uint, status, status); - TAVOR_TNF_EXIT(tavor_ci_register_physical_fmr); - return (status); - } - - /* - * If region is mapped for streaming (i.e. noncoherent), then set - * sync is required - */ - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mem_desc_p)) - mem_desc_p->pmd_sync_required = (mrhdl->mr_bindinfo.bi_flags & - IBT_MR_NONCOHERENT) ? B_TRUE : B_FALSE; - if (mem_desc_p->pmd_sync_required == B_TRUE) { - /* Fill in DMA handle for future sync operations */ - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(mrhdl->mr_bindinfo)) - mrhdl->mr_bindinfo.bi_dmahdl = - (ddi_dma_handle_t)mem_pattr->pmr_ma; - } - - /* Return the Tavor MR handle */ - *mr_p = (ibc_mr_hdl_t)mrhdl; - - TAVOR_TNF_EXIT(tavor_ci_register_physical_fmr); - return (IBT_SUCCESS); + return (IBT_NOT_SUPPORTED); } /* @@ -3371,49 +3105,11 @@ tavor_ci_register_physical_fmr(ibc_hca_hdl_t hca, * Moves an FMR (specified by 'mr') to the deregistered state. * Context: Can be called from base context only. */ +/* ARGSUSED */ static ibt_status_t tavor_ci_deregister_fmr(ibc_hca_hdl_t hca, ibc_mr_hdl_t mr) { - tavor_state_t *state; - tavor_mrhdl_t mrhdl; - int status; - - TAVOR_TNF_ENTER(tavor_ci_deregister_fmr); - - /* Check for valid HCA handle */ - if (hca == NULL) { - TNF_PROBE_0(tavor_ci_deregister_fmr_invhca_fail, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_ci_deregister_fmr); - return (IBT_HCA_HDL_INVALID); - } - - /* Check for valid memory region handle */ - if (mr == NULL) { - TNF_PROBE_0(tavor_ci_deregister_fmr_invmrhdl_fail, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_ci_deregister_fmr); - return (IBT_MR_HDL_INVALID); - } - - /* Grab the Tavor softstate pointer */ - state = (tavor_state_t *)hca; - mrhdl = (tavor_mrhdl_t)mr; - - /* - * Deregister the memory region, either "unmap" the FMR or deregister - * the normal memory region. - */ - status = tavor_deregister_fmr(state, mrhdl); - if (status != DDI_SUCCESS) { - TNF_PROBE_1(tavor_ci_deregister_mr_fmr_fail, - TAVOR_TNF_ERROR, "", tnf_uint, status, status); - TAVOR_TNF_EXIT(tavor_ci_deregister_fmr); - return (status); - } - - TAVOR_TNF_EXIT(tavor_ci_deregister_fmr); - return (IBT_SUCCESS); + return (IBT_NOT_SUPPORTED); } /* diff --git a/usr/src/uts/common/io/ib/adapters/tavor/tavor_misc.c b/usr/src/uts/common/io/ib/adapters/tavor/tavor_misc.c index b6578f085c..f8eb3c3551 100644 --- a/usr/src/uts/common/io/ib/adapters/tavor/tavor_misc.c +++ b/usr/src/uts/common/io/ib/adapters/tavor/tavor_misc.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -46,9 +46,6 @@ #include <sys/ib/adapters/tavor/tavor.h> -/* used for helping uniquify fmr pool taskq name */ -static uint_t tavor_debug_fmrpool_cnt = 0x00000000; - static void tavor_udav_sync(tavor_ahhdl_t ah, tavor_hw_udav_t *udav, uint_t flag); static int tavor_mcg_qplist_add(tavor_state_t *state, tavor_mcghdl_t mcg, @@ -67,11 +64,6 @@ static int tavor_mcg_entry_invalidate(tavor_state_t *state, tavor_hw_mcg_t *mcg_entry, uint_t indx); static int tavor_mgid_is_valid(ib_gid_t gid); static int tavor_mlid_is_valid(ib_lid_t lid); -static void tavor_fmr_processing(void *fmr_args); -static int tavor_fmr_cleanup(tavor_state_t *state, tavor_fmrhdl_t pool); -static void tavor_fmr_cache_init(tavor_fmrhdl_t fmr); -static void tavor_fmr_cache_fini(tavor_fmrhdl_t fmr); -static int tavor_fmr_avl_compare(const void *q, const void *e); /* @@ -2565,908 +2557,3 @@ tavor_dma_attr_init(ddi_dma_attr_t *dma_attr) dma_attr->dma_attr_granular = 1; dma_attr->dma_attr_flags = 0; } - -/* - * tavor_destroy_fmr_pool() - * Create a pool of FMRs. - * Context: Can be called from kernel context only. - */ -int -tavor_create_fmr_pool(tavor_state_t *state, tavor_pdhdl_t pd, - ibt_fmr_pool_attr_t *fmr_attr, tavor_fmrhdl_t *fmrpoolp) -{ - tavor_fmrhdl_t fmrpool; - tavor_fmr_list_t *fmr, *fmr_next; - tavor_mrhdl_t mr; - char taskqname[48]; - char *errormsg; - int status; - int sleep; - int i; - - TAVOR_TNF_ENTER(tavor_create_fmr_pool); - - sleep = (fmr_attr->fmr_flags & IBT_MR_SLEEP) ? TAVOR_SLEEP : - TAVOR_NOSLEEP; - if ((sleep == TAVOR_SLEEP) && - (sleep != TAVOR_SLEEPFLAG_FOR_CONTEXT())) { - TNF_PROBE_0(tavor_create_fmr_pool_invalid_flags, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_create_fmr_pool); - return (IBT_INVALID_PARAM); - } - - fmrpool = (tavor_fmrhdl_t)kmem_zalloc(sizeof (*fmrpool), sleep); - if (fmrpool == NULL) { - /* Set "status" and "errormsg" and goto failure */ - TAVOR_TNF_FAIL(IBT_INSUFF_RESOURCE, "failed FMR Pool handle"); - goto fail; - } - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*fmrpool)) - - mutex_init(&fmrpool->fmr_lock, NULL, MUTEX_DRIVER, - DDI_INTR_PRI(state->ts_intrmsi_pri)); - - fmrpool->fmr_state = state; - fmrpool->fmr_flush_function = fmr_attr->fmr_func_hdlr; - fmrpool->fmr_flush_arg = fmr_attr->fmr_func_arg; - fmrpool->fmr_pool_size = 0; - fmrpool->fmr_cache = 0; - fmrpool->fmr_max_pages = fmr_attr->fmr_max_pages_per_fmr; - fmrpool->fmr_page_sz = fmr_attr->fmr_page_sz; - fmrpool->fmr_dirty_watermark = fmr_attr->fmr_dirty_watermark; - fmrpool->fmr_dirty_len = 0; - fmrpool->fmr_flags = fmr_attr->fmr_flags; - - /* Create taskq to handle cleanup and flush processing */ - (void) snprintf(taskqname, 50, "fmrpool/%d/%d @ 0x%" PRIx64, - fmr_attr->fmr_pool_size, tavor_debug_fmrpool_cnt, - (uint64_t)(uintptr_t)fmrpool); - fmrpool->fmr_taskq = ddi_taskq_create(state->ts_dip, taskqname, - TAVOR_TASKQ_NTHREADS, TASKQ_DEFAULTPRI, 0); - if (fmrpool->fmr_taskq == NULL) { - TAVOR_TNF_FAIL(IBT_INSUFF_RESOURCE, "failed task queue"); - goto fail1; - } - - fmrpool->fmr_free_list = NULL; - fmrpool->fmr_dirty_list = NULL; - - if (fmr_attr->fmr_cache) { - tavor_fmr_cache_init(fmrpool); - } - - for (i = 0; i < fmr_attr->fmr_pool_size; i++) { - status = tavor_mr_alloc_fmr(state, pd, fmrpool, &mr); - if (status != DDI_SUCCESS) { - TAVOR_TNF_FAIL(status, "failed fmr alloc"); - goto fail2; - } - - fmr = (tavor_fmr_list_t *)kmem_zalloc( - sizeof (tavor_fmr_list_t), sleep); - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*fmr)) - - fmr->fmr = mr; - fmr->fmr_refcnt = 0; - fmr->fmr_remaps = 0; - fmr->fmr_pool = fmrpool; - fmr->fmr_in_cache = 0; - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mr)) - mr->mr_fmr = fmr; - - fmr->fmr_next = fmrpool->fmr_free_list; - fmrpool->fmr_free_list = fmr; - fmrpool->fmr_pool_size++; - } - - /* Set to return pool */ - *fmrpoolp = fmrpool; - - TAVOR_TNF_EXIT(tavor_create_fmr_pool); - return (IBT_SUCCESS); -fail2: - tavor_fmr_cache_fini(fmrpool); - for (fmr = fmrpool->fmr_free_list; fmr != NULL; fmr = fmr_next) { - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*fmr)) - fmr_next = fmr->fmr_next; - (void) tavor_mr_dealloc_fmr(state, &fmr->fmr); - kmem_free(fmr, sizeof (tavor_fmr_list_t)); - } - ddi_taskq_destroy(fmrpool->fmr_taskq); -fail1: - kmem_free(fmrpool, sizeof (*fmrpool)); -fail: - TNF_PROBE_1(tavor_create_fmr_pool_fail, TAVOR_TNF_ERROR, "", - tnf_string, msg, errormsg); - TAVOR_TNF_EXIT(tavor_create_fmr_pool); - if (status == DDI_FAILURE) { - return (ibc_get_ci_failure(0)); - } else { - return (status); - } -} - -/* - * tavor_destroy_fmr_pool() - * Destroy an FMR pool and free all associated resources. - * Context: Can be called from kernel context only. - */ -int -tavor_destroy_fmr_pool(tavor_state_t *state, tavor_fmrhdl_t fmrpool) -{ - tavor_fmr_list_t *fmr, *fmr_next; - char *errormsg; - int status; - - TAVOR_TNF_ENTER(tavor_destroy_fmr_pool); - - mutex_enter(&fmrpool->fmr_lock); - status = tavor_fmr_cleanup(state, fmrpool); - if (status != DDI_SUCCESS) { - mutex_exit(&fmrpool->fmr_lock); - TAVOR_TNF_FAIL(ibc_get_ci_failure(0), "failed fmr cleanup"); - goto fail; - } - - if (fmrpool->fmr_cache) { - tavor_fmr_cache_fini(fmrpool); - } - - for (fmr = fmrpool->fmr_free_list; fmr != NULL; fmr = fmr_next) { - fmr_next = fmr->fmr_next; - - (void) tavor_mr_dealloc_fmr(state, &fmr->fmr); - kmem_free(fmr, sizeof (tavor_fmr_list_t)); - } - mutex_exit(&fmrpool->fmr_lock); - - ddi_taskq_destroy(fmrpool->fmr_taskq); - mutex_destroy(&fmrpool->fmr_lock); - - kmem_free(fmrpool, sizeof (*fmrpool)); - - TAVOR_TNF_EXIT(tavor_destroy_fmr_pool); - return (DDI_SUCCESS); -fail: - TNF_PROBE_1(tavor_destroy_fmr_pool_fail, TAVOR_TNF_ERROR, "", - tnf_string, msg, errormsg); - TAVOR_TNF_EXIT(tavor_destroy_fmr_pool); - return (status); -} - -/* - * tavor_flush_fmr_pool() - * Ensure that all unmapped FMRs are fully invalidated. - * Context: Can be called from kernel context only. - */ -int -tavor_flush_fmr_pool(tavor_state_t *state, tavor_fmrhdl_t fmrpool) -{ - char *errormsg; - int status; - - TAVOR_TNF_ENTER(tavor_flush_fmr_pool); - - /* - * Force the unmapping of all entries on the dirty list, regardless of - * whether the watermark has been hit yet. - */ - /* grab the pool lock */ - mutex_enter(&fmrpool->fmr_lock); - status = tavor_fmr_cleanup(state, fmrpool); - if (status != DDI_SUCCESS) { - mutex_exit(&fmrpool->fmr_lock); - TAVOR_TNF_FAIL(ibc_get_ci_failure(0), "failed fmr cleanup"); - goto fail; - } - /* release the pool lock */ - mutex_exit(&fmrpool->fmr_lock); - - TAVOR_TNF_EXIT(tavor_flush_fmr_pool); - return (DDI_SUCCESS); -fail: - TNF_PROBE_1(tavor_flush_fmr_pool_fail, TAVOR_TNF_ERROR, "", - tnf_string, msg, errormsg); - TAVOR_TNF_EXIT(tavor_flush_fmr_pool); - return (status); -} - -/* - * tavor_deregister_fmr() - * Map memory into FMR - * Context: Can be called from interrupt or base context. - */ -int -tavor_register_physical_fmr(tavor_state_t *state, tavor_fmrhdl_t fmrpool, - ibt_pmr_attr_t *mem_pattr, tavor_mrhdl_t *mr, - ibt_pmr_desc_t *mem_desc_p) -{ - tavor_fmr_list_t *fmr; - tavor_fmr_list_t query; - avl_index_t where; - int status; - - TAVOR_TNF_ENTER(tavor_register_physical_fmr); - - /* Check length */ - mutex_enter(&fmrpool->fmr_lock); - if (mem_pattr->pmr_len < 1 || (mem_pattr->pmr_num_buf > - fmrpool->fmr_max_pages)) { - mutex_exit(&fmrpool->fmr_lock); - TNF_PROBE_0(tavor_register_physical_fmr_length_fail, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_register_physical_fmr); - return (IBT_MR_LEN_INVALID); - } - - mutex_enter(&fmrpool->fmr_cachelock); - /* lookup in fmr cache */ - /* if exists, grab it, and return it */ - if (fmrpool->fmr_cache) { - query.fmr_desc.pmd_iova = mem_pattr->pmr_iova; - query.fmr_desc.pmd_phys_buf_list_sz = mem_pattr->pmr_len; - fmr = (tavor_fmr_list_t *)avl_find(&fmrpool->fmr_cache_avl, - &query, &where); - - /* - * If valid FMR was found in cache, return that fmr info - */ - if (fmr != NULL) { - fmr->fmr_refcnt++; - /* Store pmr desc for use in cache */ - (void) memcpy(mem_desc_p, &fmr->fmr_desc, - sizeof (ibt_pmr_desc_t)); - *mr = (tavor_mrhdl_t)fmr->fmr; - mutex_exit(&fmrpool->fmr_cachelock); - mutex_exit(&fmrpool->fmr_lock); - TAVOR_TNF_EXIT(tavor_register_physical_fmr); - return (DDI_SUCCESS); - } - } - - /* FMR does not exist in cache, proceed with registration */ - - /* grab next free entry */ - fmr = fmrpool->fmr_free_list; - if (fmr == NULL) { - mutex_exit(&fmrpool->fmr_cachelock); - mutex_exit(&fmrpool->fmr_lock); - TNF_PROBE_0(tavor_register_physical_fmr_none_free, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_register_physical_fmr); - return (IBT_INSUFF_RESOURCE); - } - - fmrpool->fmr_free_list = fmrpool->fmr_free_list->fmr_next; - fmr->fmr_next = NULL; - - status = tavor_mr_register_physical_fmr(state, mem_pattr, fmr->fmr, - mem_desc_p); - if (status != DDI_SUCCESS) { - mutex_exit(&fmrpool->fmr_cachelock); - mutex_exit(&fmrpool->fmr_lock); - TNF_PROBE_0(tavor_register_physical_fmr_reg_fail, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_register_physical_fmr); - return (status); - } - - fmr->fmr_refcnt = 1; - fmr->fmr_remaps++; - - /* Store pmr desc for use in cache */ - (void) memcpy(&fmr->fmr_desc, mem_desc_p, sizeof (ibt_pmr_desc_t)); - *mr = (tavor_mrhdl_t)fmr->fmr; - - /* Store in cache */ - if (fmrpool->fmr_cache) { - if (!fmr->fmr_in_cache) { - avl_insert(&fmrpool->fmr_cache_avl, fmr, where); - fmr->fmr_in_cache = 1; - } - } - - mutex_exit(&fmrpool->fmr_cachelock); - mutex_exit(&fmrpool->fmr_lock); - TAVOR_TNF_EXIT(tavor_register_physical_fmr); - return (DDI_SUCCESS); -} - -/* - * tavor_deregister_fmr() - * Unmap FMR - * Context: Can be called from kernel context only. - */ -int -tavor_deregister_fmr(tavor_state_t *state, tavor_mrhdl_t mr) -{ - tavor_fmr_list_t *fmr; - tavor_fmrhdl_t fmrpool; - int status; - - fmr = mr->mr_fmr; - fmrpool = fmr->fmr_pool; - - /* Grab pool lock */ - mutex_enter(&fmrpool->fmr_lock); - fmr->fmr_refcnt--; - - if (fmr->fmr_refcnt == 0) { - /* - * First, do some bit of invalidation, reducing our exposure to - * having this region still registered in hardware. - */ - (void) tavor_mr_invalidate_fmr(state, mr); - - /* - * If we've exhausted our remaps then add the FMR to the dirty - * list, not allowing it to be re-used until we have done a - * flush. Otherwise, simply add it back to the free list for - * re-mapping. - */ - if (fmr->fmr_remaps < - state->ts_cfg_profile->cp_fmr_max_remaps) { - /* add to free list */ - fmr->fmr_next = fmrpool->fmr_free_list; - fmrpool->fmr_free_list = fmr; - } else { - /* add to dirty list */ - fmr->fmr_next = fmrpool->fmr_dirty_list; - fmrpool->fmr_dirty_list = fmr; - fmrpool->fmr_dirty_len++; - - status = ddi_taskq_dispatch(fmrpool->fmr_taskq, - tavor_fmr_processing, fmrpool, DDI_NOSLEEP); - if (status == DDI_FAILURE) { - mutex_exit(&fmrpool->fmr_lock); - TNF_PROBE_0(tavor_agent_request_cb_taskq_fail, - TAVOR_TNF_ERROR, ""); - return (IBT_INSUFF_RESOURCE); - } - } - } - /* Release pool lock */ - mutex_exit(&fmrpool->fmr_lock); - - return (DDI_SUCCESS); -} - - -/* - * tavor_fmr_processing() - * If required, perform cleanup. - * Context: Called from taskq context only. - */ -static void -tavor_fmr_processing(void *fmr_args) -{ - tavor_fmrhdl_t fmrpool; - char *errormsg; - int status; - - TAVOR_TNF_ENTER(tavor_fmr_processing); - - ASSERT(fmr_args != NULL); - - fmrpool = (tavor_fmrhdl_t)fmr_args; - - /* grab pool lock */ - mutex_enter(&fmrpool->fmr_lock); - if (fmrpool->fmr_dirty_len >= fmrpool->fmr_dirty_watermark) { - status = tavor_fmr_cleanup(fmrpool->fmr_state, fmrpool); - if (status != DDI_SUCCESS) { - mutex_exit(&fmrpool->fmr_lock); - TAVOR_TNF_FAIL(ibc_get_ci_failure(0), - "failed fmr cleanup"); - goto fail; - } - - if (fmrpool->fmr_flush_function != NULL) { - (void) fmrpool->fmr_flush_function( - (ibc_fmr_pool_hdl_t)fmrpool, - fmrpool->fmr_flush_arg); - } - } - - /* let pool lock go */ - mutex_exit(&fmrpool->fmr_lock); - - TAVOR_TNF_EXIT(tavor_fmr_processing); - return; -fail: - TNF_PROBE_1(tavor_fmr_processing, TAVOR_TNF_ERROR, "", - tnf_string, msg, errormsg); - TAVOR_TNF_EXIT(tavor_fmr_processing); -} - -/* - * tavor_fmr_cleanup() - * Perform cleaning processing, walking the list and performing the MTT sync - * operation if required. - * Context: can be called from taskq or base context. - */ -static int -tavor_fmr_cleanup(tavor_state_t *state, tavor_fmrhdl_t fmrpool) -{ - tavor_fmr_list_t *fmr; - tavor_fmr_list_t *fmr_next; - int sync_needed; - int status; - - TAVOR_TNF_ENTER(tavor_fmr_cleanup); - - ASSERT(MUTEX_HELD(&fmrpool->fmr_lock)); - - sync_needed = 0; - for (fmr = fmrpool->fmr_dirty_list; fmr; fmr = fmr_next) { - fmr_next = fmr->fmr_next; - fmr->fmr_remaps = 0; - - (void) tavor_mr_deregister_fmr(state, fmr->fmr); - - /* - * Update lists. - * - add fmr back to free list - * - remove fmr from dirty list - */ - fmr->fmr_next = fmrpool->fmr_free_list; - fmrpool->fmr_free_list = fmr; - - - /* - * Because we have updated the dirty list, and deregistered the - * FMR entry, we do need to sync the TPT, so we set the - * 'sync_needed' flag here so we sync once we finish dirty_list - * processing. - */ - sync_needed = 1; - } - - fmrpool->fmr_dirty_list = NULL; - fmrpool->fmr_dirty_len = 0; - - if (sync_needed) { - status = tavor_sync_tpt_cmd_post(state, TAVOR_CMD_NOSLEEP_SPIN); - if (status != TAVOR_CMD_SUCCESS) { - TNF_PROBE_0(tavor_fmr_cleanup, TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_fmr_cleanup); - return (status); - } - } - - TAVOR_TNF_EXIT(tavor_fmr_cleanup); - return (DDI_SUCCESS); -} - -/* - * tavor_fmr_avl_compare() - * Context: Can be called from user or kernel context. - */ -static int -tavor_fmr_avl_compare(const void *q, const void *e) -{ - tavor_fmr_list_t *entry, *query; - - TAVOR_TNF_ENTER(tavor_qpn_avl_compare); - - entry = (tavor_fmr_list_t *)e; - query = (tavor_fmr_list_t *)q; - - if (query->fmr_desc.pmd_iova < entry->fmr_desc.pmd_iova) { - TAVOR_TNF_EXIT(tavor_qpn_avl_compare); - return (-1); - } else if (query->fmr_desc.pmd_iova > entry->fmr_desc.pmd_iova) { - TAVOR_TNF_EXIT(tavor_qpn_avl_compare); - return (+1); - } else { - TAVOR_TNF_EXIT(tavor_qpn_avl_compare); - return (0); - } -} - - -/* - * tavor_fmr_cache_init() - * Context: Can be called from user or kernel context. - */ -static void -tavor_fmr_cache_init(tavor_fmrhdl_t fmr) -{ - TAVOR_TNF_ENTER(tavor_fmr_cache_init); - - /* Initialize the lock used for FMR cache AVL tree access */ - mutex_init(&fmr->fmr_cachelock, NULL, MUTEX_DRIVER, - DDI_INTR_PRI(fmr->fmr_state->ts_intrmsi_pri)); - - /* Initialize the AVL tree for the FMR cache */ - avl_create(&fmr->fmr_cache_avl, tavor_fmr_avl_compare, - sizeof (tavor_fmr_list_t), - offsetof(tavor_fmr_list_t, fmr_avlnode)); - - fmr->fmr_cache = 1; - - TAVOR_TNF_EXIT(tavor_fmr_cache_init); -} - - -/* - * tavor_fmr_cache_fini() - * Context: Can be called from user or kernel context. - */ -static void -tavor_fmr_cache_fini(tavor_fmrhdl_t fmr) -{ - void *cookie; - - TAVOR_TNF_ENTER(tavor_fmr_cache_fini); - - /* - * Empty all entries (if necessary) and destroy the AVL tree. - * The FMRs themselves are freed as part of destroy_pool() - */ - cookie = NULL; - while (((void *)(tavor_fmr_list_t *)avl_destroy_nodes( - &fmr->fmr_cache_avl, &cookie)) != NULL) { - /* loop through */ - } - avl_destroy(&fmr->fmr_cache_avl); - - /* Destroy the lock used for FMR cache */ - mutex_destroy(&fmr->fmr_cachelock); - - TAVOR_TNF_EXIT(tavor_fmr_cache_fini); -} - -/* - * tavor_get_dma_cookies() - * Return DMA cookies in the pre-allocated paddr_list_p based on the length - * needed. - * Context: Can be called from interrupt or base context. - */ -int -tavor_get_dma_cookies(tavor_state_t *state, ibt_phys_buf_t *paddr_list_p, - ibt_va_attr_t *va_attrs, uint_t list_len, uint_t *cookiecnt, - ibc_ma_hdl_t *ibc_ma_hdl_p) -{ - ddi_dma_handle_t dma_hdl; - ddi_dma_attr_t dma_attr; - ddi_dma_cookie_t dmacookie; - uint_t dma_xfer_mode; - int (*callback)(caddr_t); - int status; - int i; - - TAVOR_TNF_ENTER(tavor_get_dma_cookies); - - /* Set the callback flag appropriately */ - callback = (va_attrs->va_flags & IBT_VA_NOSLEEP) ? DDI_DMA_DONTWAIT : - DDI_DMA_SLEEP; - if ((callback == DDI_DMA_SLEEP) && - (TAVOR_SLEEP != TAVOR_SLEEPFLAG_FOR_CONTEXT())) { - TNF_PROBE_0(tavor_ci_map_mem_area_invalid_flags, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_ci_map_mem_area); - return (IBT_INVALID_PARAM); - } - - /* - * Initialize many of the default DMA attributes and allocate the DMA - * handle. Then, if we're bypassing the IOMMU, set the - * DDI_DMA_FORCE_PHYSICAL flag. - */ - tavor_dma_attr_init(&dma_attr); - -#ifdef __x86 - /* - * On x86 we can specify a maximum segment length for our returned - * cookies. - */ - if (va_attrs->va_flags & IBT_VA_FMR) { - dma_attr.dma_attr_seg = PAGESIZE - 1; - } -#endif - - /* Determine whether to map STREAMING or CONSISTENT */ - dma_xfer_mode = (va_attrs->va_flags & IBT_VA_NONCOHERENT) ? - DDI_DMA_STREAMING : DDI_DMA_CONSISTENT; - -#ifdef __sparc - /* - * First, disable streaming and switch to consistent if - * configured to do so and IOMMU BYPASS is enabled. - */ - if (state->ts_cfg_profile->cp_disable_streaming_on_bypass && - dma_xfer_mode == DDI_DMA_STREAMING && - state->ts_cfg_profile->cp_iommu_bypass == TAVOR_BINDMEM_BYPASS) { - dma_xfer_mode = DDI_DMA_CONSISTENT; - } - - /* - * Then, if streaming is still specified, then "bypass" is not - * allowed. - */ - if ((dma_xfer_mode == DDI_DMA_CONSISTENT) && - (state->ts_cfg_profile->cp_iommu_bypass == TAVOR_BINDMEM_BYPASS)) { - dma_attr.dma_attr_flags = DDI_DMA_FORCE_PHYSICAL; - } -#endif - - status = ddi_dma_alloc_handle(state->ts_dip, &dma_attr, - callback, NULL, &dma_hdl); - if (status != DDI_SUCCESS) { - TNF_PROBE_1(tavor_ci_map_mem_area_alloc_handle_fail, - TAVOR_TNF_ERROR, "", tnf_uint, status, status); - TAVOR_TNF_EXIT(tavor_ci_map_mem_area); - - switch (status) { - case DDI_DMA_NORESOURCES: - return (IBT_INSUFF_RESOURCE); - case DDI_DMA_BADATTR: - default: - return (ibc_get_ci_failure(0)); - } - } - - /* - * Now bind the handle with the correct DMA attributes. - */ - if (va_attrs->va_flags & IBT_VA_BUF) { - status = ddi_dma_buf_bind_handle(dma_hdl, va_attrs->va_buf, - DDI_DMA_RDWR | dma_xfer_mode, DDI_DMA_DONTWAIT, - NULL, &dmacookie, cookiecnt); - } else { - status = ddi_dma_addr_bind_handle(dma_hdl, NULL, - (caddr_t)(uintptr_t)va_attrs->va_vaddr, va_attrs->va_len, - DDI_DMA_RDWR | dma_xfer_mode, DDI_DMA_DONTWAIT, - NULL, &dmacookie, cookiecnt); - } - if (status != DDI_SUCCESS) { - ddi_dma_free_handle(&dma_hdl); - TNF_PROBE_0(tavor_ci_map_mem_area_bind_handle_fail, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_ci_map_mem_area); - - switch (status) { - case DDI_DMA_NORESOURCES: - return (IBT_INSUFF_RESOURCE); - case DDI_DMA_TOOBIG: - return (IBT_INVALID_PARAM); - case DDI_DMA_PARTIAL_MAP: - case DDI_DMA_INUSE: - case DDI_DMA_NOMAPPING: - default: - return (ibc_get_ci_failure(0)); - } - } - - /* - * Verify our physical buffer list (PBL) is large enough to handle the - * number of cookies that were returned. - */ - if (*cookiecnt > list_len) { - (void) ddi_dma_unbind_handle(dma_hdl); - ddi_dma_free_handle(&dma_hdl); - TNF_PROBE_0(tavor_ci_map_mem_area_toomany_cookie_fail, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_ci_map_mem_area); - return (IBT_PBL_TOO_SMALL); - } - - /* - * We store the cookies returned by the DDI into our own PBL. This - * sets the cookies up for later processing (for example, if we want to - * split up the cookies into smaller chunks). We use the laddr and - * size fields in each cookie to create each individual entry (PBE). - */ - - /* - * Store first cookie info first - */ - paddr_list_p[0].p_laddr = dmacookie.dmac_laddress; - paddr_list_p[0].p_size = dmacookie.dmac_size; - - /* - * Loop through each cookie, storing each cookie into our physical - * buffer list. - */ - for (i = 1; i < *cookiecnt; i++) { - ddi_dma_nextcookie(dma_hdl, &dmacookie); - - paddr_list_p[i].p_laddr = dmacookie.dmac_laddress; - paddr_list_p[i].p_size = dmacookie.dmac_size; - } - - /* return handle */ - *ibc_ma_hdl_p = (ibc_ma_hdl_t)dma_hdl; - TAVOR_TNF_EXIT(tavor_get_dma_cookies); - return (DDI_SUCCESS); -} - -/* - * tavor_split_dma_cookies() - * Split up cookies passed in from paddr_list_p, returning the new list in the - * same buffers, based on the pagesize to split the cookies into. - * Context: Can be called from interrupt or base context. - */ -/* ARGSUSED */ -int -tavor_split_dma_cookies(tavor_state_t *state, ibt_phys_buf_t *paddr_list, - ib_memlen_t *paddr_offset, uint_t list_len, uint_t *cookiecnt, - uint_t pagesize) -{ - uint64_t pageoffset; - uint64_t pagemask; - uint_t pageshift; - uint_t current_cookiecnt; - uint_t cookies_needed; - uint64_t last_size, extra_cookie; - int i_increment; - int i, k; - int status; - - TAVOR_TNF_ENTER(tavor_split_dma_cookies); - - /* Setup pagesize calculations */ - pageoffset = pagesize - 1; - pagemask = (~pageoffset); - pageshift = highbit(pagesize) - 1; - - /* - * Setup first cookie offset based on pagesize requested. - */ - *paddr_offset = paddr_list[0].p_laddr & pageoffset; - paddr_list[0].p_laddr &= pagemask; - - /* Save away the current number of cookies that are passed in */ - current_cookiecnt = *cookiecnt; - - /* Perform splitting up of current cookies into pagesize blocks */ - for (i = 0; i < current_cookiecnt; i += i_increment) { - /* - * If the cookie is smaller than pagesize, or already is - * pagesize, then we are already within our limits, so we skip - * it. - */ - if (paddr_list[i].p_size <= pagesize) { - i_increment = 1; - continue; - } - - /* - * If this is our first cookie, then we have to deal with the - * offset that may be present in the first address. So add - * that to our size, to calculate potential change to the last - * cookie's size. - * - * Also, calculate the number of cookies that we'll need to - * split up this block into. - */ - if (i == 0) { - last_size = (paddr_list[i].p_size + *paddr_offset) & - pageoffset; - cookies_needed = (paddr_list[i].p_size + - *paddr_offset) >> pageshift; - } else { - last_size = 0; - cookies_needed = paddr_list[i].p_size >> pageshift; - } - - /* - * If our size is not a multiple of pagesize, we need one more - * cookie. - */ - if (last_size) { - extra_cookie = 1; - } else { - extra_cookie = 0; - } - - /* - * Split cookie into pagesize chunks, shifting list of cookies - * down, using more cookie slots in the PBL if necessary. - */ - status = tavor_dma_cookie_shift(paddr_list, i, list_len, - current_cookiecnt - i, cookies_needed + extra_cookie); - if (status != 0) { - TNF_PROBE_0(tavor_split_cookies_toomany_fail, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_dma_split_cookies); - return (status); - } - - /* - * If the very first cookie, we must take possible offset into - * account. - */ - if (i == 0) { - paddr_list[i].p_size = pagesize - *paddr_offset; - } else { - paddr_list[i].p_size = pagesize; - } - - /* - * We have shifted the existing cookies down the PBL, now fill - * in the blank entries by splitting up our current block. - */ - for (k = 1; k < cookies_needed; k++) { - paddr_list[i + k].p_laddr = - paddr_list[i + k - 1].p_laddr + pagesize; - paddr_list[i + k].p_size = pagesize; - } - - /* If we have one extra cookie (of less than pagesize...) */ - if (extra_cookie) { - paddr_list[i + k].p_laddr = - paddr_list[i + k - 1].p_laddr + pagesize; - paddr_list[i + k].p_size = last_size; - } - - /* Increment cookiecnt appropriately based on cookies used */ - i_increment = cookies_needed + extra_cookie; - current_cookiecnt += i_increment - 1; - } - - /* Update to new cookie count */ - *cookiecnt = current_cookiecnt; - TAVOR_TNF_EXIT(tavor_dma_split_cookies); - return (DDI_SUCCESS); -} - -/* - * tavor_dma_cookie_shift() - * Context: Can be called from interrupt or base context. - */ -int -tavor_dma_cookie_shift(ibt_phys_buf_t *paddr_list, int start, int end, - int cookiecnt, int num_shift) -{ - int shift_start; - int i; - - TAVOR_TNF_ENTER(tavor_dma_cookie_shift); - - /* Calculating starting point in the PBL list */ - shift_start = start + cookiecnt - 1; - - /* Check if we're at the end of our PBL list */ - if ((shift_start + num_shift - 1) >= end) { - TNF_PROBE_0(tavor_dma_cookie_shift_toomany_fail, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_dma_cookie_shift); - return (IBT_PBL_TOO_SMALL); - } - - for (i = shift_start; i > start; i--) { - paddr_list[i + num_shift - 1] = paddr_list[i]; - } - - TAVOR_TNF_EXIT(tavor_dma_cookie_shift); - return (DDI_SUCCESS); -} - - -/* - * tavor_free_dma_cookies() - * Context: Can be called from interrupt or base context. - */ -int -tavor_free_dma_cookies(ibc_ma_hdl_t ma_hdl) -{ - ddi_dma_handle_t dma_hdl; - int status; - - dma_hdl = (ddi_dma_handle_t)ma_hdl; - - status = ddi_dma_unbind_handle(dma_hdl); - if (status != DDI_SUCCESS) { - TNF_PROBE_0(tavor_ci_free_dma_unbind_fail, - TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_ci_unmap_mem_area); - return (ibc_get_ci_failure(0)); - } - - ddi_dma_free_handle(&dma_hdl); - - return (DDI_SUCCESS); -} diff --git a/usr/src/uts/common/io/ib/adapters/tavor/tavor_mr.c b/usr/src/uts/common/io/ib/adapters/tavor/tavor_mr.c index 3b2e167d71..af93480582 100644 --- a/usr/src/uts/common/io/ib/adapters/tavor/tavor_mr.c +++ b/usr/src/uts/common/io/ib/adapters/tavor/tavor_mr.c @@ -68,8 +68,6 @@ static void tavor_mr_mem_unbind(tavor_state_t *state, tavor_bind_info_t *bind); static int tavor_mr_fast_mtt_write(tavor_rsrc_t *mtt, tavor_bind_info_t *bind, uint32_t mtt_pgsize_bits); -static int tavor_mr_fast_mtt_write_fmr(tavor_rsrc_t *mtt, - ibt_pmr_attr_t *mem_pattr, uint32_t mtt_pgsize_bits); static int tavor_mtt_refcnt_inc(tavor_rsrc_t *rsrc); static int tavor_mtt_refcnt_dec(tavor_rsrc_t *rsrc); @@ -424,7 +422,6 @@ tavor_mr_register_shared(tavor_state_t *state, tavor_mrhdl_t mrhdl, mr->mr_pdhdl = pd; mr->mr_rsrcp = rsrc; mr->mr_is_umem = mr_is_umem; - mr->mr_is_fmr = 0; mr->mr_umemcookie = (mr_is_umem != 0) ? umem_cookie : NULL; mr->mr_umem_cbfunc = NULL; mr->mr_umem_cbarg1 = NULL; @@ -470,321 +467,6 @@ mrshared_fail: return (status); } -/* - * tavor_mr_alloc_fmr() - * Context: Can be called from interrupt or base context. - */ -int -tavor_mr_alloc_fmr(tavor_state_t *state, tavor_pdhdl_t pd, - tavor_fmrhdl_t fmr_pool, tavor_mrhdl_t *mrhdl) -{ - tavor_rsrc_pool_info_t *rsrc_pool; - tavor_rsrc_t *mpt, *mtt, *rsrc; - tavor_hw_mpt_t mpt_entry; - tavor_mrhdl_t mr; - tavor_bind_info_t bind; - uint64_t mtt_addr, mtt_ddrbaseaddr; - uint64_t nummtt; - uint_t sleep, mtt_pgsize_bits; - int status; - char *errormsg; - - TAVOR_TNF_ENTER(tavor_mr_alloc_fmr); - - /* - * Check the sleep flag. Ensure that it is consistent with the - * current thread context (i.e. if we are currently in the interrupt - * context, then we shouldn't be attempting to sleep). - */ - sleep = (fmr_pool->fmr_flags & IBT_MR_SLEEP) ? TAVOR_SLEEP : - TAVOR_NOSLEEP; - if ((sleep == TAVOR_SLEEP) && - (sleep != TAVOR_SLEEPFLAG_FOR_CONTEXT())) { - TNF_PROBE_0(tavor_mr_alloc_fmr, TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_mr_alloc_fmr); - return (IBT_INVALID_PARAM); - } - - /* Increment the reference count on the protection domain (PD) */ - tavor_pd_refcnt_inc(pd); - - /* - * Allocate an MPT entry. This will be filled in with all the - * necessary parameters to define the FMR. Specifically, it will be - * made to reference the currently existing MTT entries and ownership - * of the MPT will be passed to the hardware in the last step below. - * If we fail here, we must undo the protection domain reference count. - */ - - status = tavor_rsrc_alloc(state, TAVOR_MPT, 1, sleep, &mpt); - if (status != DDI_SUCCESS) { - /* Set "status" and "errormsg" and goto failure */ - TAVOR_TNF_FAIL(IBT_INSUFF_RESOURCE, "failed MPT"); - goto fmralloc_fail1; - } - - /* - * Allocate the software structure for tracking the fmr memory - * region (i.e. the Tavor Memory Region handle). If we fail here, we - * must undo the protection domain reference count and the previous - * resource allocation. - */ - status = tavor_rsrc_alloc(state, TAVOR_MRHDL, 1, sleep, &rsrc); - if (status != DDI_SUCCESS) { - /* Set "status" and "errormsg" and goto failure */ - TAVOR_TNF_FAIL(IBT_INSUFF_RESOURCE, "failed MR handle"); - goto fmralloc_fail2; - } - mr = (tavor_mrhdl_t)rsrc->tr_addr; - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mr)) - - /* - * Setup and validate the memory region access flags. This means - * translating the IBTF's enable flags into the access flags that - * will be used in later operations. - */ - mr->mr_accflag = 0; - if (fmr_pool->fmr_flags & IBT_MR_ENABLE_LOCAL_WRITE) - mr->mr_accflag |= IBT_MR_LOCAL_WRITE; - if (fmr_pool->fmr_flags & IBT_MR_ENABLE_REMOTE_READ) - mr->mr_accflag |= IBT_MR_REMOTE_READ; - if (fmr_pool->fmr_flags & IBT_MR_ENABLE_REMOTE_WRITE) - mr->mr_accflag |= IBT_MR_REMOTE_WRITE; - if (fmr_pool->fmr_flags & IBT_MR_ENABLE_REMOTE_ATOMIC) - mr->mr_accflag |= IBT_MR_REMOTE_ATOMIC; - - /* - * Calculate keys (Lkey, Rkey) from MPT index. Each key is formed - * from a certain number of "constrained" bits (the least significant - * bits) and some number of "unconstrained" bits. The constrained - * bits must be set to the index of the entry in the MPT table, but - * the unconstrained bits can be set to any value we wish. Note: - * if no remote access is required, then the RKey value is not filled - * in. Otherwise both Rkey and LKey are given the same value. - */ - tavor_mr_keycalc(state, mpt->tr_indx, &mr->mr_lkey); - if ((mr->mr_accflag & IBT_MR_REMOTE_READ) || - (mr->mr_accflag & IBT_MR_REMOTE_WRITE) || - (mr->mr_accflag & IBT_MR_REMOTE_ATOMIC)) { - mr->mr_rkey = mr->mr_lkey; - } - - /* - * Determine number of pages spanned. This routine uses the - * information in the "bind" struct to determine the required - * number of MTT entries needed (and returns the suggested page size - - * as a "power-of-2" - for each MTT entry). - */ - /* Assume address will be page aligned later */ - bind.bi_addr = 0; - /* Calculate size based on given max pages */ - bind.bi_len = fmr_pool->fmr_max_pages << PAGESHIFT; - nummtt = tavor_mr_nummtt_needed(state, &bind, &mtt_pgsize_bits); - - /* - * Allocate the MTT entries. Use the calculations performed above to - * allocate the required number of MTT entries. Note: MTT entries are - * allocated in "MTT segments" which consist of complete cachelines - * (i.e. 8 entries, 16 entries, etc.) So the TAVOR_NUMMTT_TO_MTTSEG() - * macro is used to do the proper conversion. If we fail here, we - * must not only undo all the previous resource allocation (and PD - * reference count), but we must also unbind the memory. - */ - status = tavor_rsrc_alloc(state, TAVOR_MTT, - TAVOR_NUMMTT_TO_MTTSEG(nummtt), sleep, &mtt); - if (status != DDI_SUCCESS) { - /* Set "status" and "errormsg" and goto failure */ - TAVOR_TNF_FAIL(IBT_INSUFF_RESOURCE, "failed MTT"); - goto fmralloc_fail3; - } - mr->mr_logmttpgsz = mtt_pgsize_bits; - - /* - * Get the base address for the MTT table. This will be necessary - * in the next step when we are setting up the MPT entry. - */ - rsrc_pool = &state->ts_rsrc_hdl[TAVOR_MTT]; - mtt_ddrbaseaddr = (uint64_t)(uintptr_t)rsrc_pool->rsrc_ddr_offset; - - /* - * Fill in the MPT entry. This is the final step before passing - * ownership of the MPT entry to the Tavor hardware. We use all of - * the information collected/calculated above to fill in the - * requisite portions of the MPT. - */ - bzero(&mpt_entry, sizeof (tavor_hw_mpt_t)); - mpt_entry.m_io = TAVOR_MEM_CYCLE_GENERATE; - mpt_entry.en_bind = 0; - mpt_entry.atomic = (mr->mr_accflag & IBT_MR_REMOTE_ATOMIC) ? 1 : 0; - mpt_entry.rw = (mr->mr_accflag & IBT_MR_REMOTE_WRITE) ? 1 : 0; - mpt_entry.rr = (mr->mr_accflag & IBT_MR_REMOTE_READ) ? 1 : 0; - mpt_entry.lw = (mr->mr_accflag & IBT_MR_LOCAL_WRITE) ? 1 : 0; - mpt_entry.lr = 1; - mpt_entry.reg_win = TAVOR_MPT_IS_REGION; - mpt_entry.pd = pd->pd_pdnum; - mpt_entry.page_sz = mr->mr_logmttpgsz - 0xC; - mpt_entry.win_cnt_limit = TAVOR_UNLIMITED_WIN_BIND; - mtt_addr = mtt_ddrbaseaddr + (mtt->tr_indx << TAVOR_MTT_SIZE_SHIFT); - mpt_entry.mttseg_addr_h = mtt_addr >> 32; - mpt_entry.mttseg_addr_l = mtt_addr >> 6; - mpt_entry.mem_key = mr->mr_lkey; - - /* - * FMR sets these to 0 for now. Later during actual fmr registration - * these values are filled in. - */ - mpt_entry.start_addr = 0; - mpt_entry.reg_win_len = 0; - - /* - * Write the MPT entry to hardware. Lastly, we pass ownership of - * the entry to the hardware. Note: in general, this operation - * shouldn't fail. But if it does, we have to undo everything we've - * done above before returning error. - */ - status = tavor_cmn_ownership_cmd_post(state, SW2HW_MPT, &mpt_entry, - sizeof (tavor_hw_mpt_t), mpt->tr_indx, sleep); - if (status != TAVOR_CMD_SUCCESS) { - cmn_err(CE_CONT, "Tavor: SW2HW_MPT command failed: %08x\n", - status); - TNF_PROBE_1(tavor_mr_register_shared_sw2hw_mpt_cmd_fail, - TAVOR_TNF_ERROR, "", tnf_uint, status, status); - /* Set "status" and "errormsg" and goto failure */ - TAVOR_TNF_FAIL(ibc_get_ci_failure(0), - "tavor SW2HW_MPT command"); - goto fmralloc_fail4; - } - - /* - * Fill in the rest of the Tavor Memory Region handle. Having - * successfully transferred ownership of the MPT, we can update the - * following fields for use in further operations on the MR. Also, set - * that this is an FMR region. - */ - mr->mr_mptrsrcp = mpt; - mr->mr_mttrsrcp = mtt; - mr->mr_pdhdl = pd; - mr->mr_rsrcp = rsrc; - mr->mr_is_fmr = 1; - (void) memcpy(&mr->mr_bindinfo, &bind, sizeof (tavor_bind_info_t)); - - *mrhdl = mr; - - TAVOR_TNF_EXIT(tavor_mr_alloc_fmr); - return (DDI_SUCCESS); - -/* - * The following is cleanup for all possible failure cases in this routine - */ -fmralloc_fail4: - tavor_rsrc_free(state, &mtt); -fmralloc_fail3: - tavor_rsrc_free(state, &rsrc); -fmralloc_fail2: - tavor_rsrc_free(state, &mpt); -fmralloc_fail1: - tavor_pd_refcnt_dec(pd); -fmralloc_fail: - TNF_PROBE_1(tavor_mr_alloc_fmr, TAVOR_TNF_ERROR, "", - tnf_string, msg, errormsg); - TAVOR_TNF_EXIT(tavor_mr_alloc_fmr); - return (status); -} - -/* - * tavor_mr_register_physical_fmr() - * Context: Can be called from interrupt or base context. - */ -int -tavor_mr_register_physical_fmr(tavor_state_t *state, - ibt_pmr_attr_t *mem_pattr_p, tavor_mrhdl_t mr, ibt_pmr_desc_t *mem_desc_p) -{ - tavor_rsrc_t *mpt; - uint64_t *mpt_table; - int status; - char *errormsg; - - TAVOR_TNF_ENTER(tavor_mr_register_physical_fmr); - - mutex_enter(&mr->mr_lock); - mpt = mr->mr_mptrsrcp; - mpt_table = (uint64_t *)mpt->tr_addr; - - /* Write MPT status to SW bit */ - ddi_put8(mpt->tr_acchdl, (uint8_t *)&mpt_table[0], 0xF); - - /* - * Write the mapped addresses into the MTT entries. FMR needs to do - * this a little differently, so we call the fmr specific fast mtt - * write here. - */ - status = tavor_mr_fast_mtt_write_fmr(mr->mr_mttrsrcp, mem_pattr_p, - mr->mr_logmttpgsz); - if (status != DDI_SUCCESS) { - mutex_exit(&mr->mr_lock); - /* Set "status" and "errormsg" and goto failure */ - TAVOR_TNF_FAIL(ibc_get_ci_failure(0), "failed write mtt"); - goto fmr_reg_fail1; - } - - /* - * Calculate keys (Lkey, Rkey) from MPT index. Each key is formed - * from a certain number of "constrained" bits (the least significant - * bits) and some number of "unconstrained" bits. The constrained - * bits must be set to the index of the entry in the MPT table, but - * the unconstrained bits can be set to any value we wish. Note: - * if no remote access is required, then the RKey value is not filled - * in. Otherwise both Rkey and LKey are given the same value. - */ - tavor_mr_keycalc(state, mpt->tr_indx, &mr->mr_lkey); - if ((mr->mr_accflag & IBT_MR_REMOTE_READ) || - (mr->mr_accflag & IBT_MR_REMOTE_WRITE) || - (mr->mr_accflag & IBT_MR_REMOTE_ATOMIC)) { - mr->mr_rkey = mr->mr_lkey; - } - - /* write mem key value */ - ddi_put32(mpt->tr_acchdl, (uint32_t *)&mpt_table[1], mr->mr_lkey); - - /* write length value */ - ddi_put64(mpt->tr_acchdl, &mpt_table[3], mem_pattr_p->pmr_len); - - /* write start addr value */ - ddi_put64(mpt->tr_acchdl, &mpt_table[2], mem_pattr_p->pmr_iova); - - /* write lkey value */ - ddi_put32(mpt->tr_acchdl, (uint32_t *)&mpt_table[4], mr->mr_lkey); - - /* Write MPT status to HW bit */ - ddi_put8(mpt->tr_acchdl, (uint8_t *)&mpt_table[0], 0x0); - - /* Fill in return parameters */ - mem_desc_p->pmd_lkey = mr->mr_lkey; - mem_desc_p->pmd_rkey = mr->mr_rkey; - mem_desc_p->pmd_iova = mem_pattr_p->pmr_iova; - mem_desc_p->pmd_phys_buf_list_sz = mem_pattr_p->pmr_len; - - /* Fill in MR bindinfo struct for later sync or query operations */ - mr->mr_bindinfo.bi_addr = mem_pattr_p->pmr_iova; - mr->mr_bindinfo.bi_flags = mem_pattr_p->pmr_flags & IBT_MR_NONCOHERENT; - - mutex_exit(&mr->mr_lock); - - TAVOR_TNF_EXIT(tavor_mr_register_physical_fmr); - return (DDI_SUCCESS); - -fmr_reg_fail1: - /* - * Note, we fail here, and purposely leave the memory ownership in - * software. The memory tables may be corrupt, so we leave the region - * unregistered. - */ - TNF_PROBE_1(tavor_mr_register_physical_fmr_fail, TAVOR_TNF_ERROR, "", - tnf_string, msg, errormsg); - TAVOR_TNF_EXIT(tavor_mr_register_physical_fmr); - return (DDI_FAILURE); -} - /* * tavor_mr_deregister() @@ -837,17 +519,6 @@ tavor_mr_deregister(tavor_state_t *state, tavor_mrhdl_t *mrhdl, uint_t level, bind = &mr->mr_bindinfo; /* - * Check here if the memory region is really an FMR. If so, this is a - * bad thing and we shouldn't be here. Return failure. - */ - if (mr->mr_is_fmr) { - mutex_exit(&mr->mr_lock); - TNF_PROBE_0(tavor_mr_deregister_is_fmr, TAVOR_TNF_ERROR, ""); - TAVOR_TNF_EXIT(tavor_mr_deregister); - return (IBT_INVALID_PARAM); - } - - /* * Check here to see if the memory region has already been partially * deregistered as a result of the tavor_umap_umemlock_cb() callback. * If so, then jump to the end and free the remaining resources. @@ -981,113 +652,6 @@ mrdereg_finish_cleanup: return (DDI_SUCCESS); } -/* - * tavor_mr_dealloc_fmr() - * Context: Can be called from interrupt or base context. - */ -/* ARGSUSED */ -int -tavor_mr_dealloc_fmr(tavor_state_t *state, tavor_mrhdl_t *mrhdl) -{ - tavor_rsrc_t *mpt, *mtt, *rsrc; - tavor_pdhdl_t pd; - tavor_mrhdl_t mr; - - TAVOR_TNF_ENTER(tavor_mr_dealloc_fmr); - - /* - * Pull all the necessary information from the Tavor Memory Region - * handle. This is necessary here because the resource for the - * MR handle is going to be freed up as part of the this - * deregistration - */ - mr = *mrhdl; - mutex_enter(&mr->mr_lock); - mpt = mr->mr_mptrsrcp; - mtt = mr->mr_mttrsrcp; - rsrc = mr->mr_rsrcp; - pd = mr->mr_pdhdl; - mutex_exit(&mr->mr_lock); - - /* Free the MTT entries */ - tavor_rsrc_free(state, &mtt); - - /* Free the Tavor Memory Region handle */ - tavor_rsrc_free(state, &rsrc); - - /* Free up the MPT entry resource */ - tavor_rsrc_free(state, &mpt); - - /* Decrement the reference count on the protection domain (PD) */ - tavor_pd_refcnt_dec(pd); - - /* Set the mrhdl pointer to NULL and return success */ - *mrhdl = NULL; - - TAVOR_TNF_EXIT(tavor_mr_dealloc_fmr); - return (DDI_SUCCESS); -} - -/* - * tavor_mr_invalidate_fmr() - * Context: Can be called from interrupt or base context. - */ -/* ARGSUSED */ -int -tavor_mr_invalidate_fmr(tavor_state_t *state, tavor_mrhdl_t mr) -{ - tavor_rsrc_t *mpt; - uint64_t *mpt_table; - - TAVOR_TNF_ENTER(tavor_mr_invalidate_fmr); - - mutex_enter(&mr->mr_lock); - mpt = mr->mr_mptrsrcp; - mpt_table = (uint64_t *)mpt->tr_addr; - - /* Write MPT status to SW bit */ - ddi_put8(mpt->tr_acchdl, (uint8_t *)&mpt_table[0], 0xF); - - /* invalidate mem key value */ - ddi_put32(mpt->tr_acchdl, (uint32_t *)&mpt_table[1], 0); - - /* invalidate lkey value */ - ddi_put32(mpt->tr_acchdl, (uint32_t *)&mpt_table[4], 0); - - /* Write MPT status to HW bit */ - ddi_put8(mpt->tr_acchdl, (uint8_t *)&mpt_table[0], 0x0); - - mutex_exit(&mr->mr_lock); - - TAVOR_TNF_EXIT(tavor_mr_invalidate_fmr); - return (DDI_SUCCESS); -} - -/* - * tavor_mr_deregister_fmr() - * Context: Can be called from interrupt or base context. - */ -/* ARGSUSED */ -int -tavor_mr_deregister_fmr(tavor_state_t *state, tavor_mrhdl_t mr) -{ - tavor_rsrc_t *mpt; - uint64_t *mpt_table; - - TAVOR_TNF_ENTER(tavor_mr_deregister_fmr); - - mutex_enter(&mr->mr_lock); - mpt = mr->mr_mptrsrcp; - mpt_table = (uint64_t *)mpt->tr_addr; - - /* Write MPT status to SW bit */ - ddi_put8(mpt->tr_acchdl, (uint8_t *)&mpt_table[0], 0xF); - mutex_exit(&mr->mr_lock); - - TAVOR_TNF_EXIT(tavor_mr_deregister_fmr); - return (DDI_SUCCESS); -} - /* * tavor_mr_query() @@ -1859,7 +1423,6 @@ tavor_mr_common_reg(tavor_state_t *state, tavor_pdhdl_t pd, mr->mr_pdhdl = pd; mr->mr_rsrcp = rsrc; mr->mr_is_umem = mr_is_umem; - mr->mr_is_fmr = 0; mr->mr_umemcookie = (mr_is_umem != 0) ? umem_cookie : NULL; mr->mr_umem_cbfunc = NULL; mr->mr_umem_cbarg1 = NULL; @@ -2345,7 +1908,6 @@ tavor_mr_common_rereg(tavor_state_t *state, tavor_mrhdl_t mr, mr->mr_pdhdl = pd_to_use; mr->mr_accflag = acc_flags_to_use; mr->mr_is_umem = 0; - mr->mr_is_fmr = 0; mr->mr_umemcookie = NULL; /* New MR handle is same as the old */ @@ -3003,78 +2565,6 @@ tavor_mr_fast_mtt_write(tavor_rsrc_t *mtt, tavor_bind_info_t *bind, } /* - * tavor_mr_fast_mtt_write_fmr() - * Context: Can be called from interrupt or base context. - */ -static int -tavor_mr_fast_mtt_write_fmr(tavor_rsrc_t *mtt, ibt_pmr_attr_t *mem_pattr, - uint32_t mtt_pgsize_bits) -{ - uint64_t *mtt_table; - ibt_phys_addr_t *buf; - uint64_t mtt_entry; - uint64_t addr, first_addr, endaddr; - uint64_t pagesize; - int i; - - TAVOR_TNF_ENTER(tavor_mr_fast_mtt_write_fmr); - - /* Calculate page size from the suggested value passed in */ - pagesize = ((uint64_t)1 << mtt_pgsize_bits); - - /* - * Walk the "buf list" and fill in the MTT table entries - */ - mtt_table = (uint64_t *)mtt->tr_addr; - for (i = 0; i < mem_pattr->pmr_num_buf; i++) { - buf = &mem_pattr->pmr_addr_list[i]; - - /* - * For first cookie, use the offset field to determine where - * the buffer starts. The end addr is then calculated with the - * offset in mind. - */ - if (i == 0) { - first_addr = addr = buf->p_laddr + - mem_pattr->pmr_offset; - endaddr = addr + (mem_pattr->pmr_buf_sz - 1) - - mem_pattr->pmr_offset; - /* - * For last cookie, determine end addr based on starting - * address and size of the total buffer - */ - } else if (i == mem_pattr->pmr_num_buf - 1) { - addr = buf->p_laddr; - endaddr = addr + (first_addr + mem_pattr->pmr_len & - (mem_pattr->pmr_buf_sz - 1)); - /* - * For the middle cookies case, start and end addr are - * straightforward. Just use the laddr, and the size, as all - * middle cookies are a set size. - */ - } else { - addr = buf->p_laddr; - endaddr = addr + (mem_pattr->pmr_buf_sz - 1); - } - - addr = addr & ~((uint64_t)pagesize - 1); - while (addr <= endaddr) { - /* - * Fill in the mapped addresses (calculated above) and - * set TAVOR_MTT_ENTRY_PRESET flag for each MTT entry. - */ - mtt_entry = addr | TAVOR_MTT_ENTRY_PRESET; - ddi_put64(mtt->tr_acchdl, &mtt_table[i], mtt_entry); - addr += pagesize; - } - } - - TAVOR_TNF_EXIT(tavor_mr_fast_mtt_write_fmr); - return (DDI_SUCCESS); -} - - -/* * tavor_mtt_refcnt_inc() * Context: Can be called from interrupt or base context. */ diff --git a/usr/src/uts/common/io/ib/ibtl/ibtl_mem.c b/usr/src/uts/common/io/ib/ibtl/ibtl_mem.c index c8e4559e5b..5d5089e247 100644 --- a/usr/src/uts/common/io/ib/ibtl/ibtl_mem.c +++ b/usr/src/uts/common/io/ib/ibtl/ibtl_mem.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -514,10 +514,9 @@ ibt_free_mw(ibt_hca_hdl_t hca_hdl, ibt_mw_hdl_t mw_hdl) */ ibt_status_t ibt_map_mem_area(ibt_hca_hdl_t hca_hdl, ibt_va_attr_t *va_attrs, - uint_t paddr_list_len, ibt_phys_buf_t *paddr_list_p, uint_t *num_paddr_p, - size_t *paddr_bufsz_p, ib_memlen_t *paddr_offset_p, ibt_ma_hdl_t *ma_hdl_p) + uint_t paddr_list_len, ibt_reg_req_t *reg_req, ibt_ma_hdl_t *ma_hdl_p) { - ibt_status_t status; + ibt_status_t status; IBTF_DPRINTF_L3(ibtl_mem, "ibt_map_mem_area(%p, %p, %d)", hca_hdl, va_attrs, paddr_list_len); @@ -525,14 +524,12 @@ ibt_map_mem_area(ibt_hca_hdl_t hca_hdl, ibt_va_attr_t *va_attrs, status = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_map_mem_area( IBTL_HCA2CIHCA(hca_hdl), va_attrs, NULL, /* IBTL_HCA2MODI_P(hca_hdl)->mi_reserved */ - paddr_list_len, paddr_list_p, num_paddr_p, paddr_bufsz_p, - paddr_offset_p, ma_hdl_p); + paddr_list_len, reg_req, ma_hdl_p); if (status == IBT_SUCCESS) { mutex_enter(&hca_hdl->ha_mutex); hca_hdl->ha_ma_cnt++; mutex_exit(&hca_hdl->ha_mutex); } - return (status); } diff --git a/usr/src/uts/common/io/warlock/tavor.wlcmd b/usr/src/uts/common/io/warlock/tavor.wlcmd index 071211787a..31de1a5af1 100644 --- a/usr/src/uts/common/io/warlock/tavor.wlcmd +++ b/usr/src/uts/common/io/warlock/tavor.wlcmd @@ -1,5 +1,5 @@ # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -133,11 +133,6 @@ add tavor_umap_db_handle_onclose_cb/callback targets \ ### Tavor QP number AVL tree compare function root tavor_qpn_avl_compare -### Tavor FMR processing -root tavor_fmr_avl_compare -root tavor_fmr_processing -add tavor_sw_fmr_s::fmr_flush_function targets warlock_dummy - add bus_ops::bus_add_eventcall targets warlock_dummy add bus_ops::bus_get_eventcookie targets warlock_dummy add bus_ops::bus_post_event targets warlock_dummy diff --git a/usr/src/uts/common/sys/ib/adapters/hermon/hermon_hw.h b/usr/src/uts/common/sys/ib/adapters/hermon/hermon_hw.h index 13c68ab18a..ce94521478 100644 --- a/usr/src/uts/common/sys/ib/adapters/hermon/hermon_hw.h +++ b/usr/src/uts/common/sys/ib/adapters/hermon/hermon_hw.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -59,28 +59,11 @@ extern "C" { * Native page size of the adapter */ #define HERMON_PAGESIZE 0x1000 /* 4Kb */ -#define HERMON_PAGEMASK (HERMON_PAGESIZE - 1) +#define HERMON_PAGEOFFSET (HERMON_PAGESIZE - 1) +#define HERMON_PAGEMASK (~HERMON_PAGEOFFSET) #define HERMON_PAGESHIFT 0xC /* 12 */ /* - * MACROS to make some page stuff easier - */ - -/* given a value, return a value that's the next higher power of 2 */ -#define HERMON_POW2(x) (1 << highbit(x)) -/* - * given a size in bytes, return the minimum number of - * *HCA PAGES* needed to hold it - */ -#define HERMON_HCA_PAGES(x) \ - (((x + HERMON_PAGESIZE) & HERMON_PAGEMASK) >> HERMON_PAGESHIFT) - -/* - * given a size in bytes, return the power of two number of - * *HCA PAGES* needed to hold it - */ -#define HERMON_HCA_POW2_PAGES(x) (HERMON_POW2(HERMON_HCA_PAGES(x))) -/* * Offsets into the CMD BAR (BAR 0) for many of the more interesting hardware * registers. These registers include the HCR (more below), and the software * reset register (SW_RESET). @@ -1380,7 +1363,7 @@ struct hermon_hw_dmpt_s { uint32_t fast_reg_en :1; uint32_t net_cache :1; uint32_t en_inval :1; - uint32_t ren_inavl :1; + uint32_t ren_inval :1; uint32_t pd :24; /* dw 3, byte 0xc-f */ uint64_t start_addr; /* dw 4-5, byte 0x10-17 */ @@ -1542,7 +1525,7 @@ struct hermon_hw_cmpt_s { uint32_t fast_reg_en :1; uint32_t net_cache :1; uint32_t en_inval :1; - uint32_t ren_inavl :1; + uint32_t ren_inval :1; uint32_t pd :24; /* dw 3, byte 0xc-f */ uint64_t start_addr; /* dw 4-5, byte 0x10-17 */ diff --git a/usr/src/uts/common/sys/ib/adapters/hermon/hermon_misc.h b/usr/src/uts/common/sys/ib/adapters/hermon/hermon_misc.h index 233b7eabb7..7b137259cd 100644 --- a/usr/src/uts/common/sys/ib/adapters/hermon/hermon_misc.h +++ b/usr/src/uts/common/sys/ib/adapters/hermon/hermon_misc.h @@ -615,7 +615,7 @@ _NOTE(MUTEX_PROTECTS_DATA(hermon_sw_fmr_s::fmr_lock, _NOTE(MUTEX_PROTECTS_DATA(hermon_sw_fmr_s::fmr_cachelock, hermon_sw_fmr_s::fmr_cache_avl)) -#define HERMON_FMR_MAX_REMAPS 32 +#define HERMON_FMR_MAX_REMAPS 128 /* Hermon doorbell record routines */ @@ -680,17 +680,6 @@ int hermon_pkeyindex_is_valid(hermon_state_t *state, uint_t pkeyindx); int hermon_queue_alloc(hermon_state_t *state, hermon_qalloc_info_t *qa_info, uint_t sleepflag); void hermon_queue_free(hermon_qalloc_info_t *qa_info); -int hermon_get_dma_cookies(hermon_state_t *state, ibt_phys_buf_t *paddr_list_p, - ibt_va_attr_t *va_attrs, uint_t list_len, uint_t *cookiecnt, - ibc_ma_hdl_t *ibc_ma_hdl_p); -int hermon_split_dma_cookies(hermon_state_t *state, - ibt_phys_buf_t *paddr_list_p, ib_memlen_t *paddr_offset_p, - uint_t list_len, uint_t *cookiecnt, uint_t pagesize); -int hermon_dma_cookie_shift(ibt_phys_buf_t *paddr_list, int start, int end, - int cookiecnt, int num_shift); -int hermon_free_dma_cookies(ibc_ma_hdl_t ibc_ma_hdl); -int hermon_log2(long x); - #ifdef __cplusplus } diff --git a/usr/src/uts/common/sys/ib/adapters/hermon/hermon_mr.h b/usr/src/uts/common/sys/ib/adapters/hermon/hermon_mr.h index 69c7eeb650..0f8b80fd60 100644 --- a/usr/src/uts/common/sys/ib/adapters/hermon/hermon_mr.h +++ b/usr/src/uts/common/sys/ib/adapters/hermon/hermon_mr.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -211,6 +211,7 @@ struct hermon_sw_mr_s { /* entity_size (in bytes), for cMPTS */ hermon_rsrc_t *mr_rsrcp; uint_t mr_is_fmr; + uint8_t mr_fmr_key; /* per FMR 8-bit key */ hermon_fmr_list_t *mr_fmr; uint_t mr_is_umem; ddi_umem_cookie_t mr_umemcookie; @@ -220,6 +221,7 @@ struct hermon_sw_mr_s { }; _NOTE(DATA_READABLE_WITHOUT_LOCK(hermon_sw_mr_s::mr_bindinfo hermon_sw_mr_s::mr_lkey + hermon_sw_mr_s::mr_mttaddr hermon_sw_mr_s::mr_is_umem hermon_sw_mr_s::mr_is_fmr hermon_sw_mr_s::mr_fmr)) diff --git a/usr/src/uts/common/sys/ib/adapters/tavor/tavor_misc.h b/usr/src/uts/common/sys/ib/adapters/tavor/tavor_misc.h index 451ee2ffa0..4069ca8c17 100644 --- a/usr/src/uts/common/sys/ib/adapters/tavor/tavor_misc.h +++ b/usr/src/uts/common/sys/ib/adapters/tavor/tavor_misc.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -499,72 +499,6 @@ typedef struct tavor_loopback_state_s { int tls_timeout; } tavor_loopback_state_t; -/* - * Mellanox FMR - */ -typedef struct tavor_fmr_list_s { - avl_node_t fmr_avlnode; - struct tavor_fmr_list_s *fmr_next; - - tavor_mrhdl_t fmr; - ibt_pmr_desc_t fmr_desc; - tavor_fmrhdl_t fmr_pool; - uint_t fmr_refcnt; - uint_t fmr_remaps; - uint_t fmr_in_cache; -} tavor_fmr_list_t; - -struct tavor_sw_fmr_s { - tavor_state_t *fmr_state; - - kmutex_t fmr_lock; - ddi_taskq_t *fmr_taskq; - - ibt_fmr_flush_handler_t fmr_flush_function; - void *fmr_flush_arg; - - int fmr_pool_size; - int fmr_max_pages; - int fmr_page_sz; - int fmr_dirty_watermark; - int fmr_dirty_len; - int fmr_flags; - - tavor_fmr_list_t *fmr_free_list; - tavor_fmr_list_t *fmr_dirty_list; - - int fmr_cache; - avl_tree_t fmr_cache_avl; - kmutex_t fmr_cachelock; -}; -_NOTE(MUTEX_PROTECTS_DATA(tavor_sw_fmr_s::fmr_lock, - tavor_sw_fmr_s::fmr_state - tavor_sw_fmr_s::fmr_pool_size - tavor_sw_fmr_s::fmr_max_pages - tavor_sw_fmr_s::fmr_page_sz - tavor_sw_fmr_s::fmr_dirty_watermark - tavor_sw_fmr_s::fmr_dirty_len - tavor_sw_fmr_s::fmr_flags - tavor_sw_fmr_s::fmr_free_list - tavor_sw_fmr_s::fmr_dirty_list - tavor_sw_fmr_s::fmr_cache)) - -_NOTE(MUTEX_PROTECTS_DATA(tavor_sw_fmr_s::fmr_cachelock, - tavor_sw_fmr_s::fmr_cache_avl)) - -#define TAVOR_FMR_MAX_REMAPS 32 - -/* Tavor Fast Memory Registration Routines */ -int tavor_create_fmr_pool(tavor_state_t *state, tavor_pdhdl_t pdhdl, - ibt_fmr_pool_attr_t *params, tavor_fmrhdl_t *fmrhdl); -int tavor_destroy_fmr_pool(tavor_state_t *state, tavor_fmrhdl_t fmrhdl); -int tavor_flush_fmr_pool(tavor_state_t *state, tavor_fmrhdl_t fmrhdl); -int tavor_register_physical_fmr(tavor_state_t *state, tavor_fmrhdl_t fmrhdl, - ibt_pmr_attr_t *mem_pattr_p, tavor_mrhdl_t *mrhdl, - ibt_pmr_desc_t *mem_desc_p); -int tavor_deregister_fmr(tavor_state_t *state, tavor_mrhdl_t mr); - - /* Tavor Address Handle routines */ int tavor_ah_alloc(tavor_state_t *state, tavor_pdhdl_t pd, ibt_adds_vect_t *attr_p, tavor_ahhdl_t *ahhdl, uint_t sleepflag); @@ -609,15 +543,6 @@ int tavor_queue_alloc(tavor_state_t *state, tavor_qalloc_info_t *qa_info, uint_t sleepflag); void tavor_queue_free(tavor_state_t *state, tavor_qalloc_info_t *qa_info); void tavor_dma_attr_init(ddi_dma_attr_t *dma_attr); -int tavor_get_dma_cookies(tavor_state_t *state, ibt_phys_buf_t *paddr_list_p, - ibt_va_attr_t *va_attrs, uint_t list_len, uint_t *cookiecnt, - ibc_ma_hdl_t *ibc_ma_hdl_p); -int tavor_split_dma_cookies(tavor_state_t *state, ibt_phys_buf_t *paddr_list_p, - ib_memlen_t *paddr_offset_p, uint_t list_len, uint_t *cookiecnt, - uint_t pagesize); -int tavor_dma_cookie_shift(ibt_phys_buf_t *paddr_list, int start, int end, - int cookiecnt, int num_shift); -int tavor_free_dma_cookies(ibc_ma_hdl_t ibc_ma_hdl); #ifdef __cplusplus } diff --git a/usr/src/uts/common/sys/ib/adapters/tavor/tavor_mr.h b/usr/src/uts/common/sys/ib/adapters/tavor/tavor_mr.h index b99cadcbb2..c9d736e0e9 100644 --- a/usr/src/uts/common/sys/ib/adapters/tavor/tavor_mr.h +++ b/usr/src/uts/common/sys/ib/adapters/tavor/tavor_mr.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -256,8 +256,6 @@ struct tavor_sw_mr_s { uint32_t mr_rkey; uint32_t mr_logmttpgsz; tavor_rsrc_t *mr_rsrcp; - uint_t mr_is_fmr; - tavor_fmr_list_t *mr_fmr; uint_t mr_is_umem; ddi_umem_cookie_t mr_umemcookie; void (*mr_umem_cbfunc)(void *, void *); @@ -266,9 +264,7 @@ struct tavor_sw_mr_s { }; _NOTE(DATA_READABLE_WITHOUT_LOCK(tavor_sw_mr_s::mr_bindinfo tavor_sw_mr_s::mr_lkey - tavor_sw_mr_s::mr_is_umem - tavor_sw_mr_s::mr_is_fmr - tavor_sw_mr_s::mr_fmr)) + tavor_sw_mr_s::mr_is_umem)) _NOTE(MUTEX_PROTECTS_DATA(tavor_sw_mr_s::mr_lock, tavor_sw_mr_s::mr_mptrsrcp tavor_sw_mr_s::mr_mttrsrcp @@ -338,14 +334,6 @@ int tavor_mw_alloc(tavor_state_t *state, tavor_pdhdl_t pdhdl, ibt_mw_flags_t flags, tavor_mwhdl_t *mwhdl); int tavor_mw_free(tavor_state_t *state, tavor_mwhdl_t *mwhdl, uint_t sleep); void tavor_mr_keycalc(tavor_state_t *state, uint32_t indx, uint32_t *key); -int tavor_mr_alloc_fmr(tavor_state_t *state, tavor_pdhdl_t pd, - tavor_fmrhdl_t fmr_pool, tavor_mrhdl_t *mrhdl); -int tavor_mr_dealloc_fmr(tavor_state_t *state, tavor_mrhdl_t *mrhdl); -int tavor_mr_register_physical_fmr(tavor_state_t *state, - ibt_pmr_attr_t *mem_pattr_p, tavor_mrhdl_t mr, ibt_pmr_desc_t *mem_desc_p); -int tavor_mr_invalidate_fmr(tavor_state_t *state, tavor_mrhdl_t mr); -int tavor_mr_deregister_fmr(tavor_state_t *state, tavor_mrhdl_t mr); - #ifdef __cplusplus } diff --git a/usr/src/uts/common/sys/ib/adapters/tavor/tavor_typedef.h b/usr/src/uts/common/sys/ib/adapters/tavor/tavor_typedef.h index 028f198de8..9b3fc7d447 100644 --- a/usr/src/uts/common/sys/ib/adapters/tavor/tavor_typedef.h +++ b/usr/src/uts/common/sys/ib/adapters/tavor/tavor_typedef.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -87,7 +87,6 @@ typedef struct tavor_sw_pd_s *tavor_pdhdl_t; typedef struct tavor_sw_eq_s *tavor_eqhdl_t; typedef struct tavor_sw_cq_s *tavor_cqhdl_t; typedef struct tavor_sw_srq_s *tavor_srqhdl_t; -typedef struct tavor_sw_fmr_s *tavor_fmrhdl_t; typedef struct tavor_sw_ah_s *tavor_ahhdl_t; typedef struct tavor_sw_qp_s *tavor_qphdl_t; typedef struct tavor_sw_mcg_list_s *tavor_mcghdl_t; diff --git a/usr/src/uts/common/sys/ib/ibtl/ibci.h b/usr/src/uts/common/sys/ib/ibtl/ibci.h index 636773f989..63c77fae25 100644 --- a/usr/src/uts/common/sys/ib/ibtl/ibci.h +++ b/usr/src/uts/common/sys/ib/ibtl/ibci.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -136,23 +136,6 @@ typedef struct ibtl_hca_devinfo_s *ibc_clnt_hdl_t; /* ibc_attach() */ /* - * ibt_hca_attr_t - */ -#define hca_max_rdd hca_opaque2 /* Max RDDs in HCA */ -#define hca_max_eec hca_opaque3 /* Max EEContexts in HCA */ -#define hca_max_rd_sgl hca_opaque4 /* Max SGL entries per RD WR */ -#define hca_max_rdma_in_ee hca_opaque5 /* Max RDMA Reads/Atomics in */ - /* per EEC with HCA as target */ -#define hca_max_rdma_out_ee hca_opaque6 /* Max RDMA Reads/Atomics out */ - /* per EE by this HCA */ -#define hca_max_ipv6_qp hca_max_ipv6_chan -#define hca_max_ether_qp hca_max_ether_chan -#define hca_eec_max_ci_priv_sz hca_opaque7 -#define hca_rdd_max_ci_priv_sz hca_opaque8 -#define hca_max_map_per_fmr hca_opaque9 - - -/* * ibt_wc_t */ #define wc_eecn wc_detail /* End-to-End Context RD's only */ @@ -371,9 +354,8 @@ typedef struct ibc_operations_s { /* Address translation */ ibt_status_t (*ibc_map_mem_area)(ibc_hca_hdl_t hca_hdl, ibt_va_attr_t *va_attrs, void *ibtl_reserved, - uint_t paddr_list_len, ibt_phys_buf_t *paddr_list_p, - uint_t *num_paddr_p, size_t *paddr_bufsz_p, - ib_memlen_t *paddr_offset_p, ibc_ma_hdl_t *ma_hdl_p); + uint_t paddr_list_len, ibt_reg_req_t *reg_req, + ibc_ma_hdl_t *ma_hdl_p); ibt_status_t (*ibc_unmap_mem_area)(ibc_hca_hdl_t hca_hdl, ibc_ma_hdl_t ma_hdl); ibt_status_t (*ibc_map_mem_iov)(ibc_hca_hdl_t hca_hdl, diff --git a/usr/src/uts/common/sys/ib/ibtl/ibti_common.h b/usr/src/uts/common/sys/ib/ibtl/ibti_common.h index 595ff2db1e..c1d3de5422 100644 --- a/usr/src/uts/common/sys/ib/ibtl/ibti_common.h +++ b/usr/src/uts/common/sys/ib/ibtl/ibti_common.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1312,8 +1312,7 @@ ibt_status_t ibt_reregister_phys_mr(ibt_hca_hdl_t hca_hdl, ibt_mr_hdl_t mr_hdl, * is returned. */ ibt_status_t ibt_map_mem_area(ibt_hca_hdl_t hca_hdl, ibt_va_attr_t *va_attrs, - uint_t paddr_list_len, ibt_phys_buf_t *paddr_list_p, uint_t *num_paddr_p, - size_t *paddr_bufsz_p, ib_memlen_t *paddr_offset_p, ibt_ma_hdl_t *ma_hdl_p); + uint_t paddr_list_len, ibt_reg_req_t *reg_req, ibt_ma_hdl_t *ma_hdl_p); /* * ibt_unmap_mem_area() diff --git a/usr/src/uts/common/sys/ib/ibtl/ibtl_ci_types.h b/usr/src/uts/common/sys/ib/ibtl/ibtl_ci_types.h index da78146ca4..4163ec69c9 100644 --- a/usr/src/uts/common/sys/ib/ibtl/ibtl_ci_types.h +++ b/usr/src/uts/common/sys/ib/ibtl/ibtl_ci_types.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -378,6 +378,23 @@ typedef struct ibt_eec_query_attr_s { #define IBT_AH_USER_MAP IBT_UD_DEST_USER_MAP #define IBT_AH_DEFER_ALLOC IBT_UD_DEST_DEFER_ALLOC + +/* + * ibt_hca_attr_t + */ +#define hca_max_rdd hca_opaque2 /* Max RDDs in HCA */ +#define hca_max_eec hca_opaque3 /* Max EEContexts in HCA */ +#define hca_max_rd_sgl hca_opaque4 /* Max SGL entries per RD WR */ +#define hca_max_rdma_in_ee hca_opaque5 /* Max RDMA Reads/Atomics in */ + /* per EEC with HCA as target */ +#define hca_max_rdma_out_ee hca_opaque6 /* Max RDMA Reads/Atomics out */ + /* per EE by this HCA */ +#define hca_max_ipv6_qp hca_max_ipv6_chan +#define hca_max_ether_qp hca_max_ether_chan +#define hca_eec_max_ci_priv_sz hca_opaque7 +#define hca_rdd_max_ci_priv_sz hca_opaque8 +#define hca_max_map_per_fmr hca_opaque9 + #ifdef __cplusplus } #endif diff --git a/usr/src/uts/common/sys/ib/ibtl/ibtl_types.h b/usr/src/uts/common/sys/ib/ibtl/ibtl_types.h index fdb19ce6ac..89d9c040ad 100644 --- a/usr/src/uts/common/sys/ib/ibtl/ibtl_types.h +++ b/usr/src/uts/common/sys/ib/ibtl/ibtl_types.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -267,8 +267,9 @@ typedef enum ibt_srq_flags_e { * ibt_alloc_lkey() alloc flags */ typedef enum ibt_lkey_flags_e { - IBT_KEY_NO_FLAGS = 0, - IBT_KEY_REMOTE = (1 << 0) + IBT_KEY_SLEEP = 0, + IBT_KEY_NOSLEEP = (1 << 0), + IBT_KEY_REMOTE = (1 << 1) } ibt_lkey_flags_t; /* @@ -1088,7 +1089,8 @@ typedef enum ibt_va_flags_e { IBT_VA_NONCOHERENT = (1 << 1), IBT_VA_FMR = (1 << 2), IBT_VA_BLOCK_MODE = (1 << 3), - IBT_VA_BUF = (1 << 4) + IBT_VA_BUF = (1 << 4), + IBT_VA_REG_FN = (1 << 5) } ibt_va_flags_t; @@ -1309,16 +1311,16 @@ typedef struct ibt_wr_reg_pmr_s { /* client for the first byte of the */ /* region */ ib_memlen_t pmr_len; /* Length of region to register */ - ib_memlen_t pmr_offset; /* Offset of the regions starting */ + ib_memlen_t pmr_offset; /* Offset of the region's starting */ /* IOVA within the 1st physical */ /* buffer */ ibt_mr_hdl_t pmr_mr_hdl; ibt_phys_addr_t *pmr_addr_list; /* List of physical buffers accessed */ /* as an array */ size_t pmr_buf_sz; /* size of uniform size PBEs */ - uint_t pmr_num_buf; /* Num of entries in the pmr_buf_list */ - ibt_lkey_t pmr_lkey; - ibt_rkey_t pmr_rkey; + uint_t pmr_num_buf; /* #entries in the pmr_addr_list */ + ibt_lkey_t pmr_lkey; /* new lkey upon return */ + ibt_rkey_t pmr_rkey; /* new rkey upon return */ ibt_mr_flags_t pmr_flags; uint8_t pmr_key; /* Key to use on new Lkey & Rkey */ } ibt_wr_reg_pmr_t; |