root/usr/src/uts/common/sys/ib/clients/of/sol_uverbs/sol_uverbs.h
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
 */

#ifndef _SYS_IB_CLIENTS_OF_SOL_UVERBS_SOL_UVERBS_H
#define _SYS_IB_CLIENTS_OF_SOL_UVERBS_SOL_UVERBS_H

#ifdef __cplusplus
extern "C" {
#endif

/*
 *
 * NAME: sol_uverbs.h
 *
 * DESC: Solaris OFED User Verbs Kernel Agent header file.
 *
 */
#include <sys/ib/clients/of/ofed_kernel.h>
#include <sys/ib/clients/of/rdma/ib_user_verbs.h>
#include <sys/ib/clients/of/sol_uverbs/sol_uverbs_hca.h>
#include <sys/ib/clients/of/sol_ofs/sol_ofs_common.h>
#include <sys/ib/clients/of/sol_uverbs/sol_uverbs2ucma.h>

/*
 * Definitions
 */
#define SOL_UVERBS_DRIVER_MAX_HCA_MINOR (16)
#define SOL_UVERBS_DRIVER_EVENT_MINOR   (17)
#define SOL_UVERBS_DRIVER_MAX_MINOR     (18)


/*
 * Structures
 */

/*
 * Kernel User Verbs Events.
 *
 * User verbs kernel events (asynchronous and completion) representation.
 * IBT events are mapped back to OFA events.
 */
typedef struct uverbs_event {

        union {
                struct ib_uverbs_async_event_desc       async;
                struct ib_uverbs_comp_event_desc        comp;
        } ev_desc;

        llist_head_t    ev_list;
        llist_head_t    ev_obj_list;
        uint32_t        *ev_counter;
} uverbs_event_t;


/*
 * Module Context.
 *
 * There is a single module context which maintains the list
 * of HCA's retrieved from IBT. A user process indicates the
 * target HCA open via the uverbs unique minor device number
 * associated with the HCA.
 */
typedef struct {
        kmutex_t                lock;
        dev_info_t              *dip;

        /*
         * Underlying IBT HCA Info
         */

        ibt_clnt_modinfo_t      clnt_modinfo;
        ibt_clnt_hdl_t          clnt_hdl;
        uint32_t                hca_count;
        ib_guid_t               *hca_guid_list;
        sol_uverbs_hca_t        *hcas;

        /*
         * Support user asyncrhonous and completion event delivery via
         * user event filesystem.
         */
        dev_t                   dev;
} uverbs_module_context_t;

/*
 * User Event File.
 *
 * Used for delivery of asynchronous and synchronous events to the user.
 * An asynchronous event file is created during the allocation of
 * a user verbs consumer context, a completion event file is created
 * when the user verbs consumer creates a completion channel.
 */
typedef struct uverbs_ufile_uobj {
        sol_ofs_uobj_t                  uobj;
        kmutex_t                        lock;
        int                             ref;
        kcondvar_t                      poll_wait;
        pollhead_t                      poll_head;
        struct uverbs_uctxt_uobj        *uctxt;
        int                             is_async;
        llist_head_t                    event_list;
        sol_uverbs_cq_ctrl_t            ufile_notify_enabled;
        uint32_t                        ufile_cq_cnt;
} uverbs_ufile_uobj_t;

/*
 * Type of user context -
 */
#define         SOL_UVERBS_UCTXT_VERBS          0x001
#define         SOL_UVERBS_UCTXT_EVENT          0x100
#define         SOL_UVERBS_UCTXT_ASYNC          0x101
#define         SOL_UVERBS_UCTXT_COMPL          0x110

/*
 * User Context.
 *
 * A user context is created when a user process opens a specific minor
 * device.  The context maintains a list of resources created by this
 * user that allows the resources to be cleaned up on user close.
 */
typedef struct uverbs_uctxt_uobj {
        sol_ofs_uobj_t          uobj;
        kmutex_t                lock;
        uverbs_module_context_t *mod_ctxt;
        sol_uverbs_hca_t        *hca;           /* short cut to specific hca */

        /*
         * List of user resource objects created by this context.  The
         * objects themselves live in the associated object table, and
         * the code should use the table to access and use resources.
         * Any objects that remain in these list will be destroyed at
         * user close to free the associated resources.
         *
         * The user context "lock" should be held when invoking
         * routines to manipulate the lists.
         */
        genlist_t               pd_list;
        genlist_t               mr_list;
        genlist_t               cq_list;
        genlist_t               qp_list;
        genlist_t               srq_list;
        genlist_t               ah_list;

        /*
         * Event filesystem interfaces for IB asyncrhonous events
         * and completion events.
         */
        uverbs_ufile_uobj_t    *comp_evfile;
        uverbs_ufile_uobj_t    *async_evfile;

        /*
         * User context can be created for :
         *      1. All Verbs API
         *      2. For getting a file for async events.
         *      3. For getting a file for completion events.
         * For (1) - pointers to (2) & (3) will be updated. For (2) and (3)
         * pointer to (1) will be maintained.
         */
        uint16_t                uctxt_type;
        uint32_t                uctxt_verbs_id;
        uint32_t                uctxt_async_id;
        uint32_t                uctxt_comp_id;
        uint8_t                 uctxt_free_pending;
} uverbs_uctxt_uobj_t;

/*
 * User PD objects created at PD allocation
 */
typedef struct uverbs_upd_uobj {
        sol_ofs_uobj_t          uobj;
        ibt_pd_hdl_t            pd;
        genlist_entry_t         *list_entry;    /* per user ctx list entry */
        uint32_t                active_qp_cnt;
        uint8_t                 free_pending;
} uverbs_upd_uobj_t;

/*
 * User MR objects created at MR registration
 */
typedef struct uverbs_umr_uobj {
        sol_ofs_uobj_t  uobj;
        ibt_mr_hdl_t    mr;
        genlist_entry_t *list_entry;    /* per user ctx list entry */
} uverbs_umr_uobj_t;

/*
 * User CQ objects created at CQ allocation
 */
typedef struct uverbs_ucq_uobj {
        sol_ofs_uobj_t          uobj;
        ibt_cq_hdl_t            cq;
        genlist_entry_t         *list_entry;    /* per user ctx list entry */
        uverbs_uctxt_uobj_t     *uctxt;
        uverbs_ufile_uobj_t     *comp_chan;
        uint32_t                comp_events_reported;
        uint32_t                async_events_reported;
        llist_head_t            async_list;
        llist_head_t            comp_list;
        uint32_t                active_qp_cnt;
        uint8_t                 free_pending;
} uverbs_ucq_uobj_t;

/*
 * User Shared Receive CQ objects created at SRQ allocation
 */
typedef struct uverbs_usrq_uobj {
        sol_ofs_uobj_t          uobj;
        ibt_srq_hdl_t           srq;
        genlist_entry_t         *list_entry;    /* per user ctx list entry */
        uverbs_uctxt_uobj_t     *uctxt;
        uint32_t                async_events_reported;
        llist_head_t            async_list;
        uint32_t                active_qp_cnt;
        uint8_t                 free_pending;
} uverbs_usrq_uobj_t;

/*
 * User address handle objects created at AH allocation
 */
typedef struct uverbs_uah_uobj {
        sol_ofs_uobj_t  uobj;
        ibt_ah_hdl_t    ah;
        genlist_entry_t *list_entry;    /* per user ctx list entry */
} uverbs_uah_uobj_t;

/*
 * User QP objects created at QP allocation
 */
#define SOL_UVERBS_UQP_RCQ_VALID        0x01
#define SOL_UVERBS_UQP_SRQ_VALID        0x02

typedef struct uverbs_uqp_uobj {
        sol_ofs_uobj_t                  uobj;
        ibt_qp_hdl_t                    qp;
        genlist_entry_t                 *list_entry;    /* per uctx list */
        uint32_t                        max_inline_data;
        uverbs_uctxt_uobj_t             *uctxt;
        uint32_t                        qp_num;         /* 24 bits valid */
        uint32_t                        disable_qp_mod;
        enum ib_qp_type                 ofa_qp_type;
        llist_head_t                    mcast_list;
        llist_head_t                    async_list;
        uint32_t                        async_events_reported;
        uverbs_ucq_uobj_t               *uqp_rcq;
        uverbs_ucq_uobj_t               *uqp_scq;

        uint32_t                        uqp_pd_hdl;
        uint32_t                        uqp_scq_hdl;
        uint32_t                        uqp_rcq_hdl;
        uint32_t                        uqp_srq_hdl;
        uint8_t                         uqp_rcq_srq_valid;

        sol_uverbs_qp_free_state_t      uqp_free_state;
} uverbs_uqp_uobj_t;

extern sol_ofs_uobj_table_t uverbs_uctxt_uo_tbl;
extern sol_ofs_uobj_table_t uverbs_upd_uo_tbl;
extern sol_ofs_uobj_table_t uverbs_uah_uo_tbl;
extern sol_ofs_uobj_table_t uverbs_umr_uo_tbl;
extern sol_ofs_uobj_table_t uverbs_ucq_uo_tbl;
extern sol_ofs_uobj_table_t uverbs_usrq_uo_tbl;
extern sol_ofs_uobj_table_t uverbs_uqp_uo_tbl;
extern sol_ofs_uobj_table_t uverbs_ufile_uo_tbl;

/*
 * The following structure is used currently to pass data back to
 * libmthca on user allocation context.  This should be passed opaquely
 * to maintain a true hal, we'll look for a generic way to get this information
 * and deliver it opaquely post EA-1.
 */
struct mthca_alloc_ucontext_resp {
        uint32_t        qp_tab_size;
        uint32_t        uarc_size;
};

struct ib_udata {
        void    *inbuf;
        void    *outbuf;
        size_t  inlen;
        size_t  outlen;
};

int sol_uverbs_dummy_command(uverbs_uctxt_uobj_t *uctxt, char *buf,
    int in_len, int out_len);
int sol_uverbs_get_context(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
    int out_len);
int sol_uverbs_alloc_pd(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
    int out_len);
int sol_uverbs_dealloc_pd(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
    int out_len);
int sol_uverbs_create_ah(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
    int out_len);
int sol_uverbs_destroy_ah(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
    int out_len);
int sol_uverbs_query_device(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
    int out_len);
int sol_uverbs_query_port(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
    int out_len);
int sol_uverbs_query_gid(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
    int out_len);
int sol_uverbs_query_pkey(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
    int out_len);
int sol_uverbs_reg_mr(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
    int out_len);
int sol_uverbs_dereg_mr(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
    int out_len);
int sol_uverbs_create_comp_channel(uverbs_uctxt_uobj_t *uctxt, char *buf,
    int in_len, int out_len);

uint32_t
sol_uverbs_ibt_to_of_device_cap_flags(ibt_hca_flags_t flags,
    ibt_hca_flags2_t flags2);

uint64_t
sol_uverbs_ibt_to_of_page_sz(ibt_page_sizes_t page_szs);

int sol_uverbs_ibt_to_kernel_status(ibt_status_t  status);
uint32_t sol_uverbs_qpnum2uqpid(uint32_t qp_num);

int uverbs_upd_free(uverbs_upd_uobj_t *, uverbs_uctxt_uobj_t *);
int uverbs_uqp_free(uverbs_uqp_uobj_t *, uverbs_uctxt_uobj_t *);
int uverbs_usrq_free(uverbs_usrq_uobj_t *, uverbs_uctxt_uobj_t *);
int uverbs_ucq_free(uverbs_ucq_uobj_t *, uverbs_uctxt_uobj_t *);

/*
 * The following helpers simply provide easy access for acquiring and locking
 * User Objects.
 */
static inline uverbs_uctxt_uobj_t *
uverbs_uobj_get_uctxt_read(uint32_t id)
{
        return (uverbs_uctxt_uobj_t *)
            sol_ofs_uobj_get_read(&uverbs_uctxt_uo_tbl, id);
}
static inline uverbs_uctxt_uobj_t *
uverbs_uobj_get_uctxt_write(uint32_t id)
{
        return (uverbs_uctxt_uobj_t *)
            sol_ofs_uobj_get_write(&uverbs_uctxt_uo_tbl, id);
}
static inline uverbs_upd_uobj_t *
uverbs_uobj_get_upd_read(uint32_t id)
{
        return (uverbs_upd_uobj_t *)
            sol_ofs_uobj_get_read(&uverbs_upd_uo_tbl, id);
}
static inline uverbs_upd_uobj_t *
uverbs_uobj_get_upd_write(uint32_t id)
{
        return (uverbs_upd_uobj_t *)
            sol_ofs_uobj_get_write(&uverbs_upd_uo_tbl, id);
}
static inline uverbs_umr_uobj_t *
uverbs_uobj_get_umr_read(uint32_t id)
{
        return (uverbs_umr_uobj_t *)
            sol_ofs_uobj_get_read(&uverbs_umr_uo_tbl, id);
}
static inline uverbs_umr_uobj_t *
uverbs_uobj_get_umr_write(uint32_t id)
{
        return (uverbs_umr_uobj_t *)
            sol_ofs_uobj_get_write(&uverbs_umr_uo_tbl, id);
}
static inline uverbs_ucq_uobj_t *
uverbs_uobj_get_ucq_read(uint32_t id)
{
        return (uverbs_ucq_uobj_t *)
            sol_ofs_uobj_get_read(&uverbs_ucq_uo_tbl, id);
}
static inline uverbs_ucq_uobj_t *
uverbs_uobj_get_ucq_write(uint32_t id)
{
        return (uverbs_ucq_uobj_t *)
            sol_ofs_uobj_get_write(&uverbs_ucq_uo_tbl, (int)id);
}
static inline uverbs_usrq_uobj_t *
uverbs_uobj_get_usrq_read(uint32_t id)
{
        return (uverbs_usrq_uobj_t *)
            sol_ofs_uobj_get_read(&uverbs_usrq_uo_tbl, id);
}
static inline uverbs_usrq_uobj_t *
uverbs_uobj_get_usrq_write(uint32_t id)
{
        return (uverbs_usrq_uobj_t *)
            sol_ofs_uobj_get_write(&uverbs_usrq_uo_tbl, id);
}
static inline uverbs_uah_uobj_t *
uverbs_uobj_get_uah_read(uint32_t id)
{
        return (uverbs_uah_uobj_t *)
            sol_ofs_uobj_get_read(&uverbs_uah_uo_tbl, id);
}
static inline uverbs_uah_uobj_t *
uverbs_uobj_get_uah_write(uint32_t id)
{
        return (uverbs_uah_uobj_t *)
            sol_ofs_uobj_get_write(&uverbs_uah_uo_tbl, id);
}
static inline uverbs_uqp_uobj_t *
uverbs_uobj_get_uqp_read(uint32_t id)
{
        return (uverbs_uqp_uobj_t *)
            sol_ofs_uobj_get_read(&uverbs_uqp_uo_tbl, id);
}
static inline uverbs_uqp_uobj_t *
uverbs_uobj_get_uqp_write(uint32_t id)
{
        return (uverbs_uqp_uobj_t *)
            sol_ofs_uobj_get_write(&uverbs_uqp_uo_tbl, id);
}

#ifdef __cplusplus
}
#endif
#endif /* _SYS_IB_CLIENTS_OF_SOL_UVERBS_SOL_UVERBS_H */