[Fwd: [openib-general] [PATCH] iWARP Support added to the CMA]
Steve Wise
swise at opengridcomputing.com
Thu Dec 15 13:11:34 PST 2005
Here are some comments on iwcm.c:
iwcm_client struct: You probably want this ib client to be named
something other than "cm". I would suggest you make the IB CM named
"ibcm", and the IW CM named "iwcm".
iw_cm_listen() - nuke the error path printks or make them more
informative.
iw_cm_reject() - you don't need the "goto out" and the out: label.
iw_bind_qp() - this always returns -EINVAL??? Should probably always
return 0.
iw_cm_disconnect() - should there be a lock around setting the cm_id
state here?
cm_disconnect_handler() - if the upcall to the client CM fails, do you
really need to set state to IDLE? It should already be IDLE, right? Or
am I confused?
On Thu, 2005-12-15 at 12:00 -0600, Tom Tucker wrote:
> FYI, a patch to support iWARP in the CMA has been posted to OpenIB for
> review. The code is also checked into the iWARP branch in svn.
>
> -------- Forwarded Message --------
> From: Tom Tucker <tom at opengridcomputing.com>
> To: openib-general at openib.org
> Subject: [openib-general] [PATCH] iWARP Support added to the CMA
> Date: Thu, 15 Dec 2005 11:55:36 -0600
> This is a patch to the iWARP branch that adds:
>
> - A generic iWARP transport CM module
> - Support for iWARP transports to the CMA
> - Modifications to the AMSO1100 driver for the iWARP transport CM
> - ULP add_one event changes to filter events based on node_type
>
> The code has been tested on IB and iWARP HCA with both the cmatose and krping applications.
>
> The code can also be checked out from the iWARP branch with these patches applied.
>
> Signed-off-by: Tom Tucker <tom at opengridcomputing.com>
>
>
> Index: ulp/ipoib/ipoib_main.c
> ===================================================================
> --- ulp/ipoib/ipoib_main.c (revision 4186)
> +++ ulp/ipoib/ipoib_main.c (working copy)
> @@ -1024,6 +1024,9 @@
> struct ipoib_dev_priv *priv;
> int s, e, p;
>
> + if (device->node_type == IB_NODE_RNIC)
> + return;
> +
> dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL);
> if (!dev_list)
> return;
> @@ -1054,6 +1057,9 @@
> struct ipoib_dev_priv *priv, *tmp;
> struct list_head *dev_list;
>
> + if (device->node_type == IB_NODE_RNIC)
> + return;
> +
> dev_list = ib_get_client_data(device, &ipoib_client);
>
> list_for_each_entry_safe(priv, tmp, dev_list, list) {
> Index: include/rdma/ib_verbs.h
> ===================================================================
> --- include/rdma/ib_verbs.h (revision 4186)
> +++ include/rdma/ib_verbs.h (working copy)
> @@ -805,7 +805,7 @@
> struct ib_gid_cache **gid_cache;
> };
>
> -struct iw_cm;
> +struct iw_cm_provider;
> struct ib_device {
> struct device *dma_device;
>
> @@ -822,7 +822,7 @@
>
> u32 flags;
>
> - struct iw_cm *iwcm;
> + struct iw_cm_verbs *iwcm;
>
> int (*query_device)(struct ib_device *device,
> struct ib_device_attr *device_attr);
> Index: include/rdma/iw_cm.h
> ===================================================================
> --- include/rdma/iw_cm.h (revision 4186)
> +++ include/rdma/iw_cm.h (working copy)
> @@ -1,5 +1,7 @@
> /*
> * Copyright (c) 2005 Ammasso, Inc. All rights reserved.
> + * Copyright (c) 2005 Network Appliance, Inc. All rights reserved.
> + * Copyright (c) 2005 Open Grid Computing, 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
> @@ -33,112 +35,119 @@
> #define IW_CM_H
>
> #include <linux/in.h>
> +#include <rdma/ib_cm.h>
>
> -/* iWARP connection attributes. */
> +struct iw_cm_id;
> +struct iw_cm_event;
>
> -struct iw_conn_attr {
> - struct in_addr local_addr;
> - struct in_addr remote_addr;
> - u16 local_port;
> - u16 remote_port;
> +enum iw_cm_event_type {
> + IW_CM_EVENT_CONNECT_REQUEST = 1, /* connect request received */
> + IW_CM_EVENT_CONNECT_REPLY, /* reply from active connect request */
> + IW_CM_EVENT_ESTABLISHED,
> + IW_CM_EVENT_LLP_DISCONNECT,
> + IW_CM_EVENT_LLP_RESET,
> + IW_CM_EVENT_LLP_TIMEOUT,
> + IW_CM_EVENT_CLOSE
> };
>
> -/* This is provided in the event generated when
> - * a remote peer accepts our connect request
> - */
> -
> -enum conn_result {
> - IW_CONN_ACCEPT = 0,
> - IW_CONN_RESET,
> - IW_CONN_PEER_REJECT,
> - IW_CONN_TIMEDOUT,
> - IW_CONN_NO_ROUTE_TO_HOST,
> - IW_CONN_INVALID_PARM
> +struct iw_cm_event {
> + enum iw_cm_event_type event;
> + int status;
> + u32 provider_id;
> + struct sockaddr_in local_addr;
> + struct sockaddr_in remote_addr;
> + void *private_data;
> + u8 private_data_len;
> };
> -
> -/* This structure is provided in the event that
> - * completes an active connection request.
> - */
> -struct iw_conn_results {
> - enum conn_result result;
> - struct iw_conn_attr conn_attr;
> - u8 *private_data;
> - int private_data_len;
> -};
>
> -/* This is provided in the event generated by a remote
> - * connect request to a listening endpoint
> - */
> -struct iw_conn_request {
> - u32 cr_id;
> - struct iw_conn_attr conn_attr;
> - u8 *private_data;
> - int private_data_len;
> -};
> +typedef int (*iw_cm_handler)(struct iw_cm_id *cm_id,
> + struct iw_cm_event *event);
>
> -/* Connection events. */
> -enum iw_cm_event_type {
> - IW_EVENT_ACTIVE_CONNECT_RESULTS,
> - IW_EVENT_CONNECT_REQUEST,
> - IW_EVENT_DISCONNECT
> +enum iw_cm_state {
> + IW_CM_STATE_IDLE, /* unbound, inactive */
> + IW_CM_STATE_LISTEN, /* listen waiting for connect */
> + IW_CM_STATE_CONN_SENT, /* outbound waiting for peer accept */
> + IW_CM_STATE_CONN_RECV, /* inbound waiting for user accept */
> + IW_CM_STATE_ESTABLISHED, /* established */
> };
>
> -struct iw_cm_event {
> - struct ib_device *device;
> - union {
> - struct iw_conn_results active_results;
> - struct iw_conn_request conn_request;
> - } element;
> - enum iw_cm_event_type event;
> +typedef void (*iw_event_handler)(struct iw_cm_id* cm_id,
> + struct iw_cm_event* event);
> +struct iw_cm_id {
> + iw_cm_handler cm_handler; /* client callback function */
> + void *context; /* context to provide to client cb */
> + enum iw_cm_state state;
> + struct ib_device *device;
> + struct ib_qp *qp;
> + struct sockaddr_in local_addr;
> + struct sockaddr_in remote_addr;
> + u64 provider_id; /* device handle for this conn. */
> + iw_event_handler event_handler; /* callback for IW CM Provider events */
> };
>
> -/* Listening endpoint. */
> -struct iw_listen_ep_attr {
> - void (*event_handler)(struct iw_cm_event *, void *);
> - void *listen_context;
> - struct in_addr addr;
> - u16 port;
> - int backlog;
> -};
> +/**
> + * iw_create_cm_id - Allocate a communication identifier.
> + * @device: Device associated with the cm_id. All related communication will
> + * be associated with the specified device.
> + * @cm_handler: Callback invoked to notify the user of CM events.
> + * @context: User specified context associated with the communication
> + * identifier.
> + *
> + * Communication identifiers are used to track connection states,
> + * addr resolution requests, and listen requests.
> + */
> +struct iw_cm_id *iw_create_cm_id(struct ib_device *device,
> + iw_cm_handler cm_handler,
> + void *context);
>
> -struct iw_cm {
> +/* This is provided in the event generated when
> + * a remote peer accepts our connect request
> + */
>
> - int (*connect_qp)(struct ib_qp *ib_qp,
> - struct iw_conn_attr* attr,
> - void (*event_handler)(struct iw_cm_event*, void*),
> - void* context,
> - u8 *pdata,
> - int pdata_len
> - );
> +struct iw_cm_verbs {
> + int (*connect)(struct iw_cm_id* cm_id,
> + const void* private_data,
> + u8 private_data_len);
> +
> + int (*disconnect)(struct iw_cm_id* cm_id,
> + int abrupt);
>
> - int (*disconnect_qp)(struct ib_qp *qp,
> - int abrupt
> - );
> + int (*accept)(struct iw_cm_id*,
> + const void *private_data,
> + u8 pdata_data_len);
>
> - int (*accept_cr)(struct ib_device* ibdev,
> - u32 cr_id,
> - struct ib_qp *qp,
> - void (*event_handler)(struct iw_cm_event*, void*),
> - void *context,
> - u8 *pdata,
> - int pdata_len);
> + int (*reject)(struct iw_cm_id* cm_id,
> + const void* private_data,
> + u8 private_data_len);
>
> - int (*reject_cr)(struct ib_device* ibdev,
> - u32 cr_id,
> - u8 *pdata,
> - int pdata_len);
> + int (*getpeername)(struct iw_cm_id* cm_id,
> + struct sockaddr_in* local_addr,
> + struct sockaddr_in* remote_addr);
>
> - int (*query_cr)(struct ib_device* ibdev,
> - u32 cr_id,
> - struct iw_conn_request* req);
> + int (*create_listen)(struct iw_cm_id* cm_id,
> + int backlog);
>
> - int (*create_listen_ep)(struct ib_device *ibdev,
> - struct iw_listen_ep_attr *ep_attrs,
> - void **ep_handle);
> + int (*destroy_listen)(struct iw_cm_id* cm_id);
>
> - int (*destroy_listen_ep)(struct ib_device *ibdev,
> - void *ep_handle);
> -
> };
>
> +struct iw_cm_id *iw_create_cm_id(struct ib_device *device,
> + iw_cm_handler cm_handler,
> + void *context);
> +void iw_destroy_cm_id(struct iw_cm_id *cm_id);
> +int iw_cm_listen(struct iw_cm_id *cm_id, int backlog);
> +int iw_cm_getpeername(struct iw_cm_id *cm_id,
> + struct sockaddr_in* local_add,
> + struct sockaddr_in* remote_addr);
> +int iw_cm_reject(struct iw_cm_id *cm_id,
> + const void *private_data,
> + u8 private_data_len);
> +int iw_cm_accept(struct iw_cm_id *cm_id,
> + const void *private_data,
> + u8 private_data_len);
> +int iw_cm_connect(struct iw_cm_id *cm_id,
> + const void* pdata, u8 pdata_len);
> +int iw_cm_disconnect(struct iw_cm_id *cm_id);
> +int iw_cm_bind_qp(struct iw_cm_id* cm_id, struct ib_qp* qp);
> +
> #endif /* IW_CM_H */
> Index: core/cm.c
> ===================================================================
> --- core/cm.c (revision 4186)
> +++ core/cm.c (working copy)
> @@ -3227,6 +3227,10 @@
> int ret;
> u8 i;
>
> + /* Ignore RNIC devices */
> + if (device->node_type == IB_NODE_RNIC)
> + return;
> +
> cm_dev = kmalloc(sizeof(*cm_dev) + sizeof(*port) *
> device->phys_port_cnt, GFP_KERNEL);
> if (!cm_dev)
> @@ -3291,6 +3295,10 @@
> if (!cm_dev)
> return;
>
> + /* Ignore RNIC devices */
> + if (device->node_type == IB_NODE_RNIC)
> + return;
> +
> write_lock_irqsave(&cm.device_lock, flags);
> list_del(&cm_dev->list);
> write_unlock_irqrestore(&cm.device_lock, flags);
> Index: core/iwcm.c
> ===================================================================
> --- core/iwcm.c (revision 0)
> +++ core/iwcm.c (revision 0)
> @@ -0,0 +1,671 @@
> +/*
> + * 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 <rdma/ib_cache.h>
> +#include <rdma/ib_cm.h>
> +#include <rdma/iw_cm.h>
> +
> +#include "cm_msgs.h"
> +
> +MODULE_AUTHOR("Tom Tucker");
> +MODULE_DESCRIPTION("iWARP CM");
> +MODULE_LICENSE("Dual BSD/GPL");
> +
> +static void iwcm_add_one(struct ib_device *device);
> +static void iwcm_remove_one(struct ib_device *device);
> +struct iwcm_id_private;
> +
> +static struct ib_client iwcm_client = {
> + .name = "cm",
> + .add = iwcm_add_one,
> + .remove = iwcm_remove_one
> +};
> +
> +static struct {
> + spinlock_t lock;
> + struct list_head device_list;
> + rwlock_t device_lock;
> + struct workqueue_struct* wq;
> +} iwcm;
> +
> +struct iwcm_device;
> +struct iwcm_port {
> + struct iwcm_device *iwcm_dev;
> + struct sockaddr_in local_addr;
> + u8 port_num;
> +};
> +
> +struct iwcm_device {
> + struct list_head list;
> + struct ib_device *device;
> + struct iwcm_port port[0];
> +};
> +
> +struct iwcm_id_private {
> + struct iw_cm_id id;
> +
> + spinlock_t lock;
> + wait_queue_head_t wait;
> + atomic_t refcount;
> +
> + struct rb_node listen_node;
> +
> + struct list_head work_list;
> + atomic_t work_count;
> +};
> +
> +struct iwcm_work {
> + struct work_struct work;
> + struct iwcm_id_private* cm_id;
> + struct iw_cm_event event;
> +};
> +
> +/* Called whenever a reference added for a cm_id */
> +static inline void iwcm_addref_id(struct iwcm_id_private *cm_id_priv)
> +{
> + atomic_inc(&cm_id_priv->refcount);
> +}
> +
> +/* Called whenever releasing a reference to a cm id */
> +static inline void iwcm_deref_id(struct iwcm_id_private *cm_id_priv)
> +{
> + if (atomic_dec_and_test(&cm_id_priv->refcount))
> + wake_up(&cm_id_priv->wait);
> +}
> +
> +static void 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 *iwcm_id_priv;
> +
> + iwcm_id_priv = kmalloc(sizeof *iwcm_id_priv, GFP_KERNEL);
> + if (!iwcm_id_priv)
> + return ERR_PTR(-ENOMEM);
> +
> + memset(iwcm_id_priv, 0, sizeof *iwcm_id_priv);
> + iwcm_id_priv->id.state = IW_CM_STATE_IDLE;
> + iwcm_id_priv->id.device = device;
> + iwcm_id_priv->id.cm_handler = cm_handler;
> + iwcm_id_priv->id.context = context;
> + iwcm_id_priv->id.event_handler = cm_event_handler;
> +
> + spin_lock_init(&iwcm_id_priv->lock);
> + init_waitqueue_head(&iwcm_id_priv->wait);
> + atomic_set(&iwcm_id_priv->refcount, 1);
> +
> + return &iwcm_id_priv->id;
> +
> +}
> +EXPORT_SYMBOL(iw_create_cm_id);
> +
> +struct iw_cm_id* iw_clone_id(struct iw_cm_id* parent)
> +{
> + return iw_create_cm_id(parent->device,
> + parent->cm_handler,
> + parent->context);
> +}
> +
> +void iw_destroy_cm_id(struct iw_cm_id *cm_id)
> +{
> + struct iwcm_id_private *iwcm_id_priv;
> + unsigned long flags;
> + int ret = 0;
> +
> +
> + iwcm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
> +
> + spin_lock_irqsave(&iwcm_id_priv->lock, flags);
> + switch (cm_id->state) {
> + case IW_CM_STATE_LISTEN:
> + cm_id->state = IW_CM_STATE_IDLE;
> + spin_unlock_irqrestore(&iwcm_id_priv->lock, flags);
> + ret = cm_id->device->iwcm->destroy_listen(cm_id);
> + break;
> +
> + case IW_CM_STATE_CONN_RECV:
> + case IW_CM_STATE_CONN_SENT:
> + case IW_CM_STATE_ESTABLISHED:
> + cm_id->state = IW_CM_STATE_IDLE;
> + spin_unlock_irqrestore(&iwcm_id_priv->lock, flags);
> + ret = cm_id->device->iwcm->disconnect(cm_id,1);
> + break;
> +
> + case IW_CM_STATE_IDLE:
> + spin_unlock_irqrestore(&iwcm_id_priv->lock, flags);
> + break;
> +
> + default:
> + spin_unlock_irqrestore(&iwcm_id_priv->lock, flags);
> + printk(KERN_ERR "%s:%s:%u Illegal state %d for iw_cm_id.\n",
> + __FILE__, __FUNCTION__, __LINE__, cm_id->state);
> + ;
> + }
> +
> + atomic_dec(&iwcm_id_priv->refcount);
> + wait_event(iwcm_id_priv->wait, !atomic_read(&iwcm_id_priv->refcount));
> +
> + kfree(iwcm_id_priv);
> +}
> +EXPORT_SYMBOL(iw_destroy_cm_id);
> +
> +int iw_cm_listen(struct iw_cm_id *cm_id, int backlog)
> +{
> + struct iwcm_id_private *iwcm_id_priv;
> + unsigned long flags;
> + int ret = 0;
> +
> +
> + iwcm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
> +
> + if (cm_id->device == 0) {
> + printk(KERN_ERR "device is NULL\n");
> + return -EINVAL;
> + }
> +
> + if (cm_id->device->iwcm == 0) {
> + printk(KERN_ERR "iwcm is NULL\n");
> + return -EINVAL;
> + }
> +
> + spin_lock_irqsave(&iwcm_id_priv->lock, flags);
> + if (cm_id->state != IW_CM_STATE_IDLE) {
> + spin_unlock_irqrestore(&iwcm_id_priv->lock, flags);
> + return -EBUSY;
> + }
> + cm_id->state = IW_CM_STATE_LISTEN;
> + spin_unlock_irqrestore(&iwcm_id_priv->lock, flags);
> +
> + ret = cm_id->device->iwcm->create_listen(cm_id, backlog);
> + if (ret != 0) {
> + spin_lock_irqsave(&iwcm_id_priv->lock, flags);
> + cm_id->state = IW_CM_STATE_IDLE;
> + spin_unlock_irqrestore(&iwcm_id_priv->lock, flags);
> + }
> + return ret;
> +}
> +EXPORT_SYMBOL(iw_cm_listen);
> +
> +int iw_cm_getpeername(struct iw_cm_id *cm_id,
> + struct sockaddr_in* local_addr,
> + struct sockaddr_in* remote_addr)
> +{
> + if (cm_id->device == 0)
> + return -EINVAL;
> +
> + if (cm_id->device->iwcm == 0)
> + return -EINVAL;
> +
> + /* Make sure there's a connection */
> + if (cm_id->state != IW_CM_STATE_ESTABLISHED)
> + return -ENOTCONN;
> +
> + return cm_id->device->iwcm->getpeername(cm_id, local_addr, remote_addr);
> +}
> +EXPORT_SYMBOL(iw_cm_getpeername);
> +
> +int iw_cm_reject(struct iw_cm_id *cm_id,
> + const void *private_data,
> + u8 private_data_len)
> +{
> + struct iwcm_id_private *iwcm_id_priv;
> + unsigned long flags;
> + int ret;
> +
> +
> + if (cm_id->device == 0 || cm_id->device->iwcm == 0)
> + return -EINVAL;
> +
> + iwcm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
> +
> + spin_lock_irqsave(&iwcm_id_priv->lock, flags);
> + switch (cm_id->state) {
> + case IW_CM_STATE_CONN_RECV:
> + ret = cm_id->device->iwcm->reject(cm_id, private_data, private_data_len);
> + cm_id->state = IW_CM_STATE_IDLE;
> + break;
> + default:
> + ret = -EINVAL;
> + goto out;
> + }
> +
> +out: spin_unlock_irqrestore(&iwcm_id_priv->lock, flags);
> + return ret;
> +}
> +EXPORT_SYMBOL(iw_cm_reject);
> +
> +int iw_cm_accept(struct iw_cm_id *cm_id,
> + const void *private_data,
> + u8 private_data_len)
> +{
> + struct iwcm_id_private *iwcm_id_priv;
> + int ret;
> +
> + if (cm_id->device == 0 || cm_id->device->iwcm == 0)
> + return -EINVAL;
> +
> + iwcm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
> +
> + switch (cm_id->state) {
> + case IW_CM_STATE_CONN_RECV:
> + ret = cm_id->device->iwcm->accept(cm_id, private_data,
> + private_data_len);
> + if (ret == 0) {
> + struct iw_cm_event event;
> + event.event = IW_CM_EVENT_ESTABLISHED;
> + event.provider_id = cm_id->provider_id;
> + event.status = 0;
> + event.local_addr = cm_id->local_addr;
> + event.remote_addr = cm_id->remote_addr;
> + event.private_data = 0;
> + event.private_data_len = 0;
> + cm_event_handler(cm_id, &event);
> + }
> +
> + break;
> + default:
> + ret = -EINVAL;
> + }
> +
> + return ret;
> +}
> +EXPORT_SYMBOL(iw_cm_accept);
> +
> +int iw_cm_bind_qp(struct iw_cm_id* cm_id, struct ib_qp* qp)
> +{
> + int ret = -EINVAL;
> +
> + if (cm_id)
> + cm_id->qp = qp;
> +
> + return ret;
> +}
> +EXPORT_SYMBOL(iw_cm_bind_qp);
> +
> +int iw_cm_connect(struct iw_cm_id *cm_id,
> + const void* pdata, u8 pdata_len)
> +{
> + struct iwcm_id_private* cm_id_priv;
> + int ret = 0;
> + unsigned long flags;
> +
> + if (cm_id->state != IW_CM_STATE_IDLE)
> + return -EBUSY;
> +
> + if (cm_id->device == 0)
> + return -EINVAL;
> +
> + if (cm_id->device->iwcm == 0)
> + return -ENOSYS;
> +
> + cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
> +
> + spin_lock_irqsave(&cm_id_priv->lock, flags);
> + cm_id->state = IW_CM_STATE_CONN_SENT;
> + spin_unlock_irqrestore(&cm_id_priv->lock, flags);
> +
> + ret = cm_id->device->iwcm->connect(cm_id, pdata, pdata_len);
> + if (ret != 0) {
> + spin_lock_irqsave(&cm_id_priv->lock, flags);
> + cm_id->state = IW_CM_STATE_IDLE;
> + spin_unlock_irqrestore(&cm_id_priv->lock, flags);
> + }
> + return ret;
> +}
> +EXPORT_SYMBOL(iw_cm_connect);
> +
> +int iw_cm_disconnect(struct iw_cm_id *cm_id)
> +{
> + struct iwcm_id_private *iwcm_id_priv;
> + int ret;
> +
> + if (cm_id->device == 0 || cm_id->device->iwcm == 0 || cm_id->qp == 0)
> + return -EINVAL;
> +
> + iwcm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
> +
> + switch (cm_id->state) {
> + case IW_CM_STATE_ESTABLISHED:
> + ret = cm_id->device->iwcm->disconnect(cm_id, 1);
> + cm_id->state = IW_CM_STATE_IDLE;
> + if (ret == 0) {
> + struct iw_cm_event event;
> + event.event = IW_CM_EVENT_LLP_DISCONNECT;
> + event.provider_id = cm_id->provider_id;
> + event.status = 0;
> + event.local_addr = cm_id->local_addr;
> + event.remote_addr = cm_id->remote_addr;
> + event.private_data = 0;
> + event.private_data_len = 0;
> + cm_event_handler(cm_id, &event);
> + }
> +
> + break;
> + default:
> + ret = -EINVAL;
> + }
> +
> + return ret;
> +}
> +EXPORT_SYMBOL(iw_cm_disconnect);
> +
> +static void iwcm_add_one(struct ib_device *device)
> +{
> + struct iwcm_device *iwcm_dev;
> + struct iwcm_port *port;
> + unsigned long flags;
> + u8 i;
> +
> + if (device->node_type != IB_NODE_RNIC)
> + return;
> +
> + iwcm_dev = kmalloc(sizeof(*iwcm_dev) + sizeof(*port) *
> + device->phys_port_cnt, GFP_KERNEL);
> + if (!iwcm_dev)
> + return;
> +
> + iwcm_dev->device = device;
> +
> + for (i = 1; i <= device->phys_port_cnt; i++) {
> + port = &iwcm_dev->port[i-1];
> + port->iwcm_dev = iwcm_dev;
> + port->port_num = i;
> + }
> +
> + ib_set_client_data(device, &iwcm_client, iwcm_dev);
> +
> + write_lock_irqsave(&iwcm.device_lock, flags);
> + list_add_tail(&iwcm_dev->list, &iwcm.device_list);
> + write_unlock_irqrestore(&iwcm.device_lock, flags);
> + return;
> +}
> +
> +static void iwcm_remove_one(struct ib_device *device)
> +{
> + struct iwcm_device *iwcm_dev;
> + unsigned long flags;
> +
> + if (device->node_type != IB_NODE_RNIC)
> + return;
> +
> + iwcm_dev = ib_get_client_data(device, &iwcm_client);
> + if (!iwcm_dev)
> + return;
> +
> + write_lock_irqsave(&iwcm.device_lock, flags);
> + list_del(&iwcm_dev->list);
> + write_unlock_irqrestore(&iwcm.device_lock, flags);
> +
> + kfree(iwcm_dev);
> +}
> +
> +/* 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.
> + */
> +static int cm_conn_req_handler(struct iwcm_work* work)
> +{
> + struct iw_cm_id* cm_id;
> + struct iwcm_id_private* cm_id_priv;
> + unsigned long flags;
> + int rc;
> +
> + /* If the status was not successful, ignore request */
> + if (work->event.status) {
> + printk(KERN_ERR "Bad status=%d for connection request ... "
> + "should be filtered by provider\n",
> + work->event.status);
> + return work->event.status;
> + }
> + cm_id = iw_clone_id(&work->cm_id->id);
> + if (IS_ERR(cm_id))
> + return PTR_ERR(cm_id);
> +
> + cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
> + spin_lock_irqsave(&cm_id_priv->lock, flags);
> + cm_id_priv->id.local_addr = work->event.local_addr;
> + cm_id_priv->id.remote_addr = work->event.remote_addr;
> + cm_id_priv->id.provider_id = work->event.provider_id;
> + cm_id_priv->id.state = IW_CM_STATE_CONN_RECV;
> + spin_unlock_irqrestore(&cm_id_priv->lock, flags);
> +
> + /* Call the client CM handler */
> + rc = cm_id->cm_handler(cm_id, &work->event);
> + if (rc) {
> + cm_id->state = IW_CM_STATE_IDLE;
> + iw_destroy_cm_id(cm_id);
> + }
> + kfree(work);
> + return 0;
> +}
> +
> +/*
> + * Handles the transition to established state on the passive side.
> + */
> +static int cm_conn_est_handler(struct iwcm_work* work)
> +{
> + struct iwcm_id_private* cm_id_priv;
> + unsigned long flags;
> + int ret = 0;
> +
> + cm_id_priv = work->cm_id;
> + spin_lock_irqsave(&cm_id_priv->lock, flags);
> + if (cm_id_priv->id.state != IW_CM_STATE_CONN_RECV) {
> + printk(KERN_ERR "%s:%d Invalid cm_id state=%d for established event\n",
> + __FUNCTION__, __LINE__, cm_id_priv->id.state);
> + spin_unlock_irqrestore(&cm_id_priv->lock, flags);
> + ret = -EINVAL;
> + goto error_out;
> + }
> +
> + if (work->event.status == 0) {
> + cm_id_priv = work->cm_id;
> + cm_id_priv->id.local_addr = work->event.local_addr;
> + cm_id_priv->id.remote_addr = work->event.remote_addr;
> + cm_id_priv->id.state = IW_CM_STATE_ESTABLISHED;
> + } else {
> + cm_id_priv->id.state = IW_CM_STATE_IDLE;
> + }
> + spin_unlock_irqrestore(&cm_id_priv->lock, flags);
> +
> + /* Call the client CM handler */
> + ret = cm_id_priv->id.cm_handler(&cm_id_priv->id, &work->event);
> + if (ret) {
> + cm_id_priv->id.state = IW_CM_STATE_IDLE;
> + iw_destroy_cm_id(&cm_id_priv->id);
> + }
> +
> + error_out:
> + kfree(work);
> + return ret;
> +}
> +
> +/*
> + * Handles the reply to our connect request. There are three
> + * possibilities:
> + * - If the cm_id is in the wrong state when the event is
> + * delivered, the event is ignored. [What should we do when the
> + * provider does something crazy?]
> + * - If the remote peer accepts the connection, we update the 4-tuple
> + * in the cm_id with the remote peer info, move the cm_id to the
> + * ESTABLISHED state and deliver the event to the client.
> + * - If the remote peer rejects the connection, or there is some
> + * connection error, move the cm_id to the IDLE state, and deliver
> + * the event to the client.
> + */
> +static int cm_conn_rep_handler(struct iwcm_work* work)
> +{
> + struct iwcm_id_private* cm_id_priv;
> + unsigned long flags;
> + int ret = 0;
> +
> + cm_id_priv = work->cm_id;
> + spin_lock_irqsave(&cm_id_priv->lock, flags);
> + if (cm_id_priv->id.state != IW_CM_STATE_CONN_SENT) {
> + printk(KERN_ERR "%s:%d Invalid cm_id state=%d for connect reply event\n",
> + __FUNCTION__, __LINE__, cm_id_priv->id.state);
> + spin_unlock_irqrestore(&cm_id_priv->lock, flags);
> + ret = -EINVAL;
> + goto error_out;
> + }
> +
> + if (work->event.status == 0) {
> + cm_id_priv = work->cm_id;
> + cm_id_priv->id.local_addr = work->event.local_addr;
> + cm_id_priv->id.remote_addr = work->event.remote_addr;
> + cm_id_priv->id.state = IW_CM_STATE_ESTABLISHED;
> + } else {
> + cm_id_priv->id.state = IW_CM_STATE_IDLE;
> + }
> + spin_unlock_irqrestore(&cm_id_priv->lock, flags);
> +
> + /* Call the client CM handler */
> + ret = cm_id_priv->id.cm_handler(&cm_id_priv->id, &work->event);
> + if (ret) {
> + cm_id_priv->id.state = IW_CM_STATE_IDLE;
> + iw_destroy_cm_id(&cm_id_priv->id);
> + }
> +
> + error_out:
> + kfree(work);
> + return ret;
> +}
> +
> +static int cm_disconnect_handler(struct iwcm_work* work)
> +{
> + struct iwcm_id_private* cm_id_priv;
> + unsigned long flags;
> + int ret = 0;
> +
> + cm_id_priv = work->cm_id;
> + spin_lock_irqsave(&cm_id_priv->lock, flags);
> + cm_id_priv->id.state = IW_CM_STATE_IDLE;
> + spin_unlock_irqrestore(&cm_id_priv->lock, flags);
> +
> + /* Call the client CM handler */
> + ret = cm_id_priv->id.cm_handler(&cm_id_priv->id, &work->event);
> + if (ret) {
> + cm_id_priv->id.state = IW_CM_STATE_IDLE;
> + iw_destroy_cm_id(&cm_id_priv->id);
> + }
> +
> + kfree(work);
> + return ret;
> +}
> +
> +static void cm_work_handler(void* arg)
> +{
> + struct iwcm_work* work = (struct iwcm_work*)arg;
> + int rc;
> +
> + switch (work->event.event) {
> + case IW_CM_EVENT_CONNECT_REQUEST:
> + rc = cm_conn_req_handler(work);
> + break;
> + case IW_CM_EVENT_CONNECT_REPLY:
> + rc = cm_conn_rep_handler(work);
> + break;
> + case IW_CM_EVENT_ESTABLISHED:
> + rc = cm_conn_est_handler(work);
> + break;
> + case IW_CM_EVENT_LLP_DISCONNECT:
> + case IW_CM_EVENT_LLP_TIMEOUT:
> + case IW_CM_EVENT_LLP_RESET:
> + case IW_CM_EVENT_CLOSE:
> + rc = cm_disconnect_handler(work);
> + break;
> + }
> +}
> +
> +/* IW CM provider event callback handler. This function is called on
> + * interrupt context. The function builds a work queue element
> + * and enqueues it for processing on a work queue thread. This allows
> + * CM client callback functions to block.
> + */
> +static void cm_event_handler(struct iw_cm_id* cm_id,
> + struct iw_cm_event* event)
> +{
> + struct iwcm_work *work;
> + struct iwcm_id_private* cm_id_priv;
> +
> + work = kmalloc(sizeof *work, GFP_ATOMIC);
> + if (!work)
> + return;
> +
> + cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
> + INIT_WORK(&work->work, cm_work_handler, work);
> + work->cm_id = cm_id_priv;
> + work->event = *event;
> + queue_work(iwcm.wq, &work->work);
> +}
> +
> +static int __init iw_cm_init(void)
> +{
> + memset(&iwcm, 0, sizeof iwcm);
> + INIT_LIST_HEAD(&iwcm.device_list);
> + rwlock_init(&iwcm.device_lock);
> + spin_lock_init(&iwcm.lock);
> + iwcm.wq = create_workqueue("iw_cm");
> + if (!iwcm.wq)
> + return -ENOMEM;
> +
> + return ib_register_client(&iwcm_client);
> +}
> +
> +static void __exit iw_cm_cleanup(void)
> +{
> + ib_unregister_client(&iwcm_client);
> +}
> +
> +module_init(iw_cm_init);
> +module_exit(iw_cm_cleanup);
> +
> Index: core/addr.c
> ===================================================================
> --- core/addr.c (revision 4186)
> +++ core/addr.c (working copy)
> @@ -73,8 +73,13 @@
> if (!dev)
> return -EADDRNOTAVAIL;
>
> - *gid = *(union ib_gid *) (dev->dev_addr + 4);
> - *pkey = addr_get_pkey(dev);
> + if (dev->type == ARPHRD_INFINIBAND) {
> + *gid = *(union ib_gid *) (dev->dev_addr + 4);
> + *pkey = addr_get_pkey(dev);
> + } else {
> + *gid = *(union ib_gid *) (dev->dev_addr);
> + *pkey = 0;
> + }
> dev_put(dev);
> return 0;
> }
> Index: core/Makefile
> ===================================================================
> --- core/Makefile (revision 4186)
> +++ core/Makefile (working copy)
> @@ -1,6 +1,6 @@
> EXTRA_CFLAGS += -Idrivers/infiniband/include -Idrivers/infiniband/ulp/ipoib
>
> -obj-$(CONFIG_INFINIBAND) += ib_core.o ib_mad.o ib_ping.o ib_cm.o \
> +obj-$(CONFIG_INFINIBAND) += ib_core.o ib_mad.o ib_ping.o ib_cm.o iw_cm.o \
> ib_sa.o ib_at.o ib_addr.o rdma_cm.o
> obj-$(CONFIG_INFINIBAND_USER_MAD) += ib_umad.o
> obj-$(CONFIG_INFINIBAND_USER_ACCESS) += ib_uverbs.o ib_ucm.o ib_uat.o
> @@ -14,6 +14,8 @@
>
> ib_cm-y := cm.o
>
> +iw_cm-y := iwcm.o
> +
> rdma_cm-y := cma.o
>
> ib_addr-y := addr.o
> Index: core/cma.c
> ===================================================================
> --- core/cma.c (revision 4186)
> +++ core/cma.c (working copy)
> @@ -1,4 +1,5 @@
> /*
> + * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
> * Copyright (c) 2005 Voltaire Inc. All rights reserved.
> * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
> * Copyright (c) 1999-2005, Mellanox Technologies, Inc. All rights reserved.
> @@ -30,9 +31,14 @@
> */
> #include <linux/in.h>
> #include <linux/in6.h>
> +#include <linux/inetdevice.h>
> +#include <net/route.h>
> +#include <net/arp.h>
> +#include <net/neighbour.h>
> #include <rdma/rdma_cm.h>
> #include <rdma/ib_cache.h>
> #include <rdma/ib_cm.h>
> +#include <rdma/iw_cm.h>
> #include <rdma/ib_sa.h>
>
> MODULE_AUTHOR("Guy German");
> @@ -100,7 +106,10 @@
> int timeout_ms;
> struct ib_sa_query *query;
> int query_id;
> - struct ib_cm_id *cm_id;
> + union {
> + struct ib_cm_id *ib;
> + struct iw_cm_id *iw;
> + } cm_id;
> };
>
> struct cma_addr {
> @@ -266,6 +275,16 @@
> IB_QP_PKEY_INDEX | IB_QP_PORT);
> }
>
> +static int cma_init_iw_qp(struct rdma_id_private *id_priv, struct ib_qp *qp)
> +{
> + struct ib_qp_attr qp_attr;
> +
> + qp_attr.qp_state = IB_QPS_INIT;
> + qp_attr.qp_access_flags = IB_ACCESS_LOCAL_WRITE;
> +
> + return ib_modify_qp(qp, &qp_attr, IB_QP_STATE | IB_QP_ACCESS_FLAGS);
> +}
> +
> int rdma_create_qp(struct rdma_cm_id *id, struct ib_pd *pd,
> struct ib_qp_init_attr *qp_init_attr)
> {
> @@ -285,6 +304,9 @@
> case IB_NODE_CA:
> ret = cma_init_ib_qp(id_priv, qp);
> break;
> + case IB_NODE_RNIC:
> + ret = cma_init_iw_qp(id_priv, qp);
> + break;
> default:
> ret = -ENOSYS;
> break;
> @@ -314,7 +336,7 @@
>
> /* Need to update QP attributes from default values. */
> qp_attr.qp_state = IB_QPS_INIT;
> - ret = ib_cm_init_qp_attr(id_priv->cm_id, &qp_attr, &qp_attr_mask);
> + ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, &qp_attr, &qp_attr_mask);
> if (ret)
> return ret;
>
> @@ -323,7 +345,7 @@
> return ret;
>
> qp_attr.qp_state = IB_QPS_RTR;
> - ret = ib_cm_init_qp_attr(id_priv->cm_id, &qp_attr, &qp_attr_mask);
> + ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, &qp_attr, &qp_attr_mask);
> if (ret)
> return ret;
>
> @@ -337,7 +359,7 @@
> int qp_attr_mask, ret;
>
> qp_attr.qp_state = IB_QPS_RTS;
> - ret = ib_cm_init_qp_attr(id_priv->cm_id, &qp_attr, &qp_attr_mask);
> + ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, &qp_attr, &qp_attr_mask);
> if (ret)
> return ret;
>
> @@ -419,8 +441,8 @@
> {
> cma_exch(id_priv, CMA_DESTROYING);
>
> - if (id_priv->cm_id && !IS_ERR(id_priv->cm_id))
> - ib_destroy_cm_id(id_priv->cm_id);
> + if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib))
> + ib_destroy_cm_id(id_priv->cm_id.ib);
>
> list_del(&id_priv->listen_list);
> if (id_priv->cma_dev)
> @@ -476,8 +498,22 @@
> state = cma_exch(id_priv, CMA_DESTROYING);
> cma_cancel_operation(id_priv, state);
>
> - if (id_priv->cm_id && !IS_ERR(id_priv->cm_id))
> - ib_destroy_cm_id(id_priv->cm_id);
> + if (id->device) {
> + switch (id->device->node_type) {
> + case IB_NODE_RNIC:
> + if (id_priv->cm_id.iw && !IS_ERR(id_priv->cm_id.iw)) {
> + iw_destroy_cm_id(id_priv->cm_id.iw);
> + id_priv->cm_id.iw = 0;
> + }
> + break;
> + default:
> + if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib)) {
> + ib_destroy_cm_id(id_priv->cm_id.ib);
> + id_priv->cm_id.ib = 0;
> + }
> + break;
> + }
> + }
>
> if (id_priv->cma_dev) {
> down(&mutex);
> @@ -505,14 +541,14 @@
> if (ret)
> goto reject;
>
> - ret = ib_send_cm_rtu(id_priv->cm_id, NULL, 0);
> + ret = ib_send_cm_rtu(id_priv->cm_id.ib, NULL, 0);
> if (ret)
> goto reject;
>
> return 0;
> reject:
> cma_modify_qp_err(&id_priv->id);
> - ib_send_cm_rej(id_priv->cm_id, IB_CM_REJ_CONSUMER_DEFINED,
> + ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED,
> NULL, 0, NULL, 0);
> return ret;
> }
> @@ -528,7 +564,7 @@
> return 0;
> reject:
> cma_modify_qp_err(&id_priv->id);
> - ib_send_cm_rej(id_priv->cm_id, IB_CM_REJ_CONSUMER_DEFINED,
> + ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED,
> NULL, 0, NULL, 0);
> return ret;
> }
> @@ -586,7 +622,7 @@
> private_data_len);
> if (ret) {
> /* Destroy the CM ID by returning a non-zero value. */
> - id_priv->cm_id = NULL;
> + id_priv->cm_id.ib = NULL;
> cma_exch(id_priv, CMA_DESTROYING);
> cma_release_remove(id_priv);
> rdma_destroy_id(&id_priv->id);
> @@ -675,7 +711,7 @@
> goto out;
> }
>
> - conn_id->cm_id = cm_id;
> + conn_id->cm_id.ib = cm_id;
> cm_id->context = conn_id;
> cm_id->cm_handler = cma_ib_handler;
>
> @@ -685,7 +721,7 @@
> IB_CM_REQ_PRIVATE_DATA_SIZE - offset);
> if (ret) {
> /* Destroy the CM ID by returning a non-zero value. */
> - conn_id->cm_id = NULL;
> + conn_id->cm_id.ib = NULL;
> cma_exch(conn_id, CMA_DESTROYING);
> cma_release_remove(conn_id);
> rdma_destroy_id(&conn_id->id);
> @@ -695,6 +731,112 @@
> return ret;
> }
>
> +static int cma_iw_handler(struct iw_cm_id* iw_id, struct iw_cm_event* event)
> +{
> + struct rdma_id_private *id_priv = iw_id->context;
> + enum rdma_cm_event_type event_type = 0;
> + int ret = 0;
> +
> + atomic_inc(&id_priv->dev_remove);
> +
> + switch (event->event) {
> + case IW_CM_EVENT_LLP_DISCONNECT:
> + case IW_CM_EVENT_LLP_RESET:
> + case IW_CM_EVENT_LLP_TIMEOUT:
> + case IW_CM_EVENT_CLOSE:
> + event_type = RDMA_CM_EVENT_DISCONNECTED;
> + break;
> +
> + case IW_CM_EVENT_CONNECT_REQUEST:
> + BUG_ON(1);
> + break;
> +
> + case IW_CM_EVENT_CONNECT_REPLY: {
> + if (event->status)
> + event_type = RDMA_CM_EVENT_REJECTED;
> + else
> + event_type = RDMA_CM_EVENT_ESTABLISHED;
> + break;
> + }
> +
> + case IW_CM_EVENT_ESTABLISHED:
> + event_type = RDMA_CM_EVENT_ESTABLISHED;
> + break;
> + }
> +
> + ret = cma_notify_user(id_priv,
> + event_type,
> + event->status,
> + event->private_data,
> + event->private_data_len);
> + if (ret) {
> + /* Destroy the CM ID by returning a non-zero value. */
> + id_priv->cm_id.iw = NULL;
> + cma_exch(id_priv, CMA_DESTROYING);
> + cma_release_remove(id_priv);
> + rdma_destroy_id(&id_priv->id);
> + return ret;
> + }
> +
> + cma_release_remove(id_priv);
> + return ret;
> +}
> +
> +static int iw_conn_req_handler(struct iw_cm_id *cm_id,
> + struct iw_cm_event *iw_event)
> +{
> + struct rdma_cm_id* new_cm_id;
> + struct rdma_id_private *listen_id, *conn_id;
> + struct sockaddr_in* sin;
> + int ret;
> +
> + listen_id = cm_id->context;
> + atomic_inc(&listen_id->dev_remove);
> + if (!cma_comp(listen_id, CMA_LISTEN)) {
> + ret = -ECONNABORTED;
> + goto out;
> + }
> +
> + /* Create a new RDMA id the new IW CM ID */
> + new_cm_id = rdma_create_id(listen_id->id.event_handler,
> + listen_id->id.context);
> + if (!new_cm_id) {
> + ret = -ENOMEM;
> + goto out;
> + }
> + conn_id = container_of(new_cm_id, struct rdma_id_private, id);
> + atomic_inc(&conn_id->dev_remove);
> + conn_id->state = CMA_CONNECT;
> +
> + /* New connection inherits device from parent */
> + cma_attach_to_dev(conn_id, listen_id->cma_dev);
> +
> + conn_id->cm_id.iw = cm_id;
> + cm_id->context = conn_id;
> + cm_id->cm_handler = cma_iw_handler;
> +
> + sin = (struct sockaddr_in*)&new_cm_id->route.addr.src_addr;
> + *sin = iw_event->local_addr;
> +
> + sin = (struct sockaddr_in*)&new_cm_id->route.addr.dst_addr;
> + *sin = iw_event->remote_addr;
> +
> + ret = cma_notify_user(conn_id, RDMA_CM_EVENT_CONNECT_REQUEST, 0,
> + iw_event->private_data,
> + iw_event->private_data_len);
> + if (ret) {
> + /* Destroy the CM ID by returning a non-zero value. */
> + conn_id->cm_id.iw = NULL;
> + cma_exch(conn_id, CMA_DESTROYING);
> + cma_release_remove(conn_id);
> + rdma_destroy_id(&conn_id->id);
> + }
> +
> +out:
> + cma_release_remove(listen_id);
> + return ret;
> +}
> +
> static __be64 cma_get_service_id(struct sockaddr *addr)
> {
> return cpu_to_be64(((u64)IB_OPENIB_OUI << 48) +
> @@ -706,21 +848,44 @@
> __be64 svc_id;
> int ret;
>
> - id_priv->cm_id = ib_create_cm_id(id_priv->id.device, cma_req_handler,
> + id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device, cma_req_handler,
> id_priv);
> - if (IS_ERR(id_priv->cm_id))
> - return PTR_ERR(id_priv->cm_id);
> + if (IS_ERR(id_priv->cm_id.ib))
> + return PTR_ERR(id_priv->cm_id.ib);
>
> svc_id = cma_get_service_id(&id_priv->id.route.addr.src_addr);
> - ret = ib_cm_listen(id_priv->cm_id, svc_id, 0);
> + ret = ib_cm_listen(id_priv->cm_id.ib, svc_id, 0);
> if (ret) {
> - ib_destroy_cm_id(id_priv->cm_id);
> - id_priv->cm_id = NULL;
> + ib_destroy_cm_id(id_priv->cm_id.ib);
> + id_priv->cm_id.ib = NULL;
> }
>
> return ret;
> }
>
> +static int cma_iw_listen(struct rdma_id_private *id_priv)
> +{
> + int ret;
> + struct sockaddr_in* sin;
> +
> + id_priv->cm_id.iw = iw_create_cm_id(id_priv->id.device,
> + iw_conn_req_handler,
> + id_priv);
> + if (IS_ERR(id_priv->cm_id.iw))
> + return PTR_ERR(id_priv->cm_id.iw);
> +
> + sin = (struct sockaddr_in*)&id_priv->id.route.addr.src_addr;
> + id_priv->cm_id.iw->local_addr = *sin;
> +
> + ret = iw_cm_listen(id_priv->cm_id.iw, 10 /* backlog */);
> + if (ret) {
> + iw_destroy_cm_id(id_priv->cm_id.iw);
> + id_priv->cm_id.iw = NULL;
> + }
> +
> + return ret;
> +}
> +
> static int cma_duplicate_listen(struct rdma_id_private *id_priv)
> {
> struct rdma_id_private *cur_id_priv;
> @@ -785,8 +950,9 @@
> goto out;
>
> list_add_tail(&id_priv->list, &listen_any_list);
> - list_for_each_entry(cma_dev, &dev_list, list)
> + list_for_each_entry(cma_dev, &dev_list, list) {
> cma_listen_on_dev(id_priv, cma_dev);
> + }
> out:
> up(&mutex);
> return ret;
> @@ -796,7 +962,6 @@
> {
> struct rdma_id_private *id_priv;
> int ret;
> -
> id_priv = container_of(id, struct rdma_id_private, id);
> if (!cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_LISTEN))
> return -EINVAL;
> @@ -806,6 +971,9 @@
> case IB_NODE_CA:
> ret = cma_ib_listen(id_priv);
> break;
> + case IB_NODE_RNIC:
> + ret = cma_iw_listen(id_priv);
> + break;
> default:
> ret = -ENOSYS;
> break;
> @@ -890,6 +1058,30 @@
> return (id_priv->query_id < 0) ? id_priv->query_id : 0;
> }
>
> +static int cma_resolve_iw_route(struct rdma_id_private *id_priv, int timeout_ms)
> +{
> + enum rdma_cm_event_type event = RDMA_CM_EVENT_ROUTE_RESOLVED;
> + int rc;
> +
> + atomic_inc(&id_priv->dev_remove);
> +
> + if (!cma_comp_exch(id_priv, CMA_ROUTE_QUERY, CMA_ROUTE_RESOLVED))
> + BUG_ON(1);
> +
> + rc = cma_notify_user(id_priv, event, 0, NULL, 0);
> + if (rc) {
> + cma_exch(id_priv, CMA_DESTROYING);
> + cma_release_remove(id_priv);
> + cma_deref_id(id_priv);
> + rdma_destroy_id(&id_priv->id);
> + return rc;
> + }
> +
> + cma_release_remove(id_priv);
> + cma_deref_id(id_priv);
> + return rc;
> +}
> +
> int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms)
> {
> struct rdma_id_private *id_priv;
> @@ -904,6 +1096,9 @@
> case IB_NODE_CA:
> ret = cma_resolve_ib_route(id_priv, timeout_ms);
> break;
> + case IB_NODE_RNIC:
> + ret = cma_resolve_iw_route(id_priv, timeout_ms);
> + break;
> default:
> ret = -ENOSYS;
> break;
> @@ -952,20 +1147,133 @@
> cma_deref_id(id_priv);
> }
>
> +
> +/* Find the local interface with a route to the specified address and
> + * bind the CM ID to this interface's CMA device
> + */
> +static int cma_acquire_iw_dev(struct rdma_cm_id* id, struct sockaddr* addr)
> +{
> + int ret = -ENOENT;
> + struct cma_device* cma_dev;
> + struct rdma_id_private *id_priv;
> + struct sockaddr_in* sin;
> + struct rtable *rt = 0;
> + struct flowi fl;
> + struct net_device* netdev;
> + struct in_addr src_ip;
> + unsigned char* dev_addr;
> +
> + sin = (struct sockaddr_in*)addr;
> + if (sin->sin_family != AF_INET)
> + return -EINVAL;
> +
> + id_priv = container_of(id, struct rdma_id_private, id);
> +
> + /* If the address is local, use the device. If it is remote,
> + * look up a route to get the local address
> + */
> + netdev = ip_dev_find(sin->sin_addr.s_addr);
> + if (netdev) {
> + src_ip = sin->sin_addr;
> + dev_addr = netdev->dev_addr;
> + dev_put(netdev);
> + } else {
> + memset(&fl, 0, sizeof(fl));
> + fl.nl_u.ip4_u.daddr = sin->sin_addr.s_addr;
> + if (ip_route_output_key(&rt, &fl)) {
> + return -ENETUNREACH;
> + }
> + dev_addr = rt->idev->dev->dev_addr;
> + src_ip.s_addr = rt->rt_src;
> +
> + ip_rt_put(rt);
> + }
> +
> + down(&mutex);
> +
> + list_for_each_entry(cma_dev, &dev_list, list) {
> + if (memcmp(dev_addr,
> + &cma_dev->node_guid,
> + sizeof(cma_dev->node_guid)) == 0) {
> + /* If we find the device, then check if this
> + * is an iWARP device. If it is, then call the
> + * callback handler immediately because we
> + * already have the native address
> + */
> + if (cma_dev->device->node_type == IB_NODE_RNIC) {
> + struct sockaddr_in* cm_sin;
> + /* Set our source address */
> + cm_sin = (struct sockaddr_in*)
> + &id_priv->id.route.addr.src_addr;
> + cm_sin->sin_family = AF_INET;
> + cm_sin->sin_addr.s_addr = src_ip.s_addr;
> +
> + /* Claim the device in the mutex */
> + cma_attach_to_dev(id_priv, cma_dev);
> + ret = 0;
> + break;
> + }
> + }
> + }
> + up(&mutex);
> +
> + return ret;
> +}
> +
> +
> +/**
> + * rdma_resolve_addr - RDMA Resolve Address
> + *
> + * @id: RDMA identifier.
> + * @src_addr: Source IP address
> + * @dst_addr: Destination IP address
> + * &timeout_ms: Timeout to wait for address resolution
> + *
> + * Bind the specified cm_id to a local interface and if this is an IB
> + * CA, determine the GIDs associated with the specified IP addresses.
> + */
> int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
> struct sockaddr *dst_addr, int timeout_ms)
> {
> struct rdma_id_private *id_priv;
> - int ret;
> + int ret = 0;
>
> id_priv = container_of(id, struct rdma_id_private, id);
> if (!cma_comp_exch(id_priv, CMA_IDLE, CMA_ADDR_QUERY))
> return -EINVAL;
>
> atomic_inc(&id_priv->refcount);
> +
> id->route.addr.dst_addr = *dst_addr;
> - ret = ib_resolve_addr(src_addr, dst_addr, &id->route.addr.addr.ibaddr,
> - timeout_ms, addr_handler, id_priv);
> +
> + if (cma_acquire_iw_dev(id, dst_addr)==0) {
> +
> + enum rdma_cm_event_type event;
> +
> + cma_exch(id_priv, CMA_ADDR_RESOLVED);
> +
> + atomic_inc(&id_priv->dev_remove);
> +
> + event = RDMA_CM_EVENT_ADDR_RESOLVED;
> + if (cma_notify_user(id_priv, event, 0, NULL, 0)) {
> + cma_exch(id_priv, CMA_DESTROYING);
> + cma_deref_id(id_priv);
> + cma_release_remove(id_priv);
> + rdma_destroy_id(&id_priv->id);
> + return -EINVAL;
> + }
> +
> + cma_release_remove(id_priv);
> + cma_deref_id(id_priv);
> +
> + } else {
> +
> + ret = ib_resolve_addr(src_addr,
> + dst_addr, &id->route.addr.addr.ibaddr,
> + timeout_ms, addr_handler, id_priv);
> +
> + }
> +
> if (ret)
> goto err;
>
> @@ -980,10 +1288,13 @@
> int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
> {
> struct rdma_id_private *id_priv;
> + struct sockaddr_in* sin;
> struct ib_addr *ibaddr = &id->route.addr.addr.ibaddr;
> int ret;
>
> - if (addr->sa_family != AF_INET)
> + sin = (struct sockaddr_in*)addr;
> +
> + if (sin->sin_family != AF_INET)
> return -EINVAL;
>
> id_priv = container_of(id, struct rdma_id_private, id);
> @@ -994,9 +1305,11 @@
> id->route.addr.src_addr = *addr;
> ret = 0;
> } else {
> - ret = ib_translate_addr(addr, &ibaddr->sgid, &ibaddr->pkey);
> - if (!ret)
> - ret = cma_acquire_ib_dev(id_priv, &ibaddr->sgid);
> + if ((ret = cma_acquire_iw_dev(id, addr))) {
> + ret = ib_translate_addr(addr, &ibaddr->sgid, &ibaddr->pkey);
> + if (!ret)
> + ret = cma_acquire_ib_dev(id_priv, &ibaddr->sgid);
> + }
> }
>
> if (ret)
> @@ -1041,10 +1354,10 @@
> if (!private_data)
> return -ENOMEM;
>
> - id_priv->cm_id = ib_create_cm_id(id_priv->id.device, cma_ib_handler,
> + id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device, cma_ib_handler,
> id_priv);
> - if (IS_ERR(id_priv->cm_id)) {
> - ret = PTR_ERR(id_priv->cm_id);
> + if (IS_ERR(id_priv->cm_id.ib)) {
> + ret = PTR_ERR(id_priv->cm_id.ib);
> goto out;
> }
>
> @@ -1075,25 +1388,61 @@
> req.max_cm_retries = CMA_MAX_CM_RETRIES;
> req.srq = id_priv->id.qp->srq ? 1 : 0;
>
> - ret = ib_send_cm_req(id_priv->cm_id, &req);
> + ret = ib_send_cm_req(id_priv->cm_id.ib, &req);
> out:
> kfree(private_data);
> return ret;
> }
>
> +static int cma_connect_iw(struct rdma_id_private *id_priv,
> + struct rdma_conn_param *conn_param)
> +{
> + struct iw_cm_id* cm_id;
> + struct sockaddr_in* sin;
> + int ret;
> +
> + if (id_priv->id.qp == NULL)
> + return -EINVAL;
> +
> + cm_id = iw_create_cm_id(id_priv->id.device, cma_iw_handler, id_priv);
> + if (IS_ERR(cm_id)) {
> + ret = PTR_ERR(cm_id);
> + goto out;
> + }
> +
> + id_priv->cm_id.iw = cm_id;
> +
> + sin = (struct sockaddr_in*)&id_priv->id.route.addr.src_addr;
> + cm_id->local_addr = *sin;
> +
> + sin = (struct sockaddr_in*)&id_priv->id.route.addr.dst_addr;
> + cm_id->remote_addr = *sin;
> +
> + iw_cm_bind_qp(cm_id, id_priv->id.qp);
> +
> + ret = iw_cm_connect(cm_id, conn_param->private_data,
> + conn_param->private_data_len);
> +
> +out:
> + return ret;
> +}
> +
> int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
> {
> struct rdma_id_private *id_priv;
> int ret;
>
> id_priv = container_of(id, struct rdma_id_private, id);
> - if (!cma_comp_exch(id_priv, CMA_ROUTE_RESOLVED, CMA_CONNECT))
> + if (!cma_comp_exch(id_priv, CMA_ROUTE_RESOLVED, CMA_CONNECT))
> return -EINVAL;
>
> switch (id->device->node_type) {
> case IB_NODE_CA:
> ret = cma_connect_ib(id_priv, conn_param);
> break;
> + case IB_NODE_RNIC:
> + ret = cma_connect_iw(id_priv, conn_param);
> + break;
> default:
> ret = -ENOSYS;
> break;
> @@ -1131,7 +1480,7 @@
> rep.rnr_retry_count = conn_param->rnr_retry_count;
> rep.srq = id_priv->id.qp->srq ? 1 : 0;
>
> - return ib_send_cm_rep(id_priv->cm_id, &rep);
> + return ib_send_cm_rep(id_priv->cm_id.ib, &rep);
> }
>
> int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
> @@ -1147,6 +1496,12 @@
> case IB_NODE_CA:
> ret = cma_accept_ib(id_priv, conn_param);
> break;
> + case IB_NODE_RNIC: {
> + iw_cm_bind_qp(id_priv->cm_id.iw, id_priv->id.qp);
> + ret = iw_cm_accept(id_priv->cm_id.iw, conn_param->private_data,
> + conn_param->private_data_len);
> + break;
> + }
> default:
> ret = -ENOSYS;
> break;
> @@ -1175,9 +1530,15 @@
>
> switch (id->device->node_type) {
> case IB_NODE_CA:
> - ret = ib_send_cm_rej(id_priv->cm_id, IB_CM_REJ_CONSUMER_DEFINED,
> + ret = ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED,
> NULL, 0, private_data, private_data_len);
> break;
> +
> + case IB_NODE_RNIC:
> + ret = iw_cm_reject(id_priv->cm_id.iw,
> + private_data, private_data_len);
> + break;
> +
> default:
> ret = -ENOSYS;
> break;
> @@ -1190,7 +1551,6 @@
> {
> struct rdma_id_private *id_priv;
> int ret;
> -
> id_priv = container_of(id, struct rdma_id_private, id);
> if (!cma_comp(id_priv, CMA_CONNECT))
> return -EINVAL;
> @@ -1202,9 +1562,12 @@
> switch (id->device->node_type) {
> case IB_NODE_CA:
> /* Initiate or respond to a disconnect. */
> - if (ib_send_cm_dreq(id_priv->cm_id, NULL, 0))
> - ib_send_cm_drep(id_priv->cm_id, NULL, 0);
> + if (ib_send_cm_dreq(id_priv->cm_id.ib, NULL, 0))
> + ib_send_cm_drep(id_priv->cm_id.ib, NULL, 0);
> break;
> + case IB_NODE_RNIC:
> + ret = iw_cm_disconnect(id_priv->cm_id.iw);
> + break;
> default:
> break;
> }
> Index: Makefile
> ===================================================================
> --- Makefile (revision 4186)
> +++ Makefile (working copy)
> @@ -7,3 +7,5 @@
> obj-$(CONFIG_INFINIBAND_SRP) += ulp/srp/
> obj-$(CONFIG_KDAPL) += ulp/kdapl/
> obj-$(CONFIG_INFINIBAND_ISER) += ulp/iser/
> +obj-$(CONFIG_KRPING) += krping/
> +obj-$(CONFIG_RDMA_CMATOSE) += cmatose/
> Index: hw/amso1100/c2.c
> ===================================================================
> --- hw/amso1100/c2.c (revision 4482)
> +++ hw/amso1100/c2.c (working copy)
> @@ -933,7 +933,7 @@
> spin_lock_init(&c2_port->tx_lock);
>
> /* Copy our 48-bit ethernet hardware address */
> - memcpy_fromio(netdev->dev_addr, mmio_addr + C2_REGS_ENADDR, 6);
> + memcpy_fromio(netdev->dev_addr, mmio_addr + C2_REGS_RDMA_ENADDR, 6);
>
> /* Validate the MAC address */
> if(!is_valid_ether_addr(netdev->dev_addr)) {
> Index: hw/amso1100/c2_qp.c
> ===================================================================
> --- hw/amso1100/c2_qp.c (revision 4482)
> +++ hw/amso1100/c2_qp.c (working copy)
> @@ -184,7 +184,7 @@
> struct c2_vq_req *vq_req;
> ccwr_qp_destroy_req_t wr;
> ccwr_qp_destroy_rep_t *reply;
> - int err;
> + int err;
>
> /*
> * Allocate a verb request message
> @@ -343,8 +343,6 @@
> qp->send_sgl_depth = qp_attrs->cap.max_send_sge;
> qp->rdma_write_sgl_depth = qp_attrs->cap.max_send_sge;
> qp->recv_sgl_depth = qp_attrs->cap.max_recv_sge;
> - qp->event_handler = NULL;
> - qp->context = NULL;
>
> /* Initialize the SQ MQ */
> q_size = be32_to_cpu(reply->sq_depth);
> Index: hw/amso1100/c2.h
> ===================================================================
> --- hw/amso1100/c2.h (revision 4482)
> +++ hw/amso1100/c2.h (working copy)
> @@ -113,6 +113,7 @@
> C2_REGS_Q2_MSGSIZE = 0x0038,
> C2_REGS_Q2_SHARED = 0x0040,
> C2_REGS_ENADDR = 0x004C,
> + C2_REGS_RDMA_ENADDR = 0x0054,
> C2_REGS_HRX_CUR = 0x006C,
> };
>
> @@ -592,16 +593,11 @@
> extern int c2_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify);
>
> /* CM */
> -extern int c2_qp_connect(struct c2_dev *c2dev, struct c2_qp *qp, u32 remote_addr,
> - u16 remote_port, u32 pdata_len, u8 *pdata);
> -extern int c2_cr_query(struct c2_dev *c2dev, u32 cr_id,
> - struct c2_cr_query_attrs *cr_attrs);
> -extern int c2_cr_accept(struct c2_dev *c2dev, u32 cr_id, struct c2_qp *qp,
> - u32 pdata_len, u8 *pdata);
> -extern int c2_cr_reject(struct c2_dev *c2dev, u32 cr_id);
> -extern int c2_ep_listen_create(struct c2_dev *c2dev, u32 addr, u16 port,
> - u32 backlog, struct c2_ep *ep);
> -extern int c2_ep_listen_destroy(struct c2_dev *c2dev, struct c2_ep *ep);
> +extern int c2_llp_connect(struct iw_cm_id* cm_id, const void* pdata, u8 pdata_len);
> +extern int c2_llp_accept(struct iw_cm_id* cm_id, const void* pdata, u8 pdata_len);
> +extern int c2_llp_reject(struct iw_cm_id* cm_id, const void* pdata, u8 pdata_len);
> +extern int c2_llp_service_create(struct iw_cm_id* cm_id, int backlog);
> +extern int c2_llp_service_destroy(struct iw_cm_id* cm_id);
>
> /* MM */
> extern int c2_nsmr_register_phys_kern(struct c2_dev *c2dev, u64 **addr_list,
> Index: hw/amso1100/c2_pd.c
> ===================================================================
> --- hw/amso1100/c2_pd.c (revision 4482)
> +++ hw/amso1100/c2_pd.c (working copy)
> @@ -44,6 +44,8 @@
> {
> int err = 0;
>
> + printk(KERN_ERR "%s:%d\n", __FUNCTION__, __LINE__);
> +
> might_sleep();
>
> atomic_set(&pd->sqp_count, 0);
> Index: hw/amso1100/c2_ae.c
> ===================================================================
> --- hw/amso1100/c2_ae.c (revision 4482)
> +++ hw/amso1100/c2_ae.c (working copy)
> @@ -35,51 +35,37 @@
> #include "cc_status.h"
> #include "cc_ae.h"
>
> -enum conn_result
> -c2_convert_cm_status(u32 cc_status)
> +static int c2_convert_cm_status(u32 cc_status)
> {
> switch (cc_status) {
> - case CC_CONN_STATUS_SUCCESS: return IW_CONN_ACCEPT;
> - case CC_CONN_STATUS_REJECTED: return IW_CONN_RESET;
> - case CC_CONN_STATUS_REFUSED: return IW_CONN_PEER_REJECT;
> - case CC_CONN_STATUS_TIMEDOUT: return IW_CONN_TIMEDOUT;
> - case CC_CONN_STATUS_NETUNREACH: return IW_CONN_NO_ROUTE_TO_HOST;
> - case CC_CONN_STATUS_HOSTUNREACH: return IW_CONN_NO_ROUTE_TO_HOST;
> - case CC_CONN_STATUS_INVALID_RNIC: return IW_CONN_INVALID_PARM;
> - case CC_CONN_STATUS_INVALID_QP: return IW_CONN_INVALID_PARM;
> - case CC_CONN_STATUS_INVALID_QP_STATE: return IW_CONN_INVALID_PARM;
> + case CC_CONN_STATUS_SUCCESS:
> + return 0;
> + case CC_CONN_STATUS_REJECTED:
> + return -ENETRESET;
> + case CC_CONN_STATUS_REFUSED:
> + return -ECONNREFUSED;
> + case CC_CONN_STATUS_TIMEDOUT:
> + return -ETIMEDOUT;
> + case CC_CONN_STATUS_NETUNREACH:
> + return -ENETUNREACH;
> + case CC_CONN_STATUS_HOSTUNREACH:
> + return -EHOSTUNREACH;
> + case CC_CONN_STATUS_INVALID_RNIC:
> + return -EINVAL;
> + case CC_CONN_STATUS_INVALID_QP:
> + return -EINVAL;
> + case CC_CONN_STATUS_INVALID_QP_STATE:
> + return -EINVAL;
> default:
> panic("Unable to convert CM status: %d\n", cc_status);
> break;
> }
> }
>
> -static int
> -is_cm_event(cc_event_id_t id)
> -{
> - int is_cm;
> -
> - switch (id) {
> - case CCAE_ACTIVE_CONNECT_RESULTS:
> - case CCAE_BAD_CLOSE:
> - case CCAE_LLP_CLOSE_COMPLETE:
> - case CCAE_LLP_CONNECTION_RESET:
> - case CCAE_LLP_CONNECTION_LOST:
> - is_cm = 1;
> - break;
> - case CCAE_TERMINATE_MESSAGE_RECEIVED:
> - case CCAE_CQ_SQ_COMPLETION_OVERFLOW:
> - default:
> - is_cm = 0;
> - break;
> - }
> -
> - return is_cm;
> -}
> void c2_ae_event(struct c2_dev *c2dev, u32 mq_index)
> {
> - ccwr_t *wr;
> struct c2_mq *mq = c2dev->qptr_array[mq_index];
> + ccwr_t *wr;
> void *resource_user_context;
> struct iw_cm_event cm_event;
> struct ib_event ib_event;
> @@ -94,6 +80,7 @@
> if (!wr)
> return;
>
> + memset(&cm_event, 0, sizeof(cm_event));
> event_id = c2_wr_get_id(wr);
> resource_indicator = be32_to_cpu(wr->ae.ae_generic.resource_type);
> resource_user_context = (void *)(unsigned long)wr->ae.ae_generic.user_context;
> @@ -102,117 +89,126 @@
> case CC_RES_IND_QP: {
>
> struct c2_qp *qp = (struct c2_qp *)resource_user_context;
> + cm_event.status = c2_convert_cm_status(c2_wr_get_result(wr));
>
> - if (is_cm_event(event_id)) {
> -
> - cm_event.device = &c2dev->ibdev;
> - if (event_id == CCAE_ACTIVE_CONNECT_RESULTS) {
> - cm_event.event = IW_EVENT_ACTIVE_CONNECT_RESULTS;
> - cm_event.element.active_results.result =
> - c2_convert_cm_status(c2_wr_get_result(wr));
> - cm_event.element.active_results.conn_attr.local_addr.s_addr =
> - wr->ae.ae_active_connect_results.laddr;
> - cm_event.element.active_results.conn_attr.remote_addr.s_addr =
> - wr->ae.ae_active_connect_results.raddr;
> - cm_event.element.active_results.conn_attr.local_port =
> - wr->ae.ae_active_connect_results.lport;
> - cm_event.element.active_results.conn_attr.remote_port =
> - wr->ae.ae_active_connect_results.rport;
> - cm_event.element.active_results.private_data_len =
> + switch (event_id) {
> + case CCAE_ACTIVE_CONNECT_RESULTS:
> + cm_event.event = IW_CM_EVENT_CONNECT_REPLY;
> + cm_event.local_addr.sin_addr.s_addr =
> + wr->ae.ae_active_connect_results.laddr;
> + cm_event.remote_addr.sin_addr.s_addr =
> + wr->ae.ae_active_connect_results.raddr;
> + cm_event.local_addr.sin_port =
> + wr->ae.ae_active_connect_results.lport;
> + cm_event.remote_addr.sin_port =
> + wr->ae.ae_active_connect_results.rport;
> + cm_event.private_data_len =
> be32_to_cpu(wr->ae.ae_active_connect_results.private_data_length);
>
> + if (cm_event.private_data_len) {
> /* XXX */
> - pdata = kmalloc(cm_event.element.active_results.private_data_len,
> - GFP_ATOMIC);
> - if (!pdata)
> - break;
> + pdata = kmalloc(cm_event.private_data_len, GFP_ATOMIC);
> + if (!pdata) {
> + /* Ignore the request, maybe the remote peer
> + * will retry */
> + dprintk("Ignored connect request -- no memory for pdata"
> + "private_data_len=%d\n", cm_event.private_data_len);
> + goto ignore_it;
> + }
>
> memcpy(pdata,
> wr->ae.ae_active_connect_results.private_data,
> - cm_event.element.active_results.private_data_len);
> - cm_event.element.active_results.private_data = pdata;
> + cm_event.private_data_len);
>
> - } else {
> - cm_event.event = IW_EVENT_DISCONNECT;
> + cm_event.private_data = pdata;
> }
> + if (qp->cm_id->event_handler)
> + qp->cm_id->event_handler(qp->cm_id, &cm_event);
>
> - if (qp->event_handler)
> - (*qp->event_handler)(&cm_event, qp->context);
> + break;
>
> - if (pdata)
> - kfree(pdata);
> - } else {
> -
> + case CCAE_TERMINATE_MESSAGE_RECEIVED:
> + case CCAE_CQ_SQ_COMPLETION_OVERFLOW:
> ib_event.device = &c2dev->ibdev;
> ib_event.element.qp = &qp->ibqp;
> - /* XXX */
> ib_event.event = IB_EVENT_QP_REQ_ERR;
>
> if(qp->ibqp.event_handler)
> - (*qp->ibqp.event_handler)(&ib_event, qp->context);
> - }
> + (*qp->ibqp.event_handler)(&ib_event,
> + qp->ibqp.qp_context);
> + case CCAE_BAD_CLOSE:
> + case CCAE_LLP_CLOSE_COMPLETE:
> + case CCAE_LLP_CONNECTION_RESET:
> + case CCAE_LLP_CONNECTION_LOST:
> + default:
> + cm_event.event = IW_CM_EVENT_CLOSE;
> + if (qp->cm_id->event_handler)
> + qp->cm_id->event_handler(qp->cm_id, &cm_event);
>
> + }
> break;
> }
> +
> case CC_RES_IND_EP: {
>
> - struct c2_ep *ep = (struct c2_ep *)resource_user_context;
> + struct iw_cm_id* cm_id = (struct iw_cm_id*)resource_user_context;
>
> + dprintk("CC_RES_IND_EP event_id=%d\n", event_id);
> if (event_id != CCAE_CONNECTION_REQUEST) {
> dprintk("%s: Invalid event_id: %d\n", __FUNCTION__, event_id);
> break;
> }
>
> - cm_event.device = &c2dev->ibdev;
> - cm_event.event = IW_EVENT_CONNECT_REQUEST;
> - cm_event.element.conn_request.cr_id =
> + cm_event.event = IW_CM_EVENT_CONNECT_REQUEST;
> + cm_event.provider_id =
> wr->ae.ae_connection_request.cr_handle;
> - cm_event.element.conn_request.conn_attr.local_addr.s_addr =
> + cm_event.local_addr.sin_addr.s_addr =
> wr->ae.ae_connection_request.laddr;
> - cm_event.element.conn_request.conn_attr.remote_addr.s_addr =
> + cm_event.remote_addr.sin_addr.s_addr =
> wr->ae.ae_connection_request.raddr;
> - cm_event.element.conn_request.conn_attr.local_port =
> + cm_event.local_addr.sin_port =
> wr->ae.ae_connection_request.lport;
> - cm_event.element.conn_request.conn_attr.remote_port =
> + cm_event.remote_addr.sin_port =
> wr->ae.ae_connection_request.rport;
> - cm_event.element.conn_request.private_data_len =
> + cm_event.private_data_len =
> be32_to_cpu(wr->ae.ae_connection_request.private_data_length);
>
> - /* XXX */
> - pdata = kmalloc(cm_event.element.conn_request.private_data_len,
> - GFP_ATOMIC);
> - if (!pdata)
> - break;
> + if (cm_event.private_data_len) {
> + pdata = kmalloc(cm_event.private_data_len, GFP_ATOMIC);
> + if (!pdata) {
> + /* Ignore the request, maybe the remote peer
> + * will retry */
> + dprintk("Ignored connect request -- no memory for pdata"
> + "private_data_len=%d\n", cm_event.private_data_len);
> + goto ignore_it;
> + }
> + memcpy(pdata,
> + wr->ae.ae_connection_request.private_data,
> + cm_event.private_data_len);
>
> - memcpy(pdata,
> - wr->ae.ae_connection_request.private_data,
> - cm_event.element.conn_request.private_data_len);
> -
> - cm_event.element.conn_request.private_data = pdata;
> -
> - if (ep->event_handler)
> - (*ep->event_handler)(&cm_event, ep->listen_context);
> -
> - kfree(pdata);
> + cm_event.private_data = pdata;
> + }
> + if (cm_id->event_handler)
> + cm_id->event_handler(cm_id, &cm_event);
> break;
> }
> +
> case CC_RES_IND_CQ: {
> struct c2_cq *cq = (struct c2_cq *)resource_user_context;
>
> + dprintk("IB_EVENT_CQ_ERR\n");
> ib_event.device = &c2dev->ibdev;
> ib_event.element.cq = &cq->ibcq;
> ib_event.event = IB_EVENT_CQ_ERR;
>
> if (cq->ibcq.event_handler)
> - (*cq->ibcq.event_handler)(&ib_event, cq->ibcq.cq_context);
> + cq->ibcq.event_handler(&ib_event, cq->ibcq.cq_context);
> }
> +
> default:
> break;
> }
> -
> - /*
> - * free the adapter message
> - */
> +
> + ignore_it:
> c2_mq_free(mq);
> }
> -
> Index: hw/amso1100/c2_provider.c
> ===================================================================
> --- hw/amso1100/c2_provider.c (revision 4482)
> +++ hw/amso1100/c2_provider.c (working copy)
> @@ -305,8 +305,6 @@
> struct c2_cq *cq;
> int err;
>
> - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__);
> -
> cq = kmalloc(sizeof(*cq), GFP_KERNEL);
> if (!cq) {
> dprintk("%s: Unable to allocate CQ\n", __FUNCTION__);
> @@ -315,6 +313,7 @@
>
> err = c2_init_cq(to_c2dev(ibdev), entries, NULL, cq);
> if (err) {
> + dprintk("%s: error initializing CQ\n", __FUNCTION__);
> kfree(cq);
> return ERR_PTR(err);
> }
> @@ -540,156 +539,96 @@
> return -ENOSYS;
> }
>
> -static int c2_connect_qp(struct ib_qp *ib_qp,
> - struct iw_conn_attr *attr,
> - void (*event_handler)(struct iw_cm_event*, void*),
> - void *context,
> - u8 *pdata,
> - int pdata_len
> - )
> +static int c2_connect(struct iw_cm_id* cm_id,
> + const void* pdata, u8 pdata_len)
> {
> - struct c2_qp *qp = to_c2qp(ib_qp);
> int err;
> + struct c2_qp* qp = container_of(cm_id->qp, struct c2_qp, ibqp);
>
> dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__);
>
> - if (!event_handler)
> + if (cm_id->qp == NULL)
> return -EINVAL;
>
> - /*
> - * Store the event handler and the
> - * context in the QP.
> - */
> - qp->event_handler = event_handler;
> - qp->context = context;
> + /* Cache the cm_id in the qp */
> + qp->cm_id = cm_id;
>
> - err = c2_qp_connect(to_c2dev(ib_qp->device), qp,
> - attr->remote_addr.s_addr, attr->remote_port,
> - pdata_len, pdata);
> - if (err) {
> - qp->event_handler = NULL;
> - qp->context = NULL;
> - }
> + err = c2_llp_connect(cm_id, pdata, pdata_len);
>
> return err;
> }
>
> -static int c2_disconnect_qp(struct ib_qp *qp,
> - int abrupt)
> +static int c2_disconnect(struct iw_cm_id* cm_id, int abrupt)
> {
> struct ib_qp_attr attr;
> + struct ib_qp *ib_qp = cm_id->qp;
> int err;
>
> dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__);
>
> + if (ib_qp == 0)
> + /* If this is a lietening endpoint, there is no QP */
> + return 0;
> +
> memset(&attr, 0, sizeof(struct ib_qp_attr));
> if (abrupt)
> attr.qp_state = IB_QPS_ERR;
> else
> attr.qp_state = IB_QPS_SQD;
>
> - err = c2_modify_qp(qp, &attr, IB_QP_STATE);
> + err = c2_modify_qp(ib_qp, &attr, IB_QP_STATE);
> return err;
> }
>
> -static int c2_accept_cr(struct ib_device *ibdev,
> - u32 cr_id,
> - struct ib_qp *ib_qp,
> - void (*event_handler)(struct iw_cm_event*, void*),
> - void *context,
> - u8 *pdata,
> - int pdata_len)
> +static int c2_accept(struct iw_cm_id* cm_id, const void *pdata, u8 pdata_len)
> {
> - struct c2_qp *qp = to_c2qp(ib_qp);
> int err;
>
> dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__);
>
> - /*
> - * Store the event handler and the
> - * context in the QP.
> - */
> - qp->event_handler = event_handler;
> - qp->context = context;
> + err = c2_llp_accept(cm_id, pdata, pdata_len);
>
> - err = c2_cr_accept(to_c2dev(ibdev), cr_id, qp,
> - pdata_len, pdata);
> -
> return err;
> }
>
> -static int c2_reject_cr(struct ib_device *ibdev,
> - u32 cr_id,
> - u8 *pdata,
> - int pdata_len)
> +static int c2_reject(struct iw_cm_id* cm_id, const void* pdata, u8 pdata_len)
> {
> int err;
>
> dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__);
>
> - err = c2_cr_reject(to_c2dev(ibdev), cr_id);
> + err = c2_llp_reject(cm_id, pdata, pdata_len);
> return err;
> }
>
> -static int c2_query_cr(struct ib_device *ibdev,
> - u32 cr_id,
> - struct iw_conn_request *req)
> +static int c2_getpeername(struct iw_cm_id* cm_id,
> + struct sockaddr_in* local_addr,
> + struct sockaddr_in* remote_addr )
> {
> - int err;
> - struct c2_cr_query_attrs cr_attrs;
> -
> dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__);
>
> - err = c2_cr_query(to_c2dev(ibdev), cr_id, &cr_attrs);
> - if (!err) {
> - req->cr_id = cr_id;
> - req->conn_attr.local_addr.s_addr = cr_attrs.local_addr;
> - req->conn_attr.local_port = cr_attrs.local_port;
> - req->conn_attr.remote_addr.s_addr = cr_attrs.remote_addr;
> - req->conn_attr.remote_port = cr_attrs.remote_port;
> - /* XXX pdata? */
> - }
> - return err;
> + *local_addr = cm_id->local_addr;
> + *remote_addr = cm_id->remote_addr;
> + return 0;
> }
>
> -static int c2_create_listen_ep(struct ib_device *ibdev,
> - struct iw_listen_ep_attr *ep_attr,
> - void **ep_handle)
> +static int c2_service_create(struct iw_cm_id* cm_id, int backlog)
> {
> int err;
> - struct c2_ep *ep;
>
> dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__);
> -
> - ep = kmalloc(sizeof(*ep), GFP_KERNEL);
> - if (!ep) {
> - dprintk("%s: Unable to allocate EP\n", __FUNCTION__);
> - return -ENOMEM;
> - }
> -
> - ep->event_handler = ep_attr->event_handler;
> - ep->listen_context = ep_attr->listen_context;
> -
> - err = c2_ep_listen_create(to_c2dev(ibdev),
> - ep_attr->addr.s_addr, ep_attr->port,
> - ep_attr->backlog, ep);
> - if (err)
> - kfree(ep);
> - else
> - *ep_handle = (void *)ep;
> -
> + err = c2_llp_service_create(cm_id, backlog);
> return err;
> }
>
> -static int c2_destroy_listen_ep(struct ib_device *ibdev, void *ep_handle)
> +static int c2_service_destroy(struct iw_cm_id* cm_id)
> {
> - struct c2_ep *ep = (struct c2_ep *)ep_handle;
> -
> + int err;
> dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__);
>
> - c2_ep_listen_destroy(to_c2dev(ibdev), ep);
> - kfree(ep);
> - return 0;
> + err = c2_llp_service_destroy(cm_id);
> +
> + return err;
> }
>
> int c2_register_device(struct c2_dev *dev)
> @@ -742,13 +681,13 @@
> dev->ibdev.post_recv = c2_post_receive;
>
> dev->ibdev.iwcm = kmalloc(sizeof(*dev->ibdev.iwcm), GFP_KERNEL);
> - dev->ibdev.iwcm->connect_qp = c2_connect_qp;
> - dev->ibdev.iwcm->disconnect_qp = c2_disconnect_qp;
> - dev->ibdev.iwcm->accept_cr = c2_accept_cr;
> - dev->ibdev.iwcm->reject_cr = c2_reject_cr;
> - dev->ibdev.iwcm->query_cr = c2_query_cr;
> - dev->ibdev.iwcm->create_listen_ep = c2_create_listen_ep;
> - dev->ibdev.iwcm->destroy_listen_ep = c2_destroy_listen_ep;
> + dev->ibdev.iwcm->connect = c2_connect;
> + dev->ibdev.iwcm->disconnect = c2_disconnect;
> + dev->ibdev.iwcm->accept = c2_accept;
> + dev->ibdev.iwcm->reject = c2_reject;
> + dev->ibdev.iwcm->getpeername = c2_getpeername;
> + dev->ibdev.iwcm->create_listen = c2_service_create;
> + dev->ibdev.iwcm->destroy_listen = c2_service_destroy;
>
> ret = ib_register_device(&dev->ibdev);
> if (ret)
> Index: hw/amso1100/c2_provider.h
> ===================================================================
> --- hw/amso1100/c2_provider.h (revision 4482)
> +++ hw/amso1100/c2_provider.h (working copy)
> @@ -115,17 +115,15 @@
> struct c2_wq {
> spinlock_t lock;
> };
> -
> +struct iw_cm_id;
> struct c2_qp {
> struct ib_qp ibqp;
> + struct iw_cm_id* cm_id;
> spinlock_t lock;
> atomic_t refcount;
> wait_queue_head_t wait;
> int qpn;
>
> - void (*event_handler)(struct iw_cm_event *, void *);
> - void *context;
> -
> u32 adapter_handle;
> u32 send_sgl_depth;
> u32 recv_sgl_depth;
> @@ -136,15 +134,6 @@
> struct c2_mq rq_mq;
> };
>
> -struct c2_ep {
> - u32 adapter_handle;
> - void (*event_handler)(struct iw_cm_event *, void *);
> - void *listen_context;
> - u32 addr;
> - u16 port;
> - int backlog;
> -};
> -
> struct c2_cr_query_attrs {
> u32 local_addr;
> u32 remote_addr;
> Index: hw/amso1100/c2_cm.c
> ===================================================================
> --- hw/amso1100/c2_cm.c (revision 4482)
> +++ hw/amso1100/c2_cm.c (working copy)
> @@ -35,11 +35,10 @@
> #include "c2_vq.h"
> #include <rdma/iw_cm.h>
>
> -int
> -c2_qp_connect(struct c2_dev *c2dev, struct c2_qp *qp,
> - u32 remote_addr, u16 remote_port,
> - u32 pdata_len, u8 *pdata)
> +int c2_llp_connect(struct iw_cm_id* cm_id, const void* pdata, u8 pdata_len)
> {
> + struct c2_dev *c2dev = to_c2dev(cm_id->device);
> + struct c2_qp *qp = to_c2qp(cm_id->qp);
> ccwr_qp_connect_req_t *wr; /* variable size needs a malloc. */
> struct c2_vq_req *vq_req;
> int err;
> @@ -70,8 +69,8 @@
> wr->rnic_handle = c2dev->adapter_handle;
> wr->qp_handle = qp->adapter_handle;
>
> - wr->remote_addr = remote_addr; /* already in Network Byte Order */
> - wr->remote_port = remote_port; /* already in Network Byte Order */
> + wr->remote_addr = cm_id->remote_addr.sin_addr.s_addr;
> + wr->remote_port = cm_id->remote_addr.sin_port;
>
> /*
> * Move any private data from the callers's buf into
> @@ -96,14 +95,18 @@
> }
>
> int
> -c2_ep_listen_create(struct c2_dev *c2dev, u32 addr,
> - u16 port, u32 backlog, struct c2_ep *ep)
> +c2_llp_service_create(struct iw_cm_id* cm_id, int backlog)
> {
> + struct c2_dev *c2dev;
> ccwr_ep_listen_create_req_t wr;
> ccwr_ep_listen_create_rep_t *reply;
> struct c2_vq_req *vq_req;
> int err;
>
> + c2dev = to_c2dev(cm_id->device);
> + if (c2dev == NULL)
> + return -EINVAL;
> +
> /*
> * Allocate verbs request.
> */
> @@ -115,15 +118,15 @@
> * Build the WR
> */
> c2_wr_set_id(&wr, CCWR_EP_LISTEN_CREATE);
> - wr.hdr.context = (unsigned long)vq_req;
> + wr.hdr.context = (u64)(unsigned long)vq_req;
> wr.rnic_handle = c2dev->adapter_handle;
> - wr.local_addr = addr; /* already in Net Byte Order */
> - wr.local_port = port; /* already in Net Byte Order */
> + wr.local_addr = cm_id->local_addr.sin_addr.s_addr;
> + wr.local_port = cm_id->local_addr.sin_port;
> wr.backlog = cpu_to_be32(backlog);
> - wr.user_context = (unsigned long)ep;
> + wr.user_context = (u64)(unsigned long)cm_id;
>
> /*
> - * reference the request struct. dereferenced in the int handler.
> + * Reference the request struct. Dereferenced in the int handler.
> */
> vq_req_get(c2dev, vq_req);
>
> @@ -160,12 +163,7 @@
> /*
> * get the adapter handle
> */
> - ep->adapter_handle = reply->ep_handle;
> - if (port != reply->local_port)
> - {
> - // XXX
> - //*p_port = reply->local_port;
> - }
> + cm_id->provider_id = reply->ep_handle;
>
> /*
> * free vq stuff
> @@ -184,13 +182,19 @@
>
>
> int
> -c2_ep_listen_destroy(struct c2_dev *c2dev, struct c2_ep *ep)
> +c2_llp_service_destroy(struct iw_cm_id* cm_id)
> {
> +
> + struct c2_dev *c2dev;
> ccwr_ep_listen_destroy_req_t wr;
> ccwr_ep_listen_destroy_rep_t *reply;
> struct c2_vq_req *vq_req;
> int err;
>
> + c2dev = to_c2dev(cm_id->device);
> + if (c2dev == NULL)
> + return -EINVAL;
> +
> /*
> * Allocate verbs request.
> */
> @@ -205,7 +209,7 @@
> c2_wr_set_id(&wr, CCWR_EP_LISTEN_DESTROY);
> wr.hdr.context = (unsigned long)vq_req;
> wr.rnic_handle = c2dev->adapter_handle;
> - wr.ep_handle = ep->adapter_handle;
> + wr.ep_handle = cm_id->provider_id;
>
> /*
> * reference the request struct. dereferenced in the int handler.
> @@ -250,87 +254,20 @@
>
>
> int
> -c2_cr_query(struct c2_dev *c2dev, u32 cr_id,
> - struct c2_cr_query_attrs *cr_attrs)
> +c2_llp_accept(struct iw_cm_id* cm_id, const void* pdata, u8 pdata_len)
> {
> - ccwr_ep_query_req_t wr;
> - ccwr_ep_query_rep_t *reply;
> - struct c2_vq_req *vq_req;
> - int err;
> + struct c2_dev *c2dev = to_c2dev(cm_id->device);
> + struct c2_qp *qp = to_c2qp(cm_id->qp);
> + ccwr_cr_accept_req_t *wr; /* variable length WR */
> + struct c2_vq_req *vq_req;
> + ccwr_cr_accept_rep_t *reply; /* VQ Reply msg ptr. */
> + int err;
>
> - /*
> - * Create and send a WR_EP_CREATE...
> - */
> - vq_req = vq_req_alloc(c2dev);
> - if (!vq_req) {
> - return -ENOMEM;
> - }
> + /* Make sure there's a bound QP */
> + if (qp == 0)
> + return -EINVAL;
>
> - /*
> - * Build the WR
> - */
> - c2_wr_set_id(&wr, CCWR_EP_QUERY);
> - wr.hdr.context = (unsigned long)vq_req;
> - wr.rnic_handle = c2dev->adapter_handle;
> - wr.ep_handle = cr_id;
> -
> /*
> - * reference the request struct. dereferenced in the int handler.
> - */
> - vq_req_get(c2dev, vq_req);
> -
> - /*
> - * Send WR to adapter
> - */
> - err = vq_send_wr(c2dev, (ccwr_t*)&wr);
> - if (err) {
> - vq_req_put(c2dev, vq_req);
> - goto bail0;
> - }
> -
> - /*
> - * Wait for reply from adapter
> - */
> - err = vq_wait_for_reply(c2dev, vq_req);
> - if (err) {
> - goto bail0;
> - }
> -
> - /*
> - * Process reply
> - */
> - reply = (ccwr_ep_query_rep_t*)(unsigned long)vq_req->reply_msg;
> - if (!reply) {
> - err = -ENOMEM;
> - goto bail0;
> - }
> - if ( (err = c2_errno(reply)) != 0) {
> - goto bail1;
> - }
> -
> - cr_attrs->local_addr = reply->local_addr;
> - cr_attrs->local_port = reply->local_port;
> - cr_attrs->remote_addr = reply->remote_addr;
> - cr_attrs->remote_port = reply->remote_port;
> -
> -bail1:
> - vq_repbuf_free(c2dev, reply);
> -bail0:
> - vq_req_free(c2dev, vq_req);
> - return err;
> -}
> -
> -
> -int
> -c2_cr_accept(struct c2_dev *c2dev, u32 cr_id, struct c2_qp *qp,
> - u32 pdata_len, u8 *pdata)
> -{
> - ccwr_cr_accept_req_t *wr; /* variable length WR */
> - struct c2_vq_req *vq_req;
> - ccwr_cr_accept_rep_t* reply; /* VQ Reply msg ptr. */
> - int err;
> -
> - /*
> * only support the max private_data length
> */
> if (pdata_len > CC_MAX_PRIVATE_DATA_SIZE) {
> @@ -357,7 +294,7 @@
> c2_wr_set_id(wr, CCWR_CR_ACCEPT);
> wr->hdr.context = (unsigned long)vq_req;
> wr->rnic_handle = c2dev->adapter_handle;
> - wr->ep_handle = cr_id;
> + wr->ep_handle = (u32)cm_id->provider_id;
> wr->qp_handle = qp->adapter_handle;
> if (pdata) {
> wr->private_data_length = cpu_to_be32(pdata_len);
> @@ -407,15 +344,17 @@
> return err;
> }
>
> -
> int
> -c2_cr_reject(struct c2_dev *c2dev, u32 cr_id)
> +c2_llp_reject(struct iw_cm_id* cm_id, const void* pdata, u8 pdata_len)
> {
> + struct c2_dev *c2dev;
> ccwr_cr_reject_req_t wr;
> struct c2_vq_req *vq_req;
> ccwr_cr_reject_rep_t *reply;
> int err;
>
> + c2dev = to_c2dev(cm_id->device);
> +
> /*
> * Allocate verbs request.
> */
> @@ -430,7 +369,7 @@
> c2_wr_set_id(&wr, CCWR_CR_REJECT);
> wr.hdr.context = (unsigned long)vq_req;
> wr.rnic_handle = c2dev->adapter_handle;
> - wr.ep_handle = cr_id;
> + wr.ep_handle = (u32)cm_id->provider_id;
>
> /*
> * reference the request struct. dereferenced in the int handler.
>
> _______________________________________________
> openib-general mailing list
> openib-general at openib.org
> http://openib.org/mailman/listinfo/openib-general
>
> To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general
More information about the general
mailing list