<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=us-ascii">
<TITLE></TITLE>
<META content="MSHTML 6.00.2800.1458" name=GENERATOR></HEAD>
<BODY>
<P><FONT size=2>In gen1 TS cm there was a function
:<BR>ib_cm_service_assign()<BR>that return a free service_id .<BR>and then you
could call ib_cm_listen with this service_id.<BR><BR>In Dapl implementation we
use this when we want to listen on a not pre assign service_id<BR>(Dat verb:
Dat_Psp_Create_any )<BR><BR>I think gen2 cm should include something similear
:<BR><BR>There can be 2 ways to implement it :<BR>1) to add new function as it
was in gen1<BR><BR>Index:
include/ib_cm.h<BR>===================================================================<BR>+/**<BR>+
* ib_cm_service_assign() - return free service_id<BR>+ */<BR>+u64
ib_cm_service_assign()(void);<BR>+<BR><BR>2) change the ib_cm_listen to
understand that the reqeust comes without service_id<BR> and then it
will assign a service_id and only then will do the listen<BR> this
can be dane in many ways like :if the service_id == 0 (like sockets
bind)<BR> <BR><FONT face="Monotype Corsiva"
size=5> </FONT> <FONT face="Monotype Corsiva" color=#000080>Itamar
Rabenstein</FONT> <BR><FONT face="CG Times" size=2> Mellanox Technologies
Ltd</FONT> <BR><FONT face="CG Times" size=2>mailto :
itamar@mellanox.co.il</FONT> <BR><FONT face="CG Times" size=2>
phone: 972-3-6259506</FONT> </P>
<P><BR></FONT><FONT size=2>-----Original Message-----<BR>From: Sean Hefty [<A
href="mailto:mshefty@ichips.intel.com">mailto:mshefty@ichips.intel.com</A>]<BR>Sent:
Thursday, December 16, 2004 9:56 PM<BR>To: openib-general@openib.org;
halr@voltaire.com<BR>Subject: [openib-general] [PATCH] initial CM
module<BR><BR><BR>This patch adds in the initial CM API and module code.
The module loads,<BR>unloads, and allocates/deallocates connection structures,
but that's about it.<BR>This patch does not include changes needed to Kconfig or
the Makefile, since I'm<BR>not sure that it makes sense to change these
yet.<BR><BR>I will commit this unless there are any objections.<BR><BR>-
Sean<BR><BR>Index:
include/ib_cm.h<BR>===================================================================<BR>---
include/ib_cm.h (revision 0)<BR>+++
include/ib_cm.h (revision 0)<BR>@@ -0,0 +1,387
@@<BR>+/*<BR>+ * This software is available to you under a choice of one of
two<BR>+ * licenses. You may choose to be licensed under the terms of the
GNU<BR>+ * General Public License (GPL) Version 2, available at<BR>+ * <<A
href="http://www.fsf.org/copyleft/gpl.html"
target=_blank>http://www.fsf.org/copyleft/gpl.html</A>>, or the OpenIB.org
BSD<BR>+ * license, available in the LICENSE.TXT file accompanying this<BR>+ *
software. These details are also available at<BR>+ * <<A
href="http://openib.org/license.html"
target=_blank>http://openib.org/license.html</A>>.<BR>+ *<BR>+ * THE SOFTWARE
IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,<BR>+ * EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF<BR>+ * MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND<BR>+ * NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS<BR>+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN<BR>+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN<BR>+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE<BR>+ * SOFTWARE.<BR>+ *<BR>+ * Copyright (c) 2004 Intel
Corporation. All rights reserved.<BR>+ * Copyright (c) 2004 Topspin
Corporation. All rights reserved.<BR>+ * Copyright (c) 2004 Voltaire
Corporation. All rights reserved.<BR>+ *<BR>+ * $Id$<BR>+ */<BR>+#if
!defined(IB_CM_H)<BR>+#define IB_CM_H<BR>+<BR>+#include
<ib_mad.h><BR>+#include <ib_sa.h><BR>+<BR>+enum ib_cm_state
{<BR>+
IB_CM_IDLE,<BR>+
IB_CM_LISTEN,<BR>+
IB_CM_REQ_SENT,<BR>+
IB_CM_REQ_RCVD,<BR>+
IB_CM_MRA_REQ_SENT,<BR>+
IB_CM_MRA_REQ_RCVD,<BR>+
IB_CM_REP_SENT,<BR>+
IB_CM_REP_RCVD,<BR>+
IB_CM_MRA_REP_SENT,<BR>+
IB_CM_MRA_REP_RCVD,<BR>+
IB_CM_ESTABLISHED,<BR>+
IB_CM_LAP_SENT,<BR>+
IB_CM_LAP_RCVD,<BR>+
IB_CM_MRA_LAP_SENT,<BR>+
IB_CM_MRA_LAP_RCVD,<BR>+
IB_CM_DREQ_SENT,<BR>+
IB_CM_DREQ_RCVD,<BR>+
IB_CM_TIMEWAIT,<BR>+
IB_CM_SIDR_REQ_SENT,<BR>+
IB_CM_SIDR_REQ_RCVD<BR>+};<BR>+<BR>+enum ib_cm_event_type
{<BR>+
IB_CM_REQ_TIMEOUT,<BR>+
IB_CM_REQ_RECEIVED,<BR>+
IB_CM_REP_TIMEOUT,<BR>+
IB_CM_REP_RECEIVED,<BR>+
IB_CM_RTU_RECEIVED,<BR>+
IB_CM_DREQ_TIMEOUT,<BR>+
IB_CM_DREQ_RECEIVED,<BR>+
IB_CM_DREP_RECEIVED,<BR>+
IB_CM_MRA_RECEIVED,<BR>+
IB_CM_LAP_TIMEOUT,<BR>+
IB_CM_LAP_RECEIVED,<BR>+
IB_CM_APR_RECEIVED<BR>+};<BR>+<BR>+struct ib_cm_event
{<BR>+ /* a whole lot more stuff goes here
*/<BR>+
void
*private_data;<BR>+
u8
private_data_len;<BR>+ enum
ib_cm_event_type event;<BR>+};<BR>+<BR>+struct
ib_cm_id;<BR>+<BR>+typedef void (*ib_cm_handler)(struct ib_cm_id
*cm_id,<BR>+
struct ib_cm_event *event);<BR>+<BR>+struct ib_cm_id
{<BR>+
ib_cm_handler
cm_handler;<BR>+
void
*context;<BR>+
u64
service_id;<BR>+ enum
ib_cm_state
state;<BR>+};<BR>+<BR>+/**<BR>+ * ib_create_cm_id - Allocate a connection
identifier.<BR>+ * @cm_handler: Callback invoked to notify the user of CM
events.<BR>+ * @context: User specified context associated with the
connection<BR>+ * identifier.<BR>+ *<BR>+ * Connection identifiers
are used to track connection states and<BR>+ * listen requests.<BR>+
*/<BR>+struct ib_cm_id *ib_create_cm_id(ib_cm_handler
cm_handler,<BR>+
void *context);<BR>+<BR>+/**<BR>+ * ib_destroy_cm_id - Destroy a connection
identifier.<BR>+ * @cm_id: Connection identifier to destroy.<BR>+ *<BR>+ * This
call blocks until the connection identifier is destroyed.<BR>+ */<BR>+int
ib_destroy_cm_id(struct ib_cm_id *cm_id);<BR>+//*** TBD : add flags to allow
calling routine from CM callback...<BR>+<BR>+/**<BR>+ * ib_cm_listen - Initiates
listening on the specified service ID for<BR>+ * connection and
service ID resolution requests.<BR>+ * @cm_id: Connection identifier associated
with the listen request.<BR>+ * @service_id: Service identifier matched against
incoming connection<BR>+ * and service ID resolution requests.<BR>+
* @service_mask: Mask applied to service ID used to listen across a<BR>+
* range of service IDs.<BR>+ */<BR>+int ib_cm_listen(struct ib_cm_id
*cm_id,<BR>+
u64
service_id,<BR>+
u64 service_mask);<BR>+<BR>+struct ib_cm_req_param
{<BR>+ struct
ib_qp
*qp;<BR>+ struct ib_path_record
*primary_path;<BR>+ struct
ib_path_record
*alternate_path;<BR>+
u64
service_id;<BR>+
int
timeout_ms;<BR>+
void
*private_data;<BR>+
u8
private_data_len;<BR>+
u8
responder_resources;<BR>+
u8
initiator_depth;<BR>+
u8
remote_cm_response_timeout;<BR>+
u8
flow_control;<BR>+
u8
local_cm_response_timeout;<BR>+
u8
retry_count;<BR>+
u8
rnr_retry_count;<BR>+
u8
max_cm_retries;<BR>+};<BR>+<BR>+/**<BR>+ * ib_send_cm_req - Sends a connection
request to the remote node.<BR>+ * @cm_id: Connection identifier that will be
associated with the<BR>+ * connection request.<BR>+ * @param:
Connection request information needed to establish the<BR>+ *
connection.<BR>+ */<BR>+int ib_send_cm_req(struct ib_cm_id
*cm_id,<BR>+
struct ib_cm_req_param *param);<BR>+<BR>+struct ib_cm_rep_param
{<BR>+ struct ib_qp
*qp;<BR>+
void
*private_data;<BR>+
u8
reply_private_data_len;<BR>+
u8
responder_resources;<BR>+
u8
initiator_depth;<BR>+
u8
target_ack_delay;<BR>+
u8
failover_accepted;<BR>+
u8
flow_control;<BR>+
u8
rnr_retry_count;<BR>+};<BR>+<BR>+/**<BR>+ * ib_send_cm_rep - Sends a connection
reply in response to a connection<BR>+ * request.<BR>+ * @cm_id:
Connection identifier that will be associated with the<BR>+ *
connection request.<BR>+ * @param: Connection reply information needed to
establish the<BR>+ * connection.<BR>+ */<BR>+int
ib_send_cm_rep(struct ib_cm_id
*cm_id,<BR>+
struct ib_cm_req_param *param);<BR>+<BR>+/**<BR>+ * ib_send_cm_rtu - Sends a
connection ready to use message in response<BR>+ * to a connection
reply message.<BR>+ * @cm_id: Connection identifier associated with the
connection request.<BR>+ * @private_data: Optional user-defined private data
sent with the<BR>+ * ready to use message.<BR>+ * @private_data_len:
Size of the private data buffer, in bytes.<BR>+ */<BR>+int ib_send_cm_rtu(struct
ib_cm_id
*cm_id,<BR>+
void
*private_data,<BR>+
u8 private_data_len);<BR>+<BR>+/**<BR>+ * ib_send_cm_dreq - Sends a
disconnection request for an existing<BR>+ * connection.<BR>+ *
@cm_id: Connection identifier associated with the connection being<BR>+
* released.<BR>+ * @private_data: Optional user-defined private data
sent with the<BR>+ * disconnection request message.<BR>+ *
@private_data_len: Size of the private data buffer, in bytes.<BR>+ */<BR>+int
ib_send_cm_dreq(struct ib_cm_id
*cm_id,<BR>+
void
*private_data,<BR>+
u8 private_data_len);<BR>+<BR>+/**<BR>+ * ib_send_cm_drep - Sends a
disconnection reply to a disconnection request.<BR>+ * @cm_id: Connection
identifier associated with the connection being<BR>+ *
released.<BR>+ * @private_data: Optional user-defined private data sent with
the<BR>+ * disconnection reply message.<BR>+ * @private_data_len:
Size of the private data buffer, in bytes.<BR>+ */<BR>+int
ib_send_cm_drep(struct ib_cm_id
*cm_id,<BR>+
void
*private_data,<BR>+
u8 private_data_len);<BR>+<BR>+/**<BR>+ * ib_cm_establish - Forces a connection
state to established.<BR>+ * @cm_id: Connection identifier to transition to
established.<BR>+ *<BR>+ * This routine should be invoked by users who receive
messages on a<BR>+ * connected QP before an RTU has been received.<BR>+
*/<BR>+int ib_cm_establish(struct ib_cm_id *id);<BR>+<BR>+enum ib_cm_rej_reason
{<BR>+
IB_CM_REJ_NO_QP
= __constant_htons(1),<BR>+
IB_CM_REJ_NO_EEC
= __constant_htons(2),<BR>+
IB_CM_REJ_NO_RESOURCES
= __constant_htons(3),<BR>+
IB_CM_REJ_TIMEOUT
= __constant_htons(4),<BR>+
IB_CM_REJ_UNSUPPORTED
= __constant_htons(5),<BR>+
IB_CM_REJ_INVALID_COMM_ID
= __constant_htons(6),<BR>+
IB_CM_REJ_INVALID_COMM_INSTANCE
= __constant_htons(7),<BR>+
IB_CM_REJ_INVALID_SERVICE_ID
= __constant_htons(8),<BR>+
IB_CM_REJ_INVALID_TRANSPORT_TYPE =
__constant_htons(9),<BR>+
IB_CM_REJ_STALE_CONN
= __constant_htons(10),<BR>+
IB_CM_REJ_RDC_NOT_EXIST
= __constant_htons(11),<BR>+
IB_CM_REJ_INVALID_GID
= __constant_htons(12),<BR>+
IB_CM_REJ_INVALID_LID
= __constant_htons(13),<BR>+
IB_CM_REJ_INVALID_SL
= __constant_htons(14),<BR>+
IB_CM_REJ_INVALID_TRAFFIC_CLASS
= __constant_htons(15),<BR>+
IB_CM_REJ_INVALID_HOP_LIMIT
= __constant_htons(16),<BR>+
IB_CM_REJ_INVALID_PACKET_RATE
= __constant_htons(17),<BR>+
IB_CM_REJ_INVALID_ALT_GID
= __constant_htons(18),<BR>+
IB_CM_REJ_INVALID_ALT_LID
= __constant_htons(19),<BR>+
IB_CM_REJ_INVALID_ALT_SL
= __constant_htons(20),<BR>+
IB_CM_REJ_INVALID_ALT_TRAFFIC_CLASS =
__constant_htons(21),<BR>+
IB_CM_REJ_INVALID_ALT_HOP_LIMIT
= __constant_htons(22),<BR>+
IB_CM_REJ_INVALID_ALT_PACKET_RATE =
__constant_htons(23),<BR>+
IB_CM_REJ_PORT_REDIRECT
= __constant_htons(24),<BR>+
IB_CM_REJ_INVALID_MTU
= __constant_htons(26),<BR>+
IB_CM_REJ_INSUFFICIENT_RESP_RESOURCES =
__constant_htons(27),<BR>+
IB_CM_REJ_CONSUMER_DEFINED
= __constant_htons(28),<BR>+
IB_CM_REJ_INVALID_RNR_RETRY
= __constant_htons(29),<BR>+
IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID =
__constant_htons(30),<BR>+
IB_CM_REJ_INVALID_CLASS_VERSION
= __constant_htons(31),<BR>+
IB_CM_REJ_INVALID_FLOW_LABEL
= __constant_htons(32),<BR>+
IB_CM_REJ_INVALID_ALT_FLOW_LABEL =
__constant_htons(33)<BR>+};<BR>+<BR>+/**<BR>+ * ib_send_cm_rej - Sends a
connection rejection message to the<BR>+ * remote node.<BR>+ *
@cm_id: Connection identifier associated with the connection being<BR>+
* rejected.<BR>+ * @reason: Reason for the connection request
rejection.<BR>+ * @ari: Optional additional rejection information.<BR>+ *
@ari_length: Size of the additional rejection information, in bytes.<BR>+ *
@private_data: Optional user-defined private data sent with the<BR>+
* rejection message.<BR>+ * @private_data_len: Size of the private
data buffer, in bytes.<BR>+ */<BR>+int ib_send_cm_rej(struct ib_cm_id
*cm_id,<BR>+
enum ib_cm_rej_reason
reason,<BR>+
void
*ari,<BR>+
u8
ari_length,<BR>+
void
*private_data,<BR>+
u8 private_data_len);<BR>+<BR>+/**<BR>+ * ib_send_cm_mra - Sends a message
receipt acknowledgement to a connection<BR>+ * message.<BR>+ *
@cm_id: Connection identifier associated with the connection message.<BR>+ *
@service_timeout: The maximum time required for the sender to reply to<BR>+
* to the connection message.<BR>+ * @private_data: Optional
user-defined private data sent with the<BR>+ * message receipt
acknowledgement.<BR>+ * @private_data_len: Size of the private data buffer, in
bytes.<BR>+ */<BR>+int ib_send_cm_mra(struct ib_cm_id
*cm_id,<BR>+
u8
service_timeout,<BR>+
void
*private_data,<BR>+
u8 private_data_len);<BR>+<BR>+/**<BR>+ * ib_send_cm_lap - Sends a load
alternate path request.<BR>+ * @cm_id: Connection identifier associated with the
load alternate path<BR>+ * message.<BR>+ * @alternate_path: A path
record that identifies the alternate path to<BR>+ * load.<BR>+ *
@private_data: Optional user-defined private data sent with the<BR>+
* load alternate path message.<BR>+ * @private_data_len: Size of the
private data buffer, in bytes.<BR>+ */<BR>+int ib_send_cm_lap(struct ib_cm_id
*cm_id,<BR>+
struct ib_path_record
*alternate_path,<BR>+
void
*private_data,<BR>+
u8 private_data_len);<BR>+<BR>+enum ib_cm_apr_status
{<BR>+
IB_CM_APR_SUCCESS,<BR>+
IB_CM_APR_INVALID_COMM_ID,<BR>+
IB_CM_APR_UNSUPPORTED,<BR>+
IB_CM_APR_REJECT,<BR>+
IB_CM_APR_REDIRECT,<BR>+
IB_CM_APR_IS_CURRENT,<BR>+
IB_CM_APR_INVALID_QPN_EECN,<BR>+
IB_CM_APR_INVALID_LID,<BR>+
IB_CM_APR_INVALID_GID,<BR>+
IB_CM_APR_INVALID_FLOW_LABEL,<BR>+
IB_CM_APR_INVALID_TCLASS,<BR>+
IB_CM_APR_INVALID_HOP_LIMIT,<BR>+
IB_CM_APR_INVALID_PACKET_RATE,<BR>+
IB_CM_APR_INVALID_SL<BR>+};<BR>+<BR>+/**<BR>+ * ib_send_cm_apr - Sends an
alternate path response message in response to<BR>+ * a load
alternate path request.<BR>+ * @cm_id: Connection identifier associated with the
alternate path response.<BR>+ * @status: Reply status sent with the alternate
path response.<BR>+ * @info: Optional additional information sent with the
alternate path<BR>+ * response.<BR>+ * @info_length: Size of the
additional information, in bytes.<BR>+ * @private_data: Optional user-defined
private data sent with the<BR>+ * alternate path response
message.<BR>+ * @private_data_len: Size of the private data buffer, in
bytes.<BR>+ */<BR>+int ib_send_cm_apr(struct ib_cm_id
*cm_id,<BR>+
enum ib_cm_apr_status
status,<BR>+
void
*info,<BR>+
u8
info_length,<BR>+
void
*private_data,<BR>+
u8 private_data_len);<BR>+<BR>+struct ib_cm_sidr_req_param
{<BR>+ struct ib_path_record
*path;<BR>+
u64
service_id;<BR>+
int
timeout_ms;<BR>+
void
*private_data;<BR>+
u8
private_data_len;<BR>+
u16
pkey;<BR>+};<BR>+<BR>+/**<BR>+ * ib_send_cm_sidr_req - Sends a service ID
resolution request to the<BR>+ * remote node.<BR>+ * @cm_id:
Communication identifier that will be associated with the<BR>+ *
service ID resolution request.<BR>+ * @param: Service ID resolution request
information.<BR>+ */<BR>+int ib_send_cm_sidr_req(struct ib_cm_id
*cm_id,<BR>+
struct ib_cm_sidr_req_param *param);<BR>+<BR>+enum ib_cm_sidr_status
{<BR>+
IB_SIDR_SUCCESS,<BR>+
IB_SIDR_UNSUPPORTED,<BR>+
IB_SIDR_REJECT,<BR>+
IB_SIDR_NO_QP,<BR>+
IB_SIDR_REDIRECT,<BR>+
IB_SIDR_UNSUPPORTED_VERSION<BR>+};<BR>+<BR>+struct ib_cm_sidr_rep_param
{<BR>+
u32
qp_num;<BR>+
u32
qkey;<BR>+ enum ib_cm_sidr_status
status;<BR>+
void
*info;<BR>+
u8
info_length;<BR>+
void
*private_data;<BR>+
u8
private_data_len;<BR>+};<BR>+<BR>+/**<BR>+ * ib_send_cm_sidr_rep - Sends a
service ID resolution request to the<BR>+ * remote node.<BR>+ *
@cm_id: Communication identifier associated with the received service ID<BR>+
* resolution request.<BR>+ * @param: Service ID resolution reply
information.<BR>+ */<BR>+int ib_send_cm_sidr_rep(struct ib_cm_id
*cm_id,<BR>+
struct ib_cm_sidr_rep_param *param);<BR>+<BR>+#endif /* IB_CM_H */<BR>Index:
core/cm.c<BR>===================================================================<BR>---
core/cm.c (revision 0)<BR>+++ core/cm.c (revision
0)<BR>@@ -0,0 +1,292 @@<BR>+/*<BR>+ * This software is available to you under a
choice of one of two<BR>+ * licenses. You may choose to be licensed under
the terms of the GNU<BR>+ * General Public License (GPL) Version 2, available
at<BR>+ * <<A href="http://www.fsf.org/copyleft/gpl.html"
target=_blank>http://www.fsf.org/copyleft/gpl.html</A>>, or the OpenIB.org
BSD<BR>+ * license, available in the LICENSE.TXT file accompanying this<BR>+ *
software. These details are also available at<BR>+ * <<A
href="http://openib.org/license.html"
target=_blank>http://openib.org/license.html</A>>.<BR>+ *<BR>+ * THE SOFTWARE
IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,<BR>+ * EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF<BR>+ * MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND<BR>+ * NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS<BR>+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN<BR>+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN<BR>+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE<BR>+ * SOFTWARE.<BR>+ *<BR>+ * Copyright (c) 2004 Intel
Corporation. All rights reserved.<BR>+ * Copyright (c) 2004 Topspin
Corporation. All rights reserved.<BR>+ * Copyright (c) 2004 Voltaire
Corporation. All rights reserved.<BR>+ *<BR>+ * $Id$<BR>+ */<BR>+#include
<linux/err.h><BR>+#include <linux/spinlock.h><BR>+<BR>+#include
<ib_cm.h><BR>+<BR>+MODULE_AUTHOR("Sean
Hefty");<BR>+MODULE_DESCRIPTION("InfiniBand CM");<BR>+MODULE_LICENSE("Dual
BSD/GPL");<BR>+<BR>+static void cm_add_one(struct ib_device *device);<BR>+static
void cm_remove_one(struct ib_device *device);<BR>+<BR>+static struct ib_client
cm_client = {<BR>+ .name =
"cm",<BR>+ .add =
cm_add_one,<BR>+ .remove =
cm_remove_one<BR>+};<BR>+<BR>+struct cm_port
{<BR>+ struct ib_mad_agent
*mad_agent;<BR>+};<BR>+<BR>+struct ib_cm_id_private
{<BR>+ struct ib_cm_id
id;<BR>+<BR>+ spinlock_t
lock;<BR>+ wait_queue_head_t
wait;<BR>+ atomic_t
refcount;<BR>+};<BR>+<BR>+struct ib_cm_id *ib_create_cm_id(ib_cm_handler
cm_handler,<BR>+
void *context)<BR>+{<BR>+ struct
ib_cm_id_private *cm_id_priv;<BR>+<BR>+
cm_id_priv = kmalloc(sizeof *cm_id_priv,
GFP_KERNEL);<BR>+ if
(!cm_id_priv)<BR>+
return ERR_PTR(-ENOMEM);<BR>+<BR>+
cm_id_priv->id.service_id = 0;<BR>+
cm_id_priv->id.state = IB_CM_IDLE;<BR>+
cm_id_priv->id.cm_handler =
cm_handler;<BR>+ cm_id_priv->id.context =
context;<BR>+<BR>+
spin_lock_init(&cm_id_priv->lock);<BR>+
init_waitqueue_head(&cm_id_priv->wait);<BR>+
atomic_set(&cm_id_priv->refcount,
1);<BR>+<BR>+ return
&cm_id_priv->id;<BR>+}<BR>+EXPORT_SYMBOL(ib_create_cm_id);<BR>+<BR>+static
void reset_cm_state(struct ib_cm_id_private
*cm_id_priv)<BR>+{<BR>+ /* reject
connections if establishing */<BR>+ /*
disconnect established connections */<BR>+
/* update timewait info */<BR>+}<BR>+<BR>+int ib_destroy_cm_id(struct ib_cm_id
*cm_id)<BR>+{<BR>+ struct ib_cm_id_private
*cm_id_priv;<BR>+ unsigned long
flags;<BR>+<BR>+ cm_id_priv =
container_of(cm_id, struct ib_cm_id_private,
id);<BR>+<BR>+
spin_lock_irqsave(&cm_id_priv->lock,
flags);<BR>+ switch(cm_id->state)
{<BR>+ case
IB_CM_IDLE:<BR>+ case
IB_CM_LISTEN:<BR>+ case
IB_CM_TIMEWAIT:<BR>+
break; /* Connection is ready to be destroyed.
*/<BR>+
default:<BR>+
reset_cm_state(cm_id_priv);<BR>+
break;<BR>+
}<BR>+ cm_id->state =
IB_CM_IDLE;<BR>+
spin_unlock_irqrestore(&cm_id_priv->lock,
flags);<BR>+<BR>+
atomic_dec(&cm_id_priv->refcount);<BR>+
wait_event(cm_id_priv->wait,<BR>+
!atomic_read(&cm_id_priv->refcount));<BR>+
kfree(cm_id_priv);<BR>+ return
0;<BR>+}<BR>+EXPORT_SYMBOL(ib_destroy_cm_id);<BR>+<BR>+int ib_cm_listen(struct
ib_cm_id
*cm_id,<BR>+
u64
service_id,<BR>+
u64 service_mask)<BR>+{<BR>+ return
-EINVAL;<BR>+}<BR>+EXPORT_SYMBOL(ib_cm_listen);<BR>+<BR>+int
ib_send_cm_req(struct ib_cm_id
*cm_id,<BR>+
struct ib_cm_req_param *param)<BR>+{<BR>+
return -EINVAL;<BR>+}<BR>+EXPORT_SYMBOL(ib_send_cm_req);<BR>+<BR>+int
ib_send_cm_rep(struct ib_cm_id
*cm_id,<BR>+
struct ib_cm_req_param *param)<BR>+{<BR>+
return -EINVAL;<BR>+}<BR>+EXPORT_SYMBOL(ib_send_cm_rep);<BR>+<BR>+int
ib_send_cm_rtu(struct ib_cm_id
*cm_id,<BR>+
void
*private_data,<BR>+
u8 private_data_len)<BR>+{<BR>+ return
-EINVAL;<BR>+}<BR>+EXPORT_SYMBOL(ib_send_cm_rtu);<BR>+<BR>+int
ib_send_cm_dreq(struct ib_cm_id
*cm_id,<BR>+
void
*private_data,<BR>+
u8 private_data_len)<BR>+{<BR>+ return
-EINVAL;<BR>+}<BR>+EXPORT_SYMBOL(ib_send_cm_dreq);<BR>+<BR>+int
ib_send_cm_drep(struct ib_cm_id
*cm_id,<BR>+
void
*private_data,<BR>+
u8 private_data_len)<BR>+{<BR>+ return
-EINVAL;<BR>+}<BR>+EXPORT_SYMBOL(ib_send_cm_drep);<BR>+<BR>+int
ib_cm_establish(struct ib_cm_id
*id)<BR>+{<BR>+ return
-EINVAL;<BR>+}<BR>+EXPORT_SYMBOL(ib_cm_establish);<BR>+<BR>+int
ib_send_cm_rej(struct ib_cm_id
*cm_id,<BR>+
enum ib_cm_rej_reason
reason,<BR>+
void
*ari,<BR>+
u8
ari_length,<BR>+
void
*private_data,<BR>+
u8 private_data_len)<BR>+{<BR>+ return
-EINVAL;<BR>+}<BR>+EXPORT_SYMBOL(ib_send_cm_rej);<BR>+<BR>+int
ib_send_cm_mra(struct ib_cm_id
*cm_id,<BR>+
u8
service_timeout,<BR>+
void
*private_data,<BR>+
u8 private_data_len)<BR>+{<BR>+ return
-EINVAL;<BR>+}<BR>+EXPORT_SYMBOL(ib_send_cm_mra);<BR>+<BR>+int
ib_send_cm_lap(struct ib_cm_id
*cm_id,<BR>+
struct ib_path_record
*alternate_path,<BR>+
void
*private_data,<BR>+
u8 private_data_len)<BR>+{<BR>+ return
-EINVAL;<BR>+}<BR>+EXPORT_SYMBOL(ib_send_cm_lap);<BR>+<BR>+int
ib_send_cm_apr(struct ib_cm_id
*cm_id,<BR>+
enum ib_cm_apr_status
status,<BR>+
void
*info,<BR>+
u8
info_length,<BR>+
void
*private_data,<BR>+
u8 private_data_len)<BR>+{<BR>+ return
-EINVAL;<BR>+}<BR>+EXPORT_SYMBOL(ib_send_cm_apr);<BR>+<BR>+int
ib_send_cm_sidr_req(struct ib_cm_id
*cm_id,<BR>+
struct ib_cm_sidr_req_param
*param)<BR>+{<BR>+ return
-EINVAL;<BR>+}<BR>+EXPORT_SYMBOL(ib_send_cm_sidr_req);<BR>+<BR>+int
ib_send_cm_sidr_rep(struct ib_cm_id
*cm_id,<BR>+
struct ib_cm_sidr_rep_param
*param)<BR>+{<BR>+ return
-EINVAL;<BR>+}<BR>+EXPORT_SYMBOL(ib_send_cm_sidr_rep);<BR>+<BR>+static void
send_handler(struct ib_mad_agent
*mad_agent,<BR>+
struct ib_mad_send_wc
*mad_send_wc)<BR>+{<BR>+ struct cm_port
*port;<BR>+<BR>+ port = (struct cm_port
*)mad_agent->context;<BR>+}<BR>+<BR>+static void recv_handler(struct
ib_mad_agent
*mad_agent,<BR>+
struct ib_mad_recv_wc
*mad_recv_wc)<BR>+{<BR>+ struct cm_port
*port;<BR>+<BR>+ port = (struct cm_port
*)mad_agent->context;<BR>+}<BR>+<BR>+static void cm_add_one(struct ib_device
*device)<BR>+{<BR>+ struct cm_port
*port;<BR>+ struct ib_mad_reg_req
reg_req;<BR>+ u8
i;<BR>+<BR>+ port = kmalloc(sizeof *port *
device->phys_port_cnt, GFP_KERNEL);<BR>+
if
(!port)<BR>+
goto out;<BR>+<BR>+ memset(®_req, 0,
sizeof reg_req);<BR>+ reg_req.mgmt_class =
IB_MGMT_CLASS_CM;<BR>+
reg_req.mgmt_class_version = 1;<BR>+
set_bit(IB_MGMT_METHOD_GET,
reg_req.method_mask);<BR>+
set_bit(IB_MGMT_METHOD_SET,
reg_req.method_mask);<BR>+
set_bit(IB_MGMT_METHOD_GET_RESP,
reg_req.method_mask);<BR>+
set_bit(IB_MGMT_METHOD_SEND,
reg_req.method_mask);<BR>+ for (i = 1; i
<= device->phys_port_cnt; i++)
{<BR>+
port[i].mad_agent = ib_register_mad_agent(device,
i,<BR>+
IB_QPT_GSI,<BR>+
®_req,<BR>+
0,<BR>+
send_handler,<BR>+
recv_handler,<BR>+
&port[i]);<BR>+
}<BR>+<BR>+out:<BR>+
ib_set_client_data(device, &cm_client, port);<BR>+}<BR>+<BR>+static void
cm_remove_one(struct ib_device
*device)<BR>+{<BR>+ struct cm_port
*port;<BR>+ int
i;<BR>+<BR>+ port = (struct cm_port
*)ib_get_client_data(device,
&cm_client);<BR>+ if
(!port)<BR>+
return;<BR>+<BR>+ for (i = 1; i <=
device->phys_port_cnt; i++)
{<BR>+
if
(!IS_ERR(port[i].mad_agent))<BR>+
ib_unregister_mad_agent(port[i].mad_agent);<BR>+
}<BR>+ kfree(port);<BR>+}<BR>+<BR>+static
int __init ib_cm_init(void)<BR>+{<BR>+
return ib_register_client(&cm_client);<BR>+}<BR>+<BR>+static void __exit
ib_cm_cleanup(void)<BR>+{<BR>+
ib_unregister_client(&cm_client);<BR>+}<BR>+<BR>+module_init(ib_cm_init);<BR>+module_exit(ib_cm_cleanup);<BR>_______________________________________________<BR>openib-general
mailing list<BR>openib-general@openib.org<BR><A
href="http://openib.org/mailman/listinfo/openib-general"
target=_blank>http://openib.org/mailman/listinfo/openib-general</A><BR><BR>To
unsubscribe, please visit <A
href="http://openib.org/mailman/listinfo/openib-general"
target=_blank>http://openib.org/mailman/listinfo/openib-general</A>
</FONT></P></BODY></HTML>