sol_uverbs_comp.c revision c39526b769298791ff5b0b6c5e761f49aabaeb4e
/*
* 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
* 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
*/
/*
*/
/*
* NAME: sol_uverbs_comp.c
*
* OFED User Verbs Kernel completion queue/processing implementation
*
*/
#include <sys/semaphore.h>
extern char *sol_uverbs_dbg_str;
/*
* Function:
* uverbs_convert_wc
* Input:
* uctxt - Pointer to the callers user context.
* ibt_wc - Pointer to IBT work completion.
* Output:
* ofed_wc - Pointer to hold converted OFED work completion.
* Returns:
* None
* Description:
* Convert and IBT work completion to an OFED work completion.
*/
/* ARGSUSED */
static void
struct ib_uverbs_wc *ofed_wc)
{
case IBT_WC_SUCCESS:
break;
case IBT_WC_LOCAL_LEN_ERR:
break;
case IBT_WC_LOCAL_CHAN_OP_ERR:
break;
case IBT_WC_LOCAL_PROTECT_ERR:
break;
case IBT_WC_WR_FLUSHED_ERR:
break;
case IBT_WC_MEM_WIN_BIND_ERR:
break;
case IBT_WC_BAD_RESPONSE_ERR:
break;
case IBT_WC_LOCAL_ACCESS_ERR:
break;
break;
case IBT_WC_REMOTE_ACCESS_ERR:
break;
case IBT_WC_REMOTE_OP_ERR:
break;
case IBT_WC_TRANS_TIMEOUT_ERR:
break;
default:
break;
}
case IBT_WRC_SEND:
break;
case IBT_WRC_RDMAR:
break;
case IBT_WRC_RDMAW:
break;
case IBT_WRC_CSWAP:
break;
case IBT_WRC_FADD:
break;
case IBT_WRC_BIND:
break;
case IBT_WRC_RECV:
break;
case IBT_WRC_RECV_RDMAWI:
break;
case IBT_WRC_FAST_REG_PMR:
case IBT_WRC_LOCAL_INVALIDATE:
default:
break;
}
ofed_wc->vendor_err = 0;
}
}
}
/*
* Function:
* sol_uverbs_create_cq
* Input:
* uctxt - Pointer to the callers user context.
* buf - Pointer to kernel buffer containing create CQ command.
* in_len - Length in bytes of input command buffer.
* out_len - Length in bytes of output response buffer.
* Output:
* The command output buffer is updated with command results.
* Returns:
* DDI_SUCCESS on success, else error code.
* Description:
* User verbs entry point to create a device CQ.
*/
/* ARGSUSED */
int
{
struct ib_uverbs_create_cq cmd;
struct ib_uverbs_create_cq_resp resp;
int rc;
"num_cqe=%d, sched=%x, flags=%x",
/*
* To be consistent with OFED semantics, we fail a CQ that is being
* created with 0 CQ entries.
*/
goto err_out;
}
if (!ucq) {
"create_cq: mem alloc failure");
goto err_out;
}
/*
* If a event completion channel was specified look it up and
* assign the channel to the user CQ object. Note that this
* places a reference on the file itself.
*/
if (!compl_uctxt) {
"create_cq: Invalid comp channel %d",
goto chan_err;
}
"create_cq: Invalid comp channel %d, "
"verbs id %d mismatch",
goto chan_err;
}
ufile->ufile_cq_cnt++;
} else {
}
if (rc != IBT_SUCCESS) {
"create_cq: ibt_alloc_cq() (rc=%d)", rc);
goto alloc_err;
}
"create_cq: ib_alloc_cq() (rc=%d), real_size=%d",
/*
* Query underlying hardware for data used in mapping CQ back to user
* space, we will return this information in the user verbs command
* response.
*/
if (rc != IBT_SUCCESS) {
"create_cq: ibt_ci_data_out() rc=%d", rc);
goto err_cq_destroy;
}
"create_cq: User object add failed");
goto err_cq_destroy;
}
"create_cq: ibt_ci_data_out: 0x%16llx 0x%16llx "
#ifdef _LP64
#else
#endif
if (rc != 0) {
"create_cq: copyout failed %x", rc);
goto err_uo_delete;
}
if (!ucq->list_entry) {
"create_cq: Error adding ucq to cq_list");
goto err_uo_delete;
}
}
return (DDI_SUCCESS);
/*
* Need to set uo_live, so sol_ofs_uobj_remove() will
* remove the object from the object table.
*/
}
return (rc);
}
int
{
int rc;
if (rc != IBT_SUCCESS) {
"destroy_id: ibt_free_cq() rc=%d",
rc);
return (rc);
}
if (ucq->list_entry) {
}
return (0);
}
/*
* Function:
* sol_uverbs_destroy_cq
* Input:
* uctxt - Pointer to the callers user context.
* buf - Pointer to kernel buffer containing a destroy CQ command.
* in_len - Length in bytes of input command buffer.
* out_len - Length in bytes of output response buffer.
* Output:
* The command output buffer is updated with command results.
* Returns:
* DDI_SUCCESS on success, else error code.
* Description:
* User verbs entry point to destroy a device CQ.
*/
/* ARGSUSED */
int
{
struct ib_uverbs_destroy_cq cmd;
struct ib_uverbs_destroy_cq_resp resp;
int rc;
"destroy_cq: Invalid handle: %d",
goto err_out;
}
if (ucq->active_qp_cnt) {
return (EBUSY);
} else {
if (rc)
goto err_out;
}
#ifdef _LP64
#else
#endif
if (rc != 0) {
"destroy_cq: copuout failed %x", rc);
goto err_out;
}
return (DDI_SUCCESS);
return (rc);
}
/*
* Function:
* sol_uverbs_resize_cq
* Input:
* uctxt - Pointer to the callers user context.
* buf - Pointer to kernel buffer containing a resize CQ command.
* in_len - Length in bytes of input command buffer.
* out_len - Length in bytes of output response buffer.
* Output:
* The command output buffer is updated with command results.
* Returns:
* DDI_SUCCESS on success, else error code.
* Description:
* User verbs entry point to resize a device CQ.
*/
/* ARGSUSED */
int
{
struct ib_uverbs_resize_cq cmd;
struct ib_uverbs_resize_cq_resp resp;
int rc;
int resize_status;
"resize_cq: Invalid handle: %d",
goto err_out;
}
/*
* If CQ resize fails, note the error but keep going. In this case we
* expect the old CQ size to be returned, and when we extract the
* mapping data, we expect the offset and length are approrpriate for
* the old CQ.
*/
if (resize_status != IBT_SUCCESS) {
"resize_cq: ibt_resize_cq() (rc=%d), using "
"original CQ", rc);
}
if (rc != IBT_SUCCESS) {
"resize_cq: Error in ibt_ci_data_out() "
"(rc=%d)", rc);
goto err_out;
}
"resize_cq: ibt_ci_data_out: 0x%16llx 0x%16llx "
#ifdef _LP64
#else
#endif
if (rc != 0) {
"resize_cq: copyout %d", rc);
goto err_out;
}
return (resize_status);
return (rc);
}
/*
* Function:
* sol_uverbs_req_notify_cq
* Input:
* uctxt - Pointer to the callers user context.
* buf - Pointer to kernel buffer containing request notify
* command.
* in_len - Length in bytes of input command buffer.
* out_len - Length in bytes of output response buffer.
* Output:
* The command output buffer is updated with command results.
* Returns:
* DDI_SUCCESS on success, else error code.
* Description:
* User verbs entry point to request notification of CQ events.
*/
/* ARGSUSED */
int
{
struct ib_uverbs_req_notify_cq cmd;
int rc;
"req_notify_cq: List lookup failure");
goto err_out;
}
if (cmd.solicited_only != 0) {
}
if (rc != IBT_SUCCESS) {
"req_notify_cq: ibt_enable_cq_notify() "
"(rc=%d)", rc);
goto err_put;
}
return (DDI_SUCCESS);
return (rc);
}
/*
* Function:
* sol_uverbs_poll_cq
* Input:
* uctxt - Pointer to the callers user context.
* buf - Pointer to kernel buffer containing poll CQ command.
* in_len - Length in bytes of input command buffer.
* out_len - Length in bytes of output response buffer.
* Output:
* The command output buffer is updated with command results.
* Returns:
* DDI_SUCCESS on success, else error code.
* Description:
* User verbs entry point to poll a CQ for completion events. Note that
* this is a non OS Bypass version, the CQ normally would be polled
* directly from the user space driver.
*/
/* ARGSUSED */
int
{
struct ib_uverbs_poll_cq cmd;
struct ib_uverbs_poll_cq_resp resp;
struct ib_uverbs_wc ofed_wc;
int rc;
int i;
#ifdef DEBUG
#endif
"poll_cq: List lookup failure");
goto err_find;
}
if (completions == NULL) {
"poll_cq: Allocation Error");
goto err_alloc;
}
if (rc != IBT_SUCCESS) {
"poll_cq: ibt_poll_cq() (rc=%d)", rc);
goto err_poll;
}
#ifdef _LP64
#else
#endif
if (rc != 0) {
"poll_cq: copyout %x", rc);
goto err_poll;
}
#ifdef _LP64
#else
#endif
if (rc != 0) {
"poll_cq: copyout wc data %x", rc);
goto err_poll;
}
}
return (DDI_SUCCESS);
return (rc);
}
/*
* Function:
* sol_uverbs_comp_event_handler
* Input:
* ibt_cq - Handle to the IBT CQ.
* arg - Address of the associated Solaris User Verbs CQ
* object.
* Output:
* None
* Returns:
* None
* Description:
* Solaris User Verbs completion channel IBT CQ callback. Queue
* blocked waiting for the completion.
*/
/* ARGSUSED */
void
{
#ifdef DEBUG
"ucq = %p, ucq->cq = %p, ucq->uctxt = %p, ucq->comp_chan =%p",
#endif
NULL);
return;
}
return;
}
if (!entry) {
"memory allocation error");
return;
}
/*
* Add to list of entries associated with completion channel
* and the list associated with the specific CQ.
*/
#ifdef DEBUG
"Add COMP entry->ev_list=%p, &entry->ev_obj_list, entry=%p",
#endif
/* Do not notify users if sol_ucma has disabled CQ notify */
if (ufile->ufile_notify_enabled ==
return;
}
}