c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * CDDL HEADER START
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * The contents of this file are subject to the terms of the
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Common Development and Distribution License (the "License").
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * You may not use this file except in compliance with the License.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * or http://www.opensolaris.org/os/licensing.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * See the License for the specific language governing permissions
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * and limitations under the License.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * When distributing Covered Code, include this CDDL HEADER in each
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * If applicable, add the following below this CDDL HEADER, with the
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * fields enclosed by brackets "[]" replaced with your own identifying
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * information: Portions Copyright [yyyy] [name of copyright owner]
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * CDDL HEADER END
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* Solaris Open Fabric kernel verbs */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/types.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/ddi.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/sunddi.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/modctl.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/ib/clients/of/rdma/ib_verbs.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/ib/clients/of/rdma/ib_addr.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/ib/clients/of/rdma/rdma_cm.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/ib/clients/of/sol_ofs/sol_kverb_impl.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic void *statep;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otachar *sol_kverbs_dbg_str = "sol_kverbs";
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic llist_head_t client_list = LLIST_HEAD_INIT(client_list);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otakmutex_t clist_lock; /* mutex for client_list */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic void ofs_async_handler(void *, ibt_hca_hdl_t, ibt_async_code_t,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_async_event_t *);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * set ibt_client_t members. clnt->ib_client must be set before
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * this func is called.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic int
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaalloc_ibt_client(ofs_client_t *clnt)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int namelen;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(clnt->ib_client != NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "alloc_ibt_client: client: 0x%p", clnt);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * double-check the name string. if it's longer than MAXNAMELEN
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * including the string terminator, assuming the name is invalid,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * return EINVAL.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota namelen = strlen(clnt->ib_client->name);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (namelen >= MAXNAMELEN) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "alloc_ibt_client: client: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "namelen(%d) is larger than MAXNAMELEN", clnt, namelen);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota clnt->ibt_client.mi_clnt_name = kmem_zalloc(namelen + 1, KM_NOSLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (clnt->ibt_client.mi_clnt_name == NULL) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "alloc_ibt_client: client: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "no sufficient memory", clnt);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-ENOMEM);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota bcopy(clnt->ib_client->name, clnt->ibt_client.mi_clnt_name, namelen);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota clnt->ibt_client.mi_ibt_version = IBTI_V_CURR;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (clnt->ib_client->dip) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota clnt->ibt_client.mi_clnt_class = IBT_GENERIC;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota } else {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota clnt->ibt_client.mi_clnt_class = IBT_GENERIC_MISC;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota clnt->ibt_client.mi_async_handler = ofs_async_handler;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic void
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otafree_ibt_client(ofs_client_t *clnt)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int namelen = strlen(clnt->ib_client->name);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(namelen < MAXNAMELEN);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "free_ibt_client: client: 0x%p", clnt);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(clnt->ibt_client.mi_clnt_name, namelen + 1);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota clnt->ibt_client.mi_clnt_name = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * get_device() returns a pointer to struct ib_devcie with
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * the same guid as one passed to the function.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic ib_device_t *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaget_device(ofs_client_t *ofs_client, ib_guid_t guid)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ib_device_t *device;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota llist_head_t *entry;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(RW_LOCK_HELD(&ofs_client->lock));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "get_device: client: 0x%p, guid:0x%p",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client, (void *)(uintptr_t)htonll(guid));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_for_each(entry, &ofs_client->device_list) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device = entry->ptr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (device->node_guid == htonll(guid)) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(device->reg_state == IB_DEV_CLOSE);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(device->node_type == RDMA_NODE_IB_CA);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(device->clnt_hdl == (ofs_client_p_t)ofs_client);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (device);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "get_device: client: 0x%p, guid:0x%p => no match guid",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client, (void *)(uintptr_t)htonll(guid));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ofs_async_handler() is a delegated function to handle asynchrnonous events,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * which dispatches each event to corresponding qp/cq handlers registered
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * with ib_create_qp() and/or ib_create_cq().
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic void
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaofs_async_handler(void *clntp, ibt_hca_hdl_t hdl, ibt_async_code_t code,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_async_event_t *event)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client_t *ofs_client = (ofs_client_t *)clntp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct ib_event ib_event;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct ib_qp *qpp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct ib_cq *cqp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(ofs_client != NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cqp = event->ev_cq_hdl ? ibt_get_cq_private(event->ev_cq_hdl) : NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qpp = event->ev_chan_hdl ?
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_get_qp_private(event->ev_chan_hdl) : NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ofs_async_handler: client: 0x%p, hca_hdl: 0x%p, code:0x%x, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "event->qp: 0x%p, event->cq: 0x%p, event->srq: 0x%p "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "event->guid: 0x%p, event->port: 0x%x",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota clntp, hdl, code, qpp, cqp, event->ev_srq_hdl,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void *)(uintptr_t)event->ev_hca_guid, event->ev_port);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota bzero(&ib_event, sizeof (struct ib_event));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (code) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_EVENT_PATH_MIGRATED:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota FIRE_QP_EVENT(ofs_client, hdl, ib_event, qpp,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_EVENT_PATH_MIG);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_EVENT_SQD:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota FIRE_QP_EVENT(ofs_client, hdl, ib_event, qpp,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_EVENT_SQ_DRAINED);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_EVENT_COM_EST:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota FIRE_QP_EVENT(ofs_client, hdl, ib_event, qpp,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_EVENT_COMM_EST);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_ERROR_CATASTROPHIC_CHAN:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota FIRE_QP_EVENT(ofs_client, hdl, ib_event, qpp,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_EVENT_QP_FATAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_ERROR_INVALID_REQUEST_CHAN:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota FIRE_QP_EVENT(ofs_client, hdl, ib_event, qpp,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_EVENT_QP_REQ_ERR);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_ERROR_ACCESS_VIOLATION_CHAN:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota FIRE_QP_EVENT(ofs_client, hdl, ib_event, qpp,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_EVENT_QP_ACCESS_ERR);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_ERROR_PATH_MIGRATE_REQ:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota FIRE_QP_EVENT(ofs_client, hdl, ib_event, qpp,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_EVENT_PATH_MIG);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_EVENT_EMPTY_CHAN:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota FIRE_QP_EVENT(ofs_client, hdl, ib_event, qpp,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_EVENT_QP_LAST_WQE_REACHED);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_ERROR_CQ:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota FIRE_CQ_EVENT(ofs_client, hdl, ib_event, cqp,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_EVENT_CQ_ERR);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_HCA_ATTACH_EVENT:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ib_device_t *device;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int rtn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* re-use the device once it was created */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_enter(&ofs_client->lock, RW_WRITER);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device = get_device(ofs_client, event->ev_hca_guid);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (device == NULL) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device = kmem_alloc(sizeof (ib_device_t), KM_SLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device->node_type = RDMA_NODE_IB_CA;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device->reg_state = IB_DEV_CLOSE;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device->clnt_hdl = (ofs_client_p_t)ofs_client;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device->node_guid = htonll(event->ev_hca_guid);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device->data = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* add this HCA */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client->hca_num++;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota llist_head_init(&device->list, device);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota llist_add_tail(&device->list, &ofs_client->device_list);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device->hca_hdl = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device->local_dma_lkey = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device->phys_port_cnt = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* open this HCA */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_open_hca(ofs_client->ibt_hdl, event->ev_hca_guid,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota &device->hca_hdl);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rtn == IBT_SUCCESS) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_hca_attr_t hattr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client->hca_open_num++;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device->reg_state = IB_DEV_OPEN;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_set_hca_private(device->hca_hdl, device);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_query_hca(device->hca_hdl, &hattr);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rtn != IBT_SUCCESS) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device->reg_state = IB_DEV_CLOSE;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_close_hca(device->hca_hdl);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(rtn == IBT_SUCCESS);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client->hca_open_num--;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) sprintf(device->name, "%x:%x:%x",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota hattr.hca_vendor_id, hattr.hca_device_id,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota hattr.hca_version_id);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device->local_dma_lkey = hattr.hca_reserved_lkey;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device->phys_port_cnt = hattr.hca_nports;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_set_hca_private(device->hca_hdl, device);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* invoke client's callback */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ofs_client->ib_client->add) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client->ib_client->add(device);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_HCA_DETACH_EVENT:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct ib_device *device;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_enter(&ofs_client->lock, RW_WRITER);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device = ibt_get_hca_private(hdl);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (device->reg_state == IB_DEV_OPEN) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_status_t rtn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* invoke client's callback */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ofs_client->ib_client->remove) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client->ib_client->remove(device);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* change the state only */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device->reg_state = IB_DEV_CLOSE;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* close this HCA */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_close_hca(device->hca_hdl);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(rtn == IBT_SUCCESS);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client->hca_open_num--;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_EVENT_LIMIT_REACHED_SRQ:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_ERROR_CATASTROPHIC_SRQ:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "sol_ofs does not support this event(0x%x).\n"
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "\t clntp=0x%p, hca_hdl=0x%p, code=%d, eventp=0x%p\n",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota code, clntp, hdl, code, event);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ib_register_client - Register an IB client
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @client:Client to register
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Upper level users of the IB drivers can use ib_register_client() to
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * register callbacks for IB device addition and removal. When an IB
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * device is added, each registered client's add method will be called
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * (in the order the clients were registered), and when a device is
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * removed, each client's remove method will be called (in the reverse
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * order that clients were registered). In addition, when
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ib_register_client() is called, the client will receive an add
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * callback for all devices already registered.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Note that struct ib_client should have a dip pointer to the client,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * which is different from the Linux implementation.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaib_register_client(struct ib_client *client)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota uint_t i, nhcas; /* number of HCAs */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ib_guid_t *guidp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client_t *ofs_client;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota llist_head_t *entry, *tmp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ib_device_t *device;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int rtn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_register_client: client: 0x%p", client);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* get the number of HCAs on this system */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((nhcas = ibt_get_hca_list(&guidp)) == 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_register_client: client: 0x%p => no HCA", client);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-ENXIO);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* allocate a new sol_ofs_client structure */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client = kmem_zalloc(sizeof (ofs_client_t), KM_NOSLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ofs_client == NULL) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) ibt_free_hca_list(guidp, nhcas);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_register_client: client: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "no sufficient memory for ofs_client", client);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-ENOMEM);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* set members */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client->ib_client = client;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((rtn = alloc_ibt_client(ofs_client)) != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(ofs_client, sizeof (ofs_client_t));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) ibt_free_hca_list(guidp, nhcas);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_register_client: client: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "alloc_ibt_client failed w/ 0x%x", client, rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client->state = IB_OFS_CLNT_INITIALIZED;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota llist_head_init(&ofs_client->device_list, NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota llist_head_init(&ofs_client->client_list, ofs_client);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_init(&ofs_client->lock, NULL, RW_DEFAULT, NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* initialize IB client */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_enter(&ofs_client->lock, RW_WRITER);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (client->state != IB_CLNT_UNINITIALIZED) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(ofs_client, sizeof (ofs_client_t));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) ibt_free_hca_list(guidp, nhcas);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_register_client: client: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "invalid client state(%d)", client, client->state);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EPERM);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* attach this client to IBTF */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_attach(&ofs_client->ibt_client, client->dip, ofs_client,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota &ofs_client->ibt_hdl);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rtn != IBT_SUCCESS) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota free_ibt_client(ofs_client);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(ofs_client, sizeof (ofs_client_t));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) ibt_free_hca_list(guidp, nhcas);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_register_client: client: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ibt_attach failed w/ 0x%x", client, rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota client->clnt_hdl = (ofs_client_p_t)ofs_client;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota client->state = IB_CLNT_INITIALIZED;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* link this client */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&clist_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota llist_add_tail(&ofs_client->client_list, &client_list);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&clist_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* Open HCAs */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client->hca_num = nhcas;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota for (i = 0; i < ofs_client->hca_num; i++) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* allocate the ib_device structure */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device = kmem_zalloc(sizeof (ib_device_t), KM_NOSLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (device == NULL) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = -ENOMEM;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_register_client: client: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "no sufficient memory for ib_device", client);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota goto err;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device->node_guid = htonll(guidp[i]);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device->node_type = RDMA_NODE_IB_CA;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device->reg_state = IB_DEV_CLOSE;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device->clnt_hdl = (ofs_client_p_t)ofs_client;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota llist_head_init(&device->list, device);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota llist_add_tail(&device->list, &ofs_client->device_list);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_open_hca(ofs_client->ibt_hdl, guidp[i],
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota &device->hca_hdl);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rtn == IBT_SUCCESS) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_hca_attr_t hattr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client->hca_open_num++;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device->reg_state = IB_DEV_OPEN;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_query_hca(device->hca_hdl, &hattr);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rtn != IBT_SUCCESS) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = -EIO;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_register_client: client: 0x%p,"
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "hca_hdl: 0x%p ==> "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ibt_query_hca() failed w/ %d",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota client, device->hca_hdl, rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota goto err;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) sprintf(device->name, "%x:%x:%x",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota hattr.hca_vendor_id, hattr.hca_device_id,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota hattr.hca_version_id);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device->local_dma_lkey = hattr.hca_reserved_lkey;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device->phys_port_cnt = hattr.hca_nports;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_set_hca_private(device->hca_hdl, device);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* invoke client's callback */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (client->add) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota client->add(device);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ofs_client->hca_open_num == 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = -ENXIO;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_register_client: client: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "no available HCA", client);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota goto err;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) ibt_free_hca_list(guidp, nhcas);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaerr:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* first close all open HCAs */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_for_each(entry, &ofs_client->device_list) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device = entry->ptr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * If it's open already, close it after the remove
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * callback.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (device->reg_state == IB_DEV_OPEN) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_status_t rtn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* invoke client's callback */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (client->remove) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota client->remove(device);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device->reg_state = IB_DEV_CLOSE;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_close_hca(device->hca_hdl);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(rtn == IBT_SUCCESS);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client->hca_open_num--;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(ofs_client->hca_open_num == 0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* then free the devices */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_for_each_safe(entry, tmp, &ofs_client->device_list) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device = entry->ptr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* de-link and free the device */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota llist_del(entry);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(device, sizeof (ib_device_t));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client->hca_num--;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(ofs_client->hca_num == 0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* delink this client */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&clist_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota llist_del(&ofs_client->client_list);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&clist_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* detach the client */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota client->clnt_hdl = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota client->state = IB_CLNT_UNINITIALIZED;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) ibt_detach(ofs_client->ibt_hdl);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* free sol_ofs_client */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota free_ibt_client(ofs_client);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(ofs_client, sizeof (ofs_client_t));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) ibt_free_hca_list(guidp, nhcas);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ib_unregister_client - Unregister an IB client
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @client:Client to unregister
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Upper level users use ib_unregister_client() to remove their client
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * registration. When ib_unregister_client() is called, the client
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * will receive a remove callback for each IB device still registered.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaib_unregister_client(struct ib_client *client)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client_t *ofs_client;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ib_device_t *device;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota llist_head_t *entry, *tmp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(client->state == IB_CLNT_INITIALIZED &&
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota client->clnt_hdl != NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_unregister_client: client: 0x%p", client);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client = (ofs_client_t *)client->clnt_hdl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_enter(&ofs_client->lock, RW_WRITER);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* first close all open HCAs */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_for_each(entry, &ofs_client->device_list) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device = entry->ptr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * If it's open already, close it after the remove
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * callback.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (device->reg_state == IB_DEV_OPEN) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_status_t rtn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* invoke client's callback */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (client->remove) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota client->remove(device);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device->reg_state = IB_DEV_CLOSE;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_close_hca(device->hca_hdl);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rtn != IBT_SUCCESS)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_unregister_client(%p) - "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ibt_close_hca failed %d",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota client, rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client->hca_open_num--;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(ofs_client->hca_open_num == 0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* then free the devices */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_for_each_safe(entry, tmp, &ofs_client->device_list) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device = entry->ptr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* de-link and free the device */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota llist_del(entry);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(device, sizeof (ib_device_t));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client->hca_num--;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(ofs_client->hca_num == 0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* delink this client */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&clist_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota llist_del(&ofs_client->client_list);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&clist_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* detach the client */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota client->clnt_hdl = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota client->state = IB_CLNT_UNINITIALIZED;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) ibt_detach(ofs_client->ibt_hdl);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* free sol_ofs_client */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota free_ibt_client(ofs_client);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(ofs_client, sizeof (ofs_client_t));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ofs_lock_enter() and ofs_lock_exit() are used to avoid the recursive
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * rwlock while the client callbacks are invoked.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Note that the writer lock is used only in the client callback case,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * so that the kverb functions wanting to acquire the reader lock can
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * safely ignore the reader lock if the writer lock is already held.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * The writer lock shouldn't be used in no other plances.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic inline void
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaofs_lock_enter(krwlock_t *lock)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (!RW_WRITE_HELD(lock)) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_enter(lock, RW_READER);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic inline void
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaofs_lock_exit(krwlock_t *lock)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (!RW_WRITE_HELD(lock)) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_exit(lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ib_get_client_data - Get IB client context
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @device:Device to get context for
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @client:Client to get context for
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ib_get_client_data() returns client context set with
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ib_set_client_data() and returns NULL if it's not found.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid *ib_get_client_data(struct ib_device *device,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct ib_client *client)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client_t *ofs_client;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct ib_device *ib_device;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota boolean_t found = B_FALSE;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota llist_head_t *entry;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota void *data;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(device != 0 && client != 0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client = (ofs_client_t *)client->clnt_hdl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ofs_client == 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_get_client_data: device: 0x%p, client: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "no ofs_client", device, client);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_enter(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_for_each(entry, &ofs_client->device_list) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ib_device = entry->ptr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ib_device->node_guid == device->node_guid) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota found = B_TRUE;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (!found) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_get_client_data: device: 0x%p, client: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "no ib_device found", device, client);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota data = ib_device->data;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_get_client_data: device: 0x%p, client: 0x%p",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device, client);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (data);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ib_set_client_data - Set IB client context
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @device:Device to set context for
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @client:Client to set context for
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @data:Context to set
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ib_set_client_data() sets client context that can be retrieved with
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ib_get_client_data(). If the specified device is not found, the function
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * returns w/o any operations.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid ib_set_client_data(struct ib_device *device, struct ib_client *client,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota void *data)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client_t *ofs_client;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct ib_device *ib_device;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota boolean_t found = B_FALSE;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota llist_head_t *entry;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(device != 0 && client != 0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client = (ofs_client_t *)client->clnt_hdl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ofs_client == 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cmn_err(CE_WARN, "No client context found for %s/%s\n",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device->name, client->name);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_enter(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_for_each(entry, &ofs_client->device_list) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ib_device = entry->ptr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ib_device->node_guid == device->node_guid) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota found = B_TRUE;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (!found) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cmn_err(CE_WARN, "No client context found for %s/%s\n",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device->name, client->name);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ib_device->data = data;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_set_client_data: device: 0x%p, client: 0x%p, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "data: 0x%p", device, client, data);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ib_query_device - Query IB device attributes
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @device:Device to query
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @device_attr:Device attributes
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ib_query_device() returns the attributes of a device through the
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @device_attr pointer.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaib_query_device(struct ib_device *device, struct ib_device_attr *attr)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client_t *ofs_client = (ofs_client_t *)device->clnt_hdl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_hca_attr_t hattr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int rtn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_enter(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (device->reg_state != IB_DEV_OPEN) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_query_device: device: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "invalid device state (%d)", device, device->reg_state);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-ENXIO);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((rtn = ibt_query_hca(device->hca_hdl, &hattr)) != IBT_SUCCESS) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_query_device: device: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ibt_query_hca failed w/ 0x%x", device, rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EIO);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_query_device: device: 0x%p, attr: 0x%p, rtn: 0x%p",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device, attr, rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* OF order is major.micro.minor, so keep it here */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->fw_ver = (uint64_t)hattr.hca_fw_major_version << 32 |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota hattr.hca_fw_micro_version << 16 & 0xFFFF0000 |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota hattr.hca_fw_minor_version & 0xFFFF;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->device_cap_flags = IB_DEVICE_CHANGE_PHY_PORT |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_DEVICE_PORT_ACTIVE_EVENT |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_DEVICE_SYS_IMAGE_GUID |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_DEVICE_RC_RNR_NAK_GEN;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (hattr.hca_flags & IBT_HCA_PKEY_CNTR) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (hattr.hca_flags & IBT_HCA_QKEY_CNTR) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->device_cap_flags |= IB_DEVICE_BAD_QKEY_CNTR;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (hattr.hca_flags & IBT_HCA_AUTO_PATH_MIG) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (hattr.hca_flags & IBT_HCA_AH_PORT_CHECK) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->device_cap_flags |= IB_DEVICE_UD_AV_PORT_ENFORCE;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->vendor_id = hattr.hca_vendor_id;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->vendor_part_id = hattr.hca_device_id;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->hw_ver = hattr.hca_version_id;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->sys_image_guid = htonll(hattr.hca_si_guid);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_mr_size = ~0ull;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->page_size_cap = IBTF2OF_PGSZ(hattr.hca_page_sz);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_qp = hattr.hca_max_qp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_qp_wr = hattr.hca_max_qp_sz;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_sge = hattr.hca_max_sgl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_sge_rd = hattr.hca_max_rd_sgl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_cq = hattr.hca_max_cq;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_cqe = hattr.hca_max_cq_sz;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_mr = hattr.hca_max_memr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_pd = hattr.hca_max_pd;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_qp_rd_atom = hattr.hca_max_rdma_in_qp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_qp_init_rd_atom = hattr.hca_max_rdma_in_qp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_ee_rd_atom = hattr.hca_max_rdma_in_ee;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_ee_init_rd_atom = hattr.hca_max_rdma_in_ee;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_res_rd_atom = hattr.hca_max_rsc;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_srq = hattr.hca_max_srqs;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_srq_wr = hattr.hca_max_srqs_sz -1;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_srq_sge = hattr.hca_max_srq_sgl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->local_ca_ack_delay = hattr.hca_local_ack_delay;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->atomic_cap = hattr.hca_flags & IBT_HCA_ATOMICS_GLOBAL ?
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_ATOMIC_GLOB : (hattr.hca_flags & IBT_HCA_ATOMICS_HCA ?
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_ATOMIC_HCA : IB_ATOMIC_NONE);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_ee = hattr.hca_max_eec;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_rdd = hattr.hca_max_rdd;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_mw = hattr.hca_max_mem_win;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_pkeys = hattr.hca_max_port_pkey_tbl_sz;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_raw_ipv6_qp = hattr.hca_max_ipv6_qp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_raw_ethy_qp = hattr.hca_max_ether_qp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_mcast_grp = hattr.hca_max_mcg;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_mcast_qp_attach = hattr.hca_max_qp_per_mcg;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_total_mcast_qp_attach = hattr.hca_max_mcg_qps;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_ah = hattr.hca_max_ah;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_fmr = hattr.hca_max_fmrs;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_map_per_fmr = hattr.hca_opaque9; /* hca_max_map_per_fmr */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* Protection domains */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastruct ib_pd *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaib_alloc_pd(struct ib_device *device)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client_t *ofs_client = (ofs_client_t *)device->clnt_hdl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct ib_pd *pd;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int rtn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((pd = kmem_alloc(sizeof (struct ib_pd), KM_NOSLEEP)) == NULL) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_alloc_pd: device: 0x%p => no sufficient memory",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return ((struct ib_pd *)-ENOMEM);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_enter(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (device->reg_state != IB_DEV_OPEN) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_alloc_pd: device: 0x%p => invalid device state (%d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device, device->reg_state);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return ((struct ib_pd *)-ENXIO);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_alloc_pd: device: 0x%p", device);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_alloc_pd(device->hca_hdl, IBT_PD_NO_FLAGS, &pd->ibt_pd);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rtn == IBT_SUCCESS) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota pd->device = device;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_alloc_pd: device: 0x%p, pd: 0x%p, ibt_pd: 0x%p, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "rtn: 0x%x", device, pd, pd->ibt_pd, rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (pd);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(pd, sizeof (struct ib_pd));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_alloc_pd: device: 0x%p, pd: 0x%p, ibt_pd: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ibt_alloc_pd failed w/ 0x%x", device, pd, pd->ibt_pd, rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (rtn) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_INSUFF_RESOURCE:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return ((struct ib_pd *)-ENOMEM);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_HCA_HDL_INVALID:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return ((struct ib_pd *)-EFAULT);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return ((struct ib_pd *)-EIO);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaib_dealloc_pd(struct ib_pd *pd)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client_t *ofs_client = (ofs_client_t *)pd->device->clnt_hdl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int rtn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_enter(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (pd->device->reg_state != IB_DEV_OPEN) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_dealloc_pd: pd: 0x%p => invalid device state (%d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota pd, pd->device->reg_state);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-ENXIO);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_dealloc_pd: pd: 0x%p", pd);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_free_pd(pd->device->hca_hdl, pd->ibt_pd);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rtn == IBT_SUCCESS) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_dealloc_pd: pd: 0x%p, device: 0x%p, ibt_pd: 0x%p, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "rtn: 0x%x", pd, pd->device, pd->ibt_pd, rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(pd, sizeof (struct ib_pd));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_dealloc_pd: pd: 0x%p => ibt_free_pd failed w/ 0x%x",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota pd, rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (rtn) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_PD_IN_USE:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EBUSY);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_HCA_HDL_INVALID:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EFAULT);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EIO);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ofs_cq_handler() is a delegated function to handle CQ events,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * which dispatches them to corresponding cq handlers registered
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * with ib_create_cq().
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic void
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaofs_cq_handler(ibt_cq_hdl_t ibt_cq, void *arg)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct ib_cq *cq = (struct ib_cq *)ibt_get_cq_private(ibt_cq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ofs_cq_handler: ibt_cq: 0x%p, ib_cq: 0x%p, comp_handler: 0x%p, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "arg: 0x%p", ibt_cq, cq, cq->comp_handler, arg);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (cq->comp_handler) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cq->comp_handler(cq, cq->cq_context);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ib_create_cq - Creates a CQ on the specified device.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @device: The device on which to create the CQ.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @comp_handler: A user-specified callback that is invoked when a
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * completion event occurs on the CQ.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @event_handler: A user-specified callback that is invoked when an
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * asynchronous event not associated with a completion occurs on the CQ.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @cq_context: Context associated with the CQ returned to the user via
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * the associated completion and event handlers.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @cqe: The minimum size of the CQ.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @comp_vector - Completion vector used to signal completion events.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Must be >= 0 and < context->num_comp_vectors.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Users can examine the cq structure to determine the actual CQ size.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Note that comp_vector is not supported currently.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastruct ib_cq *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaib_create_cq(struct ib_device *device, ib_comp_handler comp_handler,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota void (*event_handler)(struct ib_event *, void *), void *cq_context,
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor int cqe, void *comp_vector)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client_t *ofs_client = (ofs_client_t *)device->clnt_hdl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_cq_attr_t cq_attr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota uint32_t real_size;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct ib_cq *cq;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int rtn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((cq = kmem_alloc(sizeof (struct ib_cq), KM_NOSLEEP)) == NULL) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_create_cq: device: 0x%p, comp_handler: 0x%p, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "event_handler: 0x%p, cq_context: 0x%p, cqe: 0x%x, "
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor "comp_vector: %p => no sufficient memory", device,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota comp_handler, event_handler, cq_context, cqe, comp_vector);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return ((struct ib_cq *)-ENOMEM);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_enter(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (device->reg_state != IB_DEV_OPEN) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_create_cq: device: 0x%p, comp_handler: 0x%p, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "event_handler: 0x%p, cq_context: 0x%p, cqe: 0x%x, "
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor "comp_vector: %p => invalid device state (%d)", device,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota comp_handler, event_handler, cq_context, cqe, comp_vector,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device->reg_state);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return ((struct ib_cq *)-ENXIO);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_create_cq: device: 0x%p, comp_handler: 0x%p, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "event_handler: 0x%p, cq_context: 0x%p, cqe: 0x%x, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "comp_vector: %d", device, comp_handler, event_handler,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cq_context, cqe, comp_vector);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cq_attr.cq_size = cqe;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor cq_attr.cq_sched = comp_vector;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cq_attr.cq_flags = IBT_CQ_NO_FLAGS;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_alloc_cq(device->hca_hdl, &cq_attr, &cq->ibt_cq, &real_size);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rtn == IBT_SUCCESS) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cq->device = device;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cq->comp_handler = comp_handler;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cq->event_handler = event_handler;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cq->cq_context = cq_context;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cq->cqe = real_size;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_set_cq_private(cq->ibt_cq, cq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_set_cq_handler(cq->ibt_cq, ofs_cq_handler, cq_context);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_init(&cq->lock, NULL, MUTEX_DEFAULT, NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_create_cq: device: 0x%p, cqe: 0x%x, ibt_cq: 0x%p, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "rtn: 0x%x", device, cqe, cq->ibt_cq, rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (cq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(cq, sizeof (struct ib_cq));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_create_cq: device: 0x%p, cqe: 0x%x, ibt_cq: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ibt_alloc_cq failed w/ 0x%x", device, cqe, cq->ibt_cq, rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (rtn) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_HCA_CQ_EXCEEDED:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_INVALID_PARAM:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_HCA_HDL_INVALID:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return ((struct ib_cq *)-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_INSUFF_RESOURCE:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return ((struct ib_cq *)-ENOMEM);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return ((struct ib_cq *)-EIO);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaib_destroy_cq(struct ib_cq *cq)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client_t *ofs_client = (ofs_client_t *)cq->device->clnt_hdl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int rtn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_enter(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (cq->device->reg_state != IB_DEV_OPEN) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_destroy_cq: cq: 0x%p => invalid device state (%d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cq, cq->device->reg_state);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-ENXIO);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_destroy_cq: cq: 0x%p", cq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * if IBTL_ASYNC_PENDING is set, ibt_qp is not freed
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * at this moment, but yet alive for a while. Then
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * there is a possibility that this qp is used even after
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ib_destroy_cq() is called. To distinguish this case from
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * others, clear ibt_qp here.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_set_cq_private(cq->ibt_cq, NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_free_cq(cq->ibt_cq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rtn == IBT_SUCCESS) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(cq, sizeof (struct ib_cq));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_destroy_cq: cq: 0x%p, rtn: 0x%x", cq, rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_set_cq_private(cq->ibt_cq, cq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_destroy_cq: cq: 0x%p => ibt_free_cq failed w/ 0x%x", cq, rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (rtn) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_CQ_BUSY:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EBUSY);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_HCA_HDL_INVALID:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_CQ_HDL_INVALID:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EIO);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastruct ib_qp *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaib_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *qp_init_attr)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client_t *ofs_client = pd->device->clnt_hdl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_qp_alloc_attr_t attrs;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_chan_sizes_t sizes;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ib_qpn_t qpn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_qp_hdl_t ibt_qp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct ib_qp *qp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int rtn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* sanity check */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (!(qp_init_attr->send_cq && qp_init_attr->recv_cq)) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_create_qp: pd: 0x%p => invalid cqs "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "(send_cq=0x%p, recv_cq=0x%p)", pd,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp_init_attr->send_cq, qp_init_attr->recv_cq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return ((struct ib_qp *)-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* UC, Raw IPv6 and Raw Ethernet are not supported */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (qp_init_attr->qp_type == IB_QPT_UC ||
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp_init_attr->qp_type == IB_QPT_RAW_IPV6 ||
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp_init_attr->qp_type == IB_QPT_RAW_ETY) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_create_qp: pd: 0x%p => invalid qp_type",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota pd, qp_init_attr->qp_type);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return ((struct ib_qp *)-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((qp = kmem_alloc(sizeof (struct ib_qp), KM_NOSLEEP)) == NULL) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_create_qp: pd: 0x%p, init_attr: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "no sufficient memory", pd, qp_init_attr);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return ((struct ib_qp *)-ENOMEM);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_enter(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (pd->device->reg_state != IB_DEV_OPEN) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(qp, sizeof (struct ib_qp));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_create_qp: pd: 0x%p, init_attr: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "invalid device state (%d)", pd, qp_init_attr,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota pd->device->reg_state);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return ((struct ib_qp *)-ENXIO);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_create_qp: pd: 0x%p, event_handler: 0x%p, qp_context: 0x%p, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "send_cq: 0x%p, recv_cq: 0x%p, srq: 0x%p, max_send_wr: 0x%x, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "max_recv_wr: 0x%x, max_send_sge: 0x%x, max_recv_sge: 0x%x, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "max_inline_data: 0x%x, sq_sig_type: %d, qp_type: %d, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "port_num: %d",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota pd, qp_init_attr->event_handler, qp_init_attr->qp_context,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp_init_attr->send_cq, qp_init_attr->recv_cq, qp_init_attr->srq,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp_init_attr->cap.max_send_wr, qp_init_attr->cap.max_recv_wr,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp_init_attr->cap.max_send_sge, qp_init_attr->cap.max_recv_sge,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp_init_attr->cap.max_inline_data, qp_init_attr->sq_sig_type,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp_init_attr->qp_type, qp_init_attr->port_num);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attrs.qp_alloc_flags = IBT_QP_NO_FLAGS;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (qp_init_attr->srq) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attrs.qp_alloc_flags |= IBT_QP_USES_SRQ;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attrs.qp_flags = IBT_ALL_SIGNALED | IBT_FAST_REG_RES_LKEY;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (qp_init_attr->sq_sig_type == IB_SIGNAL_REQ_WR) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attrs.qp_flags |= IBT_WR_SIGNALED;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attrs.qp_scq_hdl = qp_init_attr->send_cq->ibt_cq;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attrs.qp_rcq_hdl = qp_init_attr->recv_cq->ibt_cq;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attrs.qp_pd_hdl = pd->ibt_pd;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attrs.qp_sizes.cs_sq = qp_init_attr->cap.max_send_wr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attrs.qp_sizes.cs_rq = qp_init_attr->cap.max_recv_wr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attrs.qp_sizes.cs_sq_sgl = qp_init_attr->cap.max_send_sge;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attrs.qp_sizes.cs_rq_sgl = qp_init_attr->cap.max_recv_sge;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attrs.qp_sizes.cs_inline = qp_init_attr->cap.max_inline_data;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (qp_init_attr->qp_type) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_RC:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_alloc_qp(pd->device->hca_hdl, IBT_RC_RQP, &attrs,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota &sizes, &qpn, &ibt_qp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_UD:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_alloc_qp(pd->device->hca_hdl, IBT_UD_RQP, &attrs,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota &sizes, &qpn, &ibt_qp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_SMI:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_alloc_special_qp(pd->device->hca_hdl,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp_init_attr->port_num, IBT_SMI_SQP, &attrs, &sizes,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota &ibt_qp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_GSI:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_alloc_special_qp(pd->device->hca_hdl,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp_init_attr->port_num, IBT_GSI_SQP, &attrs, &sizes,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota &ibt_qp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* this should never happens */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(qp, sizeof (struct ib_qp));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return ((struct ib_qp *)-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rtn == IBT_SUCCESS) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* fill in ib_qp_cap w/ the real values */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp_init_attr->cap.max_send_wr = sizes.cs_sq;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp_init_attr->cap.max_recv_wr = sizes.cs_rq;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp_init_attr->cap.max_send_sge = sizes.cs_sq_sgl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp_init_attr->cap.max_recv_sge = sizes.cs_rq_sgl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* max_inline_data is not supported */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp_init_attr->cap.max_inline_data = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* fill in ib_qp */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp->device = pd->device;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp->pd = pd;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp->send_cq = qp_init_attr->send_cq;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp->recv_cq = qp_init_attr->recv_cq;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp->srq = qp_init_attr->srq;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp->event_handler = qp_init_attr->event_handler;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp->qp_context = qp_init_attr->qp_context;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp->qp_num = qp_init_attr->qp_type == IB_QPT_SMI ? 0 :
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp_init_attr->qp_type == IB_QPT_GSI ? 1 : qpn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp->qp_type = qp_init_attr->qp_type;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp->ibt_qp = ibt_qp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_set_qp_private(qp->ibt_qp, qp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_init(&qp->lock, NULL, MUTEX_DEFAULT, NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_create_qp: device: 0x%p, pd: 0x%x, init_attr: 0x%p, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "rtn: 0x%x", pd->device, pd, qp_init_attr, rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (qp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(qp, sizeof (struct ib_qp));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_create_qp: device: 0x%p, pd: 0x%x, init_attr: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ibt_alloc_(special)_qp failed w/ rtn: 0x%x", pd->device, pd,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp_init_attr, rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (rtn) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_NOT_SUPPORTED:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_QP_SRV_TYPE_INVALID:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_CQ_HDL_INVALID:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_HCA_HDL_INVALID:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_INVALID_PARAM:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_SRQ_HDL_INVALID:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_PD_HDL_INVALID:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_HCA_SGL_EXCEEDED:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_HCA_WR_EXCEEDED:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return ((struct ib_qp *)-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_INSUFF_RESOURCE:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return ((struct ib_qp *)-ENOMEM);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return ((struct ib_qp *)-EIO);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaib_destroy_qp(struct ib_qp *qp)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client_t *ofs_client = (ofs_client_t *)qp->device->clnt_hdl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int rtn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_enter(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (qp->device->reg_state != IB_DEV_OPEN) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_destroy_qp: qp: 0x%p => invalid device state (%d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp, qp->device->reg_state);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-ENXIO);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * if IBTL_ASYNC_PENDING is set, ibt_qp is not freed
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * at this moment, but yet alive for a while. Then
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * there is a possibility that this qp is used even after
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ib_destroy_qp() is called. To distinguish this case from
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * others, clear ibt_qp here.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_set_qp_private(qp->ibt_qp, NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_free_qp(qp->ibt_qp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rtn == IBT_SUCCESS) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(qp, sizeof (struct ib_qp));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_destroy_qp: qp: 0x%p, rtn: 0x%x", qp, rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_set_qp_private(qp->ibt_qp, qp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_destroy_qp: qp: 0x%p => ibt_free_qp failed w/ 0x%x", qp, rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (rtn) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_CHAN_STATE_INVALID:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_HCA_HDL_INVALID:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_QP_HDL_INVALID:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EIO);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ib_req_notify_cq - Request completion notification on a CQ.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @cq: The CQ to generate an event for.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @flags:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Must contain exactly one of %IB_CQ_SOLICITED or %IB_CQ_NEXT_COMP
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * to request an event on the next solicited event or next work
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * completion at any type, respectively. %IB_CQ_REPORT_MISSED_EVENTS
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * may also be |ed in to request a hint about missed events, as
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * described below.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Return Value:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * < 0 means an error occurred while requesting notification
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * == 0 means notification was requested successfully, and if
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * IB_CQ_REPORT_MISSED_EVENTS was passed in, then no events
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * were missed and it is safe to wait for another event. In
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * this case is it guaranteed that any work completions added
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * to the CQ since the last CQ poll will trigger a completion
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * notification event.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * > 0 is only returned if IB_CQ_REPORT_MISSED_EVENTS was passed
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * in. It means that the consumer must poll the CQ again to
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * make sure it is empty to avoid missing an event because of a
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * race between requesting notification and an entry being
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * added to the CQ. This return value means it is possible
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * (but not guaranteed) that a work completion has been added
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * to the CQ since the last poll without triggering a
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * completion notification event.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Note that IB_CQ_REPORT_MISSED_EVENTS is currently not supported.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaib_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify_flags flags)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_cq_notify_flags_t notify_type;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int rtn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client_t *ofs_client = cq->device->clnt_hdl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_enter(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (cq->device->reg_state != IB_DEV_OPEN) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_req_notify_cq: cq: 0x%p, flag: 0x%x", cq, flags);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-ENXIO);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_req_notify_cq: cq: 0x%p, flag: 0x%x", cq, flags);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (flags & IB_CQ_SOLICITED_MASK) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_CQ_SOLICITED:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota notify_type = IBT_NEXT_SOLICITED;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_CQ_NEXT_COMP:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota notify_type = IBT_NEXT_COMPLETION;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* Currently only two flags are supported */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_req_notify_cq: cq: 0x%p, flag: 0x%x => invalid flag",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cq, flags);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_enable_cq_notify(cq->ibt_cq, notify_type);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rtn == IBT_SUCCESS) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_req_notify_cq: cq: 0x%p, flag: 0x%x rtn: 0x%x",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cq, flags, rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_req_notify_cq: cq: 0x%p, flag: 0x%x => ibt_enable_cq_notify "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "failed w/ 0x%x", cq, flags, rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (rtn) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_HCA_HDL_INVALID:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_CQ_HDL_INVALID:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_CQ_NOTIFY_TYPE_INVALID:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EIO);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic const struct {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int valid;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota enum ib_qp_attr_mask req_param[IB_QPT_RAW_ETY + 1];
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota enum ib_qp_attr_mask opt_param[IB_QPT_RAW_ETY + 1];
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota} qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_RESET] = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_RESET] = { .valid = 1 },
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_INIT] = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .valid = 1,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .req_param = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_UD] = (IB_QP_PKEY_INDEX | IB_QP_PORT |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_QKEY),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_UC] = (IB_QP_PKEY_INDEX | IB_QP_PORT |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_ACCESS_FLAGS),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_RC] = (IB_QP_PKEY_INDEX | IB_QP_PORT |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_ACCESS_FLAGS),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | IB_QP_QKEY),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | IB_QP_QKEY),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota },
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota },
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_INIT] = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_RESET] = { .valid = 1 },
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_ERR] = { .valid = 1 },
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_INIT] = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .valid = 1,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .opt_param = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_UD] = (IB_QP_PKEY_INDEX | IB_QP_PORT |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_QKEY),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_UC] = (IB_QP_PKEY_INDEX | IB_QP_PORT |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_ACCESS_FLAGS),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_RC] = (IB_QP_PKEY_INDEX | IB_QP_PORT |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_ACCESS_FLAGS),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | IB_QP_QKEY),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | IB_QP_QKEY),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota },
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_RTR] = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .valid = 1,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .req_param = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_UC] = (IB_QP_AV | IB_QP_PATH_MTU |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_DEST_QPN | IB_QP_RQ_PSN),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_RC] = (IB_QP_AV | IB_QP_PATH_MTU |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_DEST_QPN | IB_QP_RQ_PSN |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_MAX_DEST_RD_ATOMIC |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_MIN_RNR_TIMER),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota },
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .opt_param = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_UD] = (IB_QP_PKEY_INDEX | IB_QP_QKEY),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_UC] = (IB_QP_ALT_PATH |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_ACCESS_FLAGS | IB_QP_PKEY_INDEX),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_RC] = (IB_QP_ALT_PATH |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_ACCESS_FLAGS | IB_QP_PKEY_INDEX),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | IB_QP_QKEY),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | IB_QP_QKEY),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota },
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_RTR] = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_RESET] = { .valid = 1 },
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_ERR] = { .valid = 1 },
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_RTS] = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .valid = 1,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .req_param = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_UD] = IB_QP_SQ_PSN,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_UC] = IB_QP_SQ_PSN,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_RC] = (IB_QP_TIMEOUT |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_RETRY_CNT | IB_QP_RNR_RETRY |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_SQ_PSN | IB_QP_MAX_QP_RD_ATOMIC),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_SMI] = IB_QP_SQ_PSN,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_GSI] = IB_QP_SQ_PSN,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota },
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .opt_param = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_UD] = (IB_QP_CUR_STATE | IB_QP_QKEY),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_UC] = (IB_QP_CUR_STATE |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_ALT_PATH | IB_QP_ACCESS_FLAGS |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_PATH_MIG_STATE),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_RC] = (IB_QP_CUR_STATE |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_ALT_PATH | IB_QP_ACCESS_FLAGS |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_MIN_RNR_TIMER | IB_QP_PATH_MIG_STATE),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_SMI] = (IB_QP_CUR_STATE | IB_QP_QKEY),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_GSI] = (IB_QP_CUR_STATE | IB_QP_QKEY),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota },
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_RTS] = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_RESET] = { .valid = 1 },
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_ERR] = { .valid = 1 },
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_RTS] = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .valid = 1,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .opt_param = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_UD] = (IB_QP_CUR_STATE | IB_QP_QKEY),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_UC] = (IB_QP_CUR_STATE |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_ACCESS_FLAGS | IB_QP_ALT_PATH |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_PATH_MIG_STATE),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_RC] = (IB_QP_CUR_STATE |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_ACCESS_FLAGS | IB_QP_ALT_PATH |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_PATH_MIG_STATE | IB_QP_MIN_RNR_TIMER),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_SMI] = (IB_QP_CUR_STATE | IB_QP_QKEY),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_GSI] = (IB_QP_CUR_STATE | IB_QP_QKEY),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota },
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_SQD] = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .valid = 1,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .opt_param = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_UD] = IB_QP_EN_SQD_ASYNC_NOTIFY,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_UC] = IB_QP_EN_SQD_ASYNC_NOTIFY,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_RC] = IB_QP_EN_SQD_ASYNC_NOTIFY,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_SMI] = IB_QP_EN_SQD_ASYNC_NOTIFY,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_GSI] = IB_QP_EN_SQD_ASYNC_NOTIFY
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota },
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota },
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_SQD] = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_RESET] = { .valid = 1 },
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_ERR] = { .valid = 1 },
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_RTS] = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .valid = 1,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .opt_param = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_UD] = (IB_QP_CUR_STATE | IB_QP_QKEY),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_UC] = (IB_QP_CUR_STATE |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_ALT_PATH | IB_QP_ACCESS_FLAGS |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_PATH_MIG_STATE),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_RC] = (IB_QP_CUR_STATE |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_ALT_PATH | IB_QP_ACCESS_FLAGS |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_MIN_RNR_TIMER | IB_QP_PATH_MIG_STATE),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_SMI] = (IB_QP_CUR_STATE | IB_QP_QKEY),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_GSI] = (IB_QP_CUR_STATE | IB_QP_QKEY),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota },
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_SQD] = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .valid = 1,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .opt_param = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_UD] = (IB_QP_PKEY_INDEX | IB_QP_QKEY),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_UC] = (IB_QP_AV | IB_QP_ALT_PATH |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_ACCESS_FLAGS | IB_QP_PKEY_INDEX |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_PATH_MIG_STATE),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_RC] = (IB_QP_PORT | IB_QP_AV |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_TIMEOUT | IB_QP_RETRY_CNT |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_RNR_RETRY | IB_QP_MAX_QP_RD_ATOMIC |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_MAX_DEST_RD_ATOMIC | IB_QP_ALT_PATH |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_ACCESS_FLAGS | IB_QP_PKEY_INDEX |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_MIN_RNR_TIMER | IB_QP_PATH_MIG_STATE),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | IB_QP_QKEY),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | IB_QP_QKEY),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota },
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_SQE] = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_RESET] = { .valid = 1 },
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_ERR] = { .valid = 1 },
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_RTS] = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .valid = 1,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .opt_param = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_UD] = (IB_QP_CUR_STATE | IB_QP_QKEY),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_UC] = (IB_QP_CUR_STATE |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IB_QP_ACCESS_FLAGS),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_SMI] = (IB_QP_CUR_STATE | IB_QP_QKEY),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPT_GSI] = (IB_QP_CUR_STATE | IB_QP_QKEY),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota },
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_ERR] = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_RESET] = { .valid = 1 },
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota [IB_QPS_ERR] = { .valid = 1 }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota};
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic inline int
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota enum ib_qp_type type, enum ib_qp_attr_mask mask)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota enum ib_qp_attr_mask req_param, opt_param;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (cur_state < 0 || cur_state > IB_QPS_ERR ||
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota next_state < 0 || next_state > IB_QPS_ERR) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp_is_ok: cur_state: %d, next_state: %d, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "qp_type: %d, attr_mask: 0x%x => invalid state(1)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cur_state, next_state, type, mask);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (mask & IB_QP_CUR_STATE &&
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cur_state != IB_QPS_RTR && cur_state != IB_QPS_RTS &&
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cur_state != IB_QPS_SQD && cur_state != IB_QPS_SQE) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp_is_ok: cur_state: %d, next_state: %d, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "qp_type: %d, attr_mask: 0x%x => invalid state(2)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cur_state, next_state, type, mask);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (!qp_state_table[cur_state][next_state].valid) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp_is_ok: cur_state: %d, next_state: %d, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "qp_type: %d, attr_mask: 0x%x => state is not valid",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cur_state, next_state, type, mask);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota req_param = qp_state_table[cur_state][next_state].req_param[type];
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota opt_param = qp_state_table[cur_state][next_state].opt_param[type];
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((mask & req_param) != req_param) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp_is_ok: cur_state: %d, next_state: %d, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "qp_type: %d, attr_mask: 0x%x => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "required param doesn't match. req_param = 0x%x",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cur_state, next_state, type, mask, req_param);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (mask & ~(req_param | opt_param | IB_QP_STATE)) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp_is_ok: cur_state: %d, next_state: %d, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "qp_type: %d, attr_mask: 0x%x => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "unsupported options. req_param = 0x%x, opt_param = 0x%x",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cur_state, next_state, type, mask, req_param, opt_param);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (1);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic inline enum ib_qp_state
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaqp_current_state(ibt_qp_query_attr_t *qp_attr)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(qp_attr->qp_info.qp_state != IBT_STATE_SQDRAIN);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (enum ib_qp_state)(qp_attr->qp_info.qp_state);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic inline ibt_tran_srv_t
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaof2ibtf_qp_type(enum ib_qp_type type)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (type) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_SMI:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_GSI:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_UD:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IBT_UD_SRV);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_RC:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IBT_RC_SRV);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_UC:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IBT_UC_SRV);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_RAW_IPV6:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IBT_RAWIP_SRV);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_RAW_ETY:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(type == IB_QPT_RAW_ETY);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IBT_RAWETHER_SRV);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic inline void
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaset_av(struct ib_ah_attr *attr, ibt_cep_path_t *pathp)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_adds_vect_t *av = &pathp->cep_adds_vect;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota pathp->cep_hca_port_num = attr->port_num;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota av->av_srate = OF2IBTF_SRATE(attr->static_rate);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota av->av_srvl = attr->sl & 0xF;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota av->av_send_grh = attr->ah_flags & IB_AH_GRH ? 1 : 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (av->av_send_grh) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota av->av_dgid.gid_prefix =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->grh.dgid.global.subnet_prefix;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota av->av_dgid.gid_guid =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->grh.dgid.global.interface_id;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota av->av_flow = attr->grh.flow_label & 0xFFFFF;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota av->av_tclass = attr->grh.traffic_class;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota av->av_hop = attr->grh.hop_limit;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota av->av_sgid_ix = attr->grh.sgid_index;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota av->av_dlid = attr->dlid;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota av->av_src_path = attr->src_path_bits;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaib_modify_qp(struct ib_qp *qp, struct ib_qp_attr *attr, int attr_mask)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota enum ib_qp_state cur_state, new_state;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_hca_attr_t hattr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_qp_query_attr_t qp_attr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_qp_info_t modify_attr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_cep_modify_flags_t flags;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int rtn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client_t *ofs_client = qp->device->clnt_hdl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_enter(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (qp->device->reg_state != IB_DEV_OPEN) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp: qp: 0x%p => invalid device state (%d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp, qp->device->reg_state);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-ENXIO);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_query_hca(qp->device->hca_hdl, &hattr);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rtn != IBT_SUCCESS) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp: qp: 0x%p, hca_hdl: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ibt_query_hca() failed w/ %d",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp, qp->device->hca_hdl, rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EIO);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* only one thread per qp is allowed during the qp modification */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&qp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* Get the current QP attributes first */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota bzero(&qp_attr, sizeof (ibt_qp_query_attr_t));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((rtn = ibt_query_qp(qp->ibt_qp, &qp_attr)) != IBT_SUCCESS) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&qp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp: qp: 0x%p, attr: 0x%p, attr_mask: 0x%x => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ibt_query_qp failed w/ 0x%x", qp, attr, attr_mask, rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EIO);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* Get the current and new state for this QP */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cur_state = attr_mask & IB_QP_CUR_STATE ? attr->cur_qp_state :
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp_current_state(&qp_attr);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota new_state = attr_mask & IB_QP_STATE ? attr->qp_state :
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cur_state;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* Sanity check of the current/new states */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (cur_state == new_state && cur_state == IB_QPS_RESET) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* Linux OF returns 0 in this case */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&qp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp: qp: 0x%p, attr: 0x%p, attr_mask: 0x%x => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "invalid state (both of current/new states are RESET)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp, attr, attr_mask);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Check if this modification request is supported with the new
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * and/or current state.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (!ib_modify_qp_is_ok(cur_state, new_state, qp->qp_type, attr_mask)) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&qp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp: qp: 0x%p, attr: 0x%p, attr_mask: 0x%x => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "invalid arguments",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp, attr, attr_mask);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* Sanity checks */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_PORT && (attr->port_num == 0 ||
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->port_num > hattr.hca_nports)) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&qp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp: qp: 0x%p, attr: 0x%p, attr_mask: 0x%x => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "invalid attr->port_num(%d), max_nports(%d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp, attr, attr_mask, attr->port_num, hattr.hca_nports);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_PKEY_INDEX &&
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->pkey_index >= hattr.hca_max_port_pkey_tbl_sz) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&qp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp: qp: 0x%p, attr: 0x%p, attr_mask: 0x%x => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "invalid attr->pkey_index(%d), max_pkey_index(%d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp, attr, attr_mask, attr->pkey_index,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota hattr.hca_max_port_pkey_tbl_sz);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_rd_atomic > hattr.hca_max_rdma_out_qp) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&qp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp: qp: 0x%p, attr: 0x%p, attr_mask: 0x%x => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "invalid attr->max_rd_atomic(0x%x), max_rdma_out_qp(0x%x)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp, attr, attr_mask, attr->max_rd_atomic,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota hattr.hca_max_rdma_out_qp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC &&
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_dest_rd_atomic > hattr.hca_max_rdma_in_qp) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&qp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp: qp: 0x%p, attr: 0x%p, attr_mask: 0x%x => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "invalid attr->max_dest_rd_atomic(0x%x), "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "max_rdma_in_qp(0x%x)", qp, attr, attr_mask,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_dest_rd_atomic, hattr.hca_max_rdma_in_qp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* copy the current setting */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr = qp_attr.qp_info;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Since it's already checked if the modification request matches
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * the new and/or current states, just assign both of states to
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * modify_attr here. The current state is required if qp_state
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * is RTR, but it's harmelss otherwise, so it's set always.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_current_state = OF2IBTF_STATE(cur_state);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_state = OF2IBTF_STATE(new_state);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_trans = of2ibtf_qp_type(qp->qp_type);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* Convert OF modification requests into IBTF ones */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota flags = IBT_CEP_SET_STATE; /* IBTF needs IBT_CEP_SET_STATE */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (cur_state == IB_QPS_RESET &&
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota new_state == IB_QPS_INIT) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota flags |= IBT_CEP_SET_RESET_INIT;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota } else if (cur_state == IB_QPS_INIT &&
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota new_state == IB_QPS_RTR) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota flags |= IBT_CEP_SET_INIT_RTR;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota } else if (cur_state == IB_QPS_RTR &&
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota new_state == IB_QPS_RTS) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota flags |= IBT_CEP_SET_RTR_RTS;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_EN_SQD_ASYNC_NOTIFY) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota flags |= IBT_CEP_SET_SQD_EVENT;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_ACCESS_FLAGS) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_flags &= ~(IBT_CEP_RDMA_RD | IBT_CEP_RDMA_WR |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota IBT_CEP_ATOMIC);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr->qp_access_flags & IB_ACCESS_REMOTE_READ) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota flags |= IBT_CEP_SET_RDMA_R;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_flags |= IBT_CEP_RDMA_RD;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr->qp_access_flags & IB_ACCESS_REMOTE_WRITE) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota flags |= IBT_CEP_SET_RDMA_W;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_flags |= IBT_CEP_RDMA_WR;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr->qp_access_flags & IB_ACCESS_REMOTE_ATOMIC) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota flags |= IBT_CEP_SET_ATOMIC;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_flags |= IBT_CEP_ATOMIC;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_PKEY_INDEX) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota flags |= IBT_CEP_SET_PKEY_IX;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (qp->qp_type) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_SMI:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_GSI:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_UD:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.ud.ud_pkey_ix =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->pkey_index;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_RC:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.rc.rc_path.cep_pkey_ix =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->pkey_index;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_UC:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.uc.uc_path.cep_pkey_ix =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->pkey_index;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* This should never happen */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&qp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp(IB_QP_PKEY_INDEX): qp: 0x%p, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "attr: 0x%p, attr_mask: 0x%x => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "invalid qp->qp_type(%d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp, attr, attr_mask, qp->qp_type);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_PORT) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota flags |= IBT_CEP_SET_PORT;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (qp->qp_type) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_SMI:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_GSI:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_UD:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.ud.ud_port = attr->port_num;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_RC:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.rc.rc_path.cep_hca_port_num =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->port_num;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_UC:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.uc.uc_path.cep_hca_port_num =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->port_num;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* This should never happen */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&qp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp(IB_QP_PORT): qp: 0x%p, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "attr: 0x%p, attr_mask: 0x%x => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "invalid qp->qp_type(%d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp, attr, attr_mask, qp->qp_type);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_QKEY) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(qp->qp_type == IB_QPT_UD || qp->qp_type == IB_QPT_SMI ||
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp->qp_type == IB_QPT_GSI);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota flags |= IBT_CEP_SET_QKEY;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.ud.ud_qkey = attr->qkey;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_AV) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota flags |= IBT_CEP_SET_ADDS_VECT;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (qp->qp_type) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_RC:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota set_av(&attr->ah_attr,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota &modify_attr.qp_transport.rc.rc_path);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_UC:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota set_av(&attr->ah_attr,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota &modify_attr.qp_transport.uc.uc_path);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_SMI:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_GSI:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_UD:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* This should never happen */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&qp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp(IB_QP_AV): qp: 0x%p, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "attr: 0x%p, attr_mask: 0x%x => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "invalid qp->qp_type(%d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp, attr, attr_mask, qp->qp_type);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_PATH_MTU) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (qp->qp_type) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_RC:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.rc.rc_path_mtu =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota OF2IBTF_PATH_MTU(attr->path_mtu);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_UC:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.uc.uc_path_mtu =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota OF2IBTF_PATH_MTU(attr->path_mtu);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_SMI:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_GSI:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_UD:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* nothing to do */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_TIMEOUT && qp->qp_type == IB_QPT_RC) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota flags |= IBT_CEP_SET_TIMEOUT;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.rc.rc_path.cep_timeout =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->timeout;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_RETRY_CNT && qp->qp_type == IB_QPT_RC) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota flags |= IBT_CEP_SET_RETRY;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.rc.rc_retry_cnt =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->retry_cnt & 0x7;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_RNR_RETRY && qp->qp_type == IB_QPT_RC) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota flags |= IBT_CEP_SET_RNR_NAK_RETRY;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.rc.rc_rnr_retry_cnt =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->rnr_retry & 0x7;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_RQ_PSN) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (qp->qp_type) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_RC:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.rc.rc_rq_psn =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->rq_psn & 0xFFFFFF;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_UC:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.uc.uc_rq_psn =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->rq_psn & 0xFFFFFF;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_SMI:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_GSI:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_UD:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* nothing to do */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC && qp->qp_type == IB_QPT_RC) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr->max_rd_atomic) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota flags |= IBT_CEP_SET_RDMARA_OUT;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.rc.rc_rdma_ra_out =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_rd_atomic;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_ALT_PATH) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* Sanity checks */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr->alt_port_num == 0 ||
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->alt_port_num > hattr.hca_nports) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&qp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp: qp: 0x%p, attr: 0x%p, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "attr_mask: 0x%x => invalid attr->alt_port_num"
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "(%d), max_nports(%d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp, attr, attr_mask, attr->alt_port_num,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota hattr.hca_nports);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr->alt_pkey_index >= hattr.hca_max_port_pkey_tbl_sz) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&qp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp: qp: 0x%p, attr: 0x%p, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "attr_mask: 0x%x => invalid attr->alt_pkey_index"
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "(%d), max_port_key_index(%d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp, attr, attr_mask, attr->alt_pkey_index,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota hattr.hca_max_port_pkey_tbl_sz);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota flags |= IBT_CEP_SET_ALT_PATH;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (qp->qp_type) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_RC:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.rc.rc_alt_path.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cep_pkey_ix = attr->alt_pkey_index;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.rc.rc_alt_path.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cep_hca_port_num = attr->alt_port_num;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota set_av(&attr->alt_ah_attr,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota &modify_attr.qp_transport.rc.rc_alt_path);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.rc.rc_alt_path.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cep_timeout = attr->alt_timeout;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_UC:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.uc.uc_alt_path.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cep_pkey_ix = attr->alt_pkey_index;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.uc.uc_alt_path.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cep_hca_port_num = attr->alt_port_num;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota set_av(&attr->alt_ah_attr,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota &modify_attr.qp_transport.uc.uc_alt_path);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.uc.uc_alt_path.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cep_timeout = attr->alt_timeout;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_SMI:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_GSI:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_UD:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* This should never happen */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&qp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp(IB_QP_ALT_PATH): qp: 0x%p, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "attr: 0x%p, attr_mask: 0x%x => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "invalid qp->qp_type(%d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp, attr, attr_mask, qp->qp_type);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_MIN_RNR_TIMER && qp->qp_type == IB_QPT_RC) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota flags |= IBT_CEP_SET_MIN_RNR_NAK;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.rc.rc_min_rnr_nak =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->min_rnr_timer & 0x1F;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_SQ_PSN) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (qp->qp_type) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_SMI:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_GSI:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_UD:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.ud.ud_sq_psn =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->sq_psn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_RC:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.rc.rc_sq_psn =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->sq_psn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_UC:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.uc.uc_sq_psn =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->sq_psn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* This should never happen */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&qp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp(IB_QP_SQ_PSN): qp: 0x%p, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "attr: 0x%p, attr_mask: 0x%x => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "invalid qp->qp_type(%d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp, attr, attr_mask, qp->qp_type);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC && qp->qp_type == IB_QPT_RC) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* Linux OF sets the value if max_dest_rd_atomic is not zero */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr->max_dest_rd_atomic) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota flags |= IBT_CEP_SET_RDMARA_IN;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.rc.rc_rdma_ra_in =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_dest_rd_atomic;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_PATH_MIG_STATE) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota flags |= IBT_CEP_SET_MIG;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (qp->qp_type) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_RC:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.rc.rc_mig_state =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota OF2IBTF_PATH_MIG_STATE(attr->path_mig_state);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_UC:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.uc.uc_mig_state =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota OF2IBTF_PATH_MIG_STATE(attr->path_mig_state);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_SMI:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_GSI:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_UD:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* This should never happen */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&qp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp(IB_QP_PATH_MIG_STATE): qp: 0x%p, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "attr: 0x%p, attr_mask: 0x%x => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "invalid qp->qp_type(%d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp, attr, attr_mask, qp->qp_type);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_CAP) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* IB_QP_CAP is not supported */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&qp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp: qp: 0x%p, attr: 0x%p, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "attr_mask: 0x%x => IB_QP_CAP is not supported",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp, attr, attr_mask);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_DEST_QPN) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (qp->qp_type) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_RC:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.rc.rc_dst_qpn =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->dest_qp_num;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_UC:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.uc.uc_dst_qpn =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->dest_qp_num;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_SMI:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_GSI:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IB_QPT_UD:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* This should never happen */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&qp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp(IB_QP_DEST_PSN): qp: 0x%p, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "attr: 0x%p, attr_mask: 0x%x => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "invalid qp->qp_type(%d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp, attr, attr_mask, qp->qp_type);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp: qp: 0x%p, attr: 0x%p, attr_mask: 0x%x, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "flags: 0x%x, modify_attr: 0x%p",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp, attr, attr_mask, flags, &modify_attr);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* Modify the QP attributes */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_modify_qp(qp->ibt_qp, flags, &modify_attr, NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rtn == IBT_SUCCESS) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&qp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&qp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp: qp: 0x%p, attr: 0x%p, attr_mask: 0x%x => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ibt_modify_qp failed w/ %d, flags: 0x%x",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp, attr, attr_mask, rtn, flags);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (rtn) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_HCA_HDL_INVALID:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_QP_HDL_INVALID:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_QP_SRV_TYPE_INVALID:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_QP_STATE_INVALID:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_HCA_PORT_INVALID:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_PKEY_IX_ILLEGAL:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EIO);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic inline enum ib_wc_status
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaibt2of_wc_status(ibt_wc_status_t status)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (status) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_WC_LOCAL_LEN_ERR:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IB_WC_LOC_LEN_ERR);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_WC_LOCAL_CHAN_OP_ERR:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IB_WC_LOC_QP_OP_ERR);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_WC_LOCAL_PROTECT_ERR:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IB_WC_LOC_PROT_ERR);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_WC_WR_FLUSHED_ERR:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IB_WC_WR_FLUSH_ERR);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_WC_MEM_WIN_BIND_ERR:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IB_WC_MW_BIND_ERR);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_WC_BAD_RESPONSE_ERR:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IB_WC_BAD_RESP_ERR);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_WC_LOCAL_ACCESS_ERR:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IB_WC_LOC_ACCESS_ERR);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_WC_REMOTE_INVALID_REQ_ERR:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IB_WC_REM_INV_REQ_ERR);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_WC_REMOTE_ACCESS_ERR:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IB_WC_REM_ACCESS_ERR);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_WC_REMOTE_OP_ERR:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IB_WC_REM_OP_ERR);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_WC_TRANS_TIMEOUT_ERR:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IB_WC_RETRY_EXC_ERR);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_WC_RNR_NAK_TIMEOUT_ERR:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IB_WC_RNR_RETRY_EXC_ERR);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_WC_SUCCESS:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* Hermon doesn't support EEC yet */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(status == IBT_WC_SUCCESS);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IB_WC_SUCCESS);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic inline enum ib_wc_opcode
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaibt2of_wc_opcode(ibt_wrc_opcode_t wc_type)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (wc_type) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_WRC_SEND:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IB_WC_SEND);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_WRC_RDMAR:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IB_WC_RDMA_READ);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_WRC_RDMAW:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IB_WC_RDMA_WRITE);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_WRC_CSWAP:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IB_WC_COMP_SWAP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_WRC_FADD:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IB_WC_FETCH_ADD);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_WRC_BIND:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IB_WC_BIND_MW);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_WRC_RECV:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IB_WC_RECV);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_WRC_RECV_RDMAWI:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(wc_type == IBT_WRC_RECV_RDMAWI);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (IB_WC_RECV_RDMA_WITH_IMM);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic inline int
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaibt2of_wc_flags(ibt_wc_flags_t wc_flags)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (wc_flags & ~IBT_WC_CKSUM_OK);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic inline void
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaset_wc(ibt_wc_t *ibt_wc, struct ib_wc *wc)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota wc->wr_id = ibt_wc->wc_id;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota wc->status = ibt2of_wc_status(ibt_wc->wc_status);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* opcode can be undefined if status is not success */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (wc->status == IB_WC_SUCCESS) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota wc->opcode = ibt2of_wc_opcode(ibt_wc->wc_type);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota wc->vendor_err = 0; /* not supported */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota wc->byte_len = ibt_wc->wc_bytes_xfer;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota wc->qp = NULL; /* not supported */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota wc->imm_data = htonl(ibt_wc->wc_immed_data);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota wc->src_qp = ibt_wc->wc_qpn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota wc->wc_flags = ibt2of_wc_flags(ibt_wc->wc_flags);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota wc->pkey_index = ibt_wc->wc_pkey_ix;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota wc->slid = ibt_wc->wc_slid;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota wc->sl = ibt_wc->wc_sl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota wc->dlid_path_bits = ibt_wc->wc_path_bits;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota wc->port_num = 0; /* not supported */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ib_poll_cq - poll a CQ for completion(s)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @cq:the CQ being polled
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @num_entries:maximum number of completions to return
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @wc:array of at least @num_entries &struct ib_wc where completions
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * will be returned
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Poll a CQ for (possibly multiple) completions. If the return value
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * is < 0, an error occurred. If the return value is >= 0, it is the
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * number of completions returned. If the return value is
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * non-negative and < num_entries, then the CQ was emptied.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Note that three following memebers in struct ib_wc are not supported
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * currently, and the values are always either 0 or NULL.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * u32 vendor_err;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * struct ib_qp *qp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * u8 port_num;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaib_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_wc_t ibt_wc;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int npolled;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_status_t rtn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client_t *ofs_client = (ofs_client_t *)cq->device->clnt_hdl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_enter(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (cq->device->reg_state != IB_DEV_OPEN) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_poll_cq: cq: 0x%p => invalid device state (%d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cq, cq->device->reg_state);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-ENXIO);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_poll_cq: cq: 0x%p, num_entries: %d, wc: 0x%p, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ibt_cq: 0x%p, ibt_wc: 0x%p",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cq, num_entries, wc, cq->ibt_cq, &ibt_wc);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* only one thread per cq is allowed during ibt_poll_cq() */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&cq->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota for (npolled = 0; npolled < num_entries; ++npolled) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota bzero(&ibt_wc, sizeof (ibt_wc_t));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_poll_cq(cq->ibt_cq, &ibt_wc, 1, NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rtn != IBT_SUCCESS) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* save this result to struct ib_wc */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota set_wc(&ibt_wc, wc + npolled);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&cq->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_lock_exit(&ofs_client->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rtn == IBT_SUCCESS || rtn == IBT_CQ_EMPTY) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (npolled);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_kverbs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_poll_cq: cq: 0x%p, num_entries: %d, wc: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ibt_poll_cq failed w/ %d, npolled = %d",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cq, num_entries, wc, rtn, npolled);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (rtn) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_HCA_HDL_INVALID:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_CQ_HDL_INVALID:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case IBT_INVALID_PARAM:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EIO);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaibt_hca_hdl_t
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaib_get_ibt_hca_hdl(struct ib_device *device)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (device->hca_hdl);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaibt_channel_hdl_t
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaib_get_ibt_channel_hdl(struct rdma_cm_id *cm)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (cm->qp == NULL ? NULL : cm->qp->ibt_qp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}