summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Taylor <Bill.Taylor@Sun.COM>2010-03-22 13:54:46 -0700
committerBill Taylor <Bill.Taylor@Sun.COM>2010-03-22 13:54:46 -0700
commitc7facc54c4abed9e554ff80225311e6b7048d3c9 (patch)
treec846e4ebb88c5255b23292f5f61bb21b6a8345c8
parentb6611e3b41e720b79f165a90cc0ffa574819d2e8 (diff)
downloadillumos-gate-c7facc54c4abed9e554ff80225311e6b7048d3c9.tar.gz
6932984 IBTF and HCA drivers need to more completely support FMR and ibt_map_mem_area()
-rw-r--r--usr/src/uts/common/io/ib/adapters/hermon/hermon.c6
-rw-r--r--usr/src/uts/common/io/ib/adapters/hermon/hermon_cfg.c30
-rw-r--r--usr/src/uts/common/io/ib/adapters/hermon/hermon_ci.c384
-rw-r--r--usr/src/uts/common/io/ib/adapters/hermon/hermon_cq.c7
-rw-r--r--usr/src/uts/common/io/ib/adapters/hermon/hermon_event.c3
-rw-r--r--usr/src/uts/common/io/ib/adapters/hermon/hermon_misc.c351
-rw-r--r--usr/src/uts/common/io/ib/adapters/hermon/hermon_mr.c215
-rw-r--r--usr/src/uts/common/io/ib/adapters/hermon/hermon_rsrc.c15
-rw-r--r--usr/src/uts/common/io/ib/adapters/hermon/hermon_srq.c4
-rw-r--r--usr/src/uts/common/io/ib/adapters/hermon/hermon_wr.c51
-rw-r--r--usr/src/uts/common/io/ib/adapters/tavor/tavor.c5
-rw-r--r--usr/src/uts/common/io/ib/adapters/tavor/tavor_cfg.c17
-rw-r--r--usr/src/uts/common/io/ib/adapters/tavor/tavor_ci.c334
-rw-r--r--usr/src/uts/common/io/ib/adapters/tavor/tavor_misc.c915
-rw-r--r--usr/src/uts/common/io/ib/adapters/tavor/tavor_mr.c510
-rw-r--r--usr/src/uts/common/io/ib/ibtl/ibtl_mem.c11
-rw-r--r--usr/src/uts/common/io/warlock/tavor.wlcmd7
-rw-r--r--usr/src/uts/common/sys/ib/adapters/hermon/hermon_hw.h27
-rw-r--r--usr/src/uts/common/sys/ib/adapters/hermon/hermon_misc.h13
-rw-r--r--usr/src/uts/common/sys/ib/adapters/hermon/hermon_mr.h4
-rw-r--r--usr/src/uts/common/sys/ib/adapters/tavor/tavor_misc.h77
-rw-r--r--usr/src/uts/common/sys/ib/adapters/tavor/tavor_mr.h16
-rw-r--r--usr/src/uts/common/sys/ib/adapters/tavor/tavor_typedef.h3
-rw-r--r--usr/src/uts/common/sys/ib/ibtl/ibci.h24
-rw-r--r--usr/src/uts/common/sys/ib/ibtl/ibti_common.h5
-rw-r--r--usr/src/uts/common/sys/ib/ibtl/ibtl_ci_types.h19
-rw-r--r--usr/src/uts/common/sys/ib/ibtl/ibtl_types.h18
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,
+ &reg_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 = &reg_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;