19517SBill.Taylor@Sun.COM /*
29517SBill.Taylor@Sun.COM * CDDL HEADER START
39517SBill.Taylor@Sun.COM *
49517SBill.Taylor@Sun.COM * The contents of this file are subject to the terms of the
59517SBill.Taylor@Sun.COM * Common Development and Distribution License (the "License").
69517SBill.Taylor@Sun.COM * You may not use this file except in compliance with the License.
79517SBill.Taylor@Sun.COM *
89517SBill.Taylor@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99517SBill.Taylor@Sun.COM * or http://www.opensolaris.org/os/licensing.
109517SBill.Taylor@Sun.COM * See the License for the specific language governing permissions
119517SBill.Taylor@Sun.COM * and limitations under the License.
129517SBill.Taylor@Sun.COM *
139517SBill.Taylor@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
149517SBill.Taylor@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159517SBill.Taylor@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
169517SBill.Taylor@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
179517SBill.Taylor@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
189517SBill.Taylor@Sun.COM *
199517SBill.Taylor@Sun.COM * CDDL HEADER END
209517SBill.Taylor@Sun.COM */
219517SBill.Taylor@Sun.COM
229517SBill.Taylor@Sun.COM /*
23*12965SWilliam.Taylor@Oracle.COM * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
249517SBill.Taylor@Sun.COM */
259517SBill.Taylor@Sun.COM
269517SBill.Taylor@Sun.COM /*
279517SBill.Taylor@Sun.COM * hermon_umap.c
289517SBill.Taylor@Sun.COM * Hermon Userland Mapping Routines
299517SBill.Taylor@Sun.COM *
309517SBill.Taylor@Sun.COM * Implements all the routines necessary for enabling direct userland
319517SBill.Taylor@Sun.COM * access to the Hermon hardware. This includes all routines necessary for
329517SBill.Taylor@Sun.COM * maintaining the "userland resources database" and all the support routines
339517SBill.Taylor@Sun.COM * for the devmap calls.
349517SBill.Taylor@Sun.COM */
359517SBill.Taylor@Sun.COM
369517SBill.Taylor@Sun.COM #include <sys/types.h>
379517SBill.Taylor@Sun.COM #include <sys/conf.h>
389517SBill.Taylor@Sun.COM #include <sys/ddi.h>
399517SBill.Taylor@Sun.COM #include <sys/sunddi.h>
409517SBill.Taylor@Sun.COM #include <sys/modctl.h>
419517SBill.Taylor@Sun.COM #include <sys/file.h>
429517SBill.Taylor@Sun.COM #include <sys/avl.h>
439517SBill.Taylor@Sun.COM #include <sys/sysmacros.h>
449517SBill.Taylor@Sun.COM
459517SBill.Taylor@Sun.COM #include <sys/ib/adapters/hermon/hermon.h>
469517SBill.Taylor@Sun.COM
479517SBill.Taylor@Sun.COM /* Hermon HCA state pointer (extern) */
489517SBill.Taylor@Sun.COM extern void *hermon_statep;
499517SBill.Taylor@Sun.COM
509517SBill.Taylor@Sun.COM /* Hermon HCA Userland Resource Database (extern) */
519517SBill.Taylor@Sun.COM extern hermon_umap_db_t hermon_userland_rsrc_db;
529517SBill.Taylor@Sun.COM
539517SBill.Taylor@Sun.COM static int hermon_umap_uarpg(hermon_state_t *state, devmap_cookie_t dhp,
549517SBill.Taylor@Sun.COM hermon_rsrc_t *rsrcp, uint64_t offset, size_t *maplen, int *err);
559517SBill.Taylor@Sun.COM static int hermon_umap_cqmem(hermon_state_t *state, devmap_cookie_t dhp,
569517SBill.Taylor@Sun.COM hermon_rsrc_t *rsrcp, offset_t off, size_t *maplen, int *err);
579517SBill.Taylor@Sun.COM static int hermon_umap_qpmem(hermon_state_t *state, devmap_cookie_t dhp,
589517SBill.Taylor@Sun.COM hermon_rsrc_t *rsrcp, offset_t off, size_t *maplen, int *err);
599517SBill.Taylor@Sun.COM static int hermon_umap_srqmem(hermon_state_t *state, devmap_cookie_t dhp,
609517SBill.Taylor@Sun.COM hermon_rsrc_t *rsrcp, offset_t off, size_t *maplen, int *err);
619517SBill.Taylor@Sun.COM static int hermon_umap_dbrecmem(hermon_state_t *state, devmap_cookie_t dhp,
629517SBill.Taylor@Sun.COM hermon_rsrc_t *rsrcp, offset_t off, size_t *maplen, int *err);
639517SBill.Taylor@Sun.COM static int hermon_devmap_umem_map(devmap_cookie_t dhp, dev_t dev, uint_t flags,
649517SBill.Taylor@Sun.COM offset_t off, size_t len, void **pvtp);
659517SBill.Taylor@Sun.COM static int hermon_devmap_umem_dup(devmap_cookie_t dhp, void *pvtp,
669517SBill.Taylor@Sun.COM devmap_cookie_t new_dhp, void **new_pvtp);
679517SBill.Taylor@Sun.COM static void hermon_devmap_umem_unmap(devmap_cookie_t dhp, void *pvtp,
689517SBill.Taylor@Sun.COM offset_t off, size_t len, devmap_cookie_t new_dhp1, void **pvtp1,
699517SBill.Taylor@Sun.COM devmap_cookie_t new_dhp2, void **pvtp2);
709517SBill.Taylor@Sun.COM static int hermon_devmap_dbrecmem_map(devmap_cookie_t dhp, dev_t dev,
719517SBill.Taylor@Sun.COM uint_t flags, offset_t off, size_t len, void **pvtp);
729517SBill.Taylor@Sun.COM static int hermon_devmap_dbrecmem_dup(devmap_cookie_t dhp, void *pvtp,
739517SBill.Taylor@Sun.COM devmap_cookie_t new_dhp, void **new_pvtp);
749517SBill.Taylor@Sun.COM static void hermon_devmap_dbrecmem_unmap(devmap_cookie_t dhp, void *pvtp,
759517SBill.Taylor@Sun.COM offset_t off, size_t len, devmap_cookie_t new_dhp1, void **pvtp1,
769517SBill.Taylor@Sun.COM devmap_cookie_t new_dhp2, void **pvtp2);
779517SBill.Taylor@Sun.COM static int hermon_devmap_devmem_map(devmap_cookie_t dhp, dev_t dev,
789517SBill.Taylor@Sun.COM uint_t flags, offset_t off, size_t len, void **pvtp);
799517SBill.Taylor@Sun.COM static int hermon_devmap_devmem_dup(devmap_cookie_t dhp, void *pvtp,
809517SBill.Taylor@Sun.COM devmap_cookie_t new_dhp, void **new_pvtp);
819517SBill.Taylor@Sun.COM static void hermon_devmap_devmem_unmap(devmap_cookie_t dhp, void *pvtp,
829517SBill.Taylor@Sun.COM offset_t off, size_t len, devmap_cookie_t new_dhp1, void **pvtp1,
839517SBill.Taylor@Sun.COM devmap_cookie_t new_dhp2, void **pvtp2);
849517SBill.Taylor@Sun.COM static ibt_status_t hermon_umap_mr_data_in(hermon_mrhdl_t mr,
859517SBill.Taylor@Sun.COM ibt_mr_data_in_t *data, size_t data_sz);
869517SBill.Taylor@Sun.COM static ibt_status_t hermon_umap_cq_data_out(hermon_cqhdl_t cq,
879517SBill.Taylor@Sun.COM mlnx_umap_cq_data_out_t *data, size_t data_sz);
889517SBill.Taylor@Sun.COM static ibt_status_t hermon_umap_qp_data_out(hermon_qphdl_t qp,
899517SBill.Taylor@Sun.COM mlnx_umap_qp_data_out_t *data, size_t data_sz);
909517SBill.Taylor@Sun.COM static ibt_status_t hermon_umap_srq_data_out(hermon_srqhdl_t srq,
919517SBill.Taylor@Sun.COM mlnx_umap_srq_data_out_t *data, size_t data_sz);
929517SBill.Taylor@Sun.COM static ibt_status_t hermon_umap_pd_data_out(hermon_pdhdl_t pd,
939517SBill.Taylor@Sun.COM mlnx_umap_pd_data_out_t *data, size_t data_sz);
949517SBill.Taylor@Sun.COM static int hermon_umap_db_compare(const void *query, const void *entry);
959517SBill.Taylor@Sun.COM
969517SBill.Taylor@Sun.COM
979517SBill.Taylor@Sun.COM /*
989517SBill.Taylor@Sun.COM * These callbacks are passed to devmap_umem_setup() and devmap_devmem_setup(),
999517SBill.Taylor@Sun.COM * respectively. They are used to handle (among other things) partial
1009517SBill.Taylor@Sun.COM * unmappings and to provide a method for invalidating mappings inherited
1019517SBill.Taylor@Sun.COM * as a result of a fork(2) system call.
1029517SBill.Taylor@Sun.COM */
1039517SBill.Taylor@Sun.COM static struct devmap_callback_ctl hermon_devmap_umem_cbops = {
1049517SBill.Taylor@Sun.COM DEVMAP_OPS_REV,
1059517SBill.Taylor@Sun.COM hermon_devmap_umem_map,
1069517SBill.Taylor@Sun.COM NULL,
1079517SBill.Taylor@Sun.COM hermon_devmap_umem_dup,
1089517SBill.Taylor@Sun.COM hermon_devmap_umem_unmap
1099517SBill.Taylor@Sun.COM };
1109517SBill.Taylor@Sun.COM static struct devmap_callback_ctl hermon_devmap_devmem_cbops = {
1119517SBill.Taylor@Sun.COM DEVMAP_OPS_REV,
1129517SBill.Taylor@Sun.COM hermon_devmap_devmem_map,
1139517SBill.Taylor@Sun.COM NULL,
1149517SBill.Taylor@Sun.COM hermon_devmap_devmem_dup,
1159517SBill.Taylor@Sun.COM hermon_devmap_devmem_unmap
1169517SBill.Taylor@Sun.COM };
1179517SBill.Taylor@Sun.COM static struct devmap_callback_ctl hermon_devmap_dbrecmem_cbops = {
1189517SBill.Taylor@Sun.COM DEVMAP_OPS_REV,
1199517SBill.Taylor@Sun.COM hermon_devmap_dbrecmem_map,
1209517SBill.Taylor@Sun.COM NULL,
1219517SBill.Taylor@Sun.COM hermon_devmap_dbrecmem_dup,
1229517SBill.Taylor@Sun.COM hermon_devmap_dbrecmem_unmap
1239517SBill.Taylor@Sun.COM };
1249517SBill.Taylor@Sun.COM
1259517SBill.Taylor@Sun.COM /*
1269517SBill.Taylor@Sun.COM * hermon_devmap()
1279517SBill.Taylor@Sun.COM * Context: Can be called from user context.
1289517SBill.Taylor@Sun.COM */
1299517SBill.Taylor@Sun.COM /* ARGSUSED */
1309517SBill.Taylor@Sun.COM int
hermon_devmap(dev_t dev,devmap_cookie_t dhp,offset_t off,size_t len,size_t * maplen,uint_t model)1319517SBill.Taylor@Sun.COM hermon_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off, size_t len,
1329517SBill.Taylor@Sun.COM size_t *maplen, uint_t model)
1339517SBill.Taylor@Sun.COM {
1349517SBill.Taylor@Sun.COM hermon_state_t *state;
1359517SBill.Taylor@Sun.COM hermon_rsrc_t *rsrcp;
1369517SBill.Taylor@Sun.COM minor_t instance;
1379517SBill.Taylor@Sun.COM uint64_t key, value;
1389517SBill.Taylor@Sun.COM uint64_t bf_offset = 0;
1399517SBill.Taylor@Sun.COM uint_t type;
1409517SBill.Taylor@Sun.COM int err, status;
1419517SBill.Taylor@Sun.COM
1429517SBill.Taylor@Sun.COM /* Get Hermon softstate structure from instance */
1439517SBill.Taylor@Sun.COM instance = HERMON_DEV_INSTANCE(dev);
1449517SBill.Taylor@Sun.COM state = ddi_get_soft_state(hermon_statep, instance);
1459517SBill.Taylor@Sun.COM if (state == NULL) {
1469517SBill.Taylor@Sun.COM return (ENXIO);
1479517SBill.Taylor@Sun.COM }
1489517SBill.Taylor@Sun.COM
1499517SBill.Taylor@Sun.COM /*
1509517SBill.Taylor@Sun.COM * Access to Hermon devmap interface is not allowed in
1519517SBill.Taylor@Sun.COM * "maintenance mode".
1529517SBill.Taylor@Sun.COM */
1539517SBill.Taylor@Sun.COM if (state->hs_operational_mode == HERMON_MAINTENANCE_MODE) {
1549517SBill.Taylor@Sun.COM return (EFAULT);
1559517SBill.Taylor@Sun.COM }
1569517SBill.Taylor@Sun.COM
1579517SBill.Taylor@Sun.COM /*
1589517SBill.Taylor@Sun.COM * The bottom bits of "offset" are undefined (number depends on
1599517SBill.Taylor@Sun.COM * system PAGESIZE). Shifting these off leaves us with a "key".
1609517SBill.Taylor@Sun.COM * The "key" is actually a combination of both a real key value
1619517SBill.Taylor@Sun.COM * (for the purpose of database lookup) and a "type" value. We
1629517SBill.Taylor@Sun.COM * extract this information before doing the database lookup.
1639517SBill.Taylor@Sun.COM */
1649517SBill.Taylor@Sun.COM key = off >> PAGESHIFT;
1659517SBill.Taylor@Sun.COM type = key & MLNX_UMAP_RSRC_TYPE_MASK;
1669517SBill.Taylor@Sun.COM key = key >> MLNX_UMAP_RSRC_TYPE_SHIFT;
1679517SBill.Taylor@Sun.COM if (type == MLNX_UMAP_BLUEFLAMEPG_RSRC) {
1689517SBill.Taylor@Sun.COM if (state->hs_devlim.blu_flm == 0) {
1699517SBill.Taylor@Sun.COM return (EFAULT);
1709517SBill.Taylor@Sun.COM }
1719517SBill.Taylor@Sun.COM bf_offset = state->hs_bf_offset;
1729517SBill.Taylor@Sun.COM type = MLNX_UMAP_UARPG_RSRC;
1739517SBill.Taylor@Sun.COM }
1749517SBill.Taylor@Sun.COM status = hermon_umap_db_find(instance, key, type, &value, 0, NULL);
1759517SBill.Taylor@Sun.COM if (status == DDI_SUCCESS) {
1769517SBill.Taylor@Sun.COM rsrcp = (hermon_rsrc_t *)(uintptr_t)value;
1779517SBill.Taylor@Sun.COM
1789517SBill.Taylor@Sun.COM switch (type) {
1799517SBill.Taylor@Sun.COM case MLNX_UMAP_UARPG_RSRC:
1809517SBill.Taylor@Sun.COM /*
1819517SBill.Taylor@Sun.COM * Double check that process who open()'d Hermon is
1829517SBill.Taylor@Sun.COM * same process attempting to mmap() UAR page.
1839517SBill.Taylor@Sun.COM */
1849517SBill.Taylor@Sun.COM if (key != ddi_get_pid()) {
1859517SBill.Taylor@Sun.COM return (EINVAL);
1869517SBill.Taylor@Sun.COM }
1879517SBill.Taylor@Sun.COM
1889517SBill.Taylor@Sun.COM /* Map the UAR page out for userland access */
1899517SBill.Taylor@Sun.COM status = hermon_umap_uarpg(state, dhp, rsrcp, bf_offset,
1909517SBill.Taylor@Sun.COM maplen, &err);
1919517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
1929517SBill.Taylor@Sun.COM return (err);
1939517SBill.Taylor@Sun.COM }
1949517SBill.Taylor@Sun.COM break;
1959517SBill.Taylor@Sun.COM
1969517SBill.Taylor@Sun.COM case MLNX_UMAP_CQMEM_RSRC:
1979517SBill.Taylor@Sun.COM /* Map the CQ memory out for userland access */
1989517SBill.Taylor@Sun.COM status = hermon_umap_cqmem(state, dhp, rsrcp, off,
1999517SBill.Taylor@Sun.COM maplen, &err);
2009517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
2019517SBill.Taylor@Sun.COM return (err);
2029517SBill.Taylor@Sun.COM }
2039517SBill.Taylor@Sun.COM break;
2049517SBill.Taylor@Sun.COM
2059517SBill.Taylor@Sun.COM case MLNX_UMAP_QPMEM_RSRC:
2069517SBill.Taylor@Sun.COM /* Map the QP memory out for userland access */
2079517SBill.Taylor@Sun.COM status = hermon_umap_qpmem(state, dhp, rsrcp, off,
2089517SBill.Taylor@Sun.COM maplen, &err);
2099517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
2109517SBill.Taylor@Sun.COM return (err);
2119517SBill.Taylor@Sun.COM }
2129517SBill.Taylor@Sun.COM break;
2139517SBill.Taylor@Sun.COM
2149517SBill.Taylor@Sun.COM case MLNX_UMAP_SRQMEM_RSRC:
2159517SBill.Taylor@Sun.COM /* Map the SRQ memory out for userland access */
2169517SBill.Taylor@Sun.COM status = hermon_umap_srqmem(state, dhp, rsrcp, off,
2179517SBill.Taylor@Sun.COM maplen, &err);
2189517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
2199517SBill.Taylor@Sun.COM return (err);
2209517SBill.Taylor@Sun.COM }
2219517SBill.Taylor@Sun.COM break;
2229517SBill.Taylor@Sun.COM
2239517SBill.Taylor@Sun.COM case MLNX_UMAP_DBRMEM_RSRC:
2249517SBill.Taylor@Sun.COM /*
2259517SBill.Taylor@Sun.COM * Map the doorbell record memory out for
2269517SBill.Taylor@Sun.COM * userland access
2279517SBill.Taylor@Sun.COM */
2289517SBill.Taylor@Sun.COM status = hermon_umap_dbrecmem(state, dhp, rsrcp, off,
2299517SBill.Taylor@Sun.COM maplen, &err);
2309517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
2319517SBill.Taylor@Sun.COM return (err);
2329517SBill.Taylor@Sun.COM }
2339517SBill.Taylor@Sun.COM break;
2349517SBill.Taylor@Sun.COM
2359517SBill.Taylor@Sun.COM default:
2369517SBill.Taylor@Sun.COM HERMON_WARNING(state, "unexpected rsrc type in devmap");
2379517SBill.Taylor@Sun.COM return (EINVAL);
2389517SBill.Taylor@Sun.COM }
2399517SBill.Taylor@Sun.COM } else {
2409517SBill.Taylor@Sun.COM return (EINVAL);
2419517SBill.Taylor@Sun.COM }
2429517SBill.Taylor@Sun.COM
2439517SBill.Taylor@Sun.COM return (0);
2449517SBill.Taylor@Sun.COM }
2459517SBill.Taylor@Sun.COM
2469517SBill.Taylor@Sun.COM
2479517SBill.Taylor@Sun.COM /*
2489517SBill.Taylor@Sun.COM * hermon_umap_uarpg()
2499517SBill.Taylor@Sun.COM * Context: Can be called from user context.
2509517SBill.Taylor@Sun.COM */
2519517SBill.Taylor@Sun.COM static int
hermon_umap_uarpg(hermon_state_t * state,devmap_cookie_t dhp,hermon_rsrc_t * rsrcp,uint64_t offset,size_t * maplen,int * err)2529517SBill.Taylor@Sun.COM hermon_umap_uarpg(hermon_state_t *state, devmap_cookie_t dhp,
2539517SBill.Taylor@Sun.COM hermon_rsrc_t *rsrcp, uint64_t offset, size_t *maplen, int *err)
2549517SBill.Taylor@Sun.COM {
2559517SBill.Taylor@Sun.COM int status;
2569517SBill.Taylor@Sun.COM uint_t maxprot;
2579517SBill.Taylor@Sun.COM ddi_device_acc_attr_t *accattrp = &state->hs_reg_accattr;
2589517SBill.Taylor@Sun.COM ddi_device_acc_attr_t accattr;
2599517SBill.Taylor@Sun.COM
2609517SBill.Taylor@Sun.COM if (offset != 0) { /* Hermon Blueflame */
2619517SBill.Taylor@Sun.COM /* Try to use write coalescing data ordering */
2629517SBill.Taylor@Sun.COM accattr = *accattrp;
2639517SBill.Taylor@Sun.COM accattr.devacc_attr_dataorder = DDI_STORECACHING_OK_ACC;
2649517SBill.Taylor@Sun.COM accattrp = &accattr;
2659517SBill.Taylor@Sun.COM }
2669517SBill.Taylor@Sun.COM
2679517SBill.Taylor@Sun.COM /* Map out the UAR page (doorbell page) */
2689517SBill.Taylor@Sun.COM maxprot = (PROT_READ | PROT_WRITE | PROT_USER);
2699517SBill.Taylor@Sun.COM status = devmap_devmem_setup(dhp, state->hs_dip,
2709517SBill.Taylor@Sun.COM &hermon_devmap_devmem_cbops, HERMON_UAR_BAR, (rsrcp->hr_indx <<
2719517SBill.Taylor@Sun.COM PAGESHIFT) + offset, PAGESIZE, maxprot, DEVMAP_ALLOW_REMAP,
2729517SBill.Taylor@Sun.COM accattrp);
2739517SBill.Taylor@Sun.COM if (status < 0) {
2749517SBill.Taylor@Sun.COM *err = status;
2759517SBill.Taylor@Sun.COM return (DDI_FAILURE);
2769517SBill.Taylor@Sun.COM }
2779517SBill.Taylor@Sun.COM
2789517SBill.Taylor@Sun.COM *maplen = PAGESIZE;
2799517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
2809517SBill.Taylor@Sun.COM }
2819517SBill.Taylor@Sun.COM
2829517SBill.Taylor@Sun.COM
2839517SBill.Taylor@Sun.COM /*
2849517SBill.Taylor@Sun.COM * hermon_umap_cqmem()
2859517SBill.Taylor@Sun.COM * Context: Can be called from user context.
2869517SBill.Taylor@Sun.COM */
2879517SBill.Taylor@Sun.COM /* ARGSUSED */
2889517SBill.Taylor@Sun.COM static int
hermon_umap_cqmem(hermon_state_t * state,devmap_cookie_t dhp,hermon_rsrc_t * rsrcp,offset_t off,size_t * maplen,int * err)2899517SBill.Taylor@Sun.COM hermon_umap_cqmem(hermon_state_t *state, devmap_cookie_t dhp,
2909517SBill.Taylor@Sun.COM hermon_rsrc_t *rsrcp, offset_t off, size_t *maplen, int *err)
2919517SBill.Taylor@Sun.COM {
2929517SBill.Taylor@Sun.COM hermon_cqhdl_t cq;
2939517SBill.Taylor@Sun.COM size_t size;
2949517SBill.Taylor@Sun.COM uint_t maxprot;
2959517SBill.Taylor@Sun.COM int status;
2969517SBill.Taylor@Sun.COM
2979517SBill.Taylor@Sun.COM /* Extract the Hermon CQ handle pointer from the hermon_rsrc_t */
2989517SBill.Taylor@Sun.COM cq = (hermon_cqhdl_t)rsrcp->hr_addr;
2999517SBill.Taylor@Sun.COM
3009517SBill.Taylor@Sun.COM /* Round-up the CQ size to system page size */
3019517SBill.Taylor@Sun.COM size = ptob(btopr(cq->cq_resize_hdl ?
3029517SBill.Taylor@Sun.COM cq->cq_resize_hdl->cq_cqinfo.qa_size : cq->cq_cqinfo.qa_size));
3039517SBill.Taylor@Sun.COM
3049517SBill.Taylor@Sun.COM /* Map out the CQ memory - use resize_hdl if non-NULL */
3059517SBill.Taylor@Sun.COM maxprot = (PROT_READ | PROT_WRITE | PROT_USER);
3069517SBill.Taylor@Sun.COM status = devmap_umem_setup(dhp, state->hs_dip,
3079517SBill.Taylor@Sun.COM &hermon_devmap_umem_cbops, cq->cq_resize_hdl ?
3089517SBill.Taylor@Sun.COM cq->cq_resize_hdl->cq_cqinfo.qa_umemcookie :
3099517SBill.Taylor@Sun.COM cq->cq_cqinfo.qa_umemcookie, 0, size,
3109517SBill.Taylor@Sun.COM maxprot, (DEVMAP_ALLOW_REMAP | DEVMAP_DEFAULTS), NULL);
3119517SBill.Taylor@Sun.COM if (status < 0) {
3129517SBill.Taylor@Sun.COM *err = status;
3139517SBill.Taylor@Sun.COM return (DDI_FAILURE);
3149517SBill.Taylor@Sun.COM }
3159517SBill.Taylor@Sun.COM *maplen = size;
3169517SBill.Taylor@Sun.COM
3179517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
3189517SBill.Taylor@Sun.COM }
3199517SBill.Taylor@Sun.COM
3209517SBill.Taylor@Sun.COM
3219517SBill.Taylor@Sun.COM /*
3229517SBill.Taylor@Sun.COM * hermon_umap_qpmem()
3239517SBill.Taylor@Sun.COM * Context: Can be called from user context.
3249517SBill.Taylor@Sun.COM */
3259517SBill.Taylor@Sun.COM /* ARGSUSED */
3269517SBill.Taylor@Sun.COM static int
hermon_umap_qpmem(hermon_state_t * state,devmap_cookie_t dhp,hermon_rsrc_t * rsrcp,offset_t off,size_t * maplen,int * err)3279517SBill.Taylor@Sun.COM hermon_umap_qpmem(hermon_state_t *state, devmap_cookie_t dhp,
3289517SBill.Taylor@Sun.COM hermon_rsrc_t *rsrcp, offset_t off, size_t *maplen, int *err)
3299517SBill.Taylor@Sun.COM {
3309517SBill.Taylor@Sun.COM hermon_qphdl_t qp;
3319517SBill.Taylor@Sun.COM offset_t offset;
3329517SBill.Taylor@Sun.COM size_t size;
3339517SBill.Taylor@Sun.COM uint_t maxprot;
3349517SBill.Taylor@Sun.COM int status;
3359517SBill.Taylor@Sun.COM
3369517SBill.Taylor@Sun.COM /* Extract the Hermon QP handle pointer from the hermon_rsrc_t */
3379517SBill.Taylor@Sun.COM qp = (hermon_qphdl_t)rsrcp->hr_addr;
3389517SBill.Taylor@Sun.COM
3399517SBill.Taylor@Sun.COM /*
3409517SBill.Taylor@Sun.COM * Calculate the offset of the first work queue (send or recv) into
3419517SBill.Taylor@Sun.COM * the memory (ddi_umem_alloc()) allocated previously for the QP.
3429517SBill.Taylor@Sun.COM */
3439517SBill.Taylor@Sun.COM offset = (offset_t)((uintptr_t)qp->qp_wqinfo.qa_buf_aligned -
3449517SBill.Taylor@Sun.COM (uintptr_t)qp->qp_wqinfo.qa_buf_real);
3459517SBill.Taylor@Sun.COM
3469517SBill.Taylor@Sun.COM /* Round-up the QP work queue sizes to system page size */
3479517SBill.Taylor@Sun.COM size = ptob(btopr(qp->qp_wqinfo.qa_size));
3489517SBill.Taylor@Sun.COM
3499517SBill.Taylor@Sun.COM /* Map out the QP memory */
3509517SBill.Taylor@Sun.COM maxprot = (PROT_READ | PROT_WRITE | PROT_USER);
3519517SBill.Taylor@Sun.COM status = devmap_umem_setup(dhp, state->hs_dip,
3529517SBill.Taylor@Sun.COM &hermon_devmap_umem_cbops, qp->qp_wqinfo.qa_umemcookie, offset,
3539517SBill.Taylor@Sun.COM size, maxprot, (DEVMAP_ALLOW_REMAP | DEVMAP_DEFAULTS), NULL);
3549517SBill.Taylor@Sun.COM if (status < 0) {
3559517SBill.Taylor@Sun.COM *err = status;
3569517SBill.Taylor@Sun.COM return (DDI_FAILURE);
3579517SBill.Taylor@Sun.COM }
3589517SBill.Taylor@Sun.COM *maplen = size;
3599517SBill.Taylor@Sun.COM
3609517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
3619517SBill.Taylor@Sun.COM }
3629517SBill.Taylor@Sun.COM
3639517SBill.Taylor@Sun.COM
3649517SBill.Taylor@Sun.COM /*
3659517SBill.Taylor@Sun.COM * hermon_umap_srqmem()
3669517SBill.Taylor@Sun.COM * Context: Can be called from user context.
3679517SBill.Taylor@Sun.COM */
3689517SBill.Taylor@Sun.COM /* ARGSUSED */
3699517SBill.Taylor@Sun.COM static int
hermon_umap_srqmem(hermon_state_t * state,devmap_cookie_t dhp,hermon_rsrc_t * rsrcp,offset_t off,size_t * maplen,int * err)3709517SBill.Taylor@Sun.COM hermon_umap_srqmem(hermon_state_t *state, devmap_cookie_t dhp,
3719517SBill.Taylor@Sun.COM hermon_rsrc_t *rsrcp, offset_t off, size_t *maplen, int *err)
3729517SBill.Taylor@Sun.COM {
3739517SBill.Taylor@Sun.COM hermon_srqhdl_t srq;
3749517SBill.Taylor@Sun.COM offset_t offset;
3759517SBill.Taylor@Sun.COM size_t size;
3769517SBill.Taylor@Sun.COM uint_t maxprot;
3779517SBill.Taylor@Sun.COM int status;
3789517SBill.Taylor@Sun.COM
3799517SBill.Taylor@Sun.COM /* Extract the Hermon SRQ handle pointer from the hermon_rsrc_t */
3809517SBill.Taylor@Sun.COM srq = (hermon_srqhdl_t)rsrcp->hr_addr;
3819517SBill.Taylor@Sun.COM
3829517SBill.Taylor@Sun.COM /*
3839517SBill.Taylor@Sun.COM * Calculate the offset of the first shared recv queue into the memory
3849517SBill.Taylor@Sun.COM * (ddi_umem_alloc()) allocated previously for the SRQ.
3859517SBill.Taylor@Sun.COM */
3869517SBill.Taylor@Sun.COM offset = (offset_t)((uintptr_t)srq->srq_wqinfo.qa_buf_aligned -
3879517SBill.Taylor@Sun.COM (uintptr_t)srq->srq_wqinfo.qa_buf_real);
3889517SBill.Taylor@Sun.COM
3899517SBill.Taylor@Sun.COM /* Round-up the SRQ work queue sizes to system page size */
3909517SBill.Taylor@Sun.COM size = ptob(btopr(srq->srq_wqinfo.qa_size));
3919517SBill.Taylor@Sun.COM
3929517SBill.Taylor@Sun.COM /* Map out the SRQ memory */
3939517SBill.Taylor@Sun.COM maxprot = (PROT_READ | PROT_WRITE | PROT_USER);
3949517SBill.Taylor@Sun.COM status = devmap_umem_setup(dhp, state->hs_dip,
3959517SBill.Taylor@Sun.COM &hermon_devmap_umem_cbops, srq->srq_wqinfo.qa_umemcookie, offset,
3969517SBill.Taylor@Sun.COM size, maxprot, (DEVMAP_ALLOW_REMAP | DEVMAP_DEFAULTS), NULL);
3979517SBill.Taylor@Sun.COM if (status < 0) {
3989517SBill.Taylor@Sun.COM *err = status;
3999517SBill.Taylor@Sun.COM return (DDI_FAILURE);
4009517SBill.Taylor@Sun.COM }
4019517SBill.Taylor@Sun.COM *maplen = size;
4029517SBill.Taylor@Sun.COM
4039517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
4049517SBill.Taylor@Sun.COM }
4059517SBill.Taylor@Sun.COM
4069517SBill.Taylor@Sun.COM
4079517SBill.Taylor@Sun.COM /*
4089517SBill.Taylor@Sun.COM * hermon_devmap_dbrecmem()
4099517SBill.Taylor@Sun.COM * Context: Can be called from user context.
4109517SBill.Taylor@Sun.COM */
4119517SBill.Taylor@Sun.COM /* ARGSUSED */
4129517SBill.Taylor@Sun.COM static int
hermon_umap_dbrecmem(hermon_state_t * state,devmap_cookie_t dhp,hermon_rsrc_t * rsrcp,offset_t off,size_t * maplen,int * err)4139517SBill.Taylor@Sun.COM hermon_umap_dbrecmem(hermon_state_t *state, devmap_cookie_t dhp,
4149517SBill.Taylor@Sun.COM hermon_rsrc_t *rsrcp, offset_t off, size_t *maplen, int *err)
4159517SBill.Taylor@Sun.COM {
4169517SBill.Taylor@Sun.COM hermon_udbr_page_t *pagep;
4179517SBill.Taylor@Sun.COM offset_t offset;
4189517SBill.Taylor@Sun.COM size_t size;
4199517SBill.Taylor@Sun.COM uint_t maxprot;
4209517SBill.Taylor@Sun.COM int status;
4219517SBill.Taylor@Sun.COM
4229517SBill.Taylor@Sun.COM /* We stored the udbr_page pointer, and not a hermon_rsrc_t */
4239517SBill.Taylor@Sun.COM pagep = (hermon_udbr_page_t *)rsrcp;
4249517SBill.Taylor@Sun.COM
4259517SBill.Taylor@Sun.COM /*
4269517SBill.Taylor@Sun.COM * Calculate the offset of the doorbell records into the memory
4279517SBill.Taylor@Sun.COM * (ddi_umem_alloc()) allocated previously for them.
4289517SBill.Taylor@Sun.COM */
4299517SBill.Taylor@Sun.COM offset = 0;
4309517SBill.Taylor@Sun.COM
4319517SBill.Taylor@Sun.COM /* Round-up the doorbell page to system page size */
4329517SBill.Taylor@Sun.COM size = PAGESIZE;
4339517SBill.Taylor@Sun.COM
4349517SBill.Taylor@Sun.COM /* Map out the Doorbell Record memory */
4359517SBill.Taylor@Sun.COM maxprot = (PROT_READ | PROT_WRITE | PROT_USER);
4369517SBill.Taylor@Sun.COM status = devmap_umem_setup(dhp, state->hs_dip,
4379517SBill.Taylor@Sun.COM &hermon_devmap_dbrecmem_cbops, pagep->upg_umemcookie, offset,
4389517SBill.Taylor@Sun.COM size, maxprot, (DEVMAP_ALLOW_REMAP | DEVMAP_DEFAULTS), NULL);
4399517SBill.Taylor@Sun.COM if (status < 0) {
4409517SBill.Taylor@Sun.COM *err = status;
4419517SBill.Taylor@Sun.COM return (DDI_FAILURE);
4429517SBill.Taylor@Sun.COM }
4439517SBill.Taylor@Sun.COM *maplen = size;
4449517SBill.Taylor@Sun.COM
4459517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
4469517SBill.Taylor@Sun.COM }
4479517SBill.Taylor@Sun.COM
4489517SBill.Taylor@Sun.COM
4499517SBill.Taylor@Sun.COM /*
4509517SBill.Taylor@Sun.COM * hermon_devmap_umem_map()
4519517SBill.Taylor@Sun.COM * Context: Can be called from kernel context.
4529517SBill.Taylor@Sun.COM */
4539517SBill.Taylor@Sun.COM /* ARGSUSED */
4549517SBill.Taylor@Sun.COM static int
hermon_devmap_umem_map(devmap_cookie_t dhp,dev_t dev,uint_t flags,offset_t off,size_t len,void ** pvtp)4559517SBill.Taylor@Sun.COM hermon_devmap_umem_map(devmap_cookie_t dhp, dev_t dev, uint_t flags,
4569517SBill.Taylor@Sun.COM offset_t off, size_t len, void **pvtp)
4579517SBill.Taylor@Sun.COM {
4589517SBill.Taylor@Sun.COM hermon_state_t *state;
4599517SBill.Taylor@Sun.COM hermon_devmap_track_t *dvm_track;
4609517SBill.Taylor@Sun.COM hermon_cqhdl_t cq;
4619517SBill.Taylor@Sun.COM hermon_qphdl_t qp;
4629517SBill.Taylor@Sun.COM hermon_srqhdl_t srq;
4639517SBill.Taylor@Sun.COM minor_t instance;
4649517SBill.Taylor@Sun.COM uint64_t key;
4659517SBill.Taylor@Sun.COM uint_t type;
4669517SBill.Taylor@Sun.COM
4679517SBill.Taylor@Sun.COM /* Get Hermon softstate structure from instance */
4689517SBill.Taylor@Sun.COM instance = HERMON_DEV_INSTANCE(dev);
4699517SBill.Taylor@Sun.COM state = ddi_get_soft_state(hermon_statep, instance);
4709517SBill.Taylor@Sun.COM if (state == NULL) {
4719517SBill.Taylor@Sun.COM return (ENXIO);
4729517SBill.Taylor@Sun.COM }
4739517SBill.Taylor@Sun.COM
4749517SBill.Taylor@Sun.COM /*
4759517SBill.Taylor@Sun.COM * The bottom bits of "offset" are undefined (number depends on
4769517SBill.Taylor@Sun.COM * system PAGESIZE). Shifting these off leaves us with a "key".
4779517SBill.Taylor@Sun.COM * The "key" is actually a combination of both a real key value
4789517SBill.Taylor@Sun.COM * (for the purpose of database lookup) and a "type" value. Although
4799517SBill.Taylor@Sun.COM * we are not going to do any database lookup per se, we do want
4809517SBill.Taylor@Sun.COM * to extract the "key" and the "type" (to enable faster lookup of
4819517SBill.Taylor@Sun.COM * the appropriate CQ or QP handle).
4829517SBill.Taylor@Sun.COM */
4839517SBill.Taylor@Sun.COM key = off >> PAGESHIFT;
4849517SBill.Taylor@Sun.COM type = key & MLNX_UMAP_RSRC_TYPE_MASK;
4859517SBill.Taylor@Sun.COM key = key >> MLNX_UMAP_RSRC_TYPE_SHIFT;
4869517SBill.Taylor@Sun.COM
4879517SBill.Taylor@Sun.COM /*
4889517SBill.Taylor@Sun.COM * Allocate an entry to track the mapping and unmapping (specifically,
4899517SBill.Taylor@Sun.COM * partial unmapping) of this resource.
4909517SBill.Taylor@Sun.COM */
4919517SBill.Taylor@Sun.COM dvm_track = (hermon_devmap_track_t *)kmem_zalloc(
4929517SBill.Taylor@Sun.COM sizeof (hermon_devmap_track_t), KM_SLEEP);
4939517SBill.Taylor@Sun.COM _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dvm_track))
4949517SBill.Taylor@Sun.COM dvm_track->hdt_offset = off;
4959517SBill.Taylor@Sun.COM dvm_track->hdt_state = state;
4969517SBill.Taylor@Sun.COM dvm_track->hdt_refcnt = 1;
4979517SBill.Taylor@Sun.COM mutex_init(&dvm_track->hdt_lock, NULL, MUTEX_DRIVER,
4989517SBill.Taylor@Sun.COM DDI_INTR_PRI(state->hs_intrmsi_pri));
4999517SBill.Taylor@Sun.COM
5009517SBill.Taylor@Sun.COM /*
5019517SBill.Taylor@Sun.COM * Depending of the type of resource that has been mapped out, we
5029517SBill.Taylor@Sun.COM * need to update the QP or CQ handle to reflect that it has, in
5039517SBill.Taylor@Sun.COM * fact, been mapped. This allows the driver code which frees a QP
5049517SBill.Taylor@Sun.COM * or a CQ to know whether it is appropriate to do a
5059517SBill.Taylor@Sun.COM * devmap_devmem_remap() to invalidate the userland mapping for the
5069517SBill.Taylor@Sun.COM * corresponding queue's memory.
5079517SBill.Taylor@Sun.COM */
5089517SBill.Taylor@Sun.COM if (type == MLNX_UMAP_CQMEM_RSRC) {
5099517SBill.Taylor@Sun.COM
5109517SBill.Taylor@Sun.COM /* Use "key" (CQ number) to do fast lookup of CQ handle */
5119517SBill.Taylor@Sun.COM cq = hermon_cqhdl_from_cqnum(state, key);
5129517SBill.Taylor@Sun.COM
5139517SBill.Taylor@Sun.COM /*
5149517SBill.Taylor@Sun.COM * Update the handle to the userland mapping. Note: If
5159517SBill.Taylor@Sun.COM * the CQ already has a valid userland mapping, then stop
5169517SBill.Taylor@Sun.COM * and return failure.
5179517SBill.Taylor@Sun.COM */
5189517SBill.Taylor@Sun.COM mutex_enter(&cq->cq_lock);
5199517SBill.Taylor@Sun.COM if (cq->cq_umap_dhp == NULL) {
5209517SBill.Taylor@Sun.COM cq->cq_umap_dhp = dhp;
5219517SBill.Taylor@Sun.COM dvm_track->hdt_size = cq->cq_cqinfo.qa_size;
5229517SBill.Taylor@Sun.COM mutex_exit(&cq->cq_lock);
5239517SBill.Taylor@Sun.COM } else if (cq->cq_resize_hdl &&
5249517SBill.Taylor@Sun.COM (cq->cq_resize_hdl->cq_umap_dhp == NULL)) {
5259517SBill.Taylor@Sun.COM cq->cq_resize_hdl->cq_umap_dhp = dhp;
5269517SBill.Taylor@Sun.COM dvm_track->hdt_size =
5279517SBill.Taylor@Sun.COM cq->cq_resize_hdl->cq_cqinfo.qa_size;
5289517SBill.Taylor@Sun.COM mutex_exit(&cq->cq_lock);
5299517SBill.Taylor@Sun.COM } else {
5309517SBill.Taylor@Sun.COM mutex_exit(&cq->cq_lock);
5319517SBill.Taylor@Sun.COM goto umem_map_fail;
5329517SBill.Taylor@Sun.COM }
5339517SBill.Taylor@Sun.COM
5349517SBill.Taylor@Sun.COM } else if (type == MLNX_UMAP_QPMEM_RSRC) {
5359517SBill.Taylor@Sun.COM
5369517SBill.Taylor@Sun.COM /* Use "key" (QP number) to do fast lookup of QP handle */
5379517SBill.Taylor@Sun.COM qp = hermon_qphdl_from_qpnum(state, key);
5389517SBill.Taylor@Sun.COM
5399517SBill.Taylor@Sun.COM /*
5409517SBill.Taylor@Sun.COM * Update the handle to the userland mapping. Note: If
5419517SBill.Taylor@Sun.COM * the CQ already has a valid userland mapping, then stop
5429517SBill.Taylor@Sun.COM * and return failure.
5439517SBill.Taylor@Sun.COM */
5449517SBill.Taylor@Sun.COM mutex_enter(&qp->qp_lock);
5459517SBill.Taylor@Sun.COM if (qp->qp_umap_dhp == NULL) {
5469517SBill.Taylor@Sun.COM qp->qp_umap_dhp = dhp;
5479517SBill.Taylor@Sun.COM dvm_track->hdt_size = qp->qp_wqinfo.qa_size;
5489517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
5499517SBill.Taylor@Sun.COM } else {
5509517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
5519517SBill.Taylor@Sun.COM goto umem_map_fail;
5529517SBill.Taylor@Sun.COM }
5539517SBill.Taylor@Sun.COM
5549517SBill.Taylor@Sun.COM } else if (type == MLNX_UMAP_SRQMEM_RSRC) {
5559517SBill.Taylor@Sun.COM
5569517SBill.Taylor@Sun.COM /* Use "key" (SRQ number) to do fast lookup on SRQ handle */
5579517SBill.Taylor@Sun.COM srq = hermon_srqhdl_from_srqnum(state, key);
5589517SBill.Taylor@Sun.COM
5599517SBill.Taylor@Sun.COM /*
5609517SBill.Taylor@Sun.COM * Update the handle to the userland mapping. Note: If the
5619517SBill.Taylor@Sun.COM * SRQ already has a valid userland mapping, then stop and
5629517SBill.Taylor@Sun.COM * return failure.
5639517SBill.Taylor@Sun.COM */
5649517SBill.Taylor@Sun.COM mutex_enter(&srq->srq_lock);
5659517SBill.Taylor@Sun.COM if (srq->srq_umap_dhp == NULL) {
5669517SBill.Taylor@Sun.COM srq->srq_umap_dhp = dhp;
5679517SBill.Taylor@Sun.COM dvm_track->hdt_size = srq->srq_wqinfo.qa_size;
5689517SBill.Taylor@Sun.COM mutex_exit(&srq->srq_lock);
5699517SBill.Taylor@Sun.COM } else {
5709517SBill.Taylor@Sun.COM mutex_exit(&srq->srq_lock);
5719517SBill.Taylor@Sun.COM goto umem_map_fail;
5729517SBill.Taylor@Sun.COM }
5739517SBill.Taylor@Sun.COM }
5749517SBill.Taylor@Sun.COM
5759517SBill.Taylor@Sun.COM /*
5769517SBill.Taylor@Sun.COM * Pass the private "Hermon devmap tracking structure" back. This
5779517SBill.Taylor@Sun.COM * pointer will be returned in subsequent "unmap" callbacks.
5789517SBill.Taylor@Sun.COM */
5799517SBill.Taylor@Sun.COM *pvtp = dvm_track;
5809517SBill.Taylor@Sun.COM
5819517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
5829517SBill.Taylor@Sun.COM
5839517SBill.Taylor@Sun.COM umem_map_fail:
5849517SBill.Taylor@Sun.COM mutex_destroy(&dvm_track->hdt_lock);
5859517SBill.Taylor@Sun.COM kmem_free(dvm_track, sizeof (hermon_devmap_track_t));
5869517SBill.Taylor@Sun.COM return (DDI_FAILURE);
5879517SBill.Taylor@Sun.COM }
5889517SBill.Taylor@Sun.COM
5899517SBill.Taylor@Sun.COM
5909517SBill.Taylor@Sun.COM /*
5919517SBill.Taylor@Sun.COM * hermon_devmap_umem_dup()
5929517SBill.Taylor@Sun.COM * Context: Can be called from kernel context.
5939517SBill.Taylor@Sun.COM */
5949517SBill.Taylor@Sun.COM /* ARGSUSED */
5959517SBill.Taylor@Sun.COM static int
hermon_devmap_umem_dup(devmap_cookie_t dhp,void * pvtp,devmap_cookie_t new_dhp,void ** new_pvtp)5969517SBill.Taylor@Sun.COM hermon_devmap_umem_dup(devmap_cookie_t dhp, void *pvtp, devmap_cookie_t new_dhp,
5979517SBill.Taylor@Sun.COM void **new_pvtp)
5989517SBill.Taylor@Sun.COM {
5999517SBill.Taylor@Sun.COM hermon_state_t *state;
6009517SBill.Taylor@Sun.COM hermon_devmap_track_t *dvm_track, *new_dvm_track;
6019517SBill.Taylor@Sun.COM uint_t maxprot;
6029517SBill.Taylor@Sun.COM int status;
6039517SBill.Taylor@Sun.COM
6049517SBill.Taylor@Sun.COM /*
6059517SBill.Taylor@Sun.COM * Extract the Hermon softstate pointer from "Hermon devmap tracking
6069517SBill.Taylor@Sun.COM * structure" (in "pvtp").
6079517SBill.Taylor@Sun.COM */
6089517SBill.Taylor@Sun.COM dvm_track = (hermon_devmap_track_t *)pvtp;
6099517SBill.Taylor@Sun.COM _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dvm_track))
6109517SBill.Taylor@Sun.COM state = dvm_track->hdt_state;
6119517SBill.Taylor@Sun.COM
6129517SBill.Taylor@Sun.COM /*
6139517SBill.Taylor@Sun.COM * Since this devmap_dup() entry point is generally called
6149517SBill.Taylor@Sun.COM * when a process does fork(2), it is incumbent upon the driver
6159517SBill.Taylor@Sun.COM * to insure that the child does not inherit a valid copy of
6169517SBill.Taylor@Sun.COM * the parent's QP or CQ resource. This is accomplished by using
6179517SBill.Taylor@Sun.COM * devmap_devmem_remap() to invalidate the child's mapping to the
6189517SBill.Taylor@Sun.COM * kernel memory.
6199517SBill.Taylor@Sun.COM */
6209517SBill.Taylor@Sun.COM maxprot = (PROT_READ | PROT_WRITE | PROT_USER);
6219517SBill.Taylor@Sun.COM status = devmap_devmem_remap(new_dhp, state->hs_dip, 0, 0,
6229517SBill.Taylor@Sun.COM dvm_track->hdt_size, maxprot, DEVMAP_MAPPING_INVALID, NULL);
6239517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
6249517SBill.Taylor@Sun.COM HERMON_WARNING(state, "failed in hermon_devmap_umem_dup()");
6259517SBill.Taylor@Sun.COM return (status);
6269517SBill.Taylor@Sun.COM }
6279517SBill.Taylor@Sun.COM
6289517SBill.Taylor@Sun.COM /*
6299517SBill.Taylor@Sun.COM * Allocate a new entry to track the subsequent unmapping
6309517SBill.Taylor@Sun.COM * (specifically, all partial unmappings) of the child's newly
6319517SBill.Taylor@Sun.COM * invalidated resource. Note: Setting the "hdt_size" field to
6329517SBill.Taylor@Sun.COM * zero here is an indication to the devmap_unmap() entry point
6339517SBill.Taylor@Sun.COM * that this mapping is invalid, and that its subsequent unmapping
6349517SBill.Taylor@Sun.COM * should not affect any of the parent's CQ or QP resources.
6359517SBill.Taylor@Sun.COM */
6369517SBill.Taylor@Sun.COM new_dvm_track = (hermon_devmap_track_t *)kmem_zalloc(
6379517SBill.Taylor@Sun.COM sizeof (hermon_devmap_track_t), KM_SLEEP);
6389517SBill.Taylor@Sun.COM _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*new_dvm_track))
6399517SBill.Taylor@Sun.COM new_dvm_track->hdt_offset = 0;
6409517SBill.Taylor@Sun.COM new_dvm_track->hdt_state = state;
6419517SBill.Taylor@Sun.COM new_dvm_track->hdt_refcnt = 1;
6429517SBill.Taylor@Sun.COM new_dvm_track->hdt_size = 0;
6439517SBill.Taylor@Sun.COM mutex_init(&new_dvm_track->hdt_lock, NULL, MUTEX_DRIVER,
6449517SBill.Taylor@Sun.COM DDI_INTR_PRI(state->hs_intrmsi_pri));
6459517SBill.Taylor@Sun.COM *new_pvtp = new_dvm_track;
6469517SBill.Taylor@Sun.COM
6479517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
6489517SBill.Taylor@Sun.COM }
6499517SBill.Taylor@Sun.COM
6509517SBill.Taylor@Sun.COM
6519517SBill.Taylor@Sun.COM /*
6529517SBill.Taylor@Sun.COM * hermon_devmap_umem_unmap()
6539517SBill.Taylor@Sun.COM * Context: Can be called from kernel context.
6549517SBill.Taylor@Sun.COM */
6559517SBill.Taylor@Sun.COM /* ARGSUSED */
6569517SBill.Taylor@Sun.COM static void
hermon_devmap_umem_unmap(devmap_cookie_t dhp,void * pvtp,offset_t off,size_t len,devmap_cookie_t new_dhp1,void ** pvtp1,devmap_cookie_t new_dhp2,void ** pvtp2)6579517SBill.Taylor@Sun.COM hermon_devmap_umem_unmap(devmap_cookie_t dhp, void *pvtp, offset_t off,
6589517SBill.Taylor@Sun.COM size_t len, devmap_cookie_t new_dhp1, void **pvtp1,
6599517SBill.Taylor@Sun.COM devmap_cookie_t new_dhp2, void **pvtp2)
6609517SBill.Taylor@Sun.COM {
6619517SBill.Taylor@Sun.COM hermon_state_t *state;
6629517SBill.Taylor@Sun.COM hermon_rsrc_t *rsrcp;
6639517SBill.Taylor@Sun.COM hermon_devmap_track_t *dvm_track;
6649517SBill.Taylor@Sun.COM hermon_cqhdl_t cq;
6659517SBill.Taylor@Sun.COM hermon_qphdl_t qp;
6669517SBill.Taylor@Sun.COM hermon_srqhdl_t srq;
6679517SBill.Taylor@Sun.COM uint64_t key, value;
6689517SBill.Taylor@Sun.COM uint_t type;
6699517SBill.Taylor@Sun.COM uint_t size;
6709517SBill.Taylor@Sun.COM int status;
6719517SBill.Taylor@Sun.COM
6729517SBill.Taylor@Sun.COM /*
6739517SBill.Taylor@Sun.COM * Extract the Hermon softstate pointer from "Hermon devmap tracking
6749517SBill.Taylor@Sun.COM * structure" (in "pvtp").
6759517SBill.Taylor@Sun.COM */
6769517SBill.Taylor@Sun.COM dvm_track = (hermon_devmap_track_t *)pvtp;
6779517SBill.Taylor@Sun.COM _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dvm_track))
6789517SBill.Taylor@Sun.COM state = dvm_track->hdt_state;
6799517SBill.Taylor@Sun.COM
6809517SBill.Taylor@Sun.COM /*
6819517SBill.Taylor@Sun.COM * Extract the "offset" from the "Hermon devmap tracking structure".
6829517SBill.Taylor@Sun.COM * Note: The input argument "off" is ignored here because the
6839517SBill.Taylor@Sun.COM * Hermon mapping interfaces define a very specific meaning to
6849517SBill.Taylor@Sun.COM * each "logical offset". Also extract the "key" and "type" encoded
6859517SBill.Taylor@Sun.COM * in the logical offset.
6869517SBill.Taylor@Sun.COM */
6879517SBill.Taylor@Sun.COM key = dvm_track->hdt_offset >> PAGESHIFT;
6889517SBill.Taylor@Sun.COM type = key & MLNX_UMAP_RSRC_TYPE_MASK;
6899517SBill.Taylor@Sun.COM key = key >> MLNX_UMAP_RSRC_TYPE_SHIFT;
6909517SBill.Taylor@Sun.COM
6919517SBill.Taylor@Sun.COM /*
6929517SBill.Taylor@Sun.COM * Extract the "size" of the mapping. If this size is determined
6939517SBill.Taylor@Sun.COM * to be zero, then it is an indication of a previously invalidated
6949517SBill.Taylor@Sun.COM * mapping, and no CQ or QP resources should be affected.
6959517SBill.Taylor@Sun.COM */
6969517SBill.Taylor@Sun.COM size = dvm_track->hdt_size;
6979517SBill.Taylor@Sun.COM
6989517SBill.Taylor@Sun.COM /*
6999517SBill.Taylor@Sun.COM * If only the "middle portion of a given mapping is being unmapped,
7009517SBill.Taylor@Sun.COM * then we are effectively creating one new piece of mapped memory.
7019517SBill.Taylor@Sun.COM * (Original region is divided into three pieces of which the middle
7029517SBill.Taylor@Sun.COM * piece is being removed. This leaves two pieces. Since we started
7039517SBill.Taylor@Sun.COM * with one piece and now have two pieces, we need to increment the
7049517SBill.Taylor@Sun.COM * counter in the "Hermon devmap tracking structure".
7059517SBill.Taylor@Sun.COM *
7069517SBill.Taylor@Sun.COM * If, however, the whole mapped region is being unmapped, then we
7079517SBill.Taylor@Sun.COM * have started with one region which we are completely removing.
7089517SBill.Taylor@Sun.COM * In this case, we need to decrement the counter in the "Hermon
7099517SBill.Taylor@Sun.COM * devmap tracking structure".
7109517SBill.Taylor@Sun.COM *
7119517SBill.Taylor@Sun.COM * In each of the remaining cases, we will have started with one
7129517SBill.Taylor@Sun.COM * mapped region and ended with one (different) region. So no counter
7139517SBill.Taylor@Sun.COM * modification is necessary.
7149517SBill.Taylor@Sun.COM */
7159517SBill.Taylor@Sun.COM mutex_enter(&dvm_track->hdt_lock);
7169517SBill.Taylor@Sun.COM if ((new_dhp1 == NULL) && (new_dhp2 == NULL)) {
7179517SBill.Taylor@Sun.COM dvm_track->hdt_refcnt--;
7189517SBill.Taylor@Sun.COM } else if ((new_dhp1 != NULL) && (new_dhp2 != NULL)) {
7199517SBill.Taylor@Sun.COM dvm_track->hdt_refcnt++;
7209517SBill.Taylor@Sun.COM }
7219517SBill.Taylor@Sun.COM mutex_exit(&dvm_track->hdt_lock);
7229517SBill.Taylor@Sun.COM
7239517SBill.Taylor@Sun.COM /*
7249517SBill.Taylor@Sun.COM * For each of the cases where the region is being divided, then we
7259517SBill.Taylor@Sun.COM * need to pass back the "Hermon devmap tracking structure". This way
7269517SBill.Taylor@Sun.COM * we get it back when each of the remaining pieces is subsequently
7279517SBill.Taylor@Sun.COM * unmapped.
7289517SBill.Taylor@Sun.COM */
7299517SBill.Taylor@Sun.COM if (new_dhp1 != NULL) {
7309517SBill.Taylor@Sun.COM *pvtp1 = pvtp;
7319517SBill.Taylor@Sun.COM }
7329517SBill.Taylor@Sun.COM if (new_dhp2 != NULL) {
7339517SBill.Taylor@Sun.COM *pvtp2 = pvtp;
7349517SBill.Taylor@Sun.COM }
7359517SBill.Taylor@Sun.COM
7369517SBill.Taylor@Sun.COM /*
7379517SBill.Taylor@Sun.COM * If the "Hermon devmap tracking structure" is no longer being
7389517SBill.Taylor@Sun.COM * referenced, then free it up. Otherwise, return.
7399517SBill.Taylor@Sun.COM */
7409517SBill.Taylor@Sun.COM if (dvm_track->hdt_refcnt == 0) {
7419517SBill.Taylor@Sun.COM mutex_destroy(&dvm_track->hdt_lock);
7429517SBill.Taylor@Sun.COM kmem_free(dvm_track, sizeof (hermon_devmap_track_t));
7439517SBill.Taylor@Sun.COM
7449517SBill.Taylor@Sun.COM /*
7459517SBill.Taylor@Sun.COM * If the mapping was invalid (see explanation above), then
7469517SBill.Taylor@Sun.COM * no further processing is necessary.
7479517SBill.Taylor@Sun.COM */
7489517SBill.Taylor@Sun.COM if (size == 0) {
7499517SBill.Taylor@Sun.COM return;
7509517SBill.Taylor@Sun.COM }
7519517SBill.Taylor@Sun.COM } else {
7529517SBill.Taylor@Sun.COM return;
7539517SBill.Taylor@Sun.COM }
7549517SBill.Taylor@Sun.COM
7559517SBill.Taylor@Sun.COM /*
7569517SBill.Taylor@Sun.COM * Now that we can guarantee that the user memory is fully unmapped,
7579517SBill.Taylor@Sun.COM * we can use the "key" and "type" values to try to find the entry
7589517SBill.Taylor@Sun.COM * in the "userland resources database". If it's found, then it
7599517SBill.Taylor@Sun.COM * indicates that the queue memory (CQ or QP) has not yet been freed.
7609517SBill.Taylor@Sun.COM * In this case, we update the corresponding CQ or QP handle to
7619517SBill.Taylor@Sun.COM * indicate that the "devmap_devmem_remap()" call will be unnecessary.
7629517SBill.Taylor@Sun.COM * If it's _not_ found, then it indicates that the CQ or QP memory
7639517SBill.Taylor@Sun.COM * was, in fact, freed before it was unmapped (thus requiring a
7649517SBill.Taylor@Sun.COM * previous invalidation by remapping - which will already have
7659517SBill.Taylor@Sun.COM * been done in the free routine).
7669517SBill.Taylor@Sun.COM */
7679517SBill.Taylor@Sun.COM status = hermon_umap_db_find(state->hs_instance, key, type, &value,
7689517SBill.Taylor@Sun.COM 0, NULL);
7699517SBill.Taylor@Sun.COM if (status == DDI_SUCCESS) {
7709517SBill.Taylor@Sun.COM /*
7719517SBill.Taylor@Sun.COM * Depending on the type of the mapped resource (CQ or QP),
7729517SBill.Taylor@Sun.COM * update handle to indicate that no invalidation remapping
7739517SBill.Taylor@Sun.COM * will be necessary.
7749517SBill.Taylor@Sun.COM */
7759517SBill.Taylor@Sun.COM if (type == MLNX_UMAP_CQMEM_RSRC) {
7769517SBill.Taylor@Sun.COM
7779517SBill.Taylor@Sun.COM /* Use "value" to convert to CQ handle */
7789517SBill.Taylor@Sun.COM rsrcp = (hermon_rsrc_t *)(uintptr_t)value;
7799517SBill.Taylor@Sun.COM cq = (hermon_cqhdl_t)rsrcp->hr_addr;
7809517SBill.Taylor@Sun.COM
7819517SBill.Taylor@Sun.COM /*
7829517SBill.Taylor@Sun.COM * Invalidate the handle to the userland mapping.
7839517SBill.Taylor@Sun.COM * Note: We must ensure that the mapping being
7849517SBill.Taylor@Sun.COM * unmapped here is the current one for the CQ. It
7859517SBill.Taylor@Sun.COM * is possible that it might not be if this CQ has
7869517SBill.Taylor@Sun.COM * been resized and the previous CQ memory has not
7879517SBill.Taylor@Sun.COM * yet been unmapped. But in that case, because of
7889517SBill.Taylor@Sun.COM * the devmap_devmem_remap(), there is no longer any
7899517SBill.Taylor@Sun.COM * association between the mapping and the real CQ
7909517SBill.Taylor@Sun.COM * kernel memory.
7919517SBill.Taylor@Sun.COM */
7929517SBill.Taylor@Sun.COM mutex_enter(&cq->cq_lock);
7939517SBill.Taylor@Sun.COM if (cq->cq_umap_dhp == dhp) {
7949517SBill.Taylor@Sun.COM cq->cq_umap_dhp = NULL;
7959517SBill.Taylor@Sun.COM if (cq->cq_resize_hdl) {
7969517SBill.Taylor@Sun.COM /* resize is DONE, switch queues */
7979517SBill.Taylor@Sun.COM hermon_cq_resize_helper(state, cq);
7989517SBill.Taylor@Sun.COM }
7999517SBill.Taylor@Sun.COM } else {
8009517SBill.Taylor@Sun.COM if (cq->cq_resize_hdl &&
8019517SBill.Taylor@Sun.COM cq->cq_resize_hdl->cq_umap_dhp == dhp) {
8029517SBill.Taylor@Sun.COM /*
8039517SBill.Taylor@Sun.COM * Unexpected case. munmap of the
8049517SBill.Taylor@Sun.COM * cq_resize buf, and not the
8059517SBill.Taylor@Sun.COM * original buf.
8069517SBill.Taylor@Sun.COM */
8079517SBill.Taylor@Sun.COM cq->cq_resize_hdl->cq_umap_dhp = NULL;
8089517SBill.Taylor@Sun.COM }
8099517SBill.Taylor@Sun.COM }
8109517SBill.Taylor@Sun.COM mutex_exit(&cq->cq_lock);
8119517SBill.Taylor@Sun.COM
8129517SBill.Taylor@Sun.COM } else if (type == MLNX_UMAP_QPMEM_RSRC) {
8139517SBill.Taylor@Sun.COM
8149517SBill.Taylor@Sun.COM /* Use "value" to convert to QP handle */
8159517SBill.Taylor@Sun.COM rsrcp = (hermon_rsrc_t *)(uintptr_t)value;
8169517SBill.Taylor@Sun.COM qp = (hermon_qphdl_t)rsrcp->hr_addr;
8179517SBill.Taylor@Sun.COM
8189517SBill.Taylor@Sun.COM /*
8199517SBill.Taylor@Sun.COM * Invalidate the handle to the userland mapping.
8209517SBill.Taylor@Sun.COM * Note: we ensure that the mapping being unmapped
8219517SBill.Taylor@Sun.COM * here is the current one for the QP. This is
8229517SBill.Taylor@Sun.COM * more of a sanity check here since, unlike CQs
8239517SBill.Taylor@Sun.COM * (above) we do not support resize of QPs.
8249517SBill.Taylor@Sun.COM */
8259517SBill.Taylor@Sun.COM mutex_enter(&qp->qp_lock);
8269517SBill.Taylor@Sun.COM if (qp->qp_umap_dhp == dhp) {
8279517SBill.Taylor@Sun.COM qp->qp_umap_dhp = NULL;
8289517SBill.Taylor@Sun.COM }
8299517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
8309517SBill.Taylor@Sun.COM
8319517SBill.Taylor@Sun.COM } else if (type == MLNX_UMAP_SRQMEM_RSRC) {
8329517SBill.Taylor@Sun.COM
8339517SBill.Taylor@Sun.COM /* Use "value" to convert to SRQ handle */
8349517SBill.Taylor@Sun.COM rsrcp = (hermon_rsrc_t *)(uintptr_t)value;
8359517SBill.Taylor@Sun.COM srq = (hermon_srqhdl_t)rsrcp->hr_addr;
8369517SBill.Taylor@Sun.COM
8379517SBill.Taylor@Sun.COM /*
8389517SBill.Taylor@Sun.COM * Invalidate the handle to the userland mapping.
8399517SBill.Taylor@Sun.COM * Note: we ensure that the mapping being unmapped
8409517SBill.Taylor@Sun.COM * here is the current one for the QP. This is
8419517SBill.Taylor@Sun.COM * more of a sanity check here since, unlike CQs
8429517SBill.Taylor@Sun.COM * (above) we do not support resize of QPs.
8439517SBill.Taylor@Sun.COM */
8449517SBill.Taylor@Sun.COM mutex_enter(&srq->srq_lock);
8459517SBill.Taylor@Sun.COM if (srq->srq_umap_dhp == dhp) {
8469517SBill.Taylor@Sun.COM srq->srq_umap_dhp = NULL;
8479517SBill.Taylor@Sun.COM }
8489517SBill.Taylor@Sun.COM mutex_exit(&srq->srq_lock);
8499517SBill.Taylor@Sun.COM }
8509517SBill.Taylor@Sun.COM }
8519517SBill.Taylor@Sun.COM }
8529517SBill.Taylor@Sun.COM
8539517SBill.Taylor@Sun.COM
8549517SBill.Taylor@Sun.COM /*
8559517SBill.Taylor@Sun.COM * hermon_devmap_devmem_map()
8569517SBill.Taylor@Sun.COM * Context: Can be called from kernel context.
8579517SBill.Taylor@Sun.COM */
8589517SBill.Taylor@Sun.COM /* ARGSUSED */
8599517SBill.Taylor@Sun.COM static int
hermon_devmap_dbrecmem_map(devmap_cookie_t dhp,dev_t dev,uint_t flags,offset_t off,size_t len,void ** pvtp)8609517SBill.Taylor@Sun.COM hermon_devmap_dbrecmem_map(devmap_cookie_t dhp, dev_t dev, uint_t flags,
8619517SBill.Taylor@Sun.COM offset_t off, size_t len, void **pvtp)
8629517SBill.Taylor@Sun.COM {
8639517SBill.Taylor@Sun.COM hermon_state_t *state;
8649517SBill.Taylor@Sun.COM hermon_devmap_track_t *dvm_track;
8659517SBill.Taylor@Sun.COM hermon_cqhdl_t cq;
8669517SBill.Taylor@Sun.COM hermon_qphdl_t qp;
8679517SBill.Taylor@Sun.COM hermon_srqhdl_t srq;
8689517SBill.Taylor@Sun.COM minor_t instance;
8699517SBill.Taylor@Sun.COM uint64_t key;
8709517SBill.Taylor@Sun.COM uint_t type;
8719517SBill.Taylor@Sun.COM
8729517SBill.Taylor@Sun.COM /* Get Hermon softstate structure from instance */
8739517SBill.Taylor@Sun.COM instance = HERMON_DEV_INSTANCE(dev);
8749517SBill.Taylor@Sun.COM state = ddi_get_soft_state(hermon_statep, instance);
8759517SBill.Taylor@Sun.COM if (state == NULL) {
8769517SBill.Taylor@Sun.COM return (ENXIO);
8779517SBill.Taylor@Sun.COM }
8789517SBill.Taylor@Sun.COM
8799517SBill.Taylor@Sun.COM /*
8809517SBill.Taylor@Sun.COM * The bottom bits of "offset" are undefined (number depends on
8819517SBill.Taylor@Sun.COM * system PAGESIZE). Shifting these off leaves us with a "key".
8829517SBill.Taylor@Sun.COM * The "key" is actually a combination of both a real key value
8839517SBill.Taylor@Sun.COM * (for the purpose of database lookup) and a "type" value. Although
8849517SBill.Taylor@Sun.COM * we are not going to do any database lookup per se, we do want
8859517SBill.Taylor@Sun.COM * to extract the "key" and the "type" (to enable faster lookup of
8869517SBill.Taylor@Sun.COM * the appropriate CQ or QP handle).
8879517SBill.Taylor@Sun.COM */
8889517SBill.Taylor@Sun.COM key = off >> PAGESHIFT;
8899517SBill.Taylor@Sun.COM type = key & MLNX_UMAP_RSRC_TYPE_MASK;
8909517SBill.Taylor@Sun.COM key = key >> MLNX_UMAP_RSRC_TYPE_SHIFT;
8919517SBill.Taylor@Sun.COM
8929517SBill.Taylor@Sun.COM /*
8939517SBill.Taylor@Sun.COM * Allocate an entry to track the mapping and unmapping (specifically,
8949517SBill.Taylor@Sun.COM * partial unmapping) of this resource.
8959517SBill.Taylor@Sun.COM */
8969517SBill.Taylor@Sun.COM dvm_track = (hermon_devmap_track_t *)kmem_zalloc(
8979517SBill.Taylor@Sun.COM sizeof (hermon_devmap_track_t), KM_SLEEP);
8989517SBill.Taylor@Sun.COM _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dvm_track))
8999517SBill.Taylor@Sun.COM dvm_track->hdt_offset = off;
9009517SBill.Taylor@Sun.COM dvm_track->hdt_state = state;
9019517SBill.Taylor@Sun.COM dvm_track->hdt_refcnt = 1;
9029517SBill.Taylor@Sun.COM mutex_init(&dvm_track->hdt_lock, NULL, MUTEX_DRIVER,
9039517SBill.Taylor@Sun.COM DDI_INTR_PRI(state->hs_intrmsi_pri));
9049517SBill.Taylor@Sun.COM
9059517SBill.Taylor@Sun.COM /*
9069517SBill.Taylor@Sun.COM * Depending of the type of resource that has been mapped out, we
9079517SBill.Taylor@Sun.COM * need to update the QP or CQ handle to reflect that it has, in
9089517SBill.Taylor@Sun.COM * fact, been mapped. This allows the driver code which frees a QP
9099517SBill.Taylor@Sun.COM * or a CQ to know whether it is appropriate to do a
9109517SBill.Taylor@Sun.COM * devmap_devmem_remap() to invalidate the userland mapping for the
9119517SBill.Taylor@Sun.COM * corresponding queue's memory.
9129517SBill.Taylor@Sun.COM */
9139517SBill.Taylor@Sun.COM if (type == MLNX_UMAP_CQMEM_RSRC) {
9149517SBill.Taylor@Sun.COM
9159517SBill.Taylor@Sun.COM /* Use "key" (CQ number) to do fast lookup of CQ handle */
9169517SBill.Taylor@Sun.COM cq = hermon_cqhdl_from_cqnum(state, key);
9179517SBill.Taylor@Sun.COM
9189517SBill.Taylor@Sun.COM /*
9199517SBill.Taylor@Sun.COM * Update the handle to the userland mapping. Note: If
9209517SBill.Taylor@Sun.COM * the CQ already has a valid userland mapping, then stop
9219517SBill.Taylor@Sun.COM * and return failure.
9229517SBill.Taylor@Sun.COM */
9239517SBill.Taylor@Sun.COM mutex_enter(&cq->cq_lock);
9249517SBill.Taylor@Sun.COM if (cq->cq_umap_dhp == NULL) {
9259517SBill.Taylor@Sun.COM cq->cq_umap_dhp = dhp;
9269517SBill.Taylor@Sun.COM dvm_track->hdt_size = cq->cq_cqinfo.qa_size;
9279517SBill.Taylor@Sun.COM mutex_exit(&cq->cq_lock);
9289517SBill.Taylor@Sun.COM } else {
9299517SBill.Taylor@Sun.COM mutex_exit(&cq->cq_lock);
9309517SBill.Taylor@Sun.COM goto umem_map_fail;
9319517SBill.Taylor@Sun.COM }
9329517SBill.Taylor@Sun.COM
9339517SBill.Taylor@Sun.COM } else if (type == MLNX_UMAP_QPMEM_RSRC) {
9349517SBill.Taylor@Sun.COM
9359517SBill.Taylor@Sun.COM /* Use "key" (QP number) to do fast lookup of QP handle */
9369517SBill.Taylor@Sun.COM qp = hermon_qphdl_from_qpnum(state, key);
9379517SBill.Taylor@Sun.COM
9389517SBill.Taylor@Sun.COM /*
9399517SBill.Taylor@Sun.COM * Update the handle to the userland mapping. Note: If
9409517SBill.Taylor@Sun.COM * the CQ already has a valid userland mapping, then stop
9419517SBill.Taylor@Sun.COM * and return failure.
9429517SBill.Taylor@Sun.COM */
9439517SBill.Taylor@Sun.COM mutex_enter(&qp->qp_lock);
9449517SBill.Taylor@Sun.COM if (qp->qp_umap_dhp == NULL) {
9459517SBill.Taylor@Sun.COM qp->qp_umap_dhp = dhp;
9469517SBill.Taylor@Sun.COM dvm_track->hdt_size = qp->qp_wqinfo.qa_size;
9479517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
9489517SBill.Taylor@Sun.COM } else {
9499517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
9509517SBill.Taylor@Sun.COM goto umem_map_fail;
9519517SBill.Taylor@Sun.COM }
9529517SBill.Taylor@Sun.COM
9539517SBill.Taylor@Sun.COM } else if (type == MLNX_UMAP_SRQMEM_RSRC) {
9549517SBill.Taylor@Sun.COM
9559517SBill.Taylor@Sun.COM /* Use "key" (SRQ number) to do fast lookup on SRQ handle */
9569517SBill.Taylor@Sun.COM srq = hermon_srqhdl_from_srqnum(state, key);
9579517SBill.Taylor@Sun.COM
9589517SBill.Taylor@Sun.COM /*
9599517SBill.Taylor@Sun.COM * Update the handle to the userland mapping. Note: If the
9609517SBill.Taylor@Sun.COM * SRQ already has a valid userland mapping, then stop and
9619517SBill.Taylor@Sun.COM * return failure.
9629517SBill.Taylor@Sun.COM */
9639517SBill.Taylor@Sun.COM mutex_enter(&srq->srq_lock);
9649517SBill.Taylor@Sun.COM if (srq->srq_umap_dhp == NULL) {
9659517SBill.Taylor@Sun.COM srq->srq_umap_dhp = dhp;
9669517SBill.Taylor@Sun.COM dvm_track->hdt_size = srq->srq_wqinfo.qa_size;
9679517SBill.Taylor@Sun.COM mutex_exit(&srq->srq_lock);
9689517SBill.Taylor@Sun.COM } else {
9699517SBill.Taylor@Sun.COM mutex_exit(&srq->srq_lock);
9709517SBill.Taylor@Sun.COM goto umem_map_fail;
9719517SBill.Taylor@Sun.COM }
9729517SBill.Taylor@Sun.COM }
9739517SBill.Taylor@Sun.COM
9749517SBill.Taylor@Sun.COM /*
9759517SBill.Taylor@Sun.COM * Pass the private "Hermon devmap tracking structure" back. This
9769517SBill.Taylor@Sun.COM * pointer will be returned in subsequent "unmap" callbacks.
9779517SBill.Taylor@Sun.COM */
9789517SBill.Taylor@Sun.COM *pvtp = dvm_track;
9799517SBill.Taylor@Sun.COM
9809517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
9819517SBill.Taylor@Sun.COM
9829517SBill.Taylor@Sun.COM umem_map_fail:
9839517SBill.Taylor@Sun.COM mutex_destroy(&dvm_track->hdt_lock);
9849517SBill.Taylor@Sun.COM kmem_free(dvm_track, sizeof (hermon_devmap_track_t));
9859517SBill.Taylor@Sun.COM return (DDI_FAILURE);
9869517SBill.Taylor@Sun.COM }
9879517SBill.Taylor@Sun.COM
9889517SBill.Taylor@Sun.COM
9899517SBill.Taylor@Sun.COM /*
9909517SBill.Taylor@Sun.COM * hermon_devmap_dbrecmem_dup()
9919517SBill.Taylor@Sun.COM * Context: Can be called from kernel context.
9929517SBill.Taylor@Sun.COM */
9939517SBill.Taylor@Sun.COM /* ARGSUSED */
9949517SBill.Taylor@Sun.COM static int
hermon_devmap_dbrecmem_dup(devmap_cookie_t dhp,void * pvtp,devmap_cookie_t new_dhp,void ** new_pvtp)9959517SBill.Taylor@Sun.COM hermon_devmap_dbrecmem_dup(devmap_cookie_t dhp, void *pvtp,
9969517SBill.Taylor@Sun.COM devmap_cookie_t new_dhp, void **new_pvtp)
9979517SBill.Taylor@Sun.COM {
9989517SBill.Taylor@Sun.COM hermon_state_t *state;
9999517SBill.Taylor@Sun.COM hermon_devmap_track_t *dvm_track, *new_dvm_track;
10009517SBill.Taylor@Sun.COM uint_t maxprot;
10019517SBill.Taylor@Sun.COM int status;
10029517SBill.Taylor@Sun.COM
10039517SBill.Taylor@Sun.COM /*
10049517SBill.Taylor@Sun.COM * Extract the Hermon softstate pointer from "Hermon devmap tracking
10059517SBill.Taylor@Sun.COM * structure" (in "pvtp").
10069517SBill.Taylor@Sun.COM */
10079517SBill.Taylor@Sun.COM dvm_track = (hermon_devmap_track_t *)pvtp;
10089517SBill.Taylor@Sun.COM _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dvm_track))
10099517SBill.Taylor@Sun.COM state = dvm_track->hdt_state;
10109517SBill.Taylor@Sun.COM
10119517SBill.Taylor@Sun.COM /*
10129517SBill.Taylor@Sun.COM * Since this devmap_dup() entry point is generally called
10139517SBill.Taylor@Sun.COM * when a process does fork(2), it is incumbent upon the driver
10149517SBill.Taylor@Sun.COM * to insure that the child does not inherit a valid copy of
10159517SBill.Taylor@Sun.COM * the parent's QP or CQ resource. This is accomplished by using
10169517SBill.Taylor@Sun.COM * devmap_devmem_remap() to invalidate the child's mapping to the
10179517SBill.Taylor@Sun.COM * kernel memory.
10189517SBill.Taylor@Sun.COM */
10199517SBill.Taylor@Sun.COM maxprot = (PROT_READ | PROT_WRITE | PROT_USER);
10209517SBill.Taylor@Sun.COM status = devmap_devmem_remap(new_dhp, state->hs_dip, 0, 0,
10219517SBill.Taylor@Sun.COM dvm_track->hdt_size, maxprot, DEVMAP_MAPPING_INVALID, NULL);
10229517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
10239517SBill.Taylor@Sun.COM HERMON_WARNING(state, "failed in hermon_devmap_dbrecmem_dup()");
10249517SBill.Taylor@Sun.COM return (status);
10259517SBill.Taylor@Sun.COM }
10269517SBill.Taylor@Sun.COM
10279517SBill.Taylor@Sun.COM /*
10289517SBill.Taylor@Sun.COM * Allocate a new entry to track the subsequent unmapping
10299517SBill.Taylor@Sun.COM * (specifically, all partial unmappings) of the child's newly
10309517SBill.Taylor@Sun.COM * invalidated resource. Note: Setting the "hdt_size" field to
10319517SBill.Taylor@Sun.COM * zero here is an indication to the devmap_unmap() entry point
10329517SBill.Taylor@Sun.COM * that this mapping is invalid, and that its subsequent unmapping
10339517SBill.Taylor@Sun.COM * should not affect any of the parent's CQ or QP resources.
10349517SBill.Taylor@Sun.COM */
10359517SBill.Taylor@Sun.COM new_dvm_track = (hermon_devmap_track_t *)kmem_zalloc(
10369517SBill.Taylor@Sun.COM sizeof (hermon_devmap_track_t), KM_SLEEP);
10379517SBill.Taylor@Sun.COM _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*new_dvm_track))
10389517SBill.Taylor@Sun.COM new_dvm_track->hdt_offset = 0;
10399517SBill.Taylor@Sun.COM new_dvm_track->hdt_state = state;
10409517SBill.Taylor@Sun.COM new_dvm_track->hdt_refcnt = 1;
10419517SBill.Taylor@Sun.COM new_dvm_track->hdt_size = 0;
10429517SBill.Taylor@Sun.COM mutex_init(&new_dvm_track->hdt_lock, NULL, MUTEX_DRIVER,
10439517SBill.Taylor@Sun.COM DDI_INTR_PRI(state->hs_intrmsi_pri));
10449517SBill.Taylor@Sun.COM *new_pvtp = new_dvm_track;
10459517SBill.Taylor@Sun.COM
10469517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
10479517SBill.Taylor@Sun.COM }
10489517SBill.Taylor@Sun.COM
10499517SBill.Taylor@Sun.COM
10509517SBill.Taylor@Sun.COM /*
10519517SBill.Taylor@Sun.COM * hermon_devmap_dbrecmem_unmap()
10529517SBill.Taylor@Sun.COM * Context: Can be called from kernel context.
10539517SBill.Taylor@Sun.COM */
10549517SBill.Taylor@Sun.COM /* ARGSUSED */
10559517SBill.Taylor@Sun.COM static void
hermon_devmap_dbrecmem_unmap(devmap_cookie_t dhp,void * pvtp,offset_t off,size_t len,devmap_cookie_t new_dhp1,void ** pvtp1,devmap_cookie_t new_dhp2,void ** pvtp2)10569517SBill.Taylor@Sun.COM hermon_devmap_dbrecmem_unmap(devmap_cookie_t dhp, void *pvtp, offset_t off,
10579517SBill.Taylor@Sun.COM size_t len, devmap_cookie_t new_dhp1, void **pvtp1,
10589517SBill.Taylor@Sun.COM devmap_cookie_t new_dhp2, void **pvtp2)
10599517SBill.Taylor@Sun.COM {
10609517SBill.Taylor@Sun.COM hermon_state_t *state;
10619517SBill.Taylor@Sun.COM hermon_rsrc_t *rsrcp;
10629517SBill.Taylor@Sun.COM hermon_devmap_track_t *dvm_track;
10639517SBill.Taylor@Sun.COM hermon_cqhdl_t cq;
10649517SBill.Taylor@Sun.COM hermon_qphdl_t qp;
10659517SBill.Taylor@Sun.COM hermon_srqhdl_t srq;
10669517SBill.Taylor@Sun.COM uint64_t key, value;
10679517SBill.Taylor@Sun.COM uint_t type;
10689517SBill.Taylor@Sun.COM uint_t size;
10699517SBill.Taylor@Sun.COM int status;
10709517SBill.Taylor@Sun.COM
10719517SBill.Taylor@Sun.COM /*
10729517SBill.Taylor@Sun.COM * Extract the Hermon softstate pointer from "Hermon devmap tracking
10739517SBill.Taylor@Sun.COM * structure" (in "pvtp").
10749517SBill.Taylor@Sun.COM */
10759517SBill.Taylor@Sun.COM dvm_track = (hermon_devmap_track_t *)pvtp;
10769517SBill.Taylor@Sun.COM _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dvm_track))
10779517SBill.Taylor@Sun.COM state = dvm_track->hdt_state;
10789517SBill.Taylor@Sun.COM
10799517SBill.Taylor@Sun.COM /*
10809517SBill.Taylor@Sun.COM * Extract the "offset" from the "Hermon devmap tracking structure".
10819517SBill.Taylor@Sun.COM * Note: The input argument "off" is ignored here because the
10829517SBill.Taylor@Sun.COM * Hermon mapping interfaces define a very specific meaning to
10839517SBill.Taylor@Sun.COM * each "logical offset". Also extract the "key" and "type" encoded
10849517SBill.Taylor@Sun.COM * in the logical offset.
10859517SBill.Taylor@Sun.COM */
10869517SBill.Taylor@Sun.COM key = dvm_track->hdt_offset >> PAGESHIFT;
10879517SBill.Taylor@Sun.COM type = key & MLNX_UMAP_RSRC_TYPE_MASK;
10889517SBill.Taylor@Sun.COM key = key >> MLNX_UMAP_RSRC_TYPE_SHIFT;
10899517SBill.Taylor@Sun.COM
10909517SBill.Taylor@Sun.COM /*
10919517SBill.Taylor@Sun.COM * Extract the "size" of the mapping. If this size is determined
10929517SBill.Taylor@Sun.COM * to be zero, then it is an indication of a previously invalidated
10939517SBill.Taylor@Sun.COM * mapping, and no CQ or QP resources should be affected.
10949517SBill.Taylor@Sun.COM */
10959517SBill.Taylor@Sun.COM size = dvm_track->hdt_size;
10969517SBill.Taylor@Sun.COM
10979517SBill.Taylor@Sun.COM /*
10989517SBill.Taylor@Sun.COM * If only the "middle portion of a given mapping is being unmapped,
10999517SBill.Taylor@Sun.COM * then we are effectively creating one new piece of mapped memory.
11009517SBill.Taylor@Sun.COM * (Original region is divided into three pieces of which the middle
11019517SBill.Taylor@Sun.COM * piece is being removed. This leaves two pieces. Since we started
11029517SBill.Taylor@Sun.COM * with one piece and now have two pieces, we need to increment the
11039517SBill.Taylor@Sun.COM * counter in the "Hermon devmap tracking structure".
11049517SBill.Taylor@Sun.COM *
11059517SBill.Taylor@Sun.COM * If, however, the whole mapped region is being unmapped, then we
11069517SBill.Taylor@Sun.COM * have started with one region which we are completely removing.
11079517SBill.Taylor@Sun.COM * In this case, we need to decrement the counter in the "Hermon
11089517SBill.Taylor@Sun.COM * devmap tracking structure".
11099517SBill.Taylor@Sun.COM *
11109517SBill.Taylor@Sun.COM * In each of the remaining cases, we will have started with one
11119517SBill.Taylor@Sun.COM * mapped region and ended with one (different) region. So no counter
11129517SBill.Taylor@Sun.COM * modification is necessary.
11139517SBill.Taylor@Sun.COM */
11149517SBill.Taylor@Sun.COM mutex_enter(&dvm_track->hdt_lock);
11159517SBill.Taylor@Sun.COM if ((new_dhp1 == NULL) && (new_dhp2 == NULL)) {
11169517SBill.Taylor@Sun.COM dvm_track->hdt_refcnt--;
11179517SBill.Taylor@Sun.COM } else if ((new_dhp1 != NULL) && (new_dhp2 != NULL)) {
11189517SBill.Taylor@Sun.COM dvm_track->hdt_refcnt++;
11199517SBill.Taylor@Sun.COM }
11209517SBill.Taylor@Sun.COM mutex_exit(&dvm_track->hdt_lock);
11219517SBill.Taylor@Sun.COM
11229517SBill.Taylor@Sun.COM /*
11239517SBill.Taylor@Sun.COM * For each of the cases where the region is being divided, then we
11249517SBill.Taylor@Sun.COM * need to pass back the "Hermon devmap tracking structure". This way
11259517SBill.Taylor@Sun.COM * we get it back when each of the remaining pieces is subsequently
11269517SBill.Taylor@Sun.COM * unmapped.
11279517SBill.Taylor@Sun.COM */
11289517SBill.Taylor@Sun.COM if (new_dhp1 != NULL) {
11299517SBill.Taylor@Sun.COM *pvtp1 = pvtp;
11309517SBill.Taylor@Sun.COM }
11319517SBill.Taylor@Sun.COM if (new_dhp2 != NULL) {
11329517SBill.Taylor@Sun.COM *pvtp2 = pvtp;
11339517SBill.Taylor@Sun.COM }
11349517SBill.Taylor@Sun.COM
11359517SBill.Taylor@Sun.COM /*
11369517SBill.Taylor@Sun.COM * If the "Hermon devmap tracking structure" is no longer being
11379517SBill.Taylor@Sun.COM * referenced, then free it up. Otherwise, return.
11389517SBill.Taylor@Sun.COM */
11399517SBill.Taylor@Sun.COM if (dvm_track->hdt_refcnt == 0) {
11409517SBill.Taylor@Sun.COM mutex_destroy(&dvm_track->hdt_lock);
11419517SBill.Taylor@Sun.COM kmem_free(dvm_track, sizeof (hermon_devmap_track_t));
11429517SBill.Taylor@Sun.COM
11439517SBill.Taylor@Sun.COM /*
11449517SBill.Taylor@Sun.COM * If the mapping was invalid (see explanation above), then
11459517SBill.Taylor@Sun.COM * no further processing is necessary.
11469517SBill.Taylor@Sun.COM */
11479517SBill.Taylor@Sun.COM if (size == 0) {
11489517SBill.Taylor@Sun.COM return;
11499517SBill.Taylor@Sun.COM }
11509517SBill.Taylor@Sun.COM } else {
11519517SBill.Taylor@Sun.COM return;
11529517SBill.Taylor@Sun.COM }
11539517SBill.Taylor@Sun.COM
11549517SBill.Taylor@Sun.COM /*
11559517SBill.Taylor@Sun.COM * Now that we can guarantee that the user memory is fully unmapped,
11569517SBill.Taylor@Sun.COM * we can use the "key" and "type" values to try to find the entry
11579517SBill.Taylor@Sun.COM * in the "userland resources database". If it's found, then it
11589517SBill.Taylor@Sun.COM * indicates that the queue memory (CQ or QP) has not yet been freed.
11599517SBill.Taylor@Sun.COM * In this case, we update the corresponding CQ or QP handle to
11609517SBill.Taylor@Sun.COM * indicate that the "devmap_devmem_remap()" call will be unnecessary.
11619517SBill.Taylor@Sun.COM * If it's _not_ found, then it indicates that the CQ or QP memory
11629517SBill.Taylor@Sun.COM * was, in fact, freed before it was unmapped (thus requiring a
11639517SBill.Taylor@Sun.COM * previous invalidation by remapping - which will already have
11649517SBill.Taylor@Sun.COM * been done in the free routine).
11659517SBill.Taylor@Sun.COM */
11669517SBill.Taylor@Sun.COM status = hermon_umap_db_find(state->hs_instance, key, type, &value,
11679517SBill.Taylor@Sun.COM 0, NULL);
11689517SBill.Taylor@Sun.COM if (status == DDI_SUCCESS) {
11699517SBill.Taylor@Sun.COM /*
11709517SBill.Taylor@Sun.COM * Depending on the type of the mapped resource (CQ or QP),
11719517SBill.Taylor@Sun.COM * update handle to indicate that no invalidation remapping
11729517SBill.Taylor@Sun.COM * will be necessary.
11739517SBill.Taylor@Sun.COM */
11749517SBill.Taylor@Sun.COM if (type == MLNX_UMAP_CQMEM_RSRC) {
11759517SBill.Taylor@Sun.COM
11769517SBill.Taylor@Sun.COM /* Use "value" to convert to CQ handle */
11779517SBill.Taylor@Sun.COM rsrcp = (hermon_rsrc_t *)(uintptr_t)value;
11789517SBill.Taylor@Sun.COM cq = (hermon_cqhdl_t)rsrcp->hr_addr;
11799517SBill.Taylor@Sun.COM
11809517SBill.Taylor@Sun.COM /*
11819517SBill.Taylor@Sun.COM * Invalidate the handle to the userland mapping.
11829517SBill.Taylor@Sun.COM * Note: We must ensure that the mapping being
11839517SBill.Taylor@Sun.COM * unmapped here is the current one for the CQ. It
11849517SBill.Taylor@Sun.COM * is possible that it might not be if this CQ has
11859517SBill.Taylor@Sun.COM * been resized and the previous CQ memory has not
11869517SBill.Taylor@Sun.COM * yet been unmapped. But in that case, because of
11879517SBill.Taylor@Sun.COM * the devmap_devmem_remap(), there is no longer any
11889517SBill.Taylor@Sun.COM * association between the mapping and the real CQ
11899517SBill.Taylor@Sun.COM * kernel memory.
11909517SBill.Taylor@Sun.COM */
11919517SBill.Taylor@Sun.COM mutex_enter(&cq->cq_lock);
11929517SBill.Taylor@Sun.COM if (cq->cq_umap_dhp == dhp) {
11939517SBill.Taylor@Sun.COM cq->cq_umap_dhp = NULL;
11949517SBill.Taylor@Sun.COM }
11959517SBill.Taylor@Sun.COM mutex_exit(&cq->cq_lock);
11969517SBill.Taylor@Sun.COM
11979517SBill.Taylor@Sun.COM } else if (type == MLNX_UMAP_QPMEM_RSRC) {
11989517SBill.Taylor@Sun.COM
11999517SBill.Taylor@Sun.COM /* Use "value" to convert to QP handle */
12009517SBill.Taylor@Sun.COM rsrcp = (hermon_rsrc_t *)(uintptr_t)value;
12019517SBill.Taylor@Sun.COM qp = (hermon_qphdl_t)rsrcp->hr_addr;
12029517SBill.Taylor@Sun.COM
12039517SBill.Taylor@Sun.COM /*
12049517SBill.Taylor@Sun.COM * Invalidate the handle to the userland mapping.
12059517SBill.Taylor@Sun.COM * Note: we ensure that the mapping being unmapped
12069517SBill.Taylor@Sun.COM * here is the current one for the QP. This is
12079517SBill.Taylor@Sun.COM * more of a sanity check here since, unlike CQs
12089517SBill.Taylor@Sun.COM * (above) we do not support resize of QPs.
12099517SBill.Taylor@Sun.COM */
12109517SBill.Taylor@Sun.COM mutex_enter(&qp->qp_lock);
12119517SBill.Taylor@Sun.COM if (qp->qp_umap_dhp == dhp) {
12129517SBill.Taylor@Sun.COM qp->qp_umap_dhp = NULL;
12139517SBill.Taylor@Sun.COM }
12149517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
12159517SBill.Taylor@Sun.COM
12169517SBill.Taylor@Sun.COM } else if (type == MLNX_UMAP_SRQMEM_RSRC) {
12179517SBill.Taylor@Sun.COM
12189517SBill.Taylor@Sun.COM /* Use "value" to convert to SRQ handle */
12199517SBill.Taylor@Sun.COM rsrcp = (hermon_rsrc_t *)(uintptr_t)value;
12209517SBill.Taylor@Sun.COM srq = (hermon_srqhdl_t)rsrcp->hr_addr;
12219517SBill.Taylor@Sun.COM
12229517SBill.Taylor@Sun.COM /*
12239517SBill.Taylor@Sun.COM * Invalidate the handle to the userland mapping.
12249517SBill.Taylor@Sun.COM * Note: we ensure that the mapping being unmapped
12259517SBill.Taylor@Sun.COM * here is the current one for the QP. This is
12269517SBill.Taylor@Sun.COM * more of a sanity check here since, unlike CQs
12279517SBill.Taylor@Sun.COM * (above) we do not support resize of QPs.
12289517SBill.Taylor@Sun.COM */
12299517SBill.Taylor@Sun.COM mutex_enter(&srq->srq_lock);
12309517SBill.Taylor@Sun.COM if (srq->srq_umap_dhp == dhp) {
12319517SBill.Taylor@Sun.COM srq->srq_umap_dhp = NULL;
12329517SBill.Taylor@Sun.COM }
12339517SBill.Taylor@Sun.COM mutex_exit(&srq->srq_lock);
12349517SBill.Taylor@Sun.COM }
12359517SBill.Taylor@Sun.COM }
12369517SBill.Taylor@Sun.COM }
12379517SBill.Taylor@Sun.COM
12389517SBill.Taylor@Sun.COM
12399517SBill.Taylor@Sun.COM /*
12409517SBill.Taylor@Sun.COM * hermon_devmap_devmem_map()
12419517SBill.Taylor@Sun.COM * Context: Can be called from kernel context.
12429517SBill.Taylor@Sun.COM */
12439517SBill.Taylor@Sun.COM /* ARGSUSED */
12449517SBill.Taylor@Sun.COM static int
hermon_devmap_devmem_map(devmap_cookie_t dhp,dev_t dev,uint_t flags,offset_t off,size_t len,void ** pvtp)12459517SBill.Taylor@Sun.COM hermon_devmap_devmem_map(devmap_cookie_t dhp, dev_t dev, uint_t flags,
12469517SBill.Taylor@Sun.COM offset_t off, size_t len, void **pvtp)
12479517SBill.Taylor@Sun.COM {
12489517SBill.Taylor@Sun.COM hermon_state_t *state;
12499517SBill.Taylor@Sun.COM hermon_devmap_track_t *dvm_track;
12509517SBill.Taylor@Sun.COM minor_t instance;
12519517SBill.Taylor@Sun.COM
12529517SBill.Taylor@Sun.COM /* Get Hermon softstate structure from instance */
12539517SBill.Taylor@Sun.COM instance = HERMON_DEV_INSTANCE(dev);
12549517SBill.Taylor@Sun.COM state = ddi_get_soft_state(hermon_statep, instance);
12559517SBill.Taylor@Sun.COM if (state == NULL) {
12569517SBill.Taylor@Sun.COM return (ENXIO);
12579517SBill.Taylor@Sun.COM }
12589517SBill.Taylor@Sun.COM
12599517SBill.Taylor@Sun.COM /*
12609517SBill.Taylor@Sun.COM * Allocate an entry to track the mapping and unmapping of this
12619517SBill.Taylor@Sun.COM * resource. Note: We don't need to initialize the "refcnt" or
12629517SBill.Taylor@Sun.COM * "offset" fields here, nor do we need to initialize the mutex
12639517SBill.Taylor@Sun.COM * used with the "refcnt". Since UAR pages are single pages, they
12649517SBill.Taylor@Sun.COM * are not subject to "partial" unmappings. This makes these other
12659517SBill.Taylor@Sun.COM * fields unnecessary.
12669517SBill.Taylor@Sun.COM */
12679517SBill.Taylor@Sun.COM dvm_track = (hermon_devmap_track_t *)kmem_zalloc(
12689517SBill.Taylor@Sun.COM sizeof (hermon_devmap_track_t), KM_SLEEP);
12699517SBill.Taylor@Sun.COM _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dvm_track))
12709517SBill.Taylor@Sun.COM dvm_track->hdt_state = state;
12719517SBill.Taylor@Sun.COM dvm_track->hdt_size = (uint_t)PAGESIZE;
12729517SBill.Taylor@Sun.COM
12739517SBill.Taylor@Sun.COM /*
12749517SBill.Taylor@Sun.COM * Pass the private "Hermon devmap tracking structure" back. This
12759517SBill.Taylor@Sun.COM * pointer will be returned in a subsequent "unmap" callback.
12769517SBill.Taylor@Sun.COM */
12779517SBill.Taylor@Sun.COM *pvtp = dvm_track;
12789517SBill.Taylor@Sun.COM
12799517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
12809517SBill.Taylor@Sun.COM }
12819517SBill.Taylor@Sun.COM
12829517SBill.Taylor@Sun.COM
12839517SBill.Taylor@Sun.COM /*
12849517SBill.Taylor@Sun.COM * hermon_devmap_devmem_dup()
12859517SBill.Taylor@Sun.COM * Context: Can be called from kernel context.
12869517SBill.Taylor@Sun.COM */
12879517SBill.Taylor@Sun.COM /* ARGSUSED */
12889517SBill.Taylor@Sun.COM static int
hermon_devmap_devmem_dup(devmap_cookie_t dhp,void * pvtp,devmap_cookie_t new_dhp,void ** new_pvtp)12899517SBill.Taylor@Sun.COM hermon_devmap_devmem_dup(devmap_cookie_t dhp, void *pvtp,
12909517SBill.Taylor@Sun.COM devmap_cookie_t new_dhp, void **new_pvtp)
12919517SBill.Taylor@Sun.COM {
12929517SBill.Taylor@Sun.COM hermon_state_t *state;
12939517SBill.Taylor@Sun.COM hermon_devmap_track_t *dvm_track;
12949517SBill.Taylor@Sun.COM uint_t maxprot;
12959517SBill.Taylor@Sun.COM int status;
12969517SBill.Taylor@Sun.COM
12979517SBill.Taylor@Sun.COM /*
12989517SBill.Taylor@Sun.COM * Extract the Hermon softstate pointer from "Hermon devmap tracking
12999517SBill.Taylor@Sun.COM * structure" (in "pvtp"). Note: If the tracking structure is NULL
13009517SBill.Taylor@Sun.COM * here, it means that the mapping corresponds to an invalid mapping.
13019517SBill.Taylor@Sun.COM * In this case, it can be safely ignored ("new_pvtp" set to NULL).
13029517SBill.Taylor@Sun.COM */
13039517SBill.Taylor@Sun.COM dvm_track = (hermon_devmap_track_t *)pvtp;
13049517SBill.Taylor@Sun.COM if (dvm_track == NULL) {
13059517SBill.Taylor@Sun.COM *new_pvtp = NULL;
13069517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
13079517SBill.Taylor@Sun.COM }
13089517SBill.Taylor@Sun.COM
13099517SBill.Taylor@Sun.COM _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dvm_track))
13109517SBill.Taylor@Sun.COM state = dvm_track->hdt_state;
13119517SBill.Taylor@Sun.COM
13129517SBill.Taylor@Sun.COM /*
13139517SBill.Taylor@Sun.COM * Since this devmap_dup() entry point is generally called
13149517SBill.Taylor@Sun.COM * when a process does fork(2), it is incumbent upon the driver
13159517SBill.Taylor@Sun.COM * to insure that the child does not inherit a valid copy of
13169517SBill.Taylor@Sun.COM * the parent's resource. This is accomplished by using
13179517SBill.Taylor@Sun.COM * devmap_devmem_remap() to invalidate the child's mapping to the
13189517SBill.Taylor@Sun.COM * kernel memory.
13199517SBill.Taylor@Sun.COM */
13209517SBill.Taylor@Sun.COM maxprot = (PROT_READ | PROT_WRITE | PROT_USER);
13219517SBill.Taylor@Sun.COM status = devmap_devmem_remap(new_dhp, state->hs_dip, 0, 0,
13229517SBill.Taylor@Sun.COM dvm_track->hdt_size, maxprot, DEVMAP_MAPPING_INVALID, NULL);
13239517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
13249517SBill.Taylor@Sun.COM HERMON_WARNING(state, "failed in hermon_devmap_devmem_dup()");
13259517SBill.Taylor@Sun.COM return (status);
13269517SBill.Taylor@Sun.COM }
13279517SBill.Taylor@Sun.COM
13289517SBill.Taylor@Sun.COM /*
13299517SBill.Taylor@Sun.COM * Since the region is invalid, there is no need for us to
13309517SBill.Taylor@Sun.COM * allocate and continue to track an additional "Hermon devmap
13319517SBill.Taylor@Sun.COM * tracking structure". Instead we return NULL here, which is an
13329517SBill.Taylor@Sun.COM * indication to the devmap_unmap() entry point that this entry
13339517SBill.Taylor@Sun.COM * can be safely ignored.
13349517SBill.Taylor@Sun.COM */
13359517SBill.Taylor@Sun.COM *new_pvtp = NULL;
13369517SBill.Taylor@Sun.COM
13379517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
13389517SBill.Taylor@Sun.COM }
13399517SBill.Taylor@Sun.COM
13409517SBill.Taylor@Sun.COM
13419517SBill.Taylor@Sun.COM /*
13429517SBill.Taylor@Sun.COM * hermon_devmap_devmem_unmap()
13439517SBill.Taylor@Sun.COM * Context: Can be called from kernel context.
13449517SBill.Taylor@Sun.COM */
13459517SBill.Taylor@Sun.COM /* ARGSUSED */
13469517SBill.Taylor@Sun.COM static void
hermon_devmap_devmem_unmap(devmap_cookie_t dhp,void * pvtp,offset_t off,size_t len,devmap_cookie_t new_dhp1,void ** pvtp1,devmap_cookie_t new_dhp2,void ** pvtp2)13479517SBill.Taylor@Sun.COM hermon_devmap_devmem_unmap(devmap_cookie_t dhp, void *pvtp, offset_t off,
13489517SBill.Taylor@Sun.COM size_t len, devmap_cookie_t new_dhp1, void **pvtp1,
13499517SBill.Taylor@Sun.COM devmap_cookie_t new_dhp2, void **pvtp2)
13509517SBill.Taylor@Sun.COM {
13519517SBill.Taylor@Sun.COM hermon_devmap_track_t *dvm_track;
13529517SBill.Taylor@Sun.COM
13539517SBill.Taylor@Sun.COM /*
13549517SBill.Taylor@Sun.COM * Free up the "Hermon devmap tracking structure" (in "pvtp").
13559517SBill.Taylor@Sun.COM * There cannot be "partial" unmappings here because all UAR pages
13569517SBill.Taylor@Sun.COM * are single pages. Note: If the tracking structure is NULL here,
13579517SBill.Taylor@Sun.COM * it means that the mapping corresponds to an invalid mapping. In
13589517SBill.Taylor@Sun.COM * this case, it can be safely ignored.
13599517SBill.Taylor@Sun.COM */
13609517SBill.Taylor@Sun.COM dvm_track = (hermon_devmap_track_t *)pvtp;
13619517SBill.Taylor@Sun.COM _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dvm_track))
13629517SBill.Taylor@Sun.COM if (dvm_track == NULL) {
13639517SBill.Taylor@Sun.COM return;
13649517SBill.Taylor@Sun.COM }
13659517SBill.Taylor@Sun.COM
13669517SBill.Taylor@Sun.COM kmem_free(dvm_track, sizeof (hermon_devmap_track_t));
13679517SBill.Taylor@Sun.COM }
13689517SBill.Taylor@Sun.COM
13699517SBill.Taylor@Sun.COM
13709517SBill.Taylor@Sun.COM /*
13719517SBill.Taylor@Sun.COM * hermon_umap_ci_data_in()
13729517SBill.Taylor@Sun.COM * Context: Can be called from user or kernel context.
13739517SBill.Taylor@Sun.COM */
13749517SBill.Taylor@Sun.COM /* ARGSUSED */
13759517SBill.Taylor@Sun.COM ibt_status_t
hermon_umap_ci_data_in(hermon_state_t * state,ibt_ci_data_flags_t flags,ibt_object_type_t object,void * hdl,void * data_p,size_t data_sz)13769517SBill.Taylor@Sun.COM hermon_umap_ci_data_in(hermon_state_t *state, ibt_ci_data_flags_t flags,
13779517SBill.Taylor@Sun.COM ibt_object_type_t object, void *hdl, void *data_p, size_t data_sz)
13789517SBill.Taylor@Sun.COM {
13799517SBill.Taylor@Sun.COM int status;
13809517SBill.Taylor@Sun.COM
13819517SBill.Taylor@Sun.COM /*
13829517SBill.Taylor@Sun.COM * Depending on the type of object about which additional information
13839517SBill.Taylor@Sun.COM * is being provided (currently only MR is supported), we call the
13849517SBill.Taylor@Sun.COM * appropriate resource-specific function.
13859517SBill.Taylor@Sun.COM */
13869517SBill.Taylor@Sun.COM switch (object) {
13879517SBill.Taylor@Sun.COM case IBT_HDL_MR:
13889517SBill.Taylor@Sun.COM status = hermon_umap_mr_data_in((hermon_mrhdl_t)hdl,
13899517SBill.Taylor@Sun.COM (ibt_mr_data_in_t *)data_p, data_sz);
13909517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
13919517SBill.Taylor@Sun.COM return (status);
13929517SBill.Taylor@Sun.COM }
13939517SBill.Taylor@Sun.COM break;
13949517SBill.Taylor@Sun.COM
13959517SBill.Taylor@Sun.COM /*
13969517SBill.Taylor@Sun.COM * For other possible valid IBT types, we return IBT_NOT_SUPPORTED,
13979517SBill.Taylor@Sun.COM * since the Hermon driver does not support these.
13989517SBill.Taylor@Sun.COM */
13999517SBill.Taylor@Sun.COM case IBT_HDL_HCA:
14009517SBill.Taylor@Sun.COM case IBT_HDL_QP:
14019517SBill.Taylor@Sun.COM case IBT_HDL_CQ:
14029517SBill.Taylor@Sun.COM case IBT_HDL_PD:
14039517SBill.Taylor@Sun.COM case IBT_HDL_MW:
14049517SBill.Taylor@Sun.COM case IBT_HDL_AH:
14059517SBill.Taylor@Sun.COM case IBT_HDL_SCHED:
14069517SBill.Taylor@Sun.COM case IBT_HDL_EEC:
14079517SBill.Taylor@Sun.COM case IBT_HDL_RDD:
14089517SBill.Taylor@Sun.COM case IBT_HDL_SRQ:
14099517SBill.Taylor@Sun.COM return (IBT_NOT_SUPPORTED);
14109517SBill.Taylor@Sun.COM
14119517SBill.Taylor@Sun.COM /*
14129517SBill.Taylor@Sun.COM * Any other types are invalid.
14139517SBill.Taylor@Sun.COM */
14149517SBill.Taylor@Sun.COM default:
14159517SBill.Taylor@Sun.COM return (IBT_INVALID_PARAM);
14169517SBill.Taylor@Sun.COM }
14179517SBill.Taylor@Sun.COM
14189517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
14199517SBill.Taylor@Sun.COM }
14209517SBill.Taylor@Sun.COM
14219517SBill.Taylor@Sun.COM
14229517SBill.Taylor@Sun.COM /*
14239517SBill.Taylor@Sun.COM * hermon_umap_mr_data_in()
14249517SBill.Taylor@Sun.COM * Context: Can be called from user or kernel context.
14259517SBill.Taylor@Sun.COM */
14269517SBill.Taylor@Sun.COM static ibt_status_t
hermon_umap_mr_data_in(hermon_mrhdl_t mr,ibt_mr_data_in_t * data,size_t data_sz)14279517SBill.Taylor@Sun.COM hermon_umap_mr_data_in(hermon_mrhdl_t mr, ibt_mr_data_in_t *data,
14289517SBill.Taylor@Sun.COM size_t data_sz)
14299517SBill.Taylor@Sun.COM {
14309517SBill.Taylor@Sun.COM if (data->mr_rev != IBT_MR_DATA_IN_IF_VERSION) {
14319517SBill.Taylor@Sun.COM return (IBT_NOT_SUPPORTED);
14329517SBill.Taylor@Sun.COM }
14339517SBill.Taylor@Sun.COM
14349517SBill.Taylor@Sun.COM /* Check for valid MR handle pointer */
14359517SBill.Taylor@Sun.COM if (mr == NULL) {
14369517SBill.Taylor@Sun.COM return (IBT_MR_HDL_INVALID);
14379517SBill.Taylor@Sun.COM }
14389517SBill.Taylor@Sun.COM
14399517SBill.Taylor@Sun.COM /* Check for valid MR input structure size */
14409517SBill.Taylor@Sun.COM if (data_sz < sizeof (ibt_mr_data_in_t)) {
14419517SBill.Taylor@Sun.COM return (IBT_INSUFF_RESOURCE);
14429517SBill.Taylor@Sun.COM }
14439517SBill.Taylor@Sun.COM _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*data))
14449517SBill.Taylor@Sun.COM
14459517SBill.Taylor@Sun.COM /*
14469517SBill.Taylor@Sun.COM * Ensure that the MR corresponds to userland memory and that it is
14479517SBill.Taylor@Sun.COM * a currently valid memory region as well.
14489517SBill.Taylor@Sun.COM */
14499517SBill.Taylor@Sun.COM mutex_enter(&mr->mr_lock);
14509517SBill.Taylor@Sun.COM if ((mr->mr_is_umem == 0) || (mr->mr_umemcookie == NULL)) {
14519517SBill.Taylor@Sun.COM mutex_exit(&mr->mr_lock);
14529517SBill.Taylor@Sun.COM return (IBT_MR_HDL_INVALID);
14539517SBill.Taylor@Sun.COM }
14549517SBill.Taylor@Sun.COM
14559517SBill.Taylor@Sun.COM /*
14569517SBill.Taylor@Sun.COM * If it has passed all the above checks, then extract the callback
14579517SBill.Taylor@Sun.COM * function and argument from the input structure. Copy them into
14589517SBill.Taylor@Sun.COM * the MR handle. This function will be called only if the memory
14599517SBill.Taylor@Sun.COM * corresponding to the MR handle gets a umem_lockmemory() callback.
14609517SBill.Taylor@Sun.COM */
14619517SBill.Taylor@Sun.COM mr->mr_umem_cbfunc = data->mr_func;
14629517SBill.Taylor@Sun.COM mr->mr_umem_cbarg1 = data->mr_arg1;
14639517SBill.Taylor@Sun.COM mr->mr_umem_cbarg2 = data->mr_arg2;
14649517SBill.Taylor@Sun.COM mutex_exit(&mr->mr_lock);
14659517SBill.Taylor@Sun.COM
14669517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
14679517SBill.Taylor@Sun.COM }
14689517SBill.Taylor@Sun.COM
14699517SBill.Taylor@Sun.COM
14709517SBill.Taylor@Sun.COM /*
14719517SBill.Taylor@Sun.COM * hermon_umap_ci_data_out()
14729517SBill.Taylor@Sun.COM * Context: Can be called from user or kernel context.
14739517SBill.Taylor@Sun.COM */
14749517SBill.Taylor@Sun.COM /* ARGSUSED */
14759517SBill.Taylor@Sun.COM ibt_status_t
hermon_umap_ci_data_out(hermon_state_t * state,ibt_ci_data_flags_t flags,ibt_object_type_t object,void * hdl,void * data_p,size_t data_sz)14769517SBill.Taylor@Sun.COM hermon_umap_ci_data_out(hermon_state_t *state, ibt_ci_data_flags_t flags,
14779517SBill.Taylor@Sun.COM ibt_object_type_t object, void *hdl, void *data_p, size_t data_sz)
14789517SBill.Taylor@Sun.COM {
14799517SBill.Taylor@Sun.COM int status;
14809517SBill.Taylor@Sun.COM
14819517SBill.Taylor@Sun.COM /*
14829517SBill.Taylor@Sun.COM * Depending on the type of object about which additional information
14839517SBill.Taylor@Sun.COM * is being requested (CQ or QP), we call the appropriate resource-
14849517SBill.Taylor@Sun.COM * specific mapping function.
14859517SBill.Taylor@Sun.COM */
14869517SBill.Taylor@Sun.COM switch (object) {
14879517SBill.Taylor@Sun.COM case IBT_HDL_CQ:
14889517SBill.Taylor@Sun.COM status = hermon_umap_cq_data_out((hermon_cqhdl_t)hdl,
14899517SBill.Taylor@Sun.COM (mlnx_umap_cq_data_out_t *)data_p, data_sz);
14909517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
14919517SBill.Taylor@Sun.COM return (status);
14929517SBill.Taylor@Sun.COM }
14939517SBill.Taylor@Sun.COM break;
14949517SBill.Taylor@Sun.COM
14959517SBill.Taylor@Sun.COM case IBT_HDL_QP:
14969517SBill.Taylor@Sun.COM status = hermon_umap_qp_data_out((hermon_qphdl_t)hdl,
14979517SBill.Taylor@Sun.COM (mlnx_umap_qp_data_out_t *)data_p, data_sz);
14989517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
14999517SBill.Taylor@Sun.COM return (status);
15009517SBill.Taylor@Sun.COM }
15019517SBill.Taylor@Sun.COM break;
15029517SBill.Taylor@Sun.COM
15039517SBill.Taylor@Sun.COM case IBT_HDL_SRQ:
15049517SBill.Taylor@Sun.COM status = hermon_umap_srq_data_out((hermon_srqhdl_t)hdl,
15059517SBill.Taylor@Sun.COM (mlnx_umap_srq_data_out_t *)data_p, data_sz);
15069517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
15079517SBill.Taylor@Sun.COM return (status);
15089517SBill.Taylor@Sun.COM }
15099517SBill.Taylor@Sun.COM break;
15109517SBill.Taylor@Sun.COM
15119517SBill.Taylor@Sun.COM case IBT_HDL_PD:
15129517SBill.Taylor@Sun.COM status = hermon_umap_pd_data_out((hermon_pdhdl_t)hdl,
15139517SBill.Taylor@Sun.COM (mlnx_umap_pd_data_out_t *)data_p, data_sz);
15149517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
15159517SBill.Taylor@Sun.COM return (status);
15169517SBill.Taylor@Sun.COM }
15179517SBill.Taylor@Sun.COM break;
15189517SBill.Taylor@Sun.COM
15199517SBill.Taylor@Sun.COM /*
15209517SBill.Taylor@Sun.COM * For other possible valid IBT types, we return IBT_NOT_SUPPORTED,
15219517SBill.Taylor@Sun.COM * since the Hermon driver does not support these.
15229517SBill.Taylor@Sun.COM */
15239517SBill.Taylor@Sun.COM case IBT_HDL_HCA:
15249517SBill.Taylor@Sun.COM case IBT_HDL_MR:
15259517SBill.Taylor@Sun.COM case IBT_HDL_MW:
15269517SBill.Taylor@Sun.COM case IBT_HDL_AH:
15279517SBill.Taylor@Sun.COM case IBT_HDL_SCHED:
15289517SBill.Taylor@Sun.COM case IBT_HDL_EEC:
15299517SBill.Taylor@Sun.COM case IBT_HDL_RDD:
15309517SBill.Taylor@Sun.COM return (IBT_NOT_SUPPORTED);
15319517SBill.Taylor@Sun.COM
15329517SBill.Taylor@Sun.COM /*
15339517SBill.Taylor@Sun.COM * Any other types are invalid.
15349517SBill.Taylor@Sun.COM */
15359517SBill.Taylor@Sun.COM default:
15369517SBill.Taylor@Sun.COM return (IBT_INVALID_PARAM);
15379517SBill.Taylor@Sun.COM }
15389517SBill.Taylor@Sun.COM
15399517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
15409517SBill.Taylor@Sun.COM }
15419517SBill.Taylor@Sun.COM
15429517SBill.Taylor@Sun.COM
15439517SBill.Taylor@Sun.COM /*
15449517SBill.Taylor@Sun.COM * hermon_umap_cq_data_out()
15459517SBill.Taylor@Sun.COM * Context: Can be called from user or kernel context.
15469517SBill.Taylor@Sun.COM */
15479517SBill.Taylor@Sun.COM static ibt_status_t
hermon_umap_cq_data_out(hermon_cqhdl_t cq,mlnx_umap_cq_data_out_t * data,size_t data_sz)15489517SBill.Taylor@Sun.COM hermon_umap_cq_data_out(hermon_cqhdl_t cq, mlnx_umap_cq_data_out_t *data,
15499517SBill.Taylor@Sun.COM size_t data_sz)
15509517SBill.Taylor@Sun.COM {
15519517SBill.Taylor@Sun.COM /* Check for valid CQ handle pointer */
15529517SBill.Taylor@Sun.COM if (cq == NULL) {
15539517SBill.Taylor@Sun.COM return (IBT_CQ_HDL_INVALID);
15549517SBill.Taylor@Sun.COM }
15559517SBill.Taylor@Sun.COM
15569517SBill.Taylor@Sun.COM /* Check for valid CQ mapping structure size */
15579517SBill.Taylor@Sun.COM if (data_sz < sizeof (mlnx_umap_cq_data_out_t)) {
15589517SBill.Taylor@Sun.COM return (IBT_INSUFF_RESOURCE);
15599517SBill.Taylor@Sun.COM }
15609517SBill.Taylor@Sun.COM _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*data))
15619517SBill.Taylor@Sun.COM
15629517SBill.Taylor@Sun.COM /* deal with cq_alloc() verses cq_resize() */
15639517SBill.Taylor@Sun.COM if (cq->cq_resize_hdl) {
15649517SBill.Taylor@Sun.COM data->mcq_maplen = cq->cq_resize_hdl->cq_cqinfo.qa_size;
15659517SBill.Taylor@Sun.COM data->mcq_numcqe = cq->cq_resize_hdl->cq_bufsz;
15669517SBill.Taylor@Sun.COM } else {
15679517SBill.Taylor@Sun.COM data->mcq_maplen = cq->cq_cqinfo.qa_size;
15689517SBill.Taylor@Sun.COM data->mcq_numcqe = cq->cq_bufsz;
15699517SBill.Taylor@Sun.COM }
15709517SBill.Taylor@Sun.COM
15719517SBill.Taylor@Sun.COM /*
15729517SBill.Taylor@Sun.COM * If it has passed all the above checks, then fill in all the useful
15739517SBill.Taylor@Sun.COM * mapping information (including the mapping offset that will be
15749517SBill.Taylor@Sun.COM * passed back to the devmap() interface during a subsequent mmap()
15759517SBill.Taylor@Sun.COM * call.
15769517SBill.Taylor@Sun.COM *
15779517SBill.Taylor@Sun.COM * The "offset" for CQ mmap()'s looks like this:
15789517SBill.Taylor@Sun.COM * +----------------------------------------+--------+--------------+
15799517SBill.Taylor@Sun.COM * | CQ Number | 0x33 | Reserved (0) |
15809517SBill.Taylor@Sun.COM * +----------------------------------------+--------+--------------+
15819517SBill.Taylor@Sun.COM * (64 - 8 - PAGESHIFT) bits 8 bits PAGESHIFT bits
15829517SBill.Taylor@Sun.COM *
15839517SBill.Taylor@Sun.COM * This returns information about the mapping offset, the length of
15849517SBill.Taylor@Sun.COM * the CQ memory, the CQ number (for use in later CQ doorbells), the
15859517SBill.Taylor@Sun.COM * number of CQEs the CQ memory can hold, and the size of each CQE.
15869517SBill.Taylor@Sun.COM */
15879517SBill.Taylor@Sun.COM data->mcq_rev = MLNX_UMAP_IF_VERSION;
15889517SBill.Taylor@Sun.COM data->mcq_mapoffset = ((((uint64_t)cq->cq_cqnum <<
15899517SBill.Taylor@Sun.COM MLNX_UMAP_RSRC_TYPE_SHIFT) | MLNX_UMAP_CQMEM_RSRC) << PAGESHIFT);
15909517SBill.Taylor@Sun.COM data->mcq_cqnum = cq->cq_cqnum;
15919517SBill.Taylor@Sun.COM data->mcq_cqesz = sizeof (hermon_hw_cqe_t);
15929517SBill.Taylor@Sun.COM
15939517SBill.Taylor@Sun.COM /* doorbell record fields */
15949517SBill.Taylor@Sun.COM data->mcq_polldbr_mapoffset = cq->cq_dbr_mapoffset;
15959517SBill.Taylor@Sun.COM data->mcq_polldbr_maplen = PAGESIZE;
15969517SBill.Taylor@Sun.COM data->mcq_polldbr_offset = (uintptr_t)cq->cq_arm_ci_vdbr &
15979517SBill.Taylor@Sun.COM PAGEOFFSET;
15989517SBill.Taylor@Sun.COM data->mcq_armdbr_mapoffset = cq->cq_dbr_mapoffset;
15999517SBill.Taylor@Sun.COM data->mcq_armdbr_maplen = PAGESIZE;
16009517SBill.Taylor@Sun.COM data->mcq_armdbr_offset = data->mcq_polldbr_offset + 4;
16019517SBill.Taylor@Sun.COM
16029517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
16039517SBill.Taylor@Sun.COM }
16049517SBill.Taylor@Sun.COM
16059517SBill.Taylor@Sun.COM
16069517SBill.Taylor@Sun.COM /*
16079517SBill.Taylor@Sun.COM * hermon_umap_qp_data_out()
16089517SBill.Taylor@Sun.COM * Context: Can be called from user or kernel context.
16099517SBill.Taylor@Sun.COM */
16109517SBill.Taylor@Sun.COM static ibt_status_t
hermon_umap_qp_data_out(hermon_qphdl_t qp,mlnx_umap_qp_data_out_t * data,size_t data_sz)16119517SBill.Taylor@Sun.COM hermon_umap_qp_data_out(hermon_qphdl_t qp, mlnx_umap_qp_data_out_t *data,
16129517SBill.Taylor@Sun.COM size_t data_sz)
16139517SBill.Taylor@Sun.COM {
16149517SBill.Taylor@Sun.COM /* Check for valid QP handle pointer */
16159517SBill.Taylor@Sun.COM if (qp == NULL) {
16169517SBill.Taylor@Sun.COM return (IBT_QP_HDL_INVALID);
16179517SBill.Taylor@Sun.COM }
16189517SBill.Taylor@Sun.COM
16199517SBill.Taylor@Sun.COM /* Check for valid QP mapping structure size */
16209517SBill.Taylor@Sun.COM if (data_sz < sizeof (mlnx_umap_qp_data_out_t)) {
16219517SBill.Taylor@Sun.COM return (IBT_INSUFF_RESOURCE);
16229517SBill.Taylor@Sun.COM }
16239517SBill.Taylor@Sun.COM _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*data))
16249517SBill.Taylor@Sun.COM
16259517SBill.Taylor@Sun.COM /*
16269517SBill.Taylor@Sun.COM * If it has passed all the checks, then fill in all the useful
16279517SBill.Taylor@Sun.COM * mapping information (including the mapping offset that will be
16289517SBill.Taylor@Sun.COM * passed back to the devmap() interface during a subsequent mmap()
16299517SBill.Taylor@Sun.COM * call.
16309517SBill.Taylor@Sun.COM *
16319517SBill.Taylor@Sun.COM * The "offset" for QP mmap()'s looks like this:
16329517SBill.Taylor@Sun.COM * +----------------------------------------+--------+--------------+
16339517SBill.Taylor@Sun.COM * | QP Number | 0x44 | Reserved (0) |
16349517SBill.Taylor@Sun.COM * +----------------------------------------+--------+--------------+
16359517SBill.Taylor@Sun.COM * (64 - 8 - PAGESHIFT) bits 8 bits PAGESHIFT bits
16369517SBill.Taylor@Sun.COM *
16379517SBill.Taylor@Sun.COM * This returns information about the mapping offset, the length of
16389517SBill.Taylor@Sun.COM * the QP memory, and the QP number (for use in later send and recv
16399517SBill.Taylor@Sun.COM * doorbells). It also returns the following information for both
16409517SBill.Taylor@Sun.COM * the receive work queue and the send work queue, respectively: the
16419517SBill.Taylor@Sun.COM * offset (from the base mapped address) of the start of the given
16429517SBill.Taylor@Sun.COM * work queue, the 64-bit IB virtual address that corresponds to
16439517SBill.Taylor@Sun.COM * the base mapped address (needed for posting WQEs though the
16449517SBill.Taylor@Sun.COM * QP doorbells), the number of WQEs the given work queue can hold,
16459517SBill.Taylor@Sun.COM * and the size of each WQE for the given work queue.
16469517SBill.Taylor@Sun.COM */
16479517SBill.Taylor@Sun.COM data->mqp_rev = MLNX_UMAP_IF_VERSION;
16489517SBill.Taylor@Sun.COM data->mqp_mapoffset = ((((uint64_t)qp->qp_qpnum <<
16499517SBill.Taylor@Sun.COM MLNX_UMAP_RSRC_TYPE_SHIFT) | MLNX_UMAP_QPMEM_RSRC) << PAGESHIFT);
16509517SBill.Taylor@Sun.COM data->mqp_maplen = qp->qp_wqinfo.qa_size;
16519517SBill.Taylor@Sun.COM data->mqp_qpnum = qp->qp_qpnum;
16529517SBill.Taylor@Sun.COM
16539517SBill.Taylor@Sun.COM /*
16549517SBill.Taylor@Sun.COM * If this QP is associated with a shared receive queue (SRQ),
16559517SBill.Taylor@Sun.COM * then return invalid RecvQ parameters. Otherwise, return
16569517SBill.Taylor@Sun.COM * the proper parameter values.
16579517SBill.Taylor@Sun.COM */
1658*12965SWilliam.Taylor@Oracle.COM if (qp->qp_alloc_flags & IBT_QP_USES_SRQ) {
16599517SBill.Taylor@Sun.COM data->mqp_rq_off = (uint32_t)qp->qp_wqinfo.qa_size;
16609517SBill.Taylor@Sun.COM data->mqp_rq_desc_addr = (uint32_t)qp->qp_wqinfo.qa_size;
16619517SBill.Taylor@Sun.COM data->mqp_rq_numwqe = 0;
16629517SBill.Taylor@Sun.COM data->mqp_rq_wqesz = 0;
16639517SBill.Taylor@Sun.COM data->mqp_rdbr_mapoffset = 0;
16649517SBill.Taylor@Sun.COM data->mqp_rdbr_maplen = 0;
16659517SBill.Taylor@Sun.COM data->mqp_rdbr_offset = 0;
16669517SBill.Taylor@Sun.COM } else {
16679517SBill.Taylor@Sun.COM data->mqp_rq_off = (uintptr_t)qp->qp_rq_buf -
16689517SBill.Taylor@Sun.COM (uintptr_t)qp->qp_wqinfo.qa_buf_aligned;
16699517SBill.Taylor@Sun.COM data->mqp_rq_desc_addr = (uint32_t)((uintptr_t)qp->qp_rq_buf -
16709517SBill.Taylor@Sun.COM qp->qp_desc_off);
16719517SBill.Taylor@Sun.COM data->mqp_rq_numwqe = qp->qp_rq_bufsz;
16729517SBill.Taylor@Sun.COM data->mqp_rq_wqesz = (1 << qp->qp_rq_log_wqesz);
16739517SBill.Taylor@Sun.COM
16749517SBill.Taylor@Sun.COM /* doorbell record fields */
16759517SBill.Taylor@Sun.COM data->mqp_rdbr_mapoffset = qp->qp_rdbr_mapoffset;
16769517SBill.Taylor@Sun.COM data->mqp_rdbr_maplen = PAGESIZE;
16779517SBill.Taylor@Sun.COM data->mqp_rdbr_offset = (uintptr_t)qp->qp_rq_vdbr &
16789517SBill.Taylor@Sun.COM PAGEOFFSET;
16799517SBill.Taylor@Sun.COM }
16809517SBill.Taylor@Sun.COM data->mqp_sq_off = (uintptr_t)qp->qp_sq_buf -
16819517SBill.Taylor@Sun.COM (uintptr_t)qp->qp_wqinfo.qa_buf_aligned;
16829517SBill.Taylor@Sun.COM data->mqp_sq_desc_addr = (uint32_t)((uintptr_t)qp->qp_sq_buf -
16839517SBill.Taylor@Sun.COM qp->qp_desc_off);
16849517SBill.Taylor@Sun.COM data->mqp_sq_numwqe = qp->qp_sq_bufsz;
16859517SBill.Taylor@Sun.COM data->mqp_sq_wqesz = (1 << qp->qp_sq_log_wqesz);
16869517SBill.Taylor@Sun.COM data->mqp_sq_headroomwqes = qp->qp_sq_hdrmwqes;
16879517SBill.Taylor@Sun.COM
16889517SBill.Taylor@Sun.COM /* doorbell record fields */
16899517SBill.Taylor@Sun.COM data->mqp_sdbr_mapoffset = 0;
16909517SBill.Taylor@Sun.COM data->mqp_sdbr_maplen = 0;
16919517SBill.Taylor@Sun.COM data->mqp_sdbr_offset = 0;
16929517SBill.Taylor@Sun.COM
16939517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
16949517SBill.Taylor@Sun.COM }
16959517SBill.Taylor@Sun.COM
16969517SBill.Taylor@Sun.COM
16979517SBill.Taylor@Sun.COM /*
16989517SBill.Taylor@Sun.COM * hermon_umap_srq_data_out()
16999517SBill.Taylor@Sun.COM * Context: Can be called from user or kernel context.
17009517SBill.Taylor@Sun.COM */
17019517SBill.Taylor@Sun.COM static ibt_status_t
hermon_umap_srq_data_out(hermon_srqhdl_t srq,mlnx_umap_srq_data_out_t * data,size_t data_sz)17029517SBill.Taylor@Sun.COM hermon_umap_srq_data_out(hermon_srqhdl_t srq, mlnx_umap_srq_data_out_t *data,
17039517SBill.Taylor@Sun.COM size_t data_sz)
17049517SBill.Taylor@Sun.COM {
17059517SBill.Taylor@Sun.COM /* Check for valid SRQ handle pointer */
17069517SBill.Taylor@Sun.COM if (srq == NULL) {
17079517SBill.Taylor@Sun.COM return (IBT_SRQ_HDL_INVALID);
17089517SBill.Taylor@Sun.COM }
17099517SBill.Taylor@Sun.COM
17109517SBill.Taylor@Sun.COM /* Check for valid SRQ mapping structure size */
17119517SBill.Taylor@Sun.COM if (data_sz < sizeof (mlnx_umap_srq_data_out_t)) {
17129517SBill.Taylor@Sun.COM return (IBT_INSUFF_RESOURCE);
17139517SBill.Taylor@Sun.COM }
17149517SBill.Taylor@Sun.COM _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*data))
17159517SBill.Taylor@Sun.COM
17169517SBill.Taylor@Sun.COM /*
17179517SBill.Taylor@Sun.COM * If it has passed all the checks, then fill in all the useful
17189517SBill.Taylor@Sun.COM * mapping information (including the mapping offset that will be
17199517SBill.Taylor@Sun.COM * passed back to the devmap() interface during a subsequent mmap()
17209517SBill.Taylor@Sun.COM * call.
17219517SBill.Taylor@Sun.COM *
17229517SBill.Taylor@Sun.COM * The "offset" for SRQ mmap()'s looks like this:
17239517SBill.Taylor@Sun.COM * +----------------------------------------+--------+--------------+
17249517SBill.Taylor@Sun.COM * | SRQ Number | 0x66 | Reserved (0) |
17259517SBill.Taylor@Sun.COM * +----------------------------------------+--------+--------------+
17269517SBill.Taylor@Sun.COM * (64 - 8 - PAGESHIFT) bits 8 bits PAGESHIFT bits
17279517SBill.Taylor@Sun.COM *
17289517SBill.Taylor@Sun.COM * This returns information about the mapping offset, the length of the
17299517SBill.Taylor@Sun.COM * SRQ memory, and the SRQ number (for use in later send and recv
17309517SBill.Taylor@Sun.COM * doorbells). It also returns the following information for the
17319517SBill.Taylor@Sun.COM * shared receive queue: the offset (from the base mapped address) of
17329517SBill.Taylor@Sun.COM * the start of the given work queue, the 64-bit IB virtual address
17339517SBill.Taylor@Sun.COM * that corresponds to the base mapped address (needed for posting WQEs
17349517SBill.Taylor@Sun.COM * though the QP doorbells), the number of WQEs the given work queue
17359517SBill.Taylor@Sun.COM * can hold, and the size of each WQE for the given work queue.
17369517SBill.Taylor@Sun.COM */
17379517SBill.Taylor@Sun.COM data->msrq_rev = MLNX_UMAP_IF_VERSION;
17389517SBill.Taylor@Sun.COM data->msrq_mapoffset = ((((uint64_t)srq->srq_srqnum <<
17399517SBill.Taylor@Sun.COM MLNX_UMAP_RSRC_TYPE_SHIFT) | MLNX_UMAP_SRQMEM_RSRC) << PAGESHIFT);
17409517SBill.Taylor@Sun.COM data->msrq_maplen = srq->srq_wqinfo.qa_size;
17419517SBill.Taylor@Sun.COM data->msrq_srqnum = srq->srq_srqnum;
17429517SBill.Taylor@Sun.COM
17439517SBill.Taylor@Sun.COM data->msrq_desc_addr = (uint32_t)((uintptr_t)srq->srq_wq_buf -
17449517SBill.Taylor@Sun.COM srq->srq_desc_off);
17459517SBill.Taylor@Sun.COM data->msrq_numwqe = srq->srq_wq_bufsz;
17469517SBill.Taylor@Sun.COM data->msrq_wqesz = (1 << srq->srq_wq_log_wqesz);
17479517SBill.Taylor@Sun.COM
17489517SBill.Taylor@Sun.COM /* doorbell record fields */
17499517SBill.Taylor@Sun.COM data->msrq_rdbr_mapoffset = srq->srq_rdbr_mapoffset;
17509517SBill.Taylor@Sun.COM data->msrq_rdbr_maplen = PAGESIZE;
17519517SBill.Taylor@Sun.COM data->msrq_rdbr_offset = (uintptr_t)srq->srq_wq_vdbr &
17529517SBill.Taylor@Sun.COM PAGEOFFSET;
17539517SBill.Taylor@Sun.COM
17549517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
17559517SBill.Taylor@Sun.COM }
17569517SBill.Taylor@Sun.COM
17579517SBill.Taylor@Sun.COM
17589517SBill.Taylor@Sun.COM /*
17599517SBill.Taylor@Sun.COM * hermon_umap_pd_data_out()
17609517SBill.Taylor@Sun.COM * Context: Can be called from user or kernel context.
17619517SBill.Taylor@Sun.COM */
17629517SBill.Taylor@Sun.COM static ibt_status_t
hermon_umap_pd_data_out(hermon_pdhdl_t pd,mlnx_umap_pd_data_out_t * data,size_t data_sz)17639517SBill.Taylor@Sun.COM hermon_umap_pd_data_out(hermon_pdhdl_t pd, mlnx_umap_pd_data_out_t *data,
17649517SBill.Taylor@Sun.COM size_t data_sz)
17659517SBill.Taylor@Sun.COM {
17669517SBill.Taylor@Sun.COM /* Check for valid PD handle pointer */
17679517SBill.Taylor@Sun.COM if (pd == NULL) {
17689517SBill.Taylor@Sun.COM return (IBT_PD_HDL_INVALID);
17699517SBill.Taylor@Sun.COM }
17709517SBill.Taylor@Sun.COM
17719517SBill.Taylor@Sun.COM /* Check for valid PD mapping structure size */
17729517SBill.Taylor@Sun.COM if (data_sz < sizeof (mlnx_umap_pd_data_out_t)) {
17739517SBill.Taylor@Sun.COM return (IBT_INSUFF_RESOURCE);
17749517SBill.Taylor@Sun.COM }
17759517SBill.Taylor@Sun.COM _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*data))
17769517SBill.Taylor@Sun.COM
17779517SBill.Taylor@Sun.COM /*
17789517SBill.Taylor@Sun.COM * If it has passed all the checks, then fill the PD table index
17799517SBill.Taylor@Sun.COM * (the PD table allocated index for the PD pd_pdnum).
17809517SBill.Taylor@Sun.COM */
17819517SBill.Taylor@Sun.COM data->mpd_rev = MLNX_UMAP_IF_VERSION;
17829517SBill.Taylor@Sun.COM data->mpd_pdnum = pd->pd_pdnum;
17839517SBill.Taylor@Sun.COM
17849517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
17859517SBill.Taylor@Sun.COM }
17869517SBill.Taylor@Sun.COM
17879517SBill.Taylor@Sun.COM
17889517SBill.Taylor@Sun.COM /*
17899517SBill.Taylor@Sun.COM * hermon_umap_db_init()
17909517SBill.Taylor@Sun.COM * Context: Only called from attach() path context
17919517SBill.Taylor@Sun.COM */
17929517SBill.Taylor@Sun.COM void
hermon_umap_db_init(void)17939517SBill.Taylor@Sun.COM hermon_umap_db_init(void)
17949517SBill.Taylor@Sun.COM {
17959517SBill.Taylor@Sun.COM /*
17969517SBill.Taylor@Sun.COM * Initialize the lock used by the Hermon "userland resources database"
17979517SBill.Taylor@Sun.COM * This is used to ensure atomic access to add, remove, and find
17989517SBill.Taylor@Sun.COM * entries in the database.
17999517SBill.Taylor@Sun.COM */
18009517SBill.Taylor@Sun.COM mutex_init(&hermon_userland_rsrc_db.hdl_umapdb_lock, NULL,
18019517SBill.Taylor@Sun.COM MUTEX_DRIVER, NULL);
18029517SBill.Taylor@Sun.COM
18039517SBill.Taylor@Sun.COM /*
18049517SBill.Taylor@Sun.COM * Initialize the AVL tree used for the "userland resources
18059517SBill.Taylor@Sun.COM * database". Using an AVL tree here provides the ability to
18069517SBill.Taylor@Sun.COM * scale the database size to large numbers of resources. The
18079517SBill.Taylor@Sun.COM * entries in the tree are "hermon_umap_db_entry_t" (see
18089517SBill.Taylor@Sun.COM * hermon_umap.h). The tree is searched with the help of the
18099517SBill.Taylor@Sun.COM * hermon_umap_db_compare() routine.
18109517SBill.Taylor@Sun.COM */
18119517SBill.Taylor@Sun.COM avl_create(&hermon_userland_rsrc_db.hdl_umapdb_avl,
18129517SBill.Taylor@Sun.COM hermon_umap_db_compare, sizeof (hermon_umap_db_entry_t),
18139517SBill.Taylor@Sun.COM offsetof(hermon_umap_db_entry_t, hdbe_avlnode));
18149517SBill.Taylor@Sun.COM }
18159517SBill.Taylor@Sun.COM
18169517SBill.Taylor@Sun.COM
18179517SBill.Taylor@Sun.COM /*
18189517SBill.Taylor@Sun.COM * hermon_umap_db_fini()
18199517SBill.Taylor@Sun.COM * Context: Only called from attach() and/or detach() path contexts
18209517SBill.Taylor@Sun.COM */
18219517SBill.Taylor@Sun.COM void
hermon_umap_db_fini(void)18229517SBill.Taylor@Sun.COM hermon_umap_db_fini(void)
18239517SBill.Taylor@Sun.COM {
18249517SBill.Taylor@Sun.COM /* Destroy the AVL tree for the "userland resources database" */
18259517SBill.Taylor@Sun.COM avl_destroy(&hermon_userland_rsrc_db.hdl_umapdb_avl);
18269517SBill.Taylor@Sun.COM
18279517SBill.Taylor@Sun.COM /* Destroy the lock for the "userland resources database" */
18289517SBill.Taylor@Sun.COM mutex_destroy(&hermon_userland_rsrc_db.hdl_umapdb_lock);
18299517SBill.Taylor@Sun.COM }
18309517SBill.Taylor@Sun.COM
18319517SBill.Taylor@Sun.COM
18329517SBill.Taylor@Sun.COM /*
18339517SBill.Taylor@Sun.COM * hermon_umap_db_alloc()
18349517SBill.Taylor@Sun.COM * Context: Can be called from user or kernel context.
18359517SBill.Taylor@Sun.COM */
18369517SBill.Taylor@Sun.COM hermon_umap_db_entry_t *
hermon_umap_db_alloc(uint_t instance,uint64_t key,uint_t type,uint64_t value)18379517SBill.Taylor@Sun.COM hermon_umap_db_alloc(uint_t instance, uint64_t key, uint_t type, uint64_t value)
18389517SBill.Taylor@Sun.COM {
18399517SBill.Taylor@Sun.COM hermon_umap_db_entry_t *umapdb;
18409517SBill.Taylor@Sun.COM
18419517SBill.Taylor@Sun.COM /* Allocate an entry to add to the "userland resources database" */
18429517SBill.Taylor@Sun.COM umapdb = kmem_zalloc(sizeof (hermon_umap_db_entry_t), KM_NOSLEEP);
18439517SBill.Taylor@Sun.COM if (umapdb == NULL) {
18449517SBill.Taylor@Sun.COM return (NULL);
18459517SBill.Taylor@Sun.COM }
18469517SBill.Taylor@Sun.COM _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*umapdb))
18479517SBill.Taylor@Sun.COM
18489517SBill.Taylor@Sun.COM /* Fill in the fields in the database entry */
18499517SBill.Taylor@Sun.COM umapdb->hdbe_common.hdb_instance = instance;
18509517SBill.Taylor@Sun.COM umapdb->hdbe_common.hdb_type = type;
18519517SBill.Taylor@Sun.COM umapdb->hdbe_common.hdb_key = key;
18529517SBill.Taylor@Sun.COM umapdb->hdbe_common.hdb_value = value;
18539517SBill.Taylor@Sun.COM
18549517SBill.Taylor@Sun.COM return (umapdb);
18559517SBill.Taylor@Sun.COM }
18569517SBill.Taylor@Sun.COM
18579517SBill.Taylor@Sun.COM
18589517SBill.Taylor@Sun.COM /*
18599517SBill.Taylor@Sun.COM * hermon_umap_db_free()
18609517SBill.Taylor@Sun.COM * Context: Can be called from user or kernel context.
18619517SBill.Taylor@Sun.COM */
18629517SBill.Taylor@Sun.COM void
hermon_umap_db_free(hermon_umap_db_entry_t * umapdb)18639517SBill.Taylor@Sun.COM hermon_umap_db_free(hermon_umap_db_entry_t *umapdb)
18649517SBill.Taylor@Sun.COM {
18659517SBill.Taylor@Sun.COM /* Free the database entry */
18669517SBill.Taylor@Sun.COM kmem_free(umapdb, sizeof (hermon_umap_db_entry_t));
18679517SBill.Taylor@Sun.COM }
18689517SBill.Taylor@Sun.COM
18699517SBill.Taylor@Sun.COM
18709517SBill.Taylor@Sun.COM /*
18719517SBill.Taylor@Sun.COM * hermon_umap_db_add()
18729517SBill.Taylor@Sun.COM * Context: Can be called from user or kernel context.
18739517SBill.Taylor@Sun.COM */
18749517SBill.Taylor@Sun.COM void
hermon_umap_db_add(hermon_umap_db_entry_t * umapdb)18759517SBill.Taylor@Sun.COM hermon_umap_db_add(hermon_umap_db_entry_t *umapdb)
18769517SBill.Taylor@Sun.COM {
18779517SBill.Taylor@Sun.COM mutex_enter(&hermon_userland_rsrc_db.hdl_umapdb_lock);
18789517SBill.Taylor@Sun.COM hermon_umap_db_add_nolock(umapdb);
18799517SBill.Taylor@Sun.COM mutex_exit(&hermon_userland_rsrc_db.hdl_umapdb_lock);
18809517SBill.Taylor@Sun.COM }
18819517SBill.Taylor@Sun.COM
18829517SBill.Taylor@Sun.COM
18839517SBill.Taylor@Sun.COM /*
18849517SBill.Taylor@Sun.COM * hermon_umap_db_add_nolock()
18859517SBill.Taylor@Sun.COM * Context: Can be called from user or kernel context.
18869517SBill.Taylor@Sun.COM */
18879517SBill.Taylor@Sun.COM void
hermon_umap_db_add_nolock(hermon_umap_db_entry_t * umapdb)18889517SBill.Taylor@Sun.COM hermon_umap_db_add_nolock(hermon_umap_db_entry_t *umapdb)
18899517SBill.Taylor@Sun.COM {
18909517SBill.Taylor@Sun.COM hermon_umap_db_query_t query;
18919517SBill.Taylor@Sun.COM avl_index_t where;
18929517SBill.Taylor@Sun.COM
18939517SBill.Taylor@Sun.COM ASSERT(MUTEX_HELD(&hermon_userland_rsrc_db.hdl_umapdb_lock));
18949517SBill.Taylor@Sun.COM
18959517SBill.Taylor@Sun.COM _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*umapdb))
18969517SBill.Taylor@Sun.COM
18979517SBill.Taylor@Sun.COM /*
18989517SBill.Taylor@Sun.COM * Copy the common portion of the "to-be-added" database entry
18999517SBill.Taylor@Sun.COM * into the "hermon_umap_db_query_t" structure. We use this structure
19009517SBill.Taylor@Sun.COM * (with no flags set) to find the appropriate location in the
19019517SBill.Taylor@Sun.COM * "userland resources database" for the new entry to be added.
19029517SBill.Taylor@Sun.COM *
19039517SBill.Taylor@Sun.COM * Note: we expect that this entry should not be found in the
19049517SBill.Taylor@Sun.COM * database (unless something bad has happened).
19059517SBill.Taylor@Sun.COM */
19069517SBill.Taylor@Sun.COM query.hqdb_common = umapdb->hdbe_common;
19079517SBill.Taylor@Sun.COM query.hqdb_flags = 0;
19089517SBill.Taylor@Sun.COM (void) avl_find(&hermon_userland_rsrc_db.hdl_umapdb_avl, &query,
19099517SBill.Taylor@Sun.COM &where);
19109517SBill.Taylor@Sun.COM
19119517SBill.Taylor@Sun.COM /*
19129517SBill.Taylor@Sun.COM * Now, using the "where" field from the avl_find() operation
19139517SBill.Taylor@Sun.COM * above, we will insert the new database entry ("umapdb").
19149517SBill.Taylor@Sun.COM */
19159517SBill.Taylor@Sun.COM avl_insert(&hermon_userland_rsrc_db.hdl_umapdb_avl, umapdb,
19169517SBill.Taylor@Sun.COM where);
19179517SBill.Taylor@Sun.COM }
19189517SBill.Taylor@Sun.COM
19199517SBill.Taylor@Sun.COM
19209517SBill.Taylor@Sun.COM /*
19219517SBill.Taylor@Sun.COM * hermon_umap_db_find()
19229517SBill.Taylor@Sun.COM * Context: Can be called from user or kernel context.
19239517SBill.Taylor@Sun.COM */
19249517SBill.Taylor@Sun.COM int
hermon_umap_db_find(uint_t instance,uint64_t key,uint_t type,uint64_t * value,uint_t flag,hermon_umap_db_entry_t ** umapdb)19259517SBill.Taylor@Sun.COM hermon_umap_db_find(uint_t instance, uint64_t key, uint_t type,
19269517SBill.Taylor@Sun.COM uint64_t *value, uint_t flag, hermon_umap_db_entry_t **umapdb)
19279517SBill.Taylor@Sun.COM {
19289517SBill.Taylor@Sun.COM int status;
19299517SBill.Taylor@Sun.COM
19309517SBill.Taylor@Sun.COM mutex_enter(&hermon_userland_rsrc_db.hdl_umapdb_lock);
19319517SBill.Taylor@Sun.COM status = hermon_umap_db_find_nolock(instance, key, type, value, flag,
19329517SBill.Taylor@Sun.COM umapdb);
19339517SBill.Taylor@Sun.COM mutex_exit(&hermon_userland_rsrc_db.hdl_umapdb_lock);
19349517SBill.Taylor@Sun.COM
19359517SBill.Taylor@Sun.COM return (status);
19369517SBill.Taylor@Sun.COM }
19379517SBill.Taylor@Sun.COM
19389517SBill.Taylor@Sun.COM
19399517SBill.Taylor@Sun.COM /*
19409517SBill.Taylor@Sun.COM * hermon_umap_db_find_nolock()
19419517SBill.Taylor@Sun.COM * Context: Can be called from user or kernel context.
19429517SBill.Taylor@Sun.COM */
19439517SBill.Taylor@Sun.COM int
hermon_umap_db_find_nolock(uint_t instance,uint64_t key,uint_t type,uint64_t * value,uint_t flags,hermon_umap_db_entry_t ** umapdb)19449517SBill.Taylor@Sun.COM hermon_umap_db_find_nolock(uint_t instance, uint64_t key, uint_t type,
19459517SBill.Taylor@Sun.COM uint64_t *value, uint_t flags, hermon_umap_db_entry_t **umapdb)
19469517SBill.Taylor@Sun.COM {
19479517SBill.Taylor@Sun.COM hermon_umap_db_query_t query;
19489517SBill.Taylor@Sun.COM hermon_umap_db_entry_t *entry;
19499517SBill.Taylor@Sun.COM avl_index_t where;
19509517SBill.Taylor@Sun.COM
19519517SBill.Taylor@Sun.COM ASSERT(MUTEX_HELD(&hermon_userland_rsrc_db.hdl_umapdb_lock));
19529517SBill.Taylor@Sun.COM
19539517SBill.Taylor@Sun.COM /*
19549517SBill.Taylor@Sun.COM * Fill in key, type, instance, and flags values of the
19559517SBill.Taylor@Sun.COM * hermon_umap_db_query_t in preparation for the database
19569517SBill.Taylor@Sun.COM * lookup.
19579517SBill.Taylor@Sun.COM */
19589517SBill.Taylor@Sun.COM query.hqdb_flags = flags;
19599517SBill.Taylor@Sun.COM query.hqdb_common.hdb_key = key;
19609517SBill.Taylor@Sun.COM query.hqdb_common.hdb_type = type;
19619517SBill.Taylor@Sun.COM query.hqdb_common.hdb_instance = instance;
19629517SBill.Taylor@Sun.COM
19639517SBill.Taylor@Sun.COM /*
19649517SBill.Taylor@Sun.COM * Perform the database query. If no entry is found, then
19659517SBill.Taylor@Sun.COM * return failure, else continue.
19669517SBill.Taylor@Sun.COM */
19679517SBill.Taylor@Sun.COM entry = (hermon_umap_db_entry_t *)avl_find(
19689517SBill.Taylor@Sun.COM &hermon_userland_rsrc_db.hdl_umapdb_avl, &query, &where);
19699517SBill.Taylor@Sun.COM if (entry == NULL) {
19709517SBill.Taylor@Sun.COM return (DDI_FAILURE);
19719517SBill.Taylor@Sun.COM }
19729517SBill.Taylor@Sun.COM _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*entry))
19739517SBill.Taylor@Sun.COM
19749517SBill.Taylor@Sun.COM /*
19759517SBill.Taylor@Sun.COM * If the flags argument specifies that the entry should
19769517SBill.Taylor@Sun.COM * be removed if found, then call avl_remove() to remove
19779517SBill.Taylor@Sun.COM * the entry from the database.
19789517SBill.Taylor@Sun.COM */
19799517SBill.Taylor@Sun.COM if (flags & HERMON_UMAP_DB_REMOVE) {
19809517SBill.Taylor@Sun.COM
19819517SBill.Taylor@Sun.COM avl_remove(&hermon_userland_rsrc_db.hdl_umapdb_avl, entry);
19829517SBill.Taylor@Sun.COM
19839517SBill.Taylor@Sun.COM /*
19849517SBill.Taylor@Sun.COM * The database entry is returned with the expectation
19859517SBill.Taylor@Sun.COM * that the caller will use hermon_umap_db_free() to
19869517SBill.Taylor@Sun.COM * free the entry's memory. ASSERT that this is non-NULL.
19879517SBill.Taylor@Sun.COM * NULL pointer should never be passed for the
19889517SBill.Taylor@Sun.COM * HERMON_UMAP_DB_REMOVE case.
19899517SBill.Taylor@Sun.COM */
19909517SBill.Taylor@Sun.COM ASSERT(umapdb != NULL);
19919517SBill.Taylor@Sun.COM }
19929517SBill.Taylor@Sun.COM
19939517SBill.Taylor@Sun.COM /*
19949517SBill.Taylor@Sun.COM * If the caller would like visibility to the database entry
19959517SBill.Taylor@Sun.COM * (indicated through the use of a non-NULL "umapdb" argument),
19969517SBill.Taylor@Sun.COM * then fill it in.
19979517SBill.Taylor@Sun.COM */
19989517SBill.Taylor@Sun.COM if (umapdb != NULL) {
19999517SBill.Taylor@Sun.COM *umapdb = entry;
20009517SBill.Taylor@Sun.COM }
20019517SBill.Taylor@Sun.COM
20029517SBill.Taylor@Sun.COM /* Extract value field from database entry and return success */
20039517SBill.Taylor@Sun.COM *value = entry->hdbe_common.hdb_value;
20049517SBill.Taylor@Sun.COM
20059517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
20069517SBill.Taylor@Sun.COM }
20079517SBill.Taylor@Sun.COM
20089517SBill.Taylor@Sun.COM
20099517SBill.Taylor@Sun.COM /*
20109517SBill.Taylor@Sun.COM * hermon_umap_umemlock_cb()
20119517SBill.Taylor@Sun.COM * Context: Can be called from callback context.
20129517SBill.Taylor@Sun.COM */
20139517SBill.Taylor@Sun.COM void
hermon_umap_umemlock_cb(ddi_umem_cookie_t * umem_cookie)20149517SBill.Taylor@Sun.COM hermon_umap_umemlock_cb(ddi_umem_cookie_t *umem_cookie)
20159517SBill.Taylor@Sun.COM {
20169517SBill.Taylor@Sun.COM hermon_umap_db_entry_t *umapdb;
20179517SBill.Taylor@Sun.COM hermon_state_t *state;
20189517SBill.Taylor@Sun.COM hermon_rsrc_t *rsrcp;
20199517SBill.Taylor@Sun.COM hermon_mrhdl_t mr;
20209517SBill.Taylor@Sun.COM uint64_t value;
20219517SBill.Taylor@Sun.COM uint_t instance;
20229517SBill.Taylor@Sun.COM int status;
20239517SBill.Taylor@Sun.COM void (*mr_callback)(void *, void *);
20249517SBill.Taylor@Sun.COM void *mr_cbarg1, *mr_cbarg2;
20259517SBill.Taylor@Sun.COM
20269517SBill.Taylor@Sun.COM /*
20279517SBill.Taylor@Sun.COM * If this was userland memory, then we need to remove its entry
20289517SBill.Taylor@Sun.COM * from the "userland resources database". Note: We use the
20299517SBill.Taylor@Sun.COM * HERMON_UMAP_DB_IGNORE_INSTANCE flag here because we don't know
20309517SBill.Taylor@Sun.COM * which instance was used when the entry was added (but we want
20319517SBill.Taylor@Sun.COM * to know after the entry is found using the other search criteria).
20329517SBill.Taylor@Sun.COM */
20339517SBill.Taylor@Sun.COM status = hermon_umap_db_find(0, (uint64_t)(uintptr_t)umem_cookie,
20349517SBill.Taylor@Sun.COM MLNX_UMAP_MRMEM_RSRC, &value, (HERMON_UMAP_DB_REMOVE |
20359517SBill.Taylor@Sun.COM HERMON_UMAP_DB_IGNORE_INSTANCE), &umapdb);
20369517SBill.Taylor@Sun.COM _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*umapdb))
20379517SBill.Taylor@Sun.COM if (status == DDI_SUCCESS) {
20389517SBill.Taylor@Sun.COM instance = umapdb->hdbe_common.hdb_instance;
20399517SBill.Taylor@Sun.COM state = ddi_get_soft_state(hermon_statep, instance);
20409517SBill.Taylor@Sun.COM if (state == NULL) {
20419517SBill.Taylor@Sun.COM cmn_err(CE_WARN, "Unable to match Hermon instance\n");
20429517SBill.Taylor@Sun.COM return;
20439517SBill.Taylor@Sun.COM }
20449517SBill.Taylor@Sun.COM
20459517SBill.Taylor@Sun.COM /* Free the database entry */
20469517SBill.Taylor@Sun.COM hermon_umap_db_free(umapdb);
20479517SBill.Taylor@Sun.COM
20489517SBill.Taylor@Sun.COM /* Use "value" to convert to an MR handle */
20499517SBill.Taylor@Sun.COM rsrcp = (hermon_rsrc_t *)(uintptr_t)value;
20509517SBill.Taylor@Sun.COM mr = (hermon_mrhdl_t)rsrcp->hr_addr;
20519517SBill.Taylor@Sun.COM
20529517SBill.Taylor@Sun.COM /*
20539517SBill.Taylor@Sun.COM * If a callback has been provided, call it first. This
20549517SBill.Taylor@Sun.COM * callback is expected to do any cleanup necessary to
20559517SBill.Taylor@Sun.COM * guarantee that the subsequent MR deregister (below)
20569517SBill.Taylor@Sun.COM * will succeed. Specifically, this means freeing up memory
20579517SBill.Taylor@Sun.COM * windows which might have been associated with the MR.
20589517SBill.Taylor@Sun.COM */
20599517SBill.Taylor@Sun.COM mutex_enter(&mr->mr_lock);
20609517SBill.Taylor@Sun.COM mr_callback = mr->mr_umem_cbfunc;
20619517SBill.Taylor@Sun.COM mr_cbarg1 = mr->mr_umem_cbarg1;
20629517SBill.Taylor@Sun.COM mr_cbarg2 = mr->mr_umem_cbarg2;
20639517SBill.Taylor@Sun.COM mutex_exit(&mr->mr_lock);
20649517SBill.Taylor@Sun.COM if (mr_callback != NULL) {
20659517SBill.Taylor@Sun.COM mr_callback(mr_cbarg1, mr_cbarg2);
20669517SBill.Taylor@Sun.COM }
20679517SBill.Taylor@Sun.COM
20689517SBill.Taylor@Sun.COM /*
20699517SBill.Taylor@Sun.COM * Then call hermon_mr_deregister() to release the resources
20709517SBill.Taylor@Sun.COM * associated with the MR handle. Note: Because this routine
20719517SBill.Taylor@Sun.COM * will also check for whether the ddi_umem_cookie_t is in the
20729517SBill.Taylor@Sun.COM * database, it will take responsibility for disabling the
20739517SBill.Taylor@Sun.COM * memory region and calling ddi_umem_unlock().
20749517SBill.Taylor@Sun.COM */
20759517SBill.Taylor@Sun.COM status = hermon_mr_deregister(state, &mr, HERMON_MR_DEREG_ALL,
20769517SBill.Taylor@Sun.COM HERMON_SLEEP);
20779517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
20789517SBill.Taylor@Sun.COM HERMON_WARNING(state, "Unexpected failure in "
20799517SBill.Taylor@Sun.COM "deregister from callback\n");
20809517SBill.Taylor@Sun.COM }
20819517SBill.Taylor@Sun.COM }
20829517SBill.Taylor@Sun.COM }
20839517SBill.Taylor@Sun.COM
20849517SBill.Taylor@Sun.COM
20859517SBill.Taylor@Sun.COM /*
20869517SBill.Taylor@Sun.COM * hermon_umap_db_compare()
20879517SBill.Taylor@Sun.COM * Context: Can be called from user or kernel context.
20889517SBill.Taylor@Sun.COM */
20899517SBill.Taylor@Sun.COM static int
hermon_umap_db_compare(const void * q,const void * e)20909517SBill.Taylor@Sun.COM hermon_umap_db_compare(const void *q, const void *e)
20919517SBill.Taylor@Sun.COM {
20929517SBill.Taylor@Sun.COM hermon_umap_db_common_t *entry_common, *query_common;
20939517SBill.Taylor@Sun.COM uint_t query_flags;
20949517SBill.Taylor@Sun.COM
20959517SBill.Taylor@Sun.COM _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*((hermon_umap_db_query_t *)q)))
20969517SBill.Taylor@Sun.COM
20979517SBill.Taylor@Sun.COM entry_common = &((hermon_umap_db_entry_t *)e)->hdbe_common;
20989517SBill.Taylor@Sun.COM query_common = &((hermon_umap_db_query_t *)q)->hqdb_common;
20999517SBill.Taylor@Sun.COM query_flags = ((hermon_umap_db_query_t *)q)->hqdb_flags;
21009517SBill.Taylor@Sun.COM
21019517SBill.Taylor@Sun.COM /*
21029517SBill.Taylor@Sun.COM * The first comparison is done on the "key" value in "query"
21039517SBill.Taylor@Sun.COM * and "entry". If they are not equal, then the appropriate
21049517SBill.Taylor@Sun.COM * search direction is returned. Else, we continue by
21059517SBill.Taylor@Sun.COM * comparing "type".
21069517SBill.Taylor@Sun.COM */
21079517SBill.Taylor@Sun.COM if (query_common->hdb_key < entry_common->hdb_key) {
21089517SBill.Taylor@Sun.COM return (-1);
21099517SBill.Taylor@Sun.COM } else if (query_common->hdb_key > entry_common->hdb_key) {
21109517SBill.Taylor@Sun.COM return (+1);
21119517SBill.Taylor@Sun.COM }
21129517SBill.Taylor@Sun.COM
21139517SBill.Taylor@Sun.COM /*
21149517SBill.Taylor@Sun.COM * If the search reaches this point, then "query" and "entry"
21159517SBill.Taylor@Sun.COM * have equal key values. So we continue be comparing their
21169517SBill.Taylor@Sun.COM * "type" values. Again, if they are not equal, then the
21179517SBill.Taylor@Sun.COM * appropriate search direction is returned. Else, we continue
21189517SBill.Taylor@Sun.COM * by comparing "instance".
21199517SBill.Taylor@Sun.COM */
21209517SBill.Taylor@Sun.COM if (query_common->hdb_type < entry_common->hdb_type) {
21219517SBill.Taylor@Sun.COM return (-1);
21229517SBill.Taylor@Sun.COM } else if (query_common->hdb_type > entry_common->hdb_type) {
21239517SBill.Taylor@Sun.COM return (+1);
21249517SBill.Taylor@Sun.COM }
21259517SBill.Taylor@Sun.COM
21269517SBill.Taylor@Sun.COM /*
21279517SBill.Taylor@Sun.COM * If the search reaches this point, then "query" and "entry"
21289517SBill.Taylor@Sun.COM * have exactly the same key and type values. Now we consult
21299517SBill.Taylor@Sun.COM * the "flags" field in the query to determine whether the
21309517SBill.Taylor@Sun.COM * "instance" is relevant to the search. If the
21319517SBill.Taylor@Sun.COM * HERMON_UMAP_DB_IGNORE_INSTANCE flags is set, then return
21329517SBill.Taylor@Sun.COM * success (0) here. Otherwise, continue the search by comparing
21339517SBill.Taylor@Sun.COM * instance values and returning the appropriate search direction.
21349517SBill.Taylor@Sun.COM */
21359517SBill.Taylor@Sun.COM if (query_flags & HERMON_UMAP_DB_IGNORE_INSTANCE) {
21369517SBill.Taylor@Sun.COM return (0);
21379517SBill.Taylor@Sun.COM }
21389517SBill.Taylor@Sun.COM
21399517SBill.Taylor@Sun.COM /*
21409517SBill.Taylor@Sun.COM * If the search has reached this point, then "query" and "entry"
21419517SBill.Taylor@Sun.COM * can only be differentiated by their instance values. If these
21429517SBill.Taylor@Sun.COM * are not equal, then return the appropriate search direction.
21439517SBill.Taylor@Sun.COM * Else, we return success (0).
21449517SBill.Taylor@Sun.COM */
21459517SBill.Taylor@Sun.COM if (query_common->hdb_instance < entry_common->hdb_instance) {
21469517SBill.Taylor@Sun.COM return (-1);
21479517SBill.Taylor@Sun.COM } else if (query_common->hdb_instance > entry_common->hdb_instance) {
21489517SBill.Taylor@Sun.COM return (+1);
21499517SBill.Taylor@Sun.COM }
21509517SBill.Taylor@Sun.COM
21519517SBill.Taylor@Sun.COM /* Everything matches... so return success */
21529517SBill.Taylor@Sun.COM return (0);
21539517SBill.Taylor@Sun.COM }
21549517SBill.Taylor@Sun.COM
21559517SBill.Taylor@Sun.COM
21569517SBill.Taylor@Sun.COM /*
21579517SBill.Taylor@Sun.COM * hermon_umap_db_set_onclose_cb()
21589517SBill.Taylor@Sun.COM * Context: Can be called from user or kernel context.
21599517SBill.Taylor@Sun.COM */
21609517SBill.Taylor@Sun.COM int
hermon_umap_db_set_onclose_cb(dev_t dev,uint64_t flag,int (* callback)(void *),void * arg)21619517SBill.Taylor@Sun.COM hermon_umap_db_set_onclose_cb(dev_t dev, uint64_t flag,
21629517SBill.Taylor@Sun.COM int (*callback)(void *), void *arg)
21639517SBill.Taylor@Sun.COM {
21649517SBill.Taylor@Sun.COM hermon_umap_db_priv_t *priv;
21659517SBill.Taylor@Sun.COM hermon_umap_db_entry_t *umapdb;
21669517SBill.Taylor@Sun.COM minor_t instance;
21679517SBill.Taylor@Sun.COM uint64_t value;
21689517SBill.Taylor@Sun.COM int status;
21699517SBill.Taylor@Sun.COM
21709517SBill.Taylor@Sun.COM instance = HERMON_DEV_INSTANCE(dev);
21719517SBill.Taylor@Sun.COM if (instance == (minor_t)-1) {
21729517SBill.Taylor@Sun.COM return (DDI_FAILURE);
21739517SBill.Taylor@Sun.COM }
21749517SBill.Taylor@Sun.COM
21759517SBill.Taylor@Sun.COM if (flag != HERMON_ONCLOSE_FLASH_INPROGRESS) {
21769517SBill.Taylor@Sun.COM return (DDI_FAILURE);
21779517SBill.Taylor@Sun.COM }
21789517SBill.Taylor@Sun.COM
21799517SBill.Taylor@Sun.COM /*
21809517SBill.Taylor@Sun.COM * Grab the lock for the "userland resources database" and find
21819517SBill.Taylor@Sun.COM * the entry corresponding to this minor number. Once it's found,
21829517SBill.Taylor@Sun.COM * allocate (if necessary) and add an entry (in the "hdb_priv"
21839517SBill.Taylor@Sun.COM * field) to indicate that further processing may be needed during
21849517SBill.Taylor@Sun.COM * Hermon's close() handling.
21859517SBill.Taylor@Sun.COM */
21869517SBill.Taylor@Sun.COM mutex_enter(&hermon_userland_rsrc_db.hdl_umapdb_lock);
21879517SBill.Taylor@Sun.COM status = hermon_umap_db_find_nolock(instance, dev,
21889517SBill.Taylor@Sun.COM MLNX_UMAP_PID_RSRC, &value, 0, &umapdb);
21899517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
21909517SBill.Taylor@Sun.COM mutex_exit(&hermon_userland_rsrc_db.hdl_umapdb_lock);
21919517SBill.Taylor@Sun.COM return (DDI_FAILURE);
21929517SBill.Taylor@Sun.COM }
21939517SBill.Taylor@Sun.COM
21949517SBill.Taylor@Sun.COM priv = (hermon_umap_db_priv_t *)umapdb->hdbe_common.hdb_priv;
21959517SBill.Taylor@Sun.COM if (priv == NULL) {
21969517SBill.Taylor@Sun.COM priv = (hermon_umap_db_priv_t *)kmem_zalloc(
21979517SBill.Taylor@Sun.COM sizeof (hermon_umap_db_priv_t), KM_NOSLEEP);
21989517SBill.Taylor@Sun.COM if (priv == NULL) {
21999517SBill.Taylor@Sun.COM mutex_exit(&hermon_userland_rsrc_db.hdl_umapdb_lock);
22009517SBill.Taylor@Sun.COM return (DDI_FAILURE);
22019517SBill.Taylor@Sun.COM }
22029517SBill.Taylor@Sun.COM }
22039517SBill.Taylor@Sun.COM
22049517SBill.Taylor@Sun.COM /*
22059517SBill.Taylor@Sun.COM * Save away the callback and argument to be used during Hermon's
22069517SBill.Taylor@Sun.COM * close() processing.
22079517SBill.Taylor@Sun.COM */
22089517SBill.Taylor@Sun.COM priv->hdp_cb = callback;
22099517SBill.Taylor@Sun.COM priv->hdp_arg = arg;
22109517SBill.Taylor@Sun.COM
22119517SBill.Taylor@Sun.COM umapdb->hdbe_common.hdb_priv = (void *)priv;
22129517SBill.Taylor@Sun.COM mutex_exit(&hermon_userland_rsrc_db.hdl_umapdb_lock);
22139517SBill.Taylor@Sun.COM
22149517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
22159517SBill.Taylor@Sun.COM }
22169517SBill.Taylor@Sun.COM
22179517SBill.Taylor@Sun.COM
22189517SBill.Taylor@Sun.COM /*
22199517SBill.Taylor@Sun.COM * hermon_umap_db_clear_onclose_cb()
22209517SBill.Taylor@Sun.COM * Context: Can be called from user or kernel context.
22219517SBill.Taylor@Sun.COM */
22229517SBill.Taylor@Sun.COM int
hermon_umap_db_clear_onclose_cb(dev_t dev,uint64_t flag)22239517SBill.Taylor@Sun.COM hermon_umap_db_clear_onclose_cb(dev_t dev, uint64_t flag)
22249517SBill.Taylor@Sun.COM {
22259517SBill.Taylor@Sun.COM hermon_umap_db_priv_t *priv;
22269517SBill.Taylor@Sun.COM hermon_umap_db_entry_t *umapdb;
22279517SBill.Taylor@Sun.COM minor_t instance;
22289517SBill.Taylor@Sun.COM uint64_t value;
22299517SBill.Taylor@Sun.COM int status;
22309517SBill.Taylor@Sun.COM
22319517SBill.Taylor@Sun.COM instance = HERMON_DEV_INSTANCE(dev);
22329517SBill.Taylor@Sun.COM if (instance == (minor_t)-1) {
22339517SBill.Taylor@Sun.COM return (DDI_FAILURE);
22349517SBill.Taylor@Sun.COM }
22359517SBill.Taylor@Sun.COM
22369517SBill.Taylor@Sun.COM if (flag != HERMON_ONCLOSE_FLASH_INPROGRESS) {
22379517SBill.Taylor@Sun.COM return (DDI_FAILURE);
22389517SBill.Taylor@Sun.COM }
22399517SBill.Taylor@Sun.COM
22409517SBill.Taylor@Sun.COM /*
22419517SBill.Taylor@Sun.COM * Grab the lock for the "userland resources database" and find
22429517SBill.Taylor@Sun.COM * the entry corresponding to this minor number. Once it's found,
22439517SBill.Taylor@Sun.COM * remove the entry (in the "hdb_priv" field) that indicated the
22449517SBill.Taylor@Sun.COM * need for further processing during Hermon's close(). Free the
22459517SBill.Taylor@Sun.COM * entry, if appropriate.
22469517SBill.Taylor@Sun.COM */
22479517SBill.Taylor@Sun.COM mutex_enter(&hermon_userland_rsrc_db.hdl_umapdb_lock);
22489517SBill.Taylor@Sun.COM status = hermon_umap_db_find_nolock(instance, dev,
22499517SBill.Taylor@Sun.COM MLNX_UMAP_PID_RSRC, &value, 0, &umapdb);
22509517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
22519517SBill.Taylor@Sun.COM mutex_exit(&hermon_userland_rsrc_db.hdl_umapdb_lock);
22529517SBill.Taylor@Sun.COM return (DDI_FAILURE);
22539517SBill.Taylor@Sun.COM }
22549517SBill.Taylor@Sun.COM
22559517SBill.Taylor@Sun.COM priv = (hermon_umap_db_priv_t *)umapdb->hdbe_common.hdb_priv;
22569517SBill.Taylor@Sun.COM if (priv != NULL) {
22579517SBill.Taylor@Sun.COM kmem_free(priv, sizeof (hermon_umap_db_priv_t));
22589517SBill.Taylor@Sun.COM priv = NULL;
22599517SBill.Taylor@Sun.COM }
22609517SBill.Taylor@Sun.COM
22619517SBill.Taylor@Sun.COM umapdb->hdbe_common.hdb_priv = (void *)priv;
22629517SBill.Taylor@Sun.COM mutex_exit(&hermon_userland_rsrc_db.hdl_umapdb_lock);
22639517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
22649517SBill.Taylor@Sun.COM }
22659517SBill.Taylor@Sun.COM
22669517SBill.Taylor@Sun.COM
22679517SBill.Taylor@Sun.COM /*
22689517SBill.Taylor@Sun.COM * hermon_umap_db_clear_onclose_cb()
22699517SBill.Taylor@Sun.COM * Context: Can be called from user or kernel context.
22709517SBill.Taylor@Sun.COM */
22719517SBill.Taylor@Sun.COM int
hermon_umap_db_handle_onclose_cb(hermon_umap_db_priv_t * priv)22729517SBill.Taylor@Sun.COM hermon_umap_db_handle_onclose_cb(hermon_umap_db_priv_t *priv)
22739517SBill.Taylor@Sun.COM {
22749517SBill.Taylor@Sun.COM int (*callback)(void *);
22759517SBill.Taylor@Sun.COM
22769517SBill.Taylor@Sun.COM ASSERT(MUTEX_HELD(&hermon_userland_rsrc_db.hdl_umapdb_lock));
22779517SBill.Taylor@Sun.COM
22789517SBill.Taylor@Sun.COM /*
22799517SBill.Taylor@Sun.COM * Call the callback.
22809517SBill.Taylor@Sun.COM * Note: Currently there is only one callback (in "hdp_cb"), but
22819517SBill.Taylor@Sun.COM * in the future there may be more, depending on what other types
22829517SBill.Taylor@Sun.COM * of interaction there are between userland processes and the
22839517SBill.Taylor@Sun.COM * driver.
22849517SBill.Taylor@Sun.COM */
22859517SBill.Taylor@Sun.COM callback = priv->hdp_cb;
22869517SBill.Taylor@Sun.COM return (callback(priv->hdp_arg));
22879517SBill.Taylor@Sun.COM }
2288