4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
27 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (C) 2006 Myricom, Inc.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lnet/klnds/mxlnd/mxlnd.h
38 * Author: Eric Barton <eric@bartonsoftware.com>
39 * Author: Scott Atchley <atchley at myri.com>
42 #ifndef AUTOCONF_INCLUDED
43 #include <linux/config.h>
45 #include <linux/module.h> /* module */
46 #include <linux/kernel.h> /* module */
48 #include <linux/string.h>
49 #include <linux/stat.h>
50 #include <linux/errno.h>
51 #include <linux/smp_lock.h>
52 #include <linux/unistd.h>
53 #include <linux/uio.h>
56 #include <asm/system.h>
57 #include <asm/uaccess.h>
60 #include <linux/init.h> /* module */
62 #include <linux/file.h>
63 #include <linux/stat.h>
64 #include <linux/list.h>
65 #include <linux/kmod.h>
66 #include <linux/sysctl.h>
67 #include <linux/random.h>
68 #include <linux/utsname.h>
69 #include <linux/jiffies.h> /* msecs_to_jiffies */
70 #include <asm/semaphore.h>
75 #include <asm/byteorder.h> /* __LITTLE_ENDIAN */
76 #include <net/arp.h> /* arp table */
77 #include <linux/netdevice.h> /* get_device_by_name */
78 #include <linux/inetdevice.h> /* neigh_lookup, etc. */
79 #include <linux/net.h> /* sock_create_kern, kernel_connect, sock_release */
81 #define DEBUG_SUBSYSTEM S_LND
83 #include "libcfs/libcfs.h"
84 #include "lnet/lnet.h"
85 #include "lnet/lib-lnet.h"
86 //#include <lnet/lnet-sysctl.h>
89 #include "mx_extensions.h"
90 #include "myriexpress.h"
92 #if LNET_MAX_IOV > MX_MAX_SEGMENTS
93 #error LNET_MAX_IOV is greater then MX_MAX_SEGMENTS
96 #define MXLND_MSG_MAGIC 0x4d583130 /* unique magic 'MX10' */
97 #define MXLND_MSG_VERSION 0x03
99 /* Using MX's 64 match bits
100 * We are using the match bits to specify message type and the cookie. The
101 * highest four bits (60-63) are reserved for message type. Below we specify
102 * the types. We reserve the remaining combinations for future use. The next 8
103 * bits (52-59) are reserved for returning a status code for failed GET_DATA
104 * (payload) messages. The last 52 bits are used for cookies. That should allow
105 * unique cookies for 4 KB messages at 10 Gbps line rate without rollover for
106 * about 8 years. That should be enough. */
108 #define MXLND_MSG_OFFSET 60 /* msg type offset */
109 #define MXLND_MSG_BITS (64 - MXLND_MSG_OFFSET)
110 #define MXLND_MSG_MASK (((1ULL<<MXLND_MSG_BITS) - 1) << MXLND_MSG_OFFSET)
111 #define MXLND_MSG_TYPE(x) (((x) & MXLND_MSG_MASK) >> MXLND_MSG_OFFSET)
113 #define MXLND_ERROR_OFFSET 52 /* error value offset */
114 #define MXLND_ERROR_BITS (MXLND_MSG_OFFSET - MXLND_ERROR_OFFSET)
115 #define MXLND_ERROR_MASK (((1ULL<<MXLND_ERROR_BITS) - 1) << MXLND_ERROR_OFFSET)
116 #define MXLND_ERROR_VAL(x) (((x) & MXLND_ERROR_MASK) >> MXLND_ERROR_OFFSET)
119 #define MXLND_MSG_ICON_REQ 0xb /* mx_iconnect() before CONN_REQ */
120 #define MXLND_MSG_CONN_REQ 0xc /* connection request */
121 #define MXLND_MSG_ICON_ACK 0x9 /* mx_iconnect() before CONN_ACK */
122 #define MXLND_MSG_CONN_ACK 0xa /* connection request response */
123 #define MXLND_MSG_BYE 0xd /* disconnect msg */
124 #define MXLND_MSG_EAGER 0xe /* eager message */
125 #define MXLND_MSG_NOOP 0x1 /* no msg, return credits */
126 #define MXLND_MSG_PUT_REQ 0x2 /* put request src->sink */
127 #define MXLND_MSG_PUT_ACK 0x3 /* put ack src<-sink */
128 #define MXLND_MSG_PUT_DATA 0x4 /* put payload src->sink */
129 #define MXLND_MSG_GET_REQ 0x5 /* get request sink->src */
130 #define MXLND_MSG_GET_DATA 0x6 /* get payload sink<-src */
132 /* when to roll-over the cookie value */
133 #define MXLND_MAX_COOKIE ((1ULL << MXLND_ERROR_OFFSET) - 1)
135 /* defaults for configurable parameters */
136 #define MXLND_N_SCHED 1 /* # schedulers (mx_wait_any() threads) */
137 #define MXLND_NDAEMONS 3 /* connd, timeoutd, tx_queued */
138 #define MXLND_MX_BOARD 0 /* Use the first MX NIC if more than 1 avail */
139 #define MXLND_MX_EP_ID 0 /* MX endpoint ID */
140 #define MXLND_COMM_TIMEOUT (20 * CFS_HZ) /* timeout for send/recv (jiffies) */
141 #define MXLND_WAIT_TIMEOUT CFS_HZ /* timeout for wait (jiffies) */
142 #define MXLND_CONNECT_TIMEOUT (5 * CFS_HZ) /* timeout for connections (jiffies) */
143 #define MXLND_POLLING 1000 /* poll iterations before blocking */
144 #define MXLND_LOOKUP_COUNT 5 /* how many times to try to resolve MAC */
145 #define MXLND_MAX_PEERS 1024 /* number of nodes talking to me */
147 #define MXLND_MSG_SIZE (4<<10) /* pre-posted eager message size */
148 #define MXLND_MSG_QUEUE_DEPTH 8 /* default msg queue depth */
149 #define MXLND_NTX 256 /* default # of tx msg descriptors */
151 #define MXLND_HASH_BITS 6 /* the number of bits to hash over */
152 #define MXLND_HASH_SIZE (1<<MXLND_HASH_BITS)
153 /* number of peer lists for lookup.
154 we hash over the last N bits of
155 the IP address converted to an int. */
156 #define MXLND_HASH_MASK (MXLND_HASH_SIZE - 1)
157 /* ensure we use only the last N bits */
159 /* derived constants... */
160 /* TX messages (shared by all connections) */
161 #define MXLND_TX_MSGS() (*kmxlnd_tunables.kmx_ntx)
162 #define MXLND_TX_MSG_BYTES() (MXLND_TX_MSGS() * MXLND_MSG_SIZE)
163 #define MXLND_TX_MSG_PAGES() ((MXLND_TX_MSG_BYTES() + PAGE_SIZE - 1)/PAGE_SIZE)
165 /* RX messages (per connection) */
166 #define MXLND_RX_MSGS() (*kmxlnd_tunables.kmx_peercredits)
167 #define MXLND_RX_MSG_BYTES() (MXLND_RX_MSGS() * MXLND_MSG_SIZE)
168 #define MXLND_RX_MSG_PAGES() ((MXLND_RX_MSG_BYTES() + PAGE_SIZE - 1)/PAGE_SIZE)
169 #define MXLND_CREDIT_HIGHWATER() (*kmxlnd_tunables.kmx_peercredits - 2)
170 /* when to send a noop to return credits */
172 /* debugging features */
173 #define MXLND_CKSUM 0 /* checksum kmx_msg_t */
174 #define MXLND_DEBUG 0 /* additional CDEBUG messages */
176 /* provide wrappers around LIBCFS_ALLOC/FREE to keep MXLND specific
177 * memory usage stats that include pages */
179 #define MXLND_ALLOC(x, size) \
181 cfs_spin_lock(&kmxlnd_data.kmx_mem_lock); \
182 kmxlnd_data.kmx_mem_used += size; \
183 cfs_spin_unlock(&kmxlnd_data.kmx_mem_lock); \
184 LIBCFS_ALLOC(x, size); \
185 if (unlikely(x == NULL)) { \
186 cfs_spin_lock(&kmxlnd_data.kmx_mem_lock); \
187 kmxlnd_data.kmx_mem_used -= size; \
188 cfs_spin_unlock(&kmxlnd_data.kmx_mem_lock); \
192 #define MXLND_FREE(x, size) \
194 cfs_spin_lock(&kmxlnd_data.kmx_mem_lock); \
195 kmxlnd_data.kmx_mem_used -= size; \
196 cfs_spin_unlock(&kmxlnd_data.kmx_mem_lock); \
197 LIBCFS_FREE(x, size); \
201 typedef struct kmx_tunables
203 int *kmx_n_waitd; /* # completion threads */
204 int *kmx_max_peers; /* max # of potential peers */
205 int *kmx_cksum; /* checksum small msgs? */
206 int *kmx_ntx; /* total # of tx */
207 int *kmx_credits; /* concurrent sends to all peers */
208 int *kmx_peercredits; /* concurrent sends to 1 peer */
209 int *kmx_board; /* MX board (NIC) number */
210 int *kmx_ep_id; /* MX endpoint number */
211 char **kmx_default_ipif; /* IPoMX interface name */
212 int *kmx_polling; /* if 0, block. if > 0, poll this many
213 iterations before blocking */
218 int mxg_npages; /* # pages */
219 struct page *mxg_pages[0];
222 /* global interface state */
223 typedef struct kmx_data
225 int kmx_init; /* initialization state */
226 cfs_atomic_t kmx_shutdown; /* shutting down? */
227 cfs_atomic_t kmx_nthreads; /* number of threads */
228 cfs_completion_t *kmx_completions; /* array of completion structs */
229 lnet_ni_t *kmx_ni; /* the LND instance */
230 u64 kmx_incarnation; /* my incarnation value */
231 long kmx_mem_used; /* memory used */
232 mx_endpoint_t kmx_endpt; /* the MX endpoint */
233 mx_endpoint_addr_t kmx_epa; /* the MX endpoint address */
235 cfs_rwlock_t kmx_global_lock; /* global lock */
236 cfs_spinlock_t kmx_mem_lock; /* memory accounting lock */
238 cfs_list_t kmx_conn_reqs; /* list of connection requests */
239 cfs_spinlock_t kmx_conn_lock; /* connection list lock */
240 cfs_semaphore_t kmx_conn_sem; /* semaphore for connection request list */
241 cfs_list_t kmx_conn_zombies; /* list of zombie connections */
242 cfs_list_t kmx_orphan_msgs; /* list of txs to cancel */
244 /* list of all known peers */
245 cfs_list_t kmx_peers[MXLND_HASH_SIZE];
246 cfs_atomic_t kmx_npeers; /* number of peers */
248 kmx_pages_t *kmx_tx_pages; /* tx msg pages */
250 struct kmx_ctx *kmx_txs; /* all tx descriptors */
251 cfs_list_t kmx_tx_idle; /* list of idle tx */
252 cfs_spinlock_t kmx_tx_idle_lock; /* lock for idle tx list */
253 s32 kmx_tx_used; /* txs in use */
254 u64 kmx_tx_next_cookie; /* unique id for tx */
255 cfs_list_t kmx_tx_queue; /* generic send queue */
256 cfs_spinlock_t kmx_tx_queue_lock; /* lock for generic sends */
257 cfs_semaphore_t kmx_tx_queue_sem; /* semaphore for tx queue */
260 #define MXLND_INIT_NOTHING 0 /* in the beginning, there was nothing... */
261 #define MXLND_INIT_DATA 1 /* main data structures created */
262 #define MXLND_INIT_TXS 2 /* tx descriptors created */
263 #define MXLND_INIT_MX 3 /* initiate MX library, open endpoint, get NIC id */
264 #define MXLND_INIT_THREADS 4 /* waitd, timeoutd, tx_queued threads */
265 #define MXLND_INIT_ALL 5 /* startup completed */
267 /************************************************************************
268 * MXLND Wire message format.
269 * These are sent in sender's byte order (i.e. receiver flips).
272 typedef struct kmx_connreq_msg
274 u32 mxcrm_queue_depth; /* per peer max messages in flight */
275 u32 mxcrm_eager_size; /* size of preposted eager messages */
276 } WIRE_ATTR kmx_connreq_msg_t;
278 typedef struct kmx_eager_msg
280 lnet_hdr_t mxem_hdr; /* lnet header */
281 char mxem_payload[0]; /* piggy-backed payload */
282 } WIRE_ATTR kmx_eager_msg_t;
284 typedef struct kmx_putreq_msg
286 lnet_hdr_t mxprm_hdr; /* lnet header */
287 u64 mxprm_cookie; /* opaque completion cookie */
288 } WIRE_ATTR kmx_putreq_msg_t;
290 typedef struct kmx_putack_msg
292 u64 mxpam_src_cookie; /* reflected completion cookie */
293 u64 mxpam_dst_cookie; /* opaque completion cookie */
294 } WIRE_ATTR kmx_putack_msg_t;
296 typedef struct kmx_getreq_msg
298 lnet_hdr_t mxgrm_hdr; /* lnet header */
299 u64 mxgrm_cookie; /* opaque completion cookie */
300 } WIRE_ATTR kmx_getreq_msg_t;
302 typedef struct kmx_msg
304 /* First two fields fixed for all time */
305 u32 mxm_magic; /* MXLND message */
306 u16 mxm_version; /* version number */
308 u8 mxm_type; /* message type */
309 u8 mxm_credits; /* returned credits */
310 u32 mxm_nob; /* # of bytes in whole message */
311 u32 mxm_cksum; /* checksum (0 == no checksum) */
312 u64 mxm_srcnid; /* sender's NID */
313 u64 mxm_srcstamp; /* sender's incarnation */
314 u64 mxm_dstnid; /* destination's NID */
315 u64 mxm_dststamp; /* destination's incarnation */
318 kmx_connreq_msg_t conn_req;
319 kmx_eager_msg_t eager;
320 kmx_putreq_msg_t put_req;
321 kmx_putack_msg_t put_ack;
322 kmx_getreq_msg_t get_req;
324 } WIRE_ATTR kmx_msg_t;
326 /***********************************************************************/
333 /* The life cycle of a request */
335 MXLND_CTX_INIT = 0, /* just created */
336 MXLND_CTX_IDLE = 1, /* available for use */
337 MXLND_CTX_PREP = 2, /* getting ready for send/recv */
338 MXLND_CTX_PENDING = 3, /* mx_isend() or mx_irecv() called */
339 MXLND_CTX_COMPLETED = 4, /* cleaning up after completion or timeout */
340 MXLND_CTX_CANCELED = 5, /* timed out but still in ctx list */
343 /* Context Structure - generic tx/rx descriptor
344 * It represents the context (or state) of each send or receive request.
345 * In other LNDs, they have separate TX and RX descriptors and this replaces both.
347 * The txs live on the global kmx_txs array for cleanup. The rxs are managed
348 * per struct kmx_conn. We will move them between the rx/tx idle lists and the
349 * pending list which is monitored by mxlnd_timeoutd().
351 typedef struct kmx_ctx
353 enum kmx_req_type mxc_type; /* TX or RX */
354 u64 mxc_incarnation; /* store the peer's incarnation here
355 to verify before changing flow
356 control credits after completion */
357 unsigned long mxc_deadline; /* request time out in absolute jiffies */
358 enum kmx_req_state mxc_state; /* what is the state of the request? */
359 cfs_list_t mxc_list; /* place on rx/tx idle list, tx q, peer tx */
360 cfs_list_t mxc_rx_list; /* place on mxp_rx_posted list */
362 lnet_nid_t mxc_nid; /* dst's NID if peer is not known */
363 struct kmx_peer *mxc_peer; /* owning peer */
364 struct kmx_conn *mxc_conn; /* owning conn */
365 kmx_msg_t *mxc_msg; /* msg hdr mapped to mxc_page */
366 lnet_msg_t *mxc_lntmsg[2]; /* lnet msgs to finalize */
368 u8 mxc_msg_type; /* what type of message is this? */
369 u64 mxc_cookie; /* completion cookie */
370 u64 mxc_match; /* MX match info */
371 mx_ksegment_t mxc_seg; /* local MX ksegment for non-DATA */
372 mx_ksegment_t *mxc_seg_list; /* MX ksegment array for DATA */
373 int mxc_nseg; /* number of segments */
374 unsigned long mxc_pin_type; /* MX_PIN_PHYSICAL [| MX_PIN_FULLPAGES] */
375 u32 mxc_nob; /* number of bytes sent/received */
376 mx_request_t mxc_mxreq; /* MX request */
377 mx_status_t mxc_status; /* MX status */
378 u32 mxc_errno; /* errno for LNET */
379 u64 mxc_get; /* # of times returned from idle list */
380 u64 mxc_put; /* # of times returned from idle list */
383 #define MXLND_CONN_DISCONNECT -2 /* conn is being destroyed - do not add txs */
384 #define MXLND_CONN_FAIL -1 /* connect failed (bad handshake, unavail, etc.) */
385 #define MXLND_CONN_INIT 0 /* in the beginning, there was nothing... */
386 #define MXLND_CONN_REQ 1 /* a connection request message is needed */
387 #define MXLND_CONN_ACK 2 /* a connection ack is needed */
388 #define MXLND_CONN_WAIT 3 /* waiting for req or ack to complete */
389 #define MXLND_CONN_READY 4 /* ready to send */
391 /* store all data from an unexpected CONN_[REQ|ACK] receive */
392 typedef struct kmx_connparams
394 cfs_list_t mxr_list; /* list to hang on kmx_conn_reqs */
395 void *mxr_context; /* context - unused - will hold net */
396 mx_endpoint_addr_t mxr_epa; /* the peer's epa */
397 u64 mxr_match; /* the CONN_REQ's match bits */
398 u32 mxr_nob; /* length of CONN_REQ message */
399 struct kmx_peer *mxr_peer; /* peer if known */
400 struct kmx_conn *mxr_conn; /* conn if known */
401 kmx_msg_t mxr_msg; /* the msg header & connreq_msg_t */
404 /* connection state - queues for queued and pending msgs */
405 typedef struct kmx_conn
407 struct kmx_peer *mxk_peer; /* owning peer */
408 cfs_list_t mxk_list; /* for placing on mxp_conns */
409 cfs_list_t mxk_zombie; /* for placing on zombies list */
410 u64 mxk_incarnation; /* connections's incarnation value */
411 u32 mxk_sid; /* peer's MX session id */
412 cfs_atomic_t mxk_refcount; /* reference counting */
413 int mxk_status; /* can we send messages? MXLND_CONN_* */
415 mx_endpoint_addr_t mxk_epa; /* peer's endpoint address */
417 cfs_spinlock_t mxk_lock; /* lock */
418 unsigned long mxk_timeout; /* expiration of oldest pending tx/rx */
419 unsigned long mxk_last_tx; /* when last tx completed with success */
420 unsigned long mxk_last_rx; /* when last rx completed */
422 kmx_pages_t *mxk_rx_pages; /* rx msg pages */
423 kmx_ctx_t *mxk_rxs; /* the rx descriptors */
424 cfs_list_t mxk_rx_idle; /* list of idle rx */
426 int mxk_credits; /* # of my credits for sending to peer */
427 int mxk_outstanding; /* # of credits to return */
429 cfs_list_t mxk_tx_credit_queue; /* send queue for peer */
430 cfs_list_t mxk_tx_free_queue; /* send queue for peer */
431 int mxk_ntx_msgs; /* # of msgs on tx queues */
432 int mxk_ntx_data ; /* # of DATA on tx queues */
433 int mxk_ntx_posted; /* # of tx msgs in flight */
434 int mxk_data_posted; /* # of tx data payloads in flight */
436 cfs_list_t mxk_pending; /* in flight rxs and txs */
440 typedef struct kmx_peer
442 cfs_list_t mxp_list; /* for placing on kmx_peers */
443 lnet_nid_t mxp_nid; /* peer's LNET NID */
444 lnet_ni_t *mxp_ni; /* LNET interface */
445 cfs_atomic_t mxp_refcount; /* reference counts */
447 cfs_list_t mxp_conns; /* list of connections */
448 kmx_conn_t *mxp_conn; /* current connection */
449 cfs_list_t mxp_tx_queue; /* msgs waiting for a conn */
451 u32 mxp_board; /* peer's board rank */
452 u32 mxp_ep_id; /* peer's MX endpoint ID */
453 u64 mxp_nic_id; /* remote's MX nic_id for mx_connect() */
455 unsigned long mxp_reconnect_time; /* when to retry connect */
456 int mxp_incompatible; /* incorrect conn_req values */
459 extern kmx_data_t kmxlnd_data;
460 extern kmx_tunables_t kmxlnd_tunables;
462 /* required for the LNET API */
463 int mxlnd_startup(lnet_ni_t *ni);
464 void mxlnd_shutdown(lnet_ni_t *ni);
465 int mxlnd_ctl(lnet_ni_t *ni, unsigned int cmd, void *arg);
466 int mxlnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg);
467 int mxlnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed,
468 unsigned int niov, struct iovec *iov, lnet_kiov_t *kiov,
469 unsigned int offset, unsigned int mlen, unsigned int rlen);
472 extern void mxlnd_thread_stop(long id);
473 extern void mxlnd_ctx_init(kmx_ctx_t *ctx);
474 extern int mxlnd_peer_alloc(kmx_peer_t **peerp, lnet_nid_t nid,
475 u32 board, u32 ep_id, u64 nic_id);
476 extern int mxlnd_alloc_pages(kmx_pages_t **pp, int npages);
477 extern void mxlnd_free_pages(kmx_pages_t *p);
480 void mxlnd_eager_recv(void *context, uint64_t match_value, uint32_t length);
481 extern mx_unexp_handler_action_t mxlnd_unexpected_recv(void *context,
482 mx_endpoint_addr_t source, uint64_t match_value, uint32_t length,
483 void *data_if_available);
484 extern void mxlnd_peer_free(kmx_peer_t *peer);
485 extern void mxlnd_conn_free_locked(kmx_conn_t *conn);
486 extern void mxlnd_conn_disconnect(kmx_conn_t *conn, int mx_dis, int send_bye);
487 extern int mxlnd_close_matching_conns(lnet_nid_t nid);
488 extern void mxlnd_sleep(unsigned long timeout);
489 extern int mxlnd_tx_queued(void *arg);
490 extern void mxlnd_handle_rx_completion(kmx_ctx_t *rx);
491 extern int mxlnd_check_sends(kmx_peer_t *peer);
492 extern int mxlnd_tx_peer_queued(void *arg);
493 extern int mxlnd_request_waitd(void *arg);
494 extern int mxlnd_unex_recvd(void *arg);
495 extern int mxlnd_timeoutd(void *arg);
496 extern int mxlnd_free_conn_zombies(void);
497 extern int mxlnd_connd(void *arg);
498 extern int mxlnd_del_peer(lnet_nid_t nid);
502 * mxlnd_nid_to_hash - hash the nid
505 * Takes the u64 nid and XORs the lowest N bits by the next lowest N bits.
508 mxlnd_nid_to_hash(lnet_nid_t nid)
510 return (nid & MXLND_HASH_MASK) ^
511 ((nid & (MXLND_HASH_MASK << MXLND_HASH_BITS)) >> MXLND_HASH_BITS);
515 #define mxlnd_peer_addref(peer) \
517 LASSERT(peer != NULL); \
518 LASSERT(cfs_atomic_read(&(peer)->mxp_refcount) > 0); \
519 cfs_atomic_inc(&(peer)->mxp_refcount); \
523 #define mxlnd_peer_decref(peer) \
525 LASSERT(cfs_atomic_read(&(peer)->mxp_refcount) > 0); \
526 if (cfs_atomic_dec_and_test(&(peer)->mxp_refcount)) \
527 mxlnd_peer_free(peer); \
530 #define mxlnd_conn_addref(conn) \
532 LASSERT(conn != NULL); \
533 LASSERT(cfs_atomic_read(&(conn)->mxk_refcount) > 0); \
534 cfs_atomic_inc(&(conn)->mxk_refcount); \
538 #define mxlnd_conn_decref(conn) \
540 LASSERT(conn != NULL); \
541 LASSERT(cfs_atomic_read(&(conn)->mxk_refcount) > 0); \
542 if (cfs_atomic_dec_and_test(&(conn)->mxk_refcount)) { \
543 cfs_spin_lock(&kmxlnd_data.kmx_conn_lock); \
544 LASSERT((conn)->mxk_status == MXLND_CONN_DISCONNECT); \
545 CDEBUG(D_NET, "adding conn %p to zombies\n", (conn)); \
546 cfs_list_add_tail(&(conn)->mxk_zombie, \
547 &kmxlnd_data.kmx_conn_zombies); \
548 cfs_spin_unlock(&kmxlnd_data.kmx_conn_lock); \
549 cfs_up(&kmxlnd_data.kmx_conn_sem); \
553 #define mxlnd_valid_msg_type(type) \
555 LASSERT((type) == MXLND_MSG_EAGER || \
556 (type) == MXLND_MSG_ICON_REQ || \
557 (type) == MXLND_MSG_CONN_REQ || \
558 (type) == MXLND_MSG_ICON_ACK || \
559 (type) == MXLND_MSG_CONN_ACK || \
560 (type) == MXLND_MSG_BYE || \
561 (type) == MXLND_MSG_NOOP || \
562 (type) == MXLND_MSG_PUT_REQ || \
563 (type) == MXLND_MSG_PUT_ACK || \
564 (type) == MXLND_MSG_PUT_DATA || \
565 (type) == MXLND_MSG_GET_REQ || \
566 (type) == MXLND_MSG_GET_DATA); \