iWARP Core Support
v5 cover iWARP Core Support
With Seans comments resolved...
I also changed iw_addr_get_dgid() to memcpy the gid like the other functions do.
----
This patchset defines the modifications to the Linux infiniband subsystem to support iWARP devices.
The patchset consists of 2 patches:
1 - New iWARP CM implementation.
2 - Core changes to support iWARP.
PATCH v5 1/2 iWARP Connection Manager.
This patch provides the new files implementing the iWARP Connection Manager.
This module is a logical instance of the xx_cm where xx is the transport type (ib or iw). The symbols exported are used by the transport independent rdma_cm module, and are available also for transport dependent ULPs.
---
drivers/infiniband/core/iwcm.c | 1008 ++++++++++++++++++++++++++++++++++++++++ include/rdma/iw_cm.h | 255 ++++++++++ include/rdma/iw_cm_private.h | 63 +++ 3 files changed, 1326 insertions(+), 0 deletions(-)
drivers/infiniband/core/iwcm.c new file +1008 -0
@@ -0,0 +1,1008 @@ +/* +* Copyright (c) 2004, 2005 Intel Corporation. All rights reserved. +* Copyright (c) 2004 Topspin Corporation. All rights reserved. +* Copyright (c) 2004, 2005 Voltaire Corporation. All rights reserved. +* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. +* Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. +* Copyright (c) 2005 Network Appliance, Inc. All rights reserved. +* +* This software is available to you under a choice of one of two +* licenses. You may choose to be licensed under the terms of the GNU +* General Public License (GPL) Version 2, available from the file +* COPYING in the main directory of this source tree, or the +* OpenIB.org BSD license below: +* +* Redistribution and use in source and binary forms, with or +* without modification, are permitted provided that the following +* conditions are met: +* +* - Redistributions of source code must retain the above +* copyright notice, this list of conditions and the following +* disclaimer. +* +* - Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +*/ +#include <linux/dma-mapping.h> +#include <linux/err.h> +#include <linux/idr.h> +#include <linux/interrupt.h> +#include <linux/pci.h> +#include <linux/rbtree.h> +#include <linux/spinlock.h> +#include <linux/workqueue.h> +#include <linux/completion.h> +#include <rdma/iw_cm.h> +#include <rdma/iw_cm_private.h> +#include <rdma/ib_addr.h> + +MODULE_AUTHOR ("Tom Tucker" ); +MODULE_DESCRIPTION ("iWARP CM" ); +MODULE_LICENSE ("Dual BSD/GPL" ); + +static struct workqueue_struct *iwcm_wq; +struct iwcm_work { +struct work_struct work; +struct iwcm_id_private *cm_id; +struct list_head list; +struct iw_cm_event event; +struct list_head free_list; +}; + +/* +* The following services provide a mechanism for pre-allocating iwcm_work +* elements. The design pre-allocates them based on the cm_id type: +* LISTENING IDS: Get enough elements preallocated to handle the +* listen backlog. +* ACTIVE IDS: 4: CONNECT_REPLY, ESTABLISHED, DISCONNECT, CLOSE +* PASSIVE IDS: 3: ESTABLISHED, DISCONNECT, CLOSE +* +* Allocating them in connect and listen avoids having to deal +* with allocation failures on the event upcall from the provider (which +* is called in the interrupt context). +* +* One exception is when creating the cm_id for incoming connection requests. +* There are two cases: +* 1) in the event upcall, cm_event_handler(), for a listening cm_id. If +* the backlog is exceeded, then no more connection request events will +* be processed. cm_event_handler() returns -ENOMEM in this case. Its up +* to the provider to reject the connectino request. +* 2) in the connection request workqueue handler, cm_conn_req_handler(). +* If work elements cannot be allocated for the new connect request cm_id, +* then IWCM will call the provider reject method. This is ok since +* cm_conn_req_handler() runs in the workqueue thread context. +*/ + +static struct iwcm_work *get_work (struct iwcm_id_private *cm_id_priv) +{ +struct iwcm_work *work; + +if (list_empty (&cm_id_priv->work_free_list)) +return NULL ; + work = list_entry(cm_id_priv->work_free_list.next, struct iwcm_work, + free_list); +list_del_init (&work->free_list); +return work; +} + +static void put_work (struct iwcm_work *work) +{ +list_add (&work->free_list, &work->cm_id->work_free_list); +} + +static void dealloc_work_entries (struct iwcm_id_private *cm_id_priv) +{ +struct list_head *e, *tmp; + +list_for_each_safe (e, tmp, &cm_id_priv->work_free_list) + kfree(list_entry(e, struct iwcm_work, free_list)); +} + +static int alloc_work_entries (struct iwcm_id_private *cm_id_priv,int count) +{ +struct iwcm_work *work; + +BUG_ON (!list_empty (&cm_id_priv->work_free_list)); +while (count--) { + work =kmalloc (sizeof (struct iwcm_work ),GFP_KERNEL ); +if (!work) { +dealloc_work_entries (cm_id_priv); +return -ENOMEM ; + } + work->cm_id = cm_id_priv; +INIT_LIST_HEAD (&work->list); +put_work (work); + } +return 0 ; +} + +/* +* Save private data from incoming connection requests in the +* cm_id_priv so the low level driver doesn't have to. Adjust +* the event ptr to point to the local copy. +*/ +static int copy_private_data (struct iwcm_id_private *cm_id_priv, +struct iw_cm_event *event) +{ +void *p; + + p =kmalloc (event->private_data_len,GFP_ATOMIC ); +if (!p) +return -ENOMEM ; +memcpy (p, event->private_data, event->private_data_len); + event->private_data = p; +return 0 ; +} + +/* +* Release a reference on cm_id. If the last reference is being removed +* and iw_destroy_cm_id is waiting, wake up the waiting thread. +*/ +static int iwcm_deref_id (struct iwcm_id_private *cm_id_priv) +{ +int ret =0 ; + +BUG_ON (atomic_read (&cm_id_priv->refcount)==0 ); +if (atomic_dec_and_test (&cm_id_priv->refcount)) { +BUG_ON (!list_empty (&cm_id_priv->work_list)); +if (waitqueue_active (&cm_id_priv->destroy_comp.wait)) { +BUG_ON (cm_id_priv->state !=IW_CM_STATE_DESTROYING ); +BUG_ON (test_bit (IWCM_F_CALLBACK_DESTROY , + &cm_id_priv->flags)); + ret =1 ; + } +complete (&cm_id_priv->destroy_comp); + } + +return ret; +} + +static void add_ref (struct iw_cm_id *cm_id) +{ +struct iwcm_id_private *cm_id_priv; + cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); +atomic_inc (&cm_id_priv->refcount); +} + +static void rem_ref (struct iw_cm_id *cm_id) +{ +struct iwcm_id_private *cm_id_priv; + cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); +iwcm_deref_id (cm_id_priv); +} + +static int cm_event_handler (struct iw_cm_id *cm_id,struct iw_cm_event *event); + +struct iw_cm_id *iw_create_cm_id (struct ib_device *device, +iw_cm_handler cm_handler, +void *context) +{ +struct iwcm_id_private *cm_id_priv; + + cm_id_priv =kzalloc (sizeof (*cm_id_priv),GFP_KERNEL ); +if (!cm_id_priv) +return ERR_PTR (-ENOMEM ); + + cm_id_priv->state =IW_CM_STATE_IDLE ; + cm_id_priv->id.device = device; + cm_id_priv->id.cm_handler = cm_handler; + cm_id_priv->id.context = context; + cm_id_priv->id.event_handler = cm_event_handler; + cm_id_priv->id.add_ref = add_ref; + cm_id_priv->id.rem_ref = rem_ref; +spin_lock_init (&cm_id_priv->lock); +atomic_set (&cm_id_priv->refcount,1 ); +init_waitqueue_head (&cm_id_priv->connect_wait); +init_completion (&cm_id_priv->destroy_comp); +INIT_LIST_HEAD (&cm_id_priv->work_list); +INIT_LIST_HEAD (&cm_id_priv->work_free_list); + +return &cm_id_priv->id; +} +EXPORT_SYMBOL (iw_create_cm_id); + + +static int iwcm_modify_qp_err (struct ib_qp *qp) +{ +struct ib_qp_attr qp_attr; + +if (!qp) +return -EINVAL ; + + qp_attr.qp_state =IB_QPS_ERR ; +return ib_modify_qp (qp, &qp_attr,IB_QP_STATE ); +} + +/* +* This is really the RDMAC CLOSING state. It is most similar to the +* IB SQD QP state. +*/ +static int iwcm_modify_qp_sqd (struct ib_qp *qp) +{ +struct ib_qp_attr qp_attr; + +BUG_ON (qp ==NULL ); + qp_attr.qp_state =IB_QPS_SQD ; +return ib_modify_qp (qp, &qp_attr,IB_QP_STATE ); +} + +/* +* CM_ID <-- CLOSING +* +* Block if a passive or active connection is currenlty being processed. Then +* process the event as follows: +* - If we are ESTABLISHED, move to CLOSING and modify the QP state +* based on the abrupt flag +* - If the connection is already in the CLOSING or IDLE state, the peer is +* disconnecting concurrently with us and we've already seen the +* DISCONNECT event -- ignore the request and return 0 +* - Disconnect on a listening endpoint returns -EINVAL +*/ +int iw_cm_disconnect (struct iw_cm_id *cm_id,int abrupt) +{ +struct iwcm_id_private *cm_id_priv; +unsigned long flags; +int ret =0 ; +struct ib_qp *qp =NULL ; + + cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); +/* Wait if we're currently in a connect or accept downcall */ +wait_event (cm_id_priv->connect_wait, + !test_bit (IWCM_F_CONNECT_WAIT , &cm_id_priv->flags)); + +spin_lock_irqsave (&cm_id_priv->lock, flags); +switch (cm_id_priv->state) { +case IW_CM_STATE_ESTABLISHED : + cm_id_priv->state =IW_CM_STATE_CLOSING ; + +/* QP could be <nul> for user-mode client */ +if (cm_id_priv->qp) + qp = cm_id_priv->qp; +else + ret = -EINVAL ; +break ; +case IW_CM_STATE_LISTEN : + ret = -EINVAL ; +break ; +case IW_CM_STATE_CLOSING : +/* remote peer closed first */ +case IW_CM_STATE_IDLE : +/* accept or connect returned !0 */ +break ; +case IW_CM_STATE_CONN_RECV : +/* +* App called disconnect before/without calling accept after +* connect_request event delivered. +*/ +break ; +case IW_CM_STATE_CONN_SENT : +/* Can only get here if wait above fails */ +default : +BUG (); + } +spin_unlock_irqrestore (&cm_id_priv->lock, flags); + +if (qp) { +if (abrupt) + ret =iwcm_modify_qp_err (qp); +else + ret =iwcm_modify_qp_sqd (qp); + +/* +* If both sides are disconnecting the QP could +* already be in ERR or SQD states +*/ + ret =0 ; + } + +return ret; +} +EXPORT_SYMBOL (iw_cm_disconnect); + +/* +* CM_ID <-- DESTROYING +* +* Clean up all resources associated with the connection and release +* the initial reference taken by iw_create_cm_id. +*/ +static void destroy_cm_id (struct iw_cm_id *cm_id) +{ +struct iwcm_id_private *cm_id_priv; +unsigned long flags; +int ret; + + cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); +/* Wait if we're currently in a connect or accept downcall. A +* listening endpoint should never block here. */ +wait_event (cm_id_priv->connect_wait, + !test_bit (IWCM_F_CONNECT_WAIT , &cm_id_priv->flags)); + +spin_lock_irqsave (&cm_id_priv->lock, flags); +switch (cm_id_priv->state) { +case IW_CM_STATE_LISTEN : + cm_id_priv->state =IW_CM_STATE_DESTROYING ; +spin_unlock_irqrestore (&cm_id_priv->lock, flags); +/* destroy the listening endpoint */ + ret = cm_id->device->iwcm->destroy_listen (cm_id); +spin_lock_irqsave (&cm_id_priv->lock, flags); +break ; +case IW_CM_STATE_ESTABLISHED : + cm_id_priv->state =IW_CM_STATE_DESTROYING ; +spin_unlock_irqrestore (&cm_id_priv->lock, flags); +/* Abrupt close of the connection */ + (void )iwcm_modify_qp_err (cm_id_priv->qp); +spin_lock_irqsave (&cm_id_priv->lock, flags); +break ; +case IW_CM_STATE_IDLE : +case IW_CM_STATE_CLOSING : + cm_id_priv->state =IW_CM_STATE_DESTROYING ; +break ; +case IW_CM_STATE_CONN_RECV : +/* +* App called destroy before/without calling accept after +* receiving connection request event notification. +*/ + cm_id_priv->state =IW_CM_STATE_DESTROYING ; +break ; +case IW_CM_STATE_CONN_SENT : +case IW_CM_STATE_DESTROYING : +default : +BUG (); +break ; + } +if (cm_id_priv->qp) { + cm_id_priv->id.device->iwcm->rem_ref (cm_id_priv->qp); + cm_id_priv->qp =NULL ; + } +spin_unlock_irqrestore (&cm_id_priv->lock, flags); + + (void )iwcm_deref_id (cm_id_priv); +} + +/* +* This function is only called by the application thread and cannot +* be called by the event thread. The function will wait for all +* references to be released on the cm_id and then kfree the cm_id +* object. +*/ +void iw_destroy_cm_id (struct iw_cm_id *cm_id) +{ +struct iwcm_id_private *cm_id_priv; + + cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); +BUG_ON (test_bit (IWCM_F_CALLBACK_DESTROY , &cm_id_priv->flags)); + +destroy_cm_id (cm_id); + +wait_for_completion (&cm_id_priv->destroy_comp); + +dealloc_work_entries (cm_id_priv); + +kfree (cm_id_priv); +} +EXPORT_SYMBOL (iw_destroy_cm_id); + +/* +* CM_ID <-- LISTEN +* +* Start listening for connect requests. Generates one CONNECT_REQUEST +* event for each inbound connect request. +*/ +int iw_cm_listen (struct iw_cm_id *cm_id,int backlog) +{ +struct iwcm_id_private *cm_id_priv; +unsigned long flags; +int ret =0 ; + + cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); + + ret =alloc_work_entries (cm_id_priv, backlog); +if (ret) +return ret; + +spin_lock_irqsave (&cm_id_priv->lock, flags); +switch (cm_id_priv->state) { +case IW_CM_STATE_IDLE : + cm_id_priv->state =IW_CM_STATE_LISTEN ; +spin_unlock_irqrestore (&cm_id_priv->lock, flags); + ret = cm_id->device->iwcm->create_listen (cm_id, backlog); +if (ret) + cm_id_priv->state =IW_CM_STATE_IDLE ; +spin_lock_irqsave (&cm_id_priv->lock, flags); +break ; +default : + ret = -EINVAL ; + } +spin_unlock_irqrestore (&cm_id_priv->lock, flags); + +return ret; +} +EXPORT_SYMBOL (iw_cm_listen); + +/* +* CM_ID <-- IDLE +* +* Rejects an inbound connection request. No events are generated. +*/ +int iw_cm_reject (struct iw_cm_id *cm_id, +const void *private_data, +u8 private_data_len) +{ +struct iwcm_id_private *cm_id_priv; +unsigned long flags; +int ret; + + cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); +set_bit (IWCM_F_CONNECT_WAIT , &cm_id_priv->flags); + +spin_lock_irqsave (&cm_id_priv->lock, flags); +if (cm_id_priv->state !=IW_CM_STATE_CONN_RECV ) { +spin_unlock_irqrestore (&cm_id_priv->lock, flags); +clear_bit (IWCM_F_CONNECT_WAIT , &cm_id_priv->flags); +wake_up_all (&cm_id_priv->connect_wait); +return -EINVAL ; + } + cm_id_priv->state =IW_CM_STATE_IDLE ; +spin_unlock_irqrestore (&cm_id_priv->lock, flags); + + ret = cm_id->device->iwcm->reject (cm_id, private_data, + private_data_len); + +clear_bit (IWCM_F_CONNECT_WAIT , &cm_id_priv->flags); +wake_up_all (&cm_id_priv->connect_wait); + +return ret; +} +EXPORT_SYMBOL (iw_cm_reject); + +/* +* CM_ID <-- ESTABLISHED +* +* Accepts an inbound connection request and generates an ESTABLISHED +* event. Callers of iw_cm_disconnect and iw_destroy_cm_id will block +* until the ESTABLISHED event is received from the provider. +*/ +int iw_cm_accept (struct iw_cm_id *cm_id, +struct iw_cm_conn_param *iw_param) +{ +struct iwcm_id_private *cm_id_priv; +struct ib_qp *qp; +unsigned long flags; +int ret; + + cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); +set_bit (IWCM_F_CONNECT_WAIT , &cm_id_priv->flags); + +spin_lock_irqsave (&cm_id_priv->lock, flags); +if (cm_id_priv->state !=IW_CM_STATE_CONN_RECV ) { +spin_unlock_irqrestore (&cm_id_priv->lock, flags); +clear_bit (IWCM_F_CONNECT_WAIT , &cm_id_priv->flags); +wake_up_all (&cm_id_priv->connect_wait); +return -EINVAL ; + } +/* Get the ib_qp given the QPN */ + qp = cm_id->device->iwcm->get_qp (cm_id->device, iw_param->qpn); +if (!qp) { +spin_unlock_irqrestore (&cm_id_priv->lock, flags); +return -EINVAL ; + } + cm_id->device->iwcm->add_ref (qp); + cm_id_priv->qp = qp; +spin_unlock_irqrestore (&cm_id_priv->lock, flags); + + ret = cm_id->device->iwcm->accept (cm_id, iw_param); +if (ret) { +/* An error on accept precludes provider events */ +BUG_ON (cm_id_priv->state !=IW_CM_STATE_CONN_RECV ); + cm_id_priv->state =IW_CM_STATE_IDLE ; +spin_lock_irqsave (&cm_id_priv->lock, flags); +if (cm_id_priv->qp) { + cm_id->device->iwcm->rem_ref (qp); + cm_id_priv->qp =NULL ; + } +spin_unlock_irqrestore (&cm_id_priv->lock, flags); +clear_bit (IWCM_F_CONNECT_WAIT , &cm_id_priv->flags); +wake_up_all (&cm_id_priv->connect_wait); + } + +return ret; +} +EXPORT_SYMBOL (iw_cm_accept); + +/* +* Active Side: CM_ID <-- CONN_SENT +* +* If successful, results in the generation of a CONNECT_REPLY +* event. iw_cm_disconnect and iw_cm_destroy will block until the +* CONNECT_REPLY event is received from the provider. +*/ +int iw_cm_connect (struct iw_cm_id *cm_id,struct iw_cm_conn_param *iw_param) +{ +struct iwcm_id_private *cm_id_priv; +int ret =0 ; +unsigned long flags; +struct ib_qp *qp; + + cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); + + ret =alloc_work_entries (cm_id_priv,4 ); +if (ret) +return ret; + +set_bit (IWCM_F_CONNECT_WAIT , &cm_id_priv->flags); +spin_lock_irqsave (&cm_id_priv->lock, flags); + +if (cm_id_priv->state !=IW_CM_STATE_IDLE ) { +spin_unlock_irqrestore (&cm_id_priv->lock, flags); +clear_bit (IWCM_F_CONNECT_WAIT , &cm_id_priv->flags); +wake_up_all (&cm_id_priv->connect_wait); +return -EINVAL ; + } + +/* Get the ib_qp given the QPN */ + qp = cm_id->device->iwcm->get_qp (cm_id->device, iw_param->qpn); +if (!qp) { +spin_unlock_irqrestore (&cm_id_priv->lock, flags); +return -EINVAL ; + } + cm_id->device->iwcm->add_ref (qp); + cm_id_priv->qp = qp; + cm_id_priv->state =IW_CM_STATE_CONN_SENT ; +spin_unlock_irqrestore (&cm_id_priv->lock, flags); + + ret = cm_id->device->iwcm->connect (cm_id, iw_param); +if (ret) { +spin_lock_irqsave (&cm_id_priv->lock, flags); +if (cm_id_priv->qp) { + cm_id->device->iwcm->rem_ref (qp); + cm_id_priv->qp =NULL ; + } +spin_unlock_irqrestore (&cm_id_priv->lock, flags); +BUG_ON (cm_id_priv->state !=IW_CM_STATE_CONN_SENT ); + cm_id_priv->state =IW_CM_STATE_IDLE ; +clear_bit (IWCM_F_CONNECT_WAIT , &cm_id_priv->flags); +wake_up_all (&cm_id_priv->connect_wait); + } + +return ret; +} +EXPORT_SYMBOL (iw_cm_connect); + +/* +* Passive Side: new CM_ID <-- CONN_RECV +* +* Handles an inbound connect request. The function creates a new +* iw_cm_id to represent the new connection and inherits the client +* callback function and other attributes from the listening parent. +* +* The work item contains a pointer to the listen_cm_id and the event. The +* listen_cm_id contains the client cm_handler, context and +* device. These are copied when the device is cloned. The event +* contains the new four tuple. +* +* An error on the child should not affect the parent, so this +* function does not return a value. +*/ +static void cm_conn_req_handler (struct iwcm_id_private *listen_id_priv, +struct iw_cm_event *iw_event) +{ +unsigned long flags; +struct iw_cm_id *cm_id; +struct iwcm_id_private *cm_id_priv; +int ret; + +/* The provider should never generate a connection request +* event with a bad status. +*/ +BUG_ON (iw_event->status); + +/* We could be destroying the listening id. If so, ignore this +* upcall. */ +spin_lock_irqsave (&listen_id_priv->lock, flags); +if (listen_id_priv->state !=IW_CM_STATE_LISTEN ) { +spin_unlock_irqrestore (&listen_id_priv->lock, flags); +return ; + } +spin_unlock_irqrestore (&listen_id_priv->lock, flags); + + cm_id =iw_create_cm_id (listen_id_priv->id.device, + listen_id_priv->id.cm_handler, + listen_id_priv->id.context); +/* If the cm_id could not be created, ignore the request */ +if (IS_ERR (cm_id)) +return ; + + cm_id->provider_data = iw_event->provider_data; + cm_id->local_addr = iw_event->local_addr; + cm_id->remote_addr = iw_event->remote_addr; + + cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); + cm_id_priv->state =IW_CM_STATE_CONN_RECV ; + + ret =alloc_work_entries (cm_id_priv,3 ); +if (ret) { +iw_cm_reject (cm_id,NULL ,0 ); +iw_destroy_cm_id (cm_id); +return ; + } + +/* Call the client CM handler */ + ret = cm_id->cm_handler (cm_id, iw_event); +if (ret) { +set_bit (IWCM_F_CALLBACK_DESTROY , &cm_id_priv->flags); +destroy_cm_id (cm_id); +if (atomic_read (&cm_id_priv->refcount)==0 ) +kfree (cm_id); + } + +if (iw_event->private_data_len) +kfree (iw_event->private_data); +} + +/* +* Passive Side: CM_ID <-- ESTABLISHED +* +* The provider generated an ESTABLISHED event which means that +* the MPA negotion has completed successfully and we are now in MPA +* FPDU mode. +* +* This event can only be received in the CONN_RECV state. If the +* remote peer closed, the ESTABLISHED event would be received followed +* by the CLOSE event. If the app closes, it will block until we wake +* it up after processing this event. +*/ +static int cm_conn_est_handler (struct iwcm_id_private *cm_id_priv, +struct iw_cm_event *iw_event) +{ +unsigned long flags; +int ret =0 ; + +spin_lock_irqsave (&cm_id_priv->lock, flags); + +/* We clear the CONNECT_WAIT bit here to allow the callback +* function to call iw_cm_disconnect. Calling iw_destroy_cm_id +* from a callback handler is not allowed */ +clear_bit (IWCM_F_CONNECT_WAIT , &cm_id_priv->flags); +BUG_ON (cm_id_priv->state !=IW_CM_STATE_CONN_RECV ); + cm_id_priv->state =IW_CM_STATE_ESTABLISHED ; +spin_unlock_irqrestore (&cm_id_priv->lock, flags); + ret = cm_id_priv->id.cm_handler (&cm_id_priv->id, iw_event); +wake_up_all (&cm_id_priv->connect_wait); + +return ret; +} + +/* +* Active Side: CM_ID <-- ESTABLISHED +* +* The app has called connect and is waiting for the established event to +* post it's requests to the server. This event will wake up anyone +* blocked in iw_cm_disconnect or iw_destroy_id. +*/ +static int cm_conn_rep_handler (struct iwcm_id_private *cm_id_priv, +struct iw_cm_event *iw_event) +{ +unsigned long flags; +int ret =0 ; + +spin_lock_irqsave (&cm_id_priv->lock, flags); +/* Clear the connect wait bit so a callback function calling +* iw_cm_disconnect will not wait and deadlock this thread */ +clear_bit (IWCM_F_CONNECT_WAIT , &cm_id_priv->flags); +BUG_ON (cm_id_priv->state !=IW_CM_STATE_CONN_SENT ); +if (iw_event->status ==IW_CM_EVENT_STATUS_ACCEPTED ) { + cm_id_priv->id.local_addr = iw_event->local_addr; + cm_id_priv->id.remote_addr = iw_event->remote_addr; + cm_id_priv->state =IW_CM_STATE_ESTABLISHED ; + }else { +/* REJECTED or RESET */ + cm_id_priv->id.device->iwcm->rem_ref (cm_id_priv->qp); + cm_id_priv->qp =NULL ; + cm_id_priv->state =IW_CM_STATE_IDLE ; + } +spin_unlock_irqrestore (&cm_id_priv->lock, flags); + ret = cm_id_priv->id.cm_handler (&cm_id_priv->id, iw_event); + +if (iw_event->private_data_len) +kfree (iw_event->private_data); + +/* Wake up waiters on connect complete */ +wake_up_all (&cm_id_priv->connect_wait); + +return ret; +} + +/* +* CM_ID <-- CLOSING +* +* If in the ESTABLISHED state, move to CLOSING. +*/ +static void cm_disconnect_handler (struct iwcm_id_private *cm_id_priv, +struct iw_cm_event *iw_event) +{ +unsigned long flags; + +spin_lock_irqsave (&cm_id_priv->lock, flags); +if (cm_id_priv->state ==IW_CM_STATE_ESTABLISHED ) + cm_id_priv->state =IW_CM_STATE_CLOSING ; +spin_unlock_irqrestore (&cm_id_priv->lock, flags); +} + +/* +* CM_ID <-- IDLE +* +* If in the ESTBLISHED or CLOSING states, the QP will have have been +* moved by the provider to the ERR state. Disassociate the CM_ID from +* the QP, move to IDLE, and remove the 'connected' reference. +* +* If in some other state, the cm_id was destroyed asynchronously. +* This is the last reference that will result in waking up +* the app thread blocked in iw_destroy_cm_id. +*/ +static int cm_close_handler (struct iwcm_id_private *cm_id_priv, +struct iw_cm_event *iw_event) +{ +unsigned long flags; +int ret =0 ; +spin_lock_irqsave (&cm_id_priv->lock, flags); + +if (cm_id_priv->qp) { + cm_id_priv->id.device->iwcm->rem_ref (cm_id_priv->qp); + cm_id_priv->qp =NULL ; + } +switch (cm_id_priv->state) { +case IW_CM_STATE_ESTABLISHED : +case IW_CM_STATE_CLOSING : + cm_id_priv->state =IW_CM_STATE_IDLE ; +spin_unlock_irqrestore (&cm_id_priv->lock, flags); + ret = cm_id_priv->id.cm_handler (&cm_id_priv->id, iw_event); +spin_lock_irqsave (&cm_id_priv->lock, flags); +break ; +case IW_CM_STATE_DESTROYING : +break ; +default : +BUG (); + } +spin_unlock_irqrestore (&cm_id_priv->lock, flags); + +return ret; +} + +static int process_event (struct iwcm_id_private *cm_id_priv, +struct iw_cm_event *iw_event) +{ +int ret =0 ; + +switch (iw_event->event) { +case IW_CM_EVENT_CONNECT_REQUEST : +cm_conn_req_handler (cm_id_priv, iw_event); +break ; +case IW_CM_EVENT_CONNECT_REPLY : + ret =cm_conn_rep_handler (cm_id_priv, iw_event); +break ; +case IW_CM_EVENT_ESTABLISHED : + ret =cm_conn_est_handler (cm_id_priv, iw_event); +break ; +case IW_CM_EVENT_DISCONNECT : +cm_disconnect_handler (cm_id_priv, iw_event); +break ; +case IW_CM_EVENT_CLOSE : + ret =cm_close_handler (cm_id_priv, iw_event); +break ; +default : +BUG (); + } + +return ret; +} + +/* +* Process events on the work_list for the cm_id. If the callback +* function requests that the cm_id be deleted, a flag is set in the +* cm_id flags to indicate that when the last reference is +* removed, the cm_id is to be destroyed. This is necessary to +* distinguish between an object that will be destroyed by the app +* thread asleep on the destroy_comp list vs. an object destroyed +* here synchronously when the last reference is removed. +*/ +static void cm_work_handler (void *arg) +{ +struct iwcm_work *work = arg, lwork; +struct iwcm_id_private *cm_id_priv = work->cm_id; +unsigned long flags; +int empty; +int ret =0 ; + +spin_lock_irqsave (&cm_id_priv->lock, flags); + empty =list_empty (&cm_id_priv->work_list); +while (!empty) { + work =list_entry (cm_id_priv->work_list.next, + struct iwcm_work, list); +list_del_init (&work->list); + empty =list_empty (&cm_id_priv->work_list); + lwork = *work; +put_work (work); +spin_unlock_irqrestore (&cm_id_priv->lock, flags); + + ret =process_event (cm_id_priv, &work->event); +if (ret) { +set_bit (IWCM_F_CALLBACK_DESTROY , &cm_id_priv->flags); +destroy_cm_id (&cm_id_priv->id); + } +BUG_ON (atomic_read (&cm_id_priv->refcount)==0 ); +if (iwcm_deref_id (cm_id_priv)) +return ; + +if (atomic_read (&cm_id_priv->refcount)==0 && +test_bit (IWCM_F_CALLBACK_DESTROY , &cm_id_priv->flags)) { +dealloc_work_entries (cm_id_priv); +kfree (cm_id_priv); +return ; + } +spin_lock_irqsave (&cm_id_priv->lock, flags); + } +spin_unlock_irqrestore (&cm_id_priv->lock, flags); +} + +/* +* This function is called on interrupt context. Schedule events on +* the iwcm_wq thread to allow callback functions to downcall into +* the CM and/or block. Events are queued to a per-CM_ID +* work_list. If this is the first event on the work_list, the work +* element is also queued on the iwcm_wq thread. +* +* Each event holds a reference on the cm_id. Until the last posted +* event has been delivered and processed, the cm_id cannot be +* deleted. +* +* Returns: +* 0 - the event was handled. +* -ENOMEM - the event was not handled due to lack of resources. +*/ +static int cm_event_handler (struct iw_cm_id *cm_id, +struct iw_cm_event *iw_event) +{ +struct iwcm_work *work; +struct iwcm_id_private *cm_id_priv; +unsigned long flags; +int ret =0 ; + + cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); + +spin_lock_irqsave (&cm_id_priv->lock, flags); + work =get_work (cm_id_priv); +if (!work) { + ret = -ENOMEM ; + goto out; + } + +INIT_WORK (&work->work, cm_work_handler, work); + work->cm_id = cm_id_priv; + work->event = *iw_event; + +if ((work->event.event ==IW_CM_EVENT_CONNECT_REQUEST || + work->event.event ==IW_CM_EVENT_CONNECT_REPLY ) && + work->event.private_data_len) { + ret =copy_private_data (cm_id_priv, &work->event); +if (ret) { +put_work (work); + goto out; + } + } + +atomic_inc (&cm_id_priv->refcount); +if (list_empty (&cm_id_priv->work_list)) { +list_add_tail (&work->list, &cm_id_priv->work_list); +queue_work (iwcm_wq, &work->work); + }else +list_add_tail (&work->list, &cm_id_priv->work_list); +out: +spin_unlock_irqrestore (&cm_id_priv->lock, flags); +return ret; +} + +static int iwcm_init_qp_init_attr (struct iwcm_id_private *cm_id_priv, +struct ib_qp_attr *qp_attr, +int *qp_attr_mask) +{ +unsigned long flags; +int ret; + +spin_lock_irqsave (&cm_id_priv->lock, flags); +switch (cm_id_priv->state) { +case IW_CM_STATE_IDLE : +case IW_CM_STATE_CONN_SENT : +case IW_CM_STATE_CONN_RECV : +case IW_CM_STATE_ESTABLISHED : + *qp_attr_mask =IB_QP_STATE |IB_QP_ACCESS_FLAGS ; + qp_attr->qp_access_flags =IB_ACCESS_LOCAL_WRITE | +IB_ACCESS_REMOTE_WRITE | +IB_ACCESS_REMOTE_READ ; + ret =0 ; +break ; +default : + ret = -EINVAL ; +break ; + } +spin_unlock_irqrestore (&cm_id_priv->lock, flags); +return ret; +} + +static int iwcm_init_qp_rts_attr (struct iwcm_id_private *cm_id_priv, +struct ib_qp_attr *qp_attr, +int *qp_attr_mask) +{ +unsigned long flags; +int ret; + +spin_lock_irqsave (&cm_id_priv->lock, flags); +switch (cm_id_priv->state) { +case IW_CM_STATE_IDLE : +case IW_CM_STATE_CONN_SENT : +case IW_CM_STATE_CONN_RECV : +case IW_CM_STATE_ESTABLISHED : + *qp_attr_mask =0 ; + ret =0 ; +break ; +default : + ret = -EINVAL ; +break ; + } +spin_unlock_irqrestore (&cm_id_priv->lock, flags); +return ret; +} + +int iw_cm_init_qp_attr (struct iw_cm_id *cm_id, +struct ib_qp_attr *qp_attr, +int *qp_attr_mask) +{ +struct iwcm_id_private *cm_id_priv; +int ret; + + cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); +switch (qp_attr->qp_state) { +case IB_QPS_INIT : +case IB_QPS_RTR : + ret =iwcm_init_qp_init_attr (cm_id_priv, + qp_attr, qp_attr_mask); +break ; +case IB_QPS_RTS : + ret =iwcm_init_qp_rts_attr (cm_id_priv, + qp_attr, qp_attr_mask); +break ; +default : + ret = -EINVAL ; +break ; + } +return ret; +} +EXPORT_SYMBOL (iw_cm_init_qp_attr); + +static int __init iw_cm_init (void ) +{ + iwcm_wq =create_singlethread_workqueue ("iw_cm_wq" ); +if (!iwcm_wq) +return -ENOMEM ; + +return 0 ; +} + +static void __exit iw_cm_cleanup(void) +{ +destroy_workqueue (iwcm_wq); +} + +module_init (iw_cm_init); +module_exit (iw_cm_cleanup);
include/rdma/iw_cm.h new file +255 -0
255 lines not on this page · raw message
include/rdma/iw_cm_private.h new file +63 -0
63 lines not on this page · raw message
Re: [PATCH v5 1/2] iWARP Connection Manager.
OK, getting closer to finishing the merge...
anyway, why is iw_cm_private.h in include/rdma where it is visible everywhere? As far as I can tell drivers/infiniband/core/iwcm.c is the only place it's included. So why not just put this stuff in drivers/infiniband/core/iwcm.h and do
#include "iwcm.h"
Or the file is small enough that maybe it's simpler just to stuff this at the top of iwcm.c and kill the include entirely?
- R.
Quoted 34 lines
include/rdma/iw_cm_private.h new file +31
-0@@ -0,0 +1,63 @@ +#ifndef IW_CM_PRIVATE_H +#define IW_CM_PRIVATE_H + +#include <rdma/iw_cm.h> + +enum iw_cm_state { +IW_CM_STATE_IDLE ,/* unbound, inactive */ +IW_CM_STATE_LISTEN ,/* listen waiting for connect */ +IW_CM_STATE_CONN_RECV ,/* inbound waiting for user accept */ +IW_CM_STATE_CONN_SENT ,/* outbound waiting for peer accept */ +IW_CM_STATE_ESTABLISHED ,/* established */ +IW_CM_STATE_CLOSING ,/* disconnect */ +IW_CM_STATE_DESTROYING /* object being deleted */ +}; + +struct iwcm_id_private { +struct iw_cm_id id; +enum iw_cm_state state; +unsigned long flags; +struct ib_qp *qp; +struct completion destroy_comp; +wait_queue_head_t connect_wait; +struct list_head work_list; +spinlock_t lock; +atomic_t refcount; +struct list_head work_free_list; +}; +#define IWCM_F_CALLBACK_DESTROY 1 +#define IWCM_F_CONNECT_WAIT 2 + +#endif /* IW_CM_PRIVATE_H */
Re: [PATCH v5 1/2] iWARP Connection Manager.
Quoted 6 lines · Roland Dreier
OK, getting closer to finishing the merge...
anyway, why is
iw_cm_private.hininclude/rdmawhere it is visible everywhere? As far as I can telldrivers/infiniband/core/iwcm.cis the only place it's included. So why not just put this stuff indrivers/infiniband/core/iwcm.hand do
The data structures really belong in iwcm.c...but I have a KDB module that dumps IB data structures. So when I was writing the IWCM, I pulled them out where I could see them without include gymnastics. It seems pretty dumb though to have header files called *private.h in a public directory. Putting them in iwcm.h is fine with me...
Here's a patch for the KDB code if anyone is interested...
KDB module for dumping OpenFabrics stack data types
From: Tom Tucker <[email protected]>
---
kdb/kdbmain.c | 2 kdb/modules/Makefile | 3 kdb/modules/kdbm_openfabrics.c | 372 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 375 insertions(+), 2 deletions(-)
kdb/kdbmain.c +1 -1
@@ -1154,8 +1154,8 @@ kdb_quiet(int reason)* none */ +void kdba_cpu_up (void ) {};extern char kdb_prompt_str[]; - static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs,
kdb_dbtrap_t db_result)
{
kdb/modules/Makefile +0 -1
@@ -6,7 +6,8 @@ # # Copyright (c) 1999-2006 Silicon Graphics, Inc. All Rights Reserved. # -obj-$(CONFIG_KDB_MODULES) += kdbm_pg.o kdbm_task.o kdbm_vm.o
kdbm_sched.o
+obj-$(CONFIG_KDB_MODULES) += kdbm_pg.o kdbm_task.o kdbm_vm.o kdbm_sched.o \
+ kdbm_openfabrics.o
ifdef CONFIG_X86
ifndef CONFIG_X86_64
obj-$(CONFIG_KDB_MODULES) += kdbm_x86.o
(quoted diff) +0 -0
b/kdb/modules/kdbm_openfabrics.c
new file mode 100644
index 0000000..fdf204b
kdb/modules/kdbm_openfabrics.c new file +98 -0
98 lines not on this page · raw message
wc_status_to_str(wc.status));
+ kdb_printf(" opcode : %s\n", wc_opcode_to_str(wc.opcode));
+ kdb_printf(" vendor_err : %d\n", wc.vendor_err);
+ kdb_printf(" byte_len : %d\n", wc.byte_len);
+ kdb_printf(" imm_data : %d\n", wc.imm_data);
+ kdb_printf(" qp_num : %d\n", wc.qp_num);
+ kdb_printf(" src_qp : %d\n", wc.src_qp);
+ kdb_printf(" wc_flags : %x\n", wc.wc_flags);
+ kdb_printf(" pkey_index : %d\n", wc.pkey_index);
+ kdb_printf(" slid : %d\n", wc.slid);
+ kdb_printf(" sl : %d\n", wc.sl);
+ kdb_printf(" dlid_path_bits : %d\n", wc.dlid_path_bits);
+ kdb_printf(" port_num : %d\n", wc.port_num);+ } else {
+ /* More than one arg */
+ kdb_printf("Specify address of ib_wc to dump\n");
+ return KDB_ARGCOUNT;
+ }
+ return ret;
+}
+
+static kdb_machreg_t sge_addr;
+static kdb_machreg_t addr;
+static int sge_no;
+
+static int
+print_ib_sge(int argc, const char **argv, const char **envp,
+ struct pt_regs *regs)
+{
+ int ret = 0;
+ struct ib_sge sge;
+
+ if (argc == 1) {
+ int nextarg = 1;
+ long offset = 0;
+
+ sge_no = 0;
+ ret = kdbgetaddrarg(argc, argv, &nextarg, &sge_addr,
+ &offset, NULL, regs);
+ if (ret)
+ return ret;
+
+ ret = kdb_getarea_size((void*)&sge, (unsigned long)sge_addr,
+ sizeof(struct ib_sge));
+ if (ret)
+ return ret;
+
+ }
+ kdb_printf("sge[%d].addr : %llx\n", sge_no, sge.addr);
+ kdb_printf("sge[%d].length : %d\n", sge_no, sge.length);
+ kdb_printf("sge[%d].lkey : %08x\n", sge_no, sge.lkey);
+ sge_no += 1;
+ sge_addr = (kdb_machreg_t)
+ ((unsigned long)sge_addr + sizeof(struct ib_sge));
+ return ret;
+}
+
+static const char *iwcm_state_str[] = {
+ "IW_CM_STATE_IDLE",
+ "IW_CM_STATE_LISTEN",
+ "IW_CM_STATE_CONN_RECV",
+ "IW_CM_STATE_CONN_SENT",
+ "IW_CM_STATE_ESTABLISHED",
+ "IW_CM_STATE_CLOSING",
+ "IW_CM_STATE_DESTROYING"
+};
+
+static inline const char *to_iwcm_state_str(int state) +{
+ if (state < 0 ||
+ state > sizeof(iwcm_state_str)/sizeof(iwcm_state_str[0]))
+ return "<invalid state>";
+
+
+ return iwcm_state_str[state];
+}
+
+static int
+print_iw_cm_id(int argc, const char **argv, const char **envp,
+ struct pt_regs *regs)
+{
+ int ret = 0;
+ struct iwcm_id_private id;
+ struct sockaddr_in *sin;
+
+ if (argc == 1) {
+ int nextarg = 1;
+ long offset = 0;
+
+ ret = kdbgetaddrarg(argc, argv, &nextarg, &addr,
+ &offset, NULL, regs);
+ if (ret)
+ return ret;
+
+ ret = kdb_getarea_size((void*)&id, (unsigned long)addr,
+ sizeof(struct iwcm_id_private));
+ if (ret)
+ return ret;
+ }
+ kdb_printf("iw_cm_handler : %p\n", id.id.cm_handler);
+ kdb_printf("context : %p\n", id.id.context);
+ sin = (struct sockaddr_in*)&id.id.local_addr;
+ kdb_printf("local_addr : %d.%d.%d.%d\n",
+ NIPQUAD(sin->sin_addr.s_addr));
+ sin = (struct sockaddr_in*)&id.id.remote_addr;
+ kdb_printf("remote_addr : %d.%d.%d.%d\n",
+ NIPQUAD(sin->sin_addr.s_addr));
+ kdb_printf("provider_data : %p\n", id.id.provider_data);
+ kdb_printf("event_handler : %p\n", id.id.event_handler);
+ kdb_printf("state : %s\n", to_iwcm_state_str(id.state));
+ kdb_printf("flags : %lx\n", id.flags);
+ kdb_printf("qp : %p\n", id.qp);
+ kdb_printf("refcount : %d\n", atomic_read(&id.refcount));+
+ return ret;
+}
+
+
+static int
+print_ib_cq(int argc, const char **argv, const char **envp,
+ struct pt_regs *regs)
+{
+ int ret = 0;
+ struct ib_cq cq;
+
+ if (argc == 1) {
+ int nextarg = 1;
+ long offset = 0;
+
+ ret = kdbgetaddrarg(argc, argv, &nextarg, &addr,
+ &offset, NULL, regs);
+ if (ret)
+ return ret;
+
+ ret = kdb_getarea_size((void*)&cq, (unsigned long)addr,
+ sizeof(struct ib_cq));
+ if (ret)
+ return ret;
+ }
+
+ kdb_printf("Completion Queue\n"
+ "----------------------------------------\n");
+ kdb_printf("device : %p\n",cq.device);
+ kdb_printf("uobject : %p\n",cq.uobject);
+ kdb_printf("comp_handler : %p\n",cq.comp_handler);
+ kdb_printf("event_handler : %p\n",cq.event_handler);
+ kdb_printf("cq_context : %p\n",cq.cq_context);
+ kdb_printf("cqe : %d\n",cq.cqe);
+ kdb_printf("usecnt : %d\n",atomic_read(&cq.usecnt));
+
+ return ret;
+}
+
+static const char *qp_type_str[] = {
+ "IB_QPT_SMI",
+ "IB_QPT_GSI",
+ "IB_QPT_RC",
+ "IB_QPT_UC",
+ "IB_QPT_UD",
+ "IB_QPT_RAW_IPV6",
+ "IB_QPT_RAW_ETY"
+};
+
+static inline const char *qp_type_to_str(int state) +{
+ if (state < 0 ||
+ state >= sizeof(qp_type_str)/sizeof(qp_type_str[0]))
+ return "<invalid type>";
+
+ return qp_type_str[state];
+}
+
+static int
+print_ib_qp(int argc, const char **argv, const char **envp,
+ struct pt_regs *regs)
+{
+ int ret = 0;
+ struct ib_qp qp;
+
+ if (argc == 1) {
+ int nextarg = 1;
+ long offset = 0;
+
+ ret = kdbgetaddrarg(argc, argv, &nextarg, &addr,
+ &offset, NULL, regs);
+ if (ret)
+ return ret;
+
+ ret = kdb_getarea_size((void*)&qp, (unsigned long)addr,
+ sizeof(struct ib_qp));
+ if (ret)
+ return ret;
+ }
+
+ kdb_printf("Queueu Pair\n"
+ "----------------------------------------\n");
+ kdb_printf("device : %p\n",qp.device);
+ kdb_printf("pd : %p\n",qp.pd);
+ kdb_printf("send_cq : %p\n",qp.send_cq);
+ kdb_printf("recv_cq : %p\n",qp.recv_cq);
+ kdb_printf("srq : %p\n",qp.srq);
+ kdb_printf("uobject : %p\n",qp.uobject);
+ kdb_printf("event_handler : %p\n",qp.event_handler);
+ kdb_printf("qp_context : %p\n",qp.qp_context);
+ kdb_printf("qp_num : %d\n",qp.qp_num);
+ kdb_printf("qp_type : %s\n",qp_type_to_str(qp.qp_type));
+
+ return ret;
+}
+
+static int
+print_ib_mr(int argc, const char **argv, const char **envp,
+ struct pt_regs *regs)
+{
+ int ret = 0;
+ struct ib_mr mr;
+
+ if (argc == 1) {
+ int nextarg = 1;
+ long offset = 0;
+
+ ret = kdbgetaddrarg(argc, argv, &nextarg, &addr,
+ &offset, NULL, regs);
+ if (ret)
+ return ret;
+
+ ret = kdb_getarea_size((void*)&mr, (unsigned long)addr,
+ sizeof(struct ib_mr));
+ if (ret)
+ return ret;
+ }
+
+ kdb_printf("Memory Region\n"
+ "----------------------------------------\n");
+ kdb_printf("device : %p\n", mr.device);
+ kdb_printf("pd : %p\n", mr.pd);
+ kdb_printf("uobject : %p\n", mr.uobject);
+ kdb_printf("lkey : %08x\n", mr.lkey);
+ kdb_printf("rkey : %08x\n", mr.rkey);
+ kdb_printf("usecnt : %d\n", atomic_read(&mr.usecnt));
+
+ return ret;
+}
+
+static int __init rdma_init(void)
+{
+ kdb_register("ib_wc",
+ print_ib_wc, "<*ib_wc>",
+ "Display the specified IB Work Completion", 0);
+ kdb_register("ib_sge",
+ print_ib_sge, "<*ib_sge>",
+ "Display the specified IB Scatter Gather Entry", 0);
+ kdb_register("ib_qp",
+ print_ib_qp, "<*ib_qp>",
+ "Display the specified IB Queue Pair", 0);
+ kdb_register("ib_cq",
+ print_ib_cq, "<*ib_cq>",
+ "Display the specified IB Completion Queue", 0);
+ kdb_register("ib_mr",
+ print_ib_mr, "<*ib_mr>",
+ "Display the specified IB Memory Region", 0);
+ kdb_register("iw_cm_id",
+ print_iw_cm_id, "<*iw_cm_id>",
+ "Display the specified IW CM ID", 0);
+ return 0;
+}
+
+static void __exit rdma_exit(void)
+{
+ kdb_unregister("ib_wc");
+ kdb_unregister("ib_sge");
+}
+
+module_init(rdma_init)
+module_exit(rdma_exit)
Quoted 46 lines
#include "iwcm.h"Or the file is small enough that maybe it's simpler just to stuff this at the top of
iwcm.cand kill the include entirely?- R.
Quoted 24 lines
include/rdma/iw_cm_private.h new file +21
-0@@ -0,0 +1,63 @@ +#ifndef IW_CM_PRIVATE_H +#define IW_CM_PRIVATE_H + +#include <rdma/iw_cm.h> + +enum iw_cm_state { + IW_CM_STATE_IDLE, /* unbound, inactive */ + IW_CM_STATE_LISTEN, /* listen waiting for connect */ + IW_CM_STATE_CONN_RECV, /* inbound waiting for user accept */ + IW_CM_STATE_CONN_SENT, /* outbound waiting for peer accept */ + IW_CM_STATE_ESTABLISHED, /* established */ + IW_CM_STATE_CLOSING, /* disconnect */ + IW_CM_STATE_DESTROYING /* object being deleted */ +}; + +struct iwcm_id_private { + struct iw_cm_id id; + enum iw_cm_state state; + unsigned long flags; + struct ib_qp *qp; + struct completion destroy_comp;include/rdma/iw_cm_private.h line 31
Quoted 10 lines
include/rdma/iw_cm_private.h new file +10
-0+wait_queue_head_t connect_wait; +struct list_head work_list; +spinlock_t lock; +atomic_t refcount; + struct list_head work_free_list; +}; +#define IWCM_F_CALLBACK_DESTROY 1 +#define IWCM_F_CONNECT_WAIT 2 + +#endif /* IW_CM_PRIVATE_H */ -
To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v5 2/2 iWARP Core Changes.
In reply to Steve WiseModifications to the existing rdma header files, core files, drivers, and ulp files to support iWARP.
---
drivers/infiniband/core/Makefile | 4 drivers/infiniband/core/addr.c | 18 + drivers/infiniband/core/cache.c | 7 - drivers/infiniband/core/cm.c | 3 drivers/infiniband/core/cma.c | 355 +++++++++++++++++++++++--- drivers/infiniband/core/device.c | 6 drivers/infiniband/core/mad.c | 11 + drivers/infiniband/core/sa_query.c | 5 drivers/infiniband/core/smi.c | 18 + drivers/infiniband/core/sysfs.c | 18 + drivers/infiniband/core/ucm.c | 5 drivers/infiniband/core/user_mad.c | 9 - drivers/infiniband/hw/ipath/ipath_verbs.c | 2 drivers/infiniband/hw/mthca/mthca_provider.c | 2 drivers/infiniband/ulp/ipoib/ipoib_main.c | 8 + drivers/infiniband/ulp/srp/ib_srp.c | 2 include/rdma/ib_addr.h | 17 + include/rdma/ib_verbs.h | 39 ++- 18 files changed, 439 insertions(+), 90 deletions(-)
drivers/infiniband/core/Makefile +3 -1
@@ -1,7 +1,7 @@ infiniband-$(CONFIG_INFINIBAND_ADDR_TRANS) := ib_addr.o rdma_cm.o obj-$(CONFIG_INFINIBAND) += ib_core.o ib_mad.o ib_sa.o \ - ib_cm.o $(infiniband-y) + ib_cm.o iw_cm.o $(infiniband-y) obj-$(CONFIG_INFINIBAND_USER_MAD) += ib_umad.o obj-$(CONFIG_INFINIBAND_USER_ACCESS) += ib_uverbs.o ib_ucm.o
@@ -14,6 +14,8 @@ ib_sa-y := sa_query.o ib_cm-y := cm.o +iw_cm-y := iwcm.o + rdma_cm-y := cma.o ib_addr-y := addr.o
drivers/infiniband/core/addr.c +11 -7
@@ -60,12 +60,15 @@ static LIST_HEAD(req_list); static DECLARE_WORK(work, process_req, NULL);static struct workqueue_struct *addr_wq; -static int copy_addr (struct rdma_dev_addr *dev_addr,struct net_device *dev, -unsigned char *dst_dev_addr) +int rdma_copy_addr (struct rdma_dev_addr *dev_addr,struct net_device *dev, +const unsigned char *dst_dev_addr) {switch (dev->type) {case ARPHRD_INFINIBAND : - dev_addr->dev_type =IB_NODE_CA ; + dev_addr->dev_type =RDMA_NODE_IB_CA ; +break ; +case ARPHRD_ETHER : + dev_addr->dev_type =RDMA_NODE_RNIC ;break ;default :return -EADDRNOTAVAIL ;
@@ -77,6 +80,7 @@ static int copy_addr(struct rdma_dev_addmemcpy (dev_addr->dst_dev_addr, dst_dev_addr,MAX_ADDR_LEN );return 0 ; } +EXPORT_SYMBOL (rdma_copy_addr);int rdma_translate_ip (struct sockaddr *addr,struct rdma_dev_addr *dev_addr) {
@@ -88,7 +92,7 @@ int rdma_translate_ip(struct sockaddr *aif (!dev)return -EADDRNOTAVAIL ; - ret =copy_addr (dev_addr, dev,NULL ); + ret =rdma_copy_addr (dev_addr, dev,NULL );dev_put (dev);return ret; }
@@ -160,7 +164,7 @@ static int addr_resolve_remote(struct so/* If the device does ARP internally, return 'done' */ if (rt->idev->dev->flags &IFF_NOARP ) { -copy_addr (addr, rt->idev->dev,NULL ); +rdma_copy_addr (addr, rt->idev->dev,NULL ); goto put; }
@@ -180,7 +184,7 @@ static int addr_resolve_remote(struct so src_in->sin_addr.s_addr = rt->rt_src; } - ret =copy_addr (addr, neigh->dev, neigh->ha); + ret =rdma_copy_addr (addr, neigh->dev, neigh->ha); release:neigh_release (neigh); put:
@@ -244,7 +248,7 @@ static int addr_resolve_local(struct socif (ZERONET (src_ip)) { src_in->sin_family = dst_in->sin_family; src_in->sin_addr.s_addr = dst_ip; - ret =copy_addr (addr, dev, dev->dev_addr); + ret =rdma_copy_addr (addr, dev, dev->dev_addr); }else if (LOOPBACK (src_ip)) { ret =rdma_translate_ip ((struct sockaddr *)dst_in, addr);if (!ret)
drivers/infiniband/core/cache.c +4 -3
@@ -32,7 +32,7 @@* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * -* $Id: cache.c 1349 2004-12-16 21:09:43Z roland $ +* $Id: cache.c 6885 2006-05-03 18:22:02Z sean.hefty $ */ #include <linux/module.h>
@@ -62,12 +62,13 @@ struct ib_update_work {static inline int start_port (struct ib_device *device) { -return device->node_type ==IB_NODE_SWITCH ?0 :1 ; +return (device->node_type ==RDMA_NODE_IB_SWITCH ) ?0 :1 ; }static inline int end_port (struct ib_device *device) { -return device->node_type ==IB_NODE_SWITCH ?0 : device->phys_port_cnt; +return (device->node_type ==RDMA_NODE_IB_SWITCH ) ? +0 : device->phys_port_cnt; } int ib_get_cached_gid(struct ib_device *device,
drivers/infiniband/core/cm.c +3 -0
@@ -3260,6 +3260,9 @@ static void cm_add_one(struct ib_deviceint ret;u8 i; +if (rdma_node_get_transport (device->node_type) !=RDMA_TRANSPORT_IB ) +return ; + cm_dev =kmalloc (sizeof (*cm_dev) +sizeof (*port) * device->phys_port_cnt,GFP_KERNEL );if (!cm_dev)
drivers/infiniband/core/cma.c +314 -41
538 lines not on this page · raw message
drivers/infiniband/core/device.c +3 -3
@@ -30,7 +30,7 @@* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * -* $Id: device.c 1349 2004-12-16 21:09:43Z roland $ +* $Id: device.c 5943 2006-03-22 00:58:04Z roland $ */ #include <linux/module.h>
@@ -505,7 +505,7 @@ int ib_query_port(struct ib_device *devi u8 port_num, struct ib_port_attr *port_attr) { -if (device->node_type ==IB_NODE_SWITCH ) { +if (device->node_type ==RDMA_NODE_IB_SWITCH ) {if (port_num)return -EINVAL ; }else if (port_num <1 || port_num > device->phys_port_cnt)
@@ -580,7 +580,7 @@ int ib_modify_port(struct ib_device *dev u8 port_num, int port_modify_mask, struct ib_port_modify *port_modify) { - if (device->node_type == IB_NODE_SWITCH) { + if (device->node_type == RDMA_NODE_IB_SWITCH) { if (port_num) return -EINVAL; } else if (port_num < 1 || port_num > device->phys_port_cnt)
drivers/infiniband/core/mad.c +7 -4
@@ -1,5 +1,5 @@/* -* Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved. +* Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. * Copyright (c) 2005 Intel Corporation. All rights reserved. * Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved. *
@@ -31,7 +31,7 @@* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * -* $Id: mad.c 5596 2006-03-03 01:00:07Z sean.hefty $ +* $Id: mad.c 7294 2006-05-17 18:12:30Z roland $ */ #include <linux/dma-mapping.h> #include <rdma/ib_cache.h>
@@ -2876,7 +2876,10 @@ static void ib_mad_init_device(struct ib {int start, end, i; -if (device->node_type ==IB_NODE_SWITCH ) { +if (rdma_node_get_transport (device->node_type) !=RDMA_TRANSPORT_IB ) +return ; + +if (device->node_type ==RDMA_NODE_IB_SWITCH ) { start =0 ; end =0 ; }else {
@@ -2923,7 +2926,7 @@ static void ib_mad_remove_device(struct {int i, num_ports, cur_port; -if (device->node_type ==IB_NODE_SWITCH ) { +if (device->node_type ==RDMA_NODE_IB_SWITCH ) { num_ports =1 ; cur_port =0 ; }else {
drivers/infiniband/core/sa_query.c +4 -1
@@ -918,7 +918,10 @@ static void ib_sa_add_one(struct ib_devistruct ib_sa_device *sa_dev;int s, e, i; -if (device->node_type ==IB_NODE_SWITCH ) +if (rdma_node_get_transport (device->node_type) !=RDMA_TRANSPORT_IB ) +return ; + +if (device->node_type ==RDMA_NODE_IB_SWITCH ) s = e =0 ;else { s =1 ;
drivers/infiniband/core/smi.c +9 -9
@@ -34,7 +34,7 @@* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * -* $Id: smi.c 1389 2004-12-27 22:56:47Z roland $ +* $Id: smi.c 5258 2006-02-01 20:32:40Z sean.hefty $ */ #include <rdma/ib_smi.h>
@@ -64,7 +64,7 @@ int smi_handle_dr_smp_send(struct ib_smp/* C14-9:2 */ if (hop_ptr && hop_ptr < hop_cnt) { -if (node_type !=IB_NODE_SWITCH ) +if (node_type !=RDMA_NODE_IB_SWITCH )return 0 ;/* smp->return_path set when received */
@@ -77,7 +77,7 @@ int smi_handle_dr_smp_send(struct ib_smpif (hop_ptr == hop_cnt) {/* smp->return_path set when received */ smp->hop_ptr++; -return (node_type ==IB_NODE_SWITCH || +return (node_type ==RDMA_NODE_IB_SWITCH || smp->dr_dlid ==IB_LID_PERMISSIVE ); }
@@ -95,7 +95,7 @@ int smi_handle_dr_smp_send(struct ib_smp/* C14-13:2 */ if (2 <= hop_ptr && hop_ptr <= hop_cnt) { -if (node_type !=IB_NODE_SWITCH ) +if (node_type !=RDMA_NODE_IB_SWITCH )return 0 ; smp->hop_ptr--;
@@ -107,7 +107,7 @@ int smi_handle_dr_smp_send(struct ib_smpif (hop_ptr ==1 ) { smp->hop_ptr--;/* C14-13:3 -- SMPs destined for SM shouldn't be here */ -return (node_type ==IB_NODE_SWITCH || +return (node_type ==RDMA_NODE_IB_SWITCH || smp->dr_slid ==IB_LID_PERMISSIVE ); }
@@ -142,7 +142,7 @@ int smi_handle_dr_smp_recv(struct ib_smp/* C14-9:2 -- intermediate hop */ if (hop_ptr && hop_ptr < hop_cnt) { -if (node_type !=IB_NODE_SWITCH ) +if (node_type !=RDMA_NODE_IB_SWITCH )return 0 ; smp->return_path[hop_ptr] = port_num;
@@ -156,7 +156,7 @@ int smi_handle_dr_smp_recv(struct ib_smp smp->return_path[hop_ptr] = port_num;/* smp->hop_ptr updated when sending */ -return (node_type ==IB_NODE_SWITCH || +return (node_type ==RDMA_NODE_IB_SWITCH || smp->dr_dlid ==IB_LID_PERMISSIVE ); }
@@ -175,7 +175,7 @@ int smi_handle_dr_smp_recv(struct ib_smp/* C14-13:2 */ if (2 <= hop_ptr && hop_ptr <= hop_cnt) { -if (node_type !=IB_NODE_SWITCH ) +if (node_type !=RDMA_NODE_IB_SWITCH )return 0 ;/* smp->hop_ptr updated when sending */
@@ -190,7 +190,7 @@ int smi_handle_dr_smp_recv(struct ib_smpreturn 1 ; }/* smp->hop_ptr updated when sending */ -return (node_type ==IB_NODE_SWITCH ); +return (node_type ==RDMA_NODE_IB_SWITCH ); }/* C14-13:4 -- hop_ptr = 0 -> give to SM */
drivers/infiniband/core/sysfs.c +12 -6
@@ -31,7 +31,7 @@* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * -* $Id: sysfs.c 1349 2004-12-16 21:09:43Z roland $ +* $Id: sysfs.c 6940 2006-05-04 17:04:55Z roland $ */ #include "core_priv.h"
@@ -589,10 +589,16 @@ static ssize_t show_node_type(struct clareturn -ENODEV ;switch (dev->node_type) { -case IB_NODE_CA :return sprintf (buf,"%d: CA\n" , dev->node_type); -case IB_NODE_SWITCH :return sprintf (buf,"%d: switch\n" , dev->node_type); -case IB_NODE_ROUTER :return sprintf (buf,"%d: router\n" , dev->node_type); -default :return sprintf (buf,"%d: <unknown>\n" , dev->node_type); +case RDMA_NODE_IB_CA : +return sprintf (buf,"%d: CA\n" , dev->node_type); +case RDMA_NODE_RNIC : +return sprintf (buf,"%d: RNIC\n" , dev->node_type); +case RDMA_NODE_IB_SWITCH : +return sprintf (buf,"%d: switch\n" , dev->node_type); +case RDMA_NODE_IB_ROUTER : +return sprintf (buf,"%d: router\n" , dev->node_type); +default : +return sprintf (buf,"%d: <unknown>\n" , dev->node_type); } }
@@ -708,7 +714,7 @@ int ib_device_register_sysfs(struct ib_dif (ret) goto err_put; -if (device->node_type ==IB_NODE_SWITCH ) { +if (device->node_type ==RDMA_NODE_IB_SWITCH ) { ret =add_port (device,0 );if (ret) goto err_put;
drivers/infiniband/core/ucm.c +3 -2
@@ -30,7 +30,7 @@* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * -* $Id: ucm.c 4311 2005-12-05 18:42:01Z sean.hefty $ +* $Id: ucm.c 7119 2006-05-11 16:40:38Z sean.hefty $ */ #include <linux/completion.h>
@@ -1247,7 +1247,8 @@ static void ib_ucm_add_one(struct ib_dev {struct ib_ucm_device *ucm_dev; -if (!device->alloc_ucontext) +if (!device->alloc_ucontext || +rdma_node_get_transport (device->node_type) !=RDMA_TRANSPORT_IB )return ; ucm_dev =kzalloc (sizeof *ucm_dev,GFP_KERNEL );
drivers/infiniband/core/user_mad.c +6 -3
@@ -1,6 +1,6 @@/* * Copyright (c) 2004 Topspin Communications. All rights reserved. -* Copyright (c) 2005 Voltaire, Inc. All rights reserved. +* Copyright (c) 2005-2006 Voltaire, Inc. All rights reserved. * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. * * This software is available to you under a choice of one of two
@@ -31,7 +31,7 @@* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * -* $Id: user_mad.c 5596 2006-03-03 01:00:07Z sean.hefty $ +* $Id: user_mad.c 6041 2006-03-27 21:06:00Z halr $ */ #include <linux/module.h>
@@ -1032,7 +1032,10 @@ static void ib_umad_add_one(struct ib_destruct ib_umad_device *umad_dev;int s, e, i; -if (device->node_type ==IB_NODE_SWITCH ) +if (rdma_node_get_transport (device->node_type) !=RDMA_TRANSPORT_IB ) +return ; + +if (device->node_type ==RDMA_NODE_IB_SWITCH ) s = e =0 ;else { s =1 ;
drivers/infiniband/hw/ipath/ipath_verbs.c +1 -1
@@ -1093,7 +1093,7 @@ static void *ipath_register_ib_device(in (1ull <<IB_USER_VERBS_CMD_QUERY_SRQ ) | (1ull <<IB_USER_VERBS_CMD_DESTROY_SRQ ) | (1ull <<IB_USER_VERBS_CMD_POST_SRQ_RECV ); - dev->node_type =IB_NODE_CA ; + dev->node_type =RDMA_NODE_IB_CA ; dev->phys_port_cnt =1 ; dev->dma_device =ipath_layer_get_device (dd); dev->class_dev.dev = dev->dma_device;
drivers/infiniband/hw/mthca/mthca_provider.c +1 -1
@@ -1292,7 +1292,7 @@ int mthca_register_device(struct mthca_d (1ull <<IB_USER_VERBS_CMD_MODIFY_SRQ ) | (1ull <<IB_USER_VERBS_CMD_QUERY_SRQ ) | (1ull <<IB_USER_VERBS_CMD_DESTROY_SRQ ); - dev->ib_dev.node_type =IB_NODE_CA ; + dev->ib_dev.node_type =RDMA_NODE_IB_CA ; dev->ib_dev.phys_port_cnt = dev->limits.num_ports; dev->ib_dev.dma_device = &dev->pdev->dev; dev->ib_dev.class_dev.dev = &dev->pdev->dev;
drivers/infiniband/ulp/ipoib/ipoib_main.c +7 -1
@@ -1107,13 +1107,16 @@ static void ipoib_add_one(struct ib_devistruct ipoib_dev_priv *priv;int s, e, p; +if (rdma_node_get_transport (device->node_type) !=RDMA_TRANSPORT_IB ) +return ; + dev_list =kmalloc (sizeof *dev_list,GFP_KERNEL );if (!dev_list)return ;INIT_LIST_HEAD (dev_list); -if (device->node_type ==IB_NODE_SWITCH ) { +if (device->node_type ==RDMA_NODE_IB_SWITCH ) { s =0 ; e =0 ; }else {
@@ -1137,6 +1140,9 @@ static void ipoib_remove_one(struct ib_dstruct ipoib_dev_priv *priv, *tmp;struct list_head *dev_list; +if (rdma_node_get_transport (device->node_type) !=RDMA_TRANSPORT_IB ) +return ; + dev_list =ib_get_client_data (device, &ipoib_client);list_for_each_entry_safe (priv, tmp, dev_list, list) {
drivers/infiniband/ulp/srp/ib_srp.c +1 -1
@@ -1880,7 +1880,7 @@ static void srp_add_one(struct ib_deviceif (IS_ERR (srp_dev->fmr_pool)) srp_dev->fmr_pool =NULL ; -if (device->node_type ==IB_NODE_SWITCH ) { +if (device->node_type ==RDMA_NODE_IB_SWITCH ) { s =0 ; e =0 ; }else {
include/rdma/ib_addr.h +16 -1
@@ -40,7 +40,7 @@ struct rdma_dev_addr {unsigned char src_dev_addr[MAX_ADDR_LEN ];unsigned char dst_dev_addr[MAX_ADDR_LEN ];unsigned char broadcast[MAX_ADDR_LEN ]; -enum ib_node_type dev_type; +enum rdma_node_type dev_type; };/**
@@ -72,6 +72,9 @@ int rdma_resolve_ip(struct sockaddr *srcvoid rdma_addr_cancel (struct rdma_dev_addr *addr); +int rdma_copy_addr (struct rdma_dev_addr *dev_addr,struct net_device *dev, +const unsigned char *dst_dev_addr); +static inline int ip_addr_size (struct sockaddr *addr) { return addr->sa_family == AF_INET6 ?
@@ -113,4 +116,16 @@ static inline void ib_addr_set_dgid(stru memcpy(dev_addr->dst_dev_addr + 4, gid, sizeof *gid); } +static inline void iw_addr_get_sgid (struct rdma_dev_addr *dev_addr, +union ib_gid *gid) +{ +memcpy (gid, dev_addr->src_dev_addr,sizeof *gid); +} + +static inline void iw_addr_get_dgid (struct rdma_dev_addr *dev_addr, +union ib_gid *gid) +{ +memcpy (gid, dev_addr->dst_dev_addr,sizeof *gid); +} +#endif /* IB_ADDR_H */
include/rdma/ib_verbs.h +34 -5
@@ -35,7 +35,7 @@* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * -* $Id: ib_verbs.h 1349 2004-12-16 21:09:43Z roland $ +* $Id: ib_verbs.h 6885 2006-05-03 18:22:02Z sean.hefty $ */ #if !defined(IB_VERBS_H )
@@ -56,12 +56,35 @@ union ib_gid { } global; }; -enum ib_node_type { -IB_NODE_CA =1 , -IB_NODE_SWITCH , -IB_NODE_ROUTER +enum rdma_node_type { +/* IB values map to NodeInfo:NodeType. */ +RDMA_NODE_IB_CA =1 , +RDMA_NODE_IB_SWITCH , +RDMA_NODE_IB_ROUTER , +RDMA_NODE_RNIC }; +enum rdma_transport_type { +RDMA_TRANSPORT_IB , +RDMA_TRANSPORT_IWARP +}; + +static inline enum rdma_transport_type +rdma_node_get_transport (enum rdma_node_type node_type) +{ +switch (node_type) { +case RDMA_NODE_IB_CA : +case RDMA_NODE_IB_SWITCH : +case RDMA_NODE_IB_ROUTER : +return RDMA_TRANSPORT_IB ; +case RDMA_NODE_RNIC : +return RDMA_TRANSPORT_IWARP ; +default : +BUG (); +return 0 ; + } +} +enum ib_device_cap_flags {IB_DEVICE_RESIZE_MAX_WR =1 ,IB_DEVICE_BAD_PKEY_CNTR = (1 <<1 ),
@@ -78,6 +101,9 @@ enum ib_device_cap_flags {IB_DEVICE_RC_RNR_NAK_GEN = (1 <<12 ),IB_DEVICE_SRQ_RESIZE = (1 <<13 ),IB_DEVICE_N_NOTIFY_CQ = (1 <<14 ), +IB_DEVICE_ZERO_STAG = (1 <<15 ), +IB_DEVICE_SEND_W_INV = (1 <<16 ), +IB_DEVICE_MEM_WINDOW = (1 <<17 ) }; enum ib_atomic_cap {
@@ -835,6 +861,7 @@ struct ib_cache {u8 *lmc_cache; }; +struct iw_cm_verbs ;struct ib_device {struct device *dma_device;
@@ -851,6 +878,8 @@ struct ib_device {u32 flags; +struct iw_cm_verbs *iwcm; +int (*query_device)(struct ib_device *device,struct ib_device_attr *device_attr); int (*query_port)(struct ib_device *device,
Re: [PATCH v5 2/2] iWARP Core Changes.
While merging this, I uninlined rdma_node_get_transport, since I don't think there's any reason to make it inline:
add/remove: 1/0 grow/shrink: 7/16 up/down: 65/-146 (-81)
function old new deltardma_node_get_transport - 33 +33
rdma_init_qp_attr 96 109 +13 rdma_resolve_route 612 620 +8 cma_add_one 241 245 +4 rdma_create_qp 302 305 +3 cma_rep_recv 94 96 +2 show_pkey 110 111 +1 rdma_reject 122 123 +1 rdma_accept 410 408 -2 cma_cleanup 52 50 -2 cma_acquire_dev 181 179 -2 rdma_connect 767 764 -3 rdma_listen 831 825 -6 rdma_disconnect 151 145 -6 ib_sa_add_one 455 446 -9 ib_mad_init_device 1393 1384 -9 ipoib_remove_one 160 150 -10 ib_ucm_add_one 377 365 -12 cma_destroy_listen 196 184 -12 cma_cancel_operation 258 246 -12 cm_add_one 446 434 -12 ipoib_add_one 766 753 -13 ib_umad_add_one 985 968 -17 rdma_destroy_id 322 303 -19
drivers/infiniband/core/verbs.c +17 -0
@@ -79,6 +79,23 @@ enum ib_rate mult_to_ib_rate(int mult) }EXPORT_SYMBOL (mult_to_ib_rate); +enum rdma_transport_type +rdma_node_get_transport (enum rdma_node_type node_type) +{ +switch (node_type) { +case RDMA_NODE_IB_CA : +case RDMA_NODE_IB_SWITCH : +case RDMA_NODE_IB_ROUTER : +return RDMA_TRANSPORT_IB ; +case RDMA_NODE_RNIC : +return RDMA_TRANSPORT_IWARP ; +default : +BUG (); +return 0 ; + } +} +EXPORT_SYMBOL (rdma_node_get_transport); +/* Protection domains */ struct ib_pd *ib_alloc_pd (struct ib_device *device)
include/rdma/ib_verbs.h +2 -15
@@ -69,21 +69,8 @@ enum rdma_transport_type {RDMA_TRANSPORT_IWARP }; -static inline enum rdma_transport_type -rdma_node_get_transport (enum rdma_node_type node_type) -{ -switch (node_type) { -case RDMA_NODE_IB_CA : -case RDMA_NODE_IB_SWITCH : -case RDMA_NODE_IB_ROUTER : -return RDMA_TRANSPORT_IB ; -case RDMA_NODE_RNIC : -return RDMA_TRANSPORT_IWARP ; -default : -BUG (); -return 0 ; - } -} +enum rdma_transport_type +rdma_node_get_transport(enum rdma_node_type node_type) __attribute_const__;enum ib_device_cap_flags {IB_DEVICE_RESIZE_MAX_WR =1 ,