ibtl_cq.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/ib/ibtl/impl/ibtl.h>
/*
* ibtl_cq.c
* These routines implement (most of) the verbs related to
* Completion Queues.
*/
/*
* Globals
*/
static char ibtf_cq[] = "ibtl_cq";
/*
* This file contains code for the TI CQ calls
*/
/*
* ibt_alloc_cq_sched() - Reserve CQ scheduling class resources
*
* chan - IBT Channel Handle.
* load - Expected CQ load in class, 0 = unspecified
* sched_hdl_p - Returned scheduling handle.
*/
ibt_status_t
ibt_alloc_cq_sched(ibt_hca_hdl_t hca_hdl, ibt_cq_sched_attr_t *attr,
ibt_sched_hdl_t *sched_hdl_p)
{
ibc_cq_handler_attr_t handler_attrs;
ibt_cq_priority_t priority;
IBTF_DPRINTF_L3(ibtf_cq, "ibt_alloc_cq_sched(%p, %p, %p)",
hca_hdl, attr, sched_hdl_p);
/* Validate and Convert the IBT CQ priority */
priority = attr->cqs_priority;
if ((priority < IBT_CQ_DEFAULT) || (priority > IBT_CQ_PRI_16)) {
return (IBT_CQ_INVALID_PRIORITY);
}
/*
* Do we need to check for valid range for load ? What's the valid
* range?
*/
*sched_hdl_p = NULL; /* Function not implemented fully yet */
return (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_cq_sched(
IBTL_HCA2CIHCA(hca_hdl), attr->cqs_flags, &handler_attrs));
}
/*
* ibt_free_cq_sched() - Free CQ scheduling class resources
*
* chan - IBT Channel Handle.
* sched_hdl - Scheduling handle returned from ibt_alloc_cq_sched.
* load - CQ load being removed.
*/
ibt_status_t
ibt_free_cq_sched(ibt_hca_hdl_t hca_hdl, ibt_sched_hdl_t sched_hdl,
uint_t load)
{
ibt_cq_handler_id_t handler_id = 0;
IBTF_DPRINTF_L3(ibtf_cq, "ibt_free_cq_sched(%p, %d, %p)",
hca_hdl, sched_hdl, load);
/*
* Function not fully implemented should get handler ID from
* sched_hdl.
*/
return (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_free_cq_sched(
IBTL_HCA2CIHCA(hca_hdl), handler_id));
}
/*
*
* ibt_alloc_cq() - Allocate a completion queue
*/
ibt_status_t
ibt_alloc_cq(ibt_hca_hdl_t hca_hdl, ibt_cq_attr_t *cq_attr,
ibt_cq_hdl_t *ibt_cq_p, uint32_t *real_size)
{
ibt_status_t status;
ibt_cq_hdl_t ibt_cq;
IBTF_DPRINTF_L3(ibtf_cq, "ibt_alloc_cq(%p, %p)",
hca_hdl, cq_attr);
ibt_cq = kmem_zalloc(sizeof (struct ibtl_cq_s), KM_SLEEP);
*ibt_cq_p = ibt_cq;
_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibt_cq->cq_in_thread))
_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibt_cq->cq_ibc_cq_hdl))
_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibt_cq->cq_hca))
/*
* Set the following values before creating CI CQ, to avoid race
* conditions on async callback.
*/
ibt_cq->cq_hca = hca_hdl;
ibtl_qp_flow_control_enter();
status = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_cq(
IBTL_HCA2CIHCA(hca_hdl), ibt_cq, cq_attr, &ibt_cq->cq_ibc_cq_hdl,
real_size);
ibtl_qp_flow_control_exit();
if (status != IBT_SUCCESS) {
IBTF_DPRINTF_L2(ibtf_cq, "ibt_alloc_cq: "
"CI CQ handle allocation failed: status = %d", status);
kmem_free(ibt_cq, sizeof (struct ibtl_cq_s));
*ibt_cq_p = NULL;
return (status);
}
if (cq_attr->cq_flags & IBT_CQ_HANDLER_IN_THREAD) {
ibt_cq->cq_in_thread = 1;
/* We may want additional CQ threads now. */
ibtl_another_cq_handler_in_thread();
}
_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibt_cq->cq_in_thread))
_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibt_cq->cq_ibc_cq_hdl))
_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibt_cq->cq_hca))
mutex_init(&ibt_cq->cq_mutex, NULL, MUTEX_DEFAULT, NULL);
/* Update the cq resource count */
mutex_enter(&hca_hdl->ha_mutex);
hca_hdl->ha_cq_cnt++;
mutex_exit(&hca_hdl->ha_mutex);
return (IBT_SUCCESS);
}
/*
* ibt_free_cq() - Free a completion queue
*
*/
ibt_status_t
ibt_free_cq(ibt_cq_hdl_t ibt_cq)
{
ibt_status_t status;
ibtl_hca_t *ibt_hca = ibt_cq->cq_hca;
IBTF_DPRINTF_L3(ibtf_cq, "ibt_free_cq(%p)", ibt_cq);
ibtl_free_cq_check(ibt_cq);
status = ((IBTL_CQ2CIHCAOPS_P(ibt_cq))->ibc_free_cq)
(IBTL_CQ2CIHCA(ibt_cq), ibt_cq->cq_ibc_cq_hdl);
if (status != IBT_SUCCESS) {
IBTF_DPRINTF_L2(ibtf_cq, "ibt_free_cq: "
"CI CQ handle de-allocation failed: status = %d", status);
return (status);
}
/* mutex_destroy(&ibt_cq->cq_mutex); */
ibtl_free_cq_async_check(ibt_cq);
/* Update the cq resource count */
mutex_enter(&ibt_hca->ha_mutex);
ibt_hca->ha_cq_cnt--;
mutex_exit(&ibt_hca->ha_mutex);
return (status);
}
/*
* ibt_query_cq() - Returns the size of the cq
*/
ibt_status_t
ibt_query_cq(ibt_cq_hdl_t ibt_cq, uint32_t *entries_p)
{
IBTF_DPRINTF_L3(ibtf_cq, "ibt_query_cq(%p)", ibt_cq);
return (IBTL_CQ2CIHCAOPS_P(ibt_cq)->ibc_query_cq(IBTL_CQ2CIHCA(ibt_cq),
ibt_cq->cq_ibc_cq_hdl, entries_p));
}
/*
* ibt_resize_cq() - Change the size of a cq.
*/
ibt_status_t
ibt_resize_cq(ibt_cq_hdl_t ibt_cq, uint32_t new_sz, uint32_t *real_sz)
{
IBTF_DPRINTF_L3(ibtf_cq, "ibt_resize_cq(%p, %d)", ibt_cq, new_sz);
return (IBTL_CQ2CIHCAOPS_P(ibt_cq)->ibc_resize_cq(IBTL_CQ2CIHCA(ibt_cq),
ibt_cq->cq_ibc_cq_hdl, new_sz, real_sz));
}
/*
* ibt_poll_cq()
* Poll the specified CQ for a work request (WR) completion. If a CQ
* contains a completed WR, the completed WR at the head of the CQ is
* returned.
*
* ibt_cq The CQ handle.
*
* work_completions An array of work completions.
*
* num_wc Size of the Work completion array. The
* requested number of completions.
*
* num_polled The actual number of completions returned.
*
*/
ibt_status_t
ibt_poll_cq(ibt_cq_hdl_t ibt_cq, ibt_wc_t *work_completions, uint_t num_wc,
uint_t *num_polled)
{
IBTF_DPRINTF_L4(ibtf_cq, "ibt_poll_cq(%p)", ibt_cq);
return (IBTL_CQ2CIHCAOPS_P(ibt_cq)->ibc_poll_cq(IBTL_CQ2CIHCA(ibt_cq),
ibt_cq->cq_ibc_cq_hdl, work_completions, num_wc, num_polled));
}
_NOTE(SCHEME_PROTECTS_DATA("client managed", ibtl_cq_s::cq_clnt_private))
/*
* ibt_set_cq_private - Sets the private data on a given CQ
*
* ibt_cq The ibt_cq_hdl_t of the allocated CQ.
* clnt_private The client private data.
*/
void
ibt_set_cq_private(ibt_cq_hdl_t ibt_cq, void *clnt_private)
{
ibt_cq->cq_clnt_private = clnt_private;
}
/*
* ibt_get_cq_private - Retrieves the private data for a given CQ
*
* ibt_cq The ibt_cq_hdl_t of the allocated CQ.
*/
void *
ibt_get_cq_private(ibt_cq_hdl_t ibt_cq)
{
return (ibt_cq->cq_clnt_private);
}