c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * CDDL HEADER START
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 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * See the License for the specific language governing permissions
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * and limitations under the License.
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 * CDDL HEADER END
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* Solaris Open Fabric kernel verbs */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/ib/clients/of/sol_ofs/sol_kverb_impl.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic llist_head_t client_list = LLIST_HEAD_INIT(client_list);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic void ofs_async_handler(void *, ibt_hca_hdl_t, ibt_async_code_t,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * set ibt_client_t members. clnt->ib_client must be set before
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * this func is called.
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 "alloc_ibt_client: client: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "namelen(%d) is larger than MAXNAMELEN", clnt, namelen);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota clnt->ibt_client.mi_clnt_name = kmem_zalloc(namelen + 1, KM_NOSLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "alloc_ibt_client: client: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota bcopy(clnt->ib_client->name, clnt->ibt_client.mi_clnt_name, namelen);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota clnt->ibt_client.mi_async_handler = ofs_async_handler;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(clnt->ibt_client.mi_clnt_name, namelen + 1);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * get_device() returns a pointer to struct ib_devcie with
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * the same guid as one passed to the function.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaget_device(ofs_client_t *ofs_client, ib_guid_t guid)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "get_device: client: 0x%p, guid:0x%p",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(device->clnt_hdl == (ofs_client_p_t)ofs_client);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "get_device: client: 0x%p, guid:0x%p => no match guid",
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 Otaofs_async_handler(void *clntp, ibt_hca_hdl_t hdl, ibt_async_code_t code,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cqp = event->ev_cq_hdl ? ibt_get_cq_private(event->ev_cq_hdl) : NULL;
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 (void *)(uintptr_t)event->ev_hca_guid, event->ev_port);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* re-use the device once it was created */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device = get_device(ofs_client, event->ev_hca_guid);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device = kmem_alloc(sizeof (ib_device_t), KM_SLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* add this HCA */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota llist_add_tail(&device->list, &ofs_client->device_list);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* open this HCA */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_open_hca(ofs_client->ibt_hdl, event->ev_hca_guid,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* invoke client's callback */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* invoke client's callback */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* change the state only */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* close this HCA */
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 * ib_register_client - Register an IB client
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @client:Client to register
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 * Note that struct ib_client should have a dip pointer to the client,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * which is different from the Linux implementation.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* get the number of HCAs on this system */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_register_client: client: 0x%p => no HCA", client);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* allocate a new sol_ofs_client structure */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client = kmem_zalloc(sizeof (ofs_client_t), KM_NOSLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_register_client: client: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* set members */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_register_client: client: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota llist_head_init(&ofs_client->client_list, ofs_client);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_init(&ofs_client->lock, NULL, RW_DEFAULT, NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* initialize IB client */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_register_client: client: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "invalid client state(%d)", client, client->state);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* attach this client to IBTF */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_attach(&ofs_client->ibt_client, client->dip, ofs_client,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_register_client: client: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* link this client */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota llist_add_tail(&ofs_client->client_list, &client_list);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* Open HCAs */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* allocate the ib_device structure */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota device = kmem_zalloc(sizeof (ib_device_t), KM_NOSLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_register_client: client: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota llist_add_tail(&device->list, &ofs_client->device_list);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_register_client: client: 0x%p,"
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "hca_hdl: 0x%p ==> "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ibt_query_hca() failed w/ %d",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* invoke client's callback */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_register_client: client: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* first close all open HCAs */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * If it's open already, close it after the remove
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * callback.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* invoke client's callback */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* then free the devices */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_for_each_safe(entry, tmp, &ofs_client->device_list) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* de-link and free the device */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* delink this client */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* detach the client */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* free sol_ofs_client */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ib_unregister_client - Unregister an IB client
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @client:Client to unregister
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 /* first close all open HCAs */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * If it's open already, close it after the remove
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * callback.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* invoke client's callback */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_unregister_client(%p) - "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ibt_close_hca failed %d",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* then free the devices */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_for_each_safe(entry, tmp, &ofs_client->device_list) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* de-link and free the device */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* delink this client */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* detach the client */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* free sol_ofs_client */
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 * 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 Otastatic inline void
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic inline void
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 * 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 "ib_get_client_data: device: 0x%p, client: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_get_client_data: device: 0x%p, client: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_get_client_data: device: 0x%p, client: 0x%p",
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 * 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 Otavoid ib_set_client_data(struct ib_device *device, struct ib_client *client,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cmn_err(CE_WARN, "No client context found for %s/%s\n",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cmn_err(CE_WARN, "No client context found for %s/%s\n",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_set_client_data: device: 0x%p, client: 0x%p, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ib_query_device - Query IB device attributes
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @device:Device to query
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @device_attr:Device attributes
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ib_query_device() returns the attributes of a device through the
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @device_attr pointer.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaib_query_device(struct ib_device *device, struct ib_device_attr *attr)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client_t *ofs_client = (ofs_client_t *)device->clnt_hdl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_query_device: device: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "invalid device state (%d)", device, device->reg_state);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((rtn = ibt_query_hca(device->hca_hdl, &hattr)) != IBT_SUCCESS) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_query_device: device: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_query_device: device: 0x%p, attr: 0x%p, rtn: 0x%p",
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 attr->device_cap_flags = IB_DEVICE_CHANGE_PHY_PORT |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->device_cap_flags |= IB_DEVICE_UD_AV_PORT_ENFORCE;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->page_size_cap = IBTF2OF_PGSZ(hattr.hca_page_sz);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_qp_init_rd_atom = hattr.hca_max_rdma_in_qp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota attr->max_ee_init_rd_atom = hattr.hca_max_rdma_in_ee;
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 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_map_per_fmr = hattr.hca_opaque9; /* hca_max_map_per_fmr */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* Protection domains */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client_t *ofs_client = (ofs_client_t *)device->clnt_hdl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((pd = kmem_alloc(sizeof (struct ib_pd), KM_NOSLEEP)) == NULL) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_alloc_pd: device: 0x%p => no sufficient memory",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_alloc_pd: device: 0x%p => invalid device state (%d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_alloc_pd(device->hca_hdl, IBT_PD_NO_FLAGS, &pd->ibt_pd);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_alloc_pd: device: 0x%p, pd: 0x%p, ibt_pd: 0x%p, "
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 ofs_client_t *ofs_client = (ofs_client_t *)pd->device->clnt_hdl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_dealloc_pd: pd: 0x%p => invalid device state (%d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_free_pd(pd->device->hca_hdl, pd->ibt_pd);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_dealloc_pd: pd: 0x%p, device: 0x%p, ibt_pd: 0x%p, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_dealloc_pd: pd: 0x%p => ibt_free_pd failed w/ 0x%x",
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 struct ib_cq *cq = (struct ib_cq *)ibt_get_cq_private(ibt_cq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ofs_cq_handler: ibt_cq: 0x%p, ib_cq: 0x%p, comp_handler: 0x%p, "
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 * Users can examine the cq structure to determine the actual CQ size.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Note that comp_vector is not supported currently.
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,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client_t *ofs_client = (ofs_client_t *)device->clnt_hdl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((cq = kmem_alloc(sizeof (struct ib_cq), KM_NOSLEEP)) == NULL) {
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 "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 "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 rtn = ibt_alloc_cq(device->hca_hdl, &cq_attr, &cq->ibt_cq, &real_size);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_set_cq_handler(cq->ibt_cq, ofs_cq_handler, cq_context);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_create_cq: device: 0x%p, cqe: 0x%x, ibt_cq: 0x%p, "
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 ofs_client_t *ofs_client = (ofs_client_t *)cq->device->clnt_hdl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_destroy_cq: cq: 0x%p => invalid device state (%d)",
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 return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_destroy_cq: cq: 0x%p => ibt_free_cq failed w/ 0x%x", cq, rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaib_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *qp_init_attr)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* sanity check */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (!(qp_init_attr->send_cq && qp_init_attr->recv_cq)) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_create_qp: pd: 0x%p => invalid cqs "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* UC, Raw IPv6 and Raw Ethernet are not supported */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_create_qp: pd: 0x%p => invalid qp_type",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((qp = kmem_alloc(sizeof (struct ib_qp), KM_NOSLEEP)) == NULL) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_create_qp: pd: 0x%p, init_attr: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_create_qp: pd: 0x%p, init_attr: 0x%p => "
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 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_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 rtn = ibt_alloc_qp(pd->device->hca_hdl, IBT_RC_RQP, &attrs,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_alloc_qp(pd->device->hca_hdl, IBT_UD_RQP, &attrs,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp_init_attr->port_num, IBT_SMI_SQP, &attrs, &sizes,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp_init_attr->port_num, IBT_GSI_SQP, &attrs, &sizes,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* this should never happens */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* fill in ib_qp_cap w/ the real values */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* max_inline_data is not supported */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* fill in ib_qp */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp->qp_num = qp_init_attr->qp_type == IB_QPT_SMI ? 0 :
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_create_qp: device: 0x%p, pd: 0x%x, init_attr: 0x%p, "
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 ofs_client_t *ofs_client = (ofs_client_t *)qp->device->clnt_hdl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_destroy_qp: qp: 0x%p => invalid device state (%d)",
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 return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_destroy_qp: qp: 0x%p => ibt_free_qp failed w/ 0x%x", qp, rtn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ib_req_notify_cq - Request completion notification on a CQ.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * @cq: The CQ to generate an event for.
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 * 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 * Note that IB_CQ_REPORT_MISSED_EVENTS is currently not supported.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaib_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify_flags flags)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_req_notify_cq: cq: 0x%p, flag: 0x%x", cq, flags);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_req_notify_cq: cq: 0x%p, flag: 0x%x", cq, flags);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* Currently only two flags are supported */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_req_notify_cq: cq: 0x%p, flag: 0x%x => invalid flag",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_enable_cq_notify(cq->ibt_cq, notify_type);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_req_notify_cq: cq: 0x%p, flag: 0x%x rtn: 0x%x",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_req_notify_cq: cq: 0x%p, flag: 0x%x => ibt_enable_cq_notify "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic const struct {
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 Otastatic inline int
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state,
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 return (0);
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 "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 return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (!qp_state_table[cur_state][next_state].valid) {
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 return (0);
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 "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 return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (mask & ~(req_param | opt_param | IB_QP_STATE)) {
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 return (1);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic inline enum ib_qp_state
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 Otastatic inline void
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaset_av(struct ib_ah_attr *attr, ibt_cep_path_t *pathp)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota av->av_send_grh = attr->ah_flags & IB_AH_GRH ? 1 : 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaib_modify_qp(struct ib_qp *qp, struct ib_qp_attr *attr, int attr_mask)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp: qp: 0x%p => invalid device state (%d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp: qp: 0x%p, hca_hdl: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ibt_query_hca() failed w/ %d",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* only one thread per qp is allowed during the qp modification */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* Get the current QP attributes first */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((rtn = ibt_query_qp(qp->ibt_qp, &qp_attr)) != IBT_SUCCESS) {
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 /* 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 new_state = attr_mask & IB_QP_STATE ? attr->qp_state :
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 "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 return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Check if this modification request is supported with the new
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * and/or current state.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (!ib_modify_qp_is_ok(cur_state, new_state, qp->qp_type, attr_mask)) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_modify_qp: qp: 0x%p, attr: 0x%p, attr_mask: 0x%x => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "invalid arguments",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* Sanity checks */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_PORT && (attr->port_num == 0 ||
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 attr->pkey_index >= hattr.hca_max_port_pkey_tbl_sz) {
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 "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 attr->max_dest_rd_atomic > hattr.hca_max_rdma_in_qp) {
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 attr->max_dest_rd_atomic, hattr.hca_max_rdma_in_qp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* copy the current setting */
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 modify_attr.qp_current_state = OF2IBTF_STATE(cur_state);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_trans = of2ibtf_qp_type(qp->qp_type);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* Convert OF modification requests into IBTF ones */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota flags = IBT_CEP_SET_STATE; /* IBTF needs IBT_CEP_SET_STATE */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_flags &= ~(IBT_CEP_RDMA_RD | IBT_CEP_RDMA_WR |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr->qp_access_flags & IB_ACCESS_REMOTE_READ) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr->qp_access_flags & IB_ACCESS_REMOTE_WRITE) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr->qp_access_flags & IB_ACCESS_REMOTE_ATOMIC) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* This should never happen */
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 modify_attr.qp_transport.ud.ud_port = attr->port_num;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.rc.rc_path.cep_hca_port_num =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modify_attr.qp_transport.uc.uc_path.cep_hca_port_num =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* This should never happen */
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 ASSERT(qp->qp_type == IB_QPT_UD || qp->qp_type == IB_QPT_SMI ||
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* This should never happen */
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 /* nothing to do */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_TIMEOUT && qp->qp_type == IB_QPT_RC) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_RETRY_CNT && qp->qp_type == IB_QPT_RC) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_RNR_RETRY && qp->qp_type == IB_QPT_RC) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* nothing to do */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC && qp->qp_type == IB_QPT_RC) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* Sanity checks */
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 if (attr->alt_pkey_index >= hattr.hca_max_port_pkey_tbl_sz) {
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 /* This should never happen */
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 if (attr_mask & IB_QP_MIN_RNR_TIMER && qp->qp_type == IB_QPT_RC) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* This should never happen */
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 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 /* This should never happen */
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 /* IB_QP_CAP is not supported */
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 /* This should never happen */
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 "ib_modify_qp: qp: 0x%p, attr: 0x%p, attr_mask: 0x%x, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "flags: 0x%x, modify_attr: 0x%p",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* Modify the QP attributes */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rtn = ibt_modify_qp(qp->ibt_qp, flags, &modify_attr, NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
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 Otastatic inline enum ib_wc_status
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* Hermon doesn't support EEC yet */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic inline enum ib_wc_opcode
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic inline int
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic inline void
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* opcode can be undefined if status is not success */
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 * 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 * 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 Otaib_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client_t *ofs_client = (ofs_client_t *)cq->device->clnt_hdl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_poll_cq: cq: 0x%p => invalid device state (%d)",
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 /* only one thread per cq is allowed during ibt_poll_cq() */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota for (npolled = 0; npolled < num_entries; ++npolled) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* save this result to struct ib_wc */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ib_poll_cq: cq: 0x%p, num_entries: %d, wc: 0x%p => "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ibt_poll_cq failed w/ %d, npolled = %d",