1 // SPDX-License-Identifier: GPL-2.0
3 * Shared Memory Communications over RDMA (SMC-R) and RoCE
5 * Link Layer Control (LLC)
7 * Copyright IBM Corp. 2016
9 * Author(s): Klaus Wacker <Klaus.Wacker@de.ibm.com>
10 * Ursula Braun <ubraun@linux.vnet.ibm.com>
14 #include <rdma/ib_verbs.h>
22 #define SMC_LLC_DATA_LEN 40
25 struct smc_wr_rx_hdr common
;
29 #if defined(__BIG_ENDIAN_BITFIELD)
32 #elif defined(__LITTLE_ENDIAN_BITFIELD)
33 u8 add_link_rej_rsn
:4,
37 u16 length_v2
; /* 44 - 8192*/
40 } __packed
; /* format defined in
41 * IBM Shared Memory Communications Version 2
42 * (https://www.ibm.com/support/pages/node/6326337)
45 #define SMC_LLC_FLAG_NO_RMBE_EYEC 0x03
47 struct smc_llc_msg_confirm_link
{ /* type 0x01 */
48 struct smc_llc_hdr hd
;
49 u8 sender_mac
[ETH_ALEN
];
50 u8 sender_gid
[SMC_GID_SIZE
];
53 u8 link_uid
[SMC_LGR_ID_SIZE
];
59 #define SMC_LLC_FLAG_ADD_LNK_REJ 0x40
60 #define SMC_LLC_REJ_RSN_NO_ALT_PATH 1
62 struct smc_llc_msg_add_link
{ /* type 0x02 */
63 struct smc_llc_hdr hd
;
64 u8 sender_mac
[ETH_ALEN
];
66 u8 sender_gid
[SMC_GID_SIZE
];
69 #if defined(__BIG_ENDIAN_BITFIELD)
72 #elif defined(__LITTLE_ENDIAN_BITFIELD)
80 struct smc_llc_msg_add_link_cont_rt
{
86 struct smc_llc_msg_add_link_v2_ext
{
87 #if defined(__BIG_ENDIAN_BITFIELD)
90 #elif defined(__LITTLE_ENDIAN_BITFIELD)
95 u8 client_target_gid
[SMC_GID_SIZE
];
98 struct smc_llc_msg_add_link_cont_rt rt
[];
99 } __packed
; /* format defined in
100 * IBM Shared Memory Communications Version 2
101 * (https://www.ibm.com/support/pages/node/6326337)
104 struct smc_llc_msg_req_add_link_v2
{
105 struct smc_llc_hdr hd
;
109 u8 gid
[][SMC_GID_SIZE
];
112 #define SMC_LLC_RKEYS_PER_CONT_MSG 2
114 struct smc_llc_msg_add_link_cont
{ /* type 0x03 */
115 struct smc_llc_hdr hd
;
119 struct smc_llc_msg_add_link_cont_rt rt
[SMC_LLC_RKEYS_PER_CONT_MSG
];
121 } __packed
; /* format defined in RFC7609 */
123 #define SMC_LLC_FLAG_DEL_LINK_ALL 0x40
124 #define SMC_LLC_FLAG_DEL_LINK_ORDERLY 0x20
126 struct smc_llc_msg_del_link
{ /* type 0x04 */
127 struct smc_llc_hdr hd
;
131 } __packed
; /* format defined in RFC7609 */
133 struct smc_llc_msg_test_link
{ /* type 0x07 */
134 struct smc_llc_hdr hd
;
139 struct smc_rmb_rtoken
{
141 u8 num_rkeys
; /* first rtoken byte of CONFIRM LINK msg */
142 /* is actually the num of rtokens, first */
143 /* rtoken is always for the current link */
144 u8 link_id
; /* link id of the rtoken */
148 } __packed
; /* format defined in RFC7609 */
150 #define SMC_LLC_RKEYS_PER_MSG 3
151 #define SMC_LLC_RKEYS_PER_MSG_V2 255
153 struct smc_llc_msg_confirm_rkey
{ /* type 0x06 */
154 struct smc_llc_hdr hd
;
155 struct smc_rmb_rtoken rtoken
[SMC_LLC_RKEYS_PER_MSG
];
159 #define SMC_LLC_DEL_RKEY_MAX 8
160 #define SMC_LLC_FLAG_RKEY_RETRY 0x10
161 #define SMC_LLC_FLAG_RKEY_NEG 0x20
163 struct smc_llc_msg_delete_rkey
{ /* type 0x09 */
164 struct smc_llc_hdr hd
;
172 struct smc_llc_msg_delete_rkey_v2
{ /* type 0x29 */
173 struct smc_llc_hdr hd
;
181 struct smc_llc_msg_confirm_link confirm_link
;
182 struct smc_llc_msg_add_link add_link
;
183 struct smc_llc_msg_req_add_link_v2 req_add_link
;
184 struct smc_llc_msg_add_link_cont add_link_cont
;
185 struct smc_llc_msg_del_link delete_link
;
187 struct smc_llc_msg_confirm_rkey confirm_rkey
;
188 struct smc_llc_msg_delete_rkey delete_rkey
;
190 struct smc_llc_msg_test_link test_link
;
192 struct smc_llc_hdr hdr
;
193 u8 data
[SMC_LLC_DATA_LEN
];
197 #define SMC_LLC_FLAG_RESP 0x80
199 struct smc_llc_qentry
{
200 struct list_head list
;
201 struct smc_link
*link
;
202 union smc_llc_msg msg
;
205 static void smc_llc_enqueue(struct smc_link
*link
, union smc_llc_msg
*llc
);
207 struct smc_llc_qentry
*smc_llc_flow_qentry_clr(struct smc_llc_flow
*flow
)
209 struct smc_llc_qentry
*qentry
= flow
->qentry
;
215 void smc_llc_flow_qentry_del(struct smc_llc_flow
*flow
)
217 struct smc_llc_qentry
*qentry
;
220 qentry
= flow
->qentry
;
226 static inline void smc_llc_flow_qentry_set(struct smc_llc_flow
*flow
,
227 struct smc_llc_qentry
*qentry
)
229 flow
->qentry
= qentry
;
232 static void smc_llc_flow_parallel(struct smc_link_group
*lgr
, u8 flow_type
,
233 struct smc_llc_qentry
*qentry
)
235 u8 msg_type
= qentry
->msg
.raw
.hdr
.common
.llc_type
;
237 if ((msg_type
== SMC_LLC_ADD_LINK
|| msg_type
== SMC_LLC_DELETE_LINK
) &&
238 flow_type
!= msg_type
&& !lgr
->delayed_event
) {
239 lgr
->delayed_event
= qentry
;
242 /* drop parallel or already-in-progress llc requests */
243 if (flow_type
!= msg_type
)
244 pr_warn_once("smc: SMC-R lg %*phN net %llu dropped parallel "
245 "LLC msg: msg %d flow %d role %d\n",
246 SMC_LGR_ID_SIZE
, &lgr
->id
,
247 lgr
->net
->net_cookie
,
248 qentry
->msg
.raw
.hdr
.common
.type
,
249 flow_type
, lgr
->role
);
253 /* try to start a new llc flow, initiated by an incoming llc msg */
254 static bool smc_llc_flow_start(struct smc_llc_flow
*flow
,
255 struct smc_llc_qentry
*qentry
)
257 struct smc_link_group
*lgr
= qentry
->link
->lgr
;
259 spin_lock_bh(&lgr
->llc_flow_lock
);
261 /* a flow is already active */
262 smc_llc_flow_parallel(lgr
, flow
->type
, qentry
);
263 spin_unlock_bh(&lgr
->llc_flow_lock
);
266 switch (qentry
->msg
.raw
.hdr
.common
.llc_type
) {
267 case SMC_LLC_ADD_LINK
:
268 flow
->type
= SMC_LLC_FLOW_ADD_LINK
;
270 case SMC_LLC_DELETE_LINK
:
271 flow
->type
= SMC_LLC_FLOW_DEL_LINK
;
273 case SMC_LLC_CONFIRM_RKEY
:
274 case SMC_LLC_DELETE_RKEY
:
275 flow
->type
= SMC_LLC_FLOW_RKEY
;
278 flow
->type
= SMC_LLC_FLOW_NONE
;
280 smc_llc_flow_qentry_set(flow
, qentry
);
281 spin_unlock_bh(&lgr
->llc_flow_lock
);
285 /* start a new local llc flow, wait till current flow finished */
286 int smc_llc_flow_initiate(struct smc_link_group
*lgr
,
287 enum smc_llc_flowtype type
)
289 enum smc_llc_flowtype allowed_remote
= SMC_LLC_FLOW_NONE
;
292 /* all flows except confirm_rkey and delete_rkey are exclusive,
293 * confirm/delete rkey flows can run concurrently (local and remote)
295 if (type
== SMC_LLC_FLOW_RKEY
)
296 allowed_remote
= SMC_LLC_FLOW_RKEY
;
298 if (list_empty(&lgr
->list
))
300 spin_lock_bh(&lgr
->llc_flow_lock
);
301 if (lgr
->llc_flow_lcl
.type
== SMC_LLC_FLOW_NONE
&&
302 (lgr
->llc_flow_rmt
.type
== SMC_LLC_FLOW_NONE
||
303 lgr
->llc_flow_rmt
.type
== allowed_remote
)) {
304 lgr
->llc_flow_lcl
.type
= type
;
305 spin_unlock_bh(&lgr
->llc_flow_lock
);
308 spin_unlock_bh(&lgr
->llc_flow_lock
);
309 rc
= wait_event_timeout(lgr
->llc_flow_waiter
, (list_empty(&lgr
->list
) ||
310 (lgr
->llc_flow_lcl
.type
== SMC_LLC_FLOW_NONE
&&
311 (lgr
->llc_flow_rmt
.type
== SMC_LLC_FLOW_NONE
||
312 lgr
->llc_flow_rmt
.type
== allowed_remote
))),
313 SMC_LLC_WAIT_TIME
* 10);
319 /* finish the current llc flow */
320 void smc_llc_flow_stop(struct smc_link_group
*lgr
, struct smc_llc_flow
*flow
)
322 spin_lock_bh(&lgr
->llc_flow_lock
);
323 memset(flow
, 0, sizeof(*flow
));
324 flow
->type
= SMC_LLC_FLOW_NONE
;
325 spin_unlock_bh(&lgr
->llc_flow_lock
);
326 if (!list_empty(&lgr
->list
) && lgr
->delayed_event
&&
327 flow
== &lgr
->llc_flow_lcl
)
328 schedule_work(&lgr
->llc_event_work
);
330 wake_up(&lgr
->llc_flow_waiter
);
333 /* lnk is optional and used for early wakeup when link goes down, useful in
334 * cases where we wait for a response on the link after we sent a request
336 struct smc_llc_qentry
*smc_llc_wait(struct smc_link_group
*lgr
,
337 struct smc_link
*lnk
,
338 int time_out
, u8 exp_msg
)
340 struct smc_llc_flow
*flow
= &lgr
->llc_flow_lcl
;
343 wait_event_timeout(lgr
->llc_msg_waiter
,
345 (lnk
&& !smc_link_usable(lnk
)) ||
346 list_empty(&lgr
->list
)),
349 (lnk
&& !smc_link_usable(lnk
)) || list_empty(&lgr
->list
)) {
350 smc_llc_flow_qentry_del(flow
);
353 rcv_msg
= flow
->qentry
->msg
.raw
.hdr
.common
.llc_type
;
354 if (exp_msg
&& rcv_msg
!= exp_msg
) {
355 if (exp_msg
== SMC_LLC_ADD_LINK
&&
356 rcv_msg
== SMC_LLC_DELETE_LINK
) {
357 /* flow_start will delay the unexpected msg */
358 smc_llc_flow_start(&lgr
->llc_flow_lcl
,
359 smc_llc_flow_qentry_clr(flow
));
362 pr_warn_once("smc: SMC-R lg %*phN net %llu dropped unexpected LLC msg: "
363 "msg %d exp %d flow %d role %d flags %x\n",
364 SMC_LGR_ID_SIZE
, &lgr
->id
, lgr
->net
->net_cookie
,
366 flow
->type
, lgr
->role
,
367 flow
->qentry
->msg
.raw
.hdr
.flags
);
368 smc_llc_flow_qentry_del(flow
);
374 /********************************** send *************************************/
376 struct smc_llc_tx_pend
{
379 /* handler for send/transmission completion of an LLC msg */
380 static void smc_llc_tx_handler(struct smc_wr_tx_pend_priv
*pend
,
381 struct smc_link
*link
,
382 enum ib_wc_status wc_status
)
384 /* future work: handle wc_status error for recovery and failover */
388 * smc_llc_add_pending_send() - add LLC control message to pending WQE transmits
389 * @link: Pointer to SMC link used for sending LLC control message.
390 * @wr_buf: Out variable returning pointer to work request payload buffer.
391 * @pend: Out variable returning pointer to private pending WR tracking.
392 * It's the context the transmit complete handler will get.
394 * Reserves and pre-fills an entry for a pending work request send/tx.
395 * Used by mid-level smc_llc_send_msg() to prepare for later actual send/tx.
396 * Can sleep due to smc_get_ctrl_buf (if not in softirq context).
398 * Return: 0 on success, otherwise an error value.
400 static int smc_llc_add_pending_send(struct smc_link
*link
,
401 struct smc_wr_buf
**wr_buf
,
402 struct smc_wr_tx_pend_priv
**pend
)
406 rc
= smc_wr_tx_get_free_slot(link
, smc_llc_tx_handler
, wr_buf
, NULL
,
411 sizeof(union smc_llc_msg
) > SMC_WR_BUF_SIZE
,
412 "must increase SMC_WR_BUF_SIZE to at least sizeof(struct smc_llc_msg)");
414 sizeof(union smc_llc_msg
) != SMC_WR_TX_SIZE
,
415 "must adapt SMC_WR_TX_SIZE to sizeof(struct smc_llc_msg); if not all smc_wr upper layer protocols use the same message size any more, must start to set link->wr_tx_sges[i].length on each individual smc_wr_tx_send()");
417 sizeof(struct smc_llc_tx_pend
) > SMC_WR_TX_PEND_PRIV_SIZE
,
418 "must increase SMC_WR_TX_PEND_PRIV_SIZE to at least sizeof(struct smc_llc_tx_pend)");
422 static int smc_llc_add_pending_send_v2(struct smc_link
*link
,
423 struct smc_wr_v2_buf
**wr_buf
,
424 struct smc_wr_tx_pend_priv
**pend
)
428 rc
= smc_wr_tx_get_v2_slot(link
, smc_llc_tx_handler
, wr_buf
, pend
);
434 static void smc_llc_init_msg_hdr(struct smc_llc_hdr
*hdr
,
435 struct smc_link_group
*lgr
, size_t len
)
437 if (lgr
->smc_version
== SMC_V2
) {
438 hdr
->common
.llc_version
= SMC_V2
;
439 hdr
->length_v2
= len
;
441 hdr
->common
.llc_version
= 0;
446 /* high-level API to send LLC confirm link */
447 int smc_llc_send_confirm_link(struct smc_link
*link
,
448 enum smc_llc_reqresp reqresp
)
450 struct smc_llc_msg_confirm_link
*confllc
;
451 struct smc_wr_tx_pend_priv
*pend
;
452 struct smc_wr_buf
*wr_buf
;
455 if (!smc_wr_tx_link_hold(link
))
457 rc
= smc_llc_add_pending_send(link
, &wr_buf
, &pend
);
460 confllc
= (struct smc_llc_msg_confirm_link
*)wr_buf
;
461 memset(confllc
, 0, sizeof(*confllc
));
462 confllc
->hd
.common
.llc_type
= SMC_LLC_CONFIRM_LINK
;
463 smc_llc_init_msg_hdr(&confllc
->hd
, link
->lgr
, sizeof(*confllc
));
464 confllc
->hd
.flags
|= SMC_LLC_FLAG_NO_RMBE_EYEC
;
465 if (reqresp
== SMC_LLC_RESP
)
466 confllc
->hd
.flags
|= SMC_LLC_FLAG_RESP
;
467 memcpy(confllc
->sender_mac
, link
->smcibdev
->mac
[link
->ibport
- 1],
469 memcpy(confllc
->sender_gid
, link
->gid
, SMC_GID_SIZE
);
470 hton24(confllc
->sender_qp_num
, link
->roce_qp
->qp_num
);
471 confllc
->link_num
= link
->link_id
;
472 memcpy(confllc
->link_uid
, link
->link_uid
, SMC_LGR_ID_SIZE
);
473 confllc
->max_links
= SMC_LINKS_ADD_LNK_MAX
;
474 if (link
->lgr
->smc_version
== SMC_V2
&&
475 link
->lgr
->peer_smc_release
>= SMC_RELEASE_1
) {
476 confllc
->max_conns
= link
->lgr
->max_conns
;
477 confllc
->max_links
= link
->lgr
->max_links
;
479 /* send llc message */
480 rc
= smc_wr_tx_send(link
, pend
);
482 smc_wr_tx_link_put(link
);
486 /* send LLC confirm rkey request */
487 static int smc_llc_send_confirm_rkey(struct smc_link
*send_link
,
488 struct smc_buf_desc
*rmb_desc
)
490 struct smc_llc_msg_confirm_rkey
*rkeyllc
;
491 struct smc_wr_tx_pend_priv
*pend
;
492 struct smc_wr_buf
*wr_buf
;
493 struct smc_link
*link
;
496 if (!smc_wr_tx_link_hold(send_link
))
498 rc
= smc_llc_add_pending_send(send_link
, &wr_buf
, &pend
);
501 rkeyllc
= (struct smc_llc_msg_confirm_rkey
*)wr_buf
;
502 memset(rkeyllc
, 0, sizeof(*rkeyllc
));
503 rkeyllc
->hd
.common
.llc_type
= SMC_LLC_CONFIRM_RKEY
;
504 smc_llc_init_msg_hdr(&rkeyllc
->hd
, send_link
->lgr
, sizeof(*rkeyllc
));
507 for (i
= 0; i
< SMC_LINKS_PER_LGR_MAX
; i
++) {
508 link
= &send_link
->lgr
->lnk
[i
];
509 if (smc_link_active(link
) && link
!= send_link
) {
510 rkeyllc
->rtoken
[rtok_ix
].link_id
= link
->link_id
;
511 rkeyllc
->rtoken
[rtok_ix
].rmb_key
=
512 htonl(rmb_desc
->mr
[link
->link_idx
]->rkey
);
513 rkeyllc
->rtoken
[rtok_ix
].rmb_vaddr
= rmb_desc
->is_vm
?
514 cpu_to_be64((uintptr_t)rmb_desc
->cpu_addr
) :
515 cpu_to_be64((u64
)sg_dma_address
516 (rmb_desc
->sgt
[link
->link_idx
].sgl
));
520 /* rkey of send_link is in rtoken[0] */
521 rkeyllc
->rtoken
[0].num_rkeys
= rtok_ix
- 1;
522 rkeyllc
->rtoken
[0].rmb_key
=
523 htonl(rmb_desc
->mr
[send_link
->link_idx
]->rkey
);
524 rkeyllc
->rtoken
[0].rmb_vaddr
= rmb_desc
->is_vm
?
525 cpu_to_be64((uintptr_t)rmb_desc
->cpu_addr
) :
526 cpu_to_be64((u64
)sg_dma_address
527 (rmb_desc
->sgt
[send_link
->link_idx
].sgl
));
528 /* send llc message */
529 rc
= smc_wr_tx_send(send_link
, pend
);
531 smc_wr_tx_link_put(send_link
);
535 /* send LLC delete rkey request */
536 static int smc_llc_send_delete_rkey(struct smc_link
*link
,
537 struct smc_buf_desc
*rmb_desc
)
539 struct smc_llc_msg_delete_rkey
*rkeyllc
;
540 struct smc_wr_tx_pend_priv
*pend
;
541 struct smc_wr_buf
*wr_buf
;
544 if (!smc_wr_tx_link_hold(link
))
546 rc
= smc_llc_add_pending_send(link
, &wr_buf
, &pend
);
549 rkeyllc
= (struct smc_llc_msg_delete_rkey
*)wr_buf
;
550 memset(rkeyllc
, 0, sizeof(*rkeyllc
));
551 rkeyllc
->hd
.common
.llc_type
= SMC_LLC_DELETE_RKEY
;
552 smc_llc_init_msg_hdr(&rkeyllc
->hd
, link
->lgr
, sizeof(*rkeyllc
));
553 rkeyllc
->num_rkeys
= 1;
554 rkeyllc
->rkey
[0] = htonl(rmb_desc
->mr
[link
->link_idx
]->rkey
);
555 /* send llc message */
556 rc
= smc_wr_tx_send(link
, pend
);
558 smc_wr_tx_link_put(link
);
562 /* return first buffer from any of the next buf lists */
563 static struct smc_buf_desc
*_smc_llc_get_next_rmb(struct smc_link_group
*lgr
,
566 struct smc_buf_desc
*buf_pos
;
568 while (*buf_lst
< SMC_RMBE_SIZES
) {
569 buf_pos
= list_first_entry_or_null(&lgr
->rmbs
[*buf_lst
],
570 struct smc_buf_desc
, list
);
578 /* return next rmb from buffer lists */
579 static struct smc_buf_desc
*smc_llc_get_next_rmb(struct smc_link_group
*lgr
,
581 struct smc_buf_desc
*buf_pos
)
583 struct smc_buf_desc
*buf_next
;
586 return _smc_llc_get_next_rmb(lgr
, buf_lst
);
588 if (list_is_last(&buf_pos
->list
, &lgr
->rmbs
[*buf_lst
])) {
590 return _smc_llc_get_next_rmb(lgr
, buf_lst
);
592 buf_next
= list_next_entry(buf_pos
, list
);
596 static struct smc_buf_desc
*smc_llc_get_first_rmb(struct smc_link_group
*lgr
,
600 return smc_llc_get_next_rmb(lgr
, buf_lst
, NULL
);
603 static int smc_llc_fill_ext_v2(struct smc_llc_msg_add_link_v2_ext
*ext
,
604 struct smc_link
*link
, struct smc_link
*link_new
)
606 struct smc_link_group
*lgr
= link
->lgr
;
607 struct smc_buf_desc
*buf_pos
;
608 int prim_lnk_idx
, lnk_idx
, i
;
609 struct smc_buf_desc
*rmb
;
610 int len
= sizeof(*ext
);
613 ext
->v2_direct
= !lgr
->uses_gateway
;
614 memcpy(ext
->client_target_gid
, link_new
->gid
, SMC_GID_SIZE
);
616 prim_lnk_idx
= link
->link_idx
;
617 lnk_idx
= link_new
->link_idx
;
618 down_write(&lgr
->rmbs_lock
);
619 ext
->num_rkeys
= lgr
->conns_num
;
622 buf_pos
= smc_llc_get_first_rmb(lgr
, &buf_lst
);
623 for (i
= 0; i
< ext
->num_rkeys
; i
++) {
624 while (buf_pos
&& !(buf_pos
)->used
)
625 buf_pos
= smc_llc_get_next_rmb(lgr
, &buf_lst
, buf_pos
);
629 ext
->rt
[i
].rmb_key
= htonl(rmb
->mr
[prim_lnk_idx
]->rkey
);
630 ext
->rt
[i
].rmb_key_new
= htonl(rmb
->mr
[lnk_idx
]->rkey
);
631 ext
->rt
[i
].rmb_vaddr_new
= rmb
->is_vm
?
632 cpu_to_be64((uintptr_t)rmb
->cpu_addr
) :
633 cpu_to_be64((u64
)sg_dma_address(rmb
->sgt
[lnk_idx
].sgl
));
634 buf_pos
= smc_llc_get_next_rmb(lgr
, &buf_lst
, buf_pos
);
636 len
+= i
* sizeof(ext
->rt
[0]);
638 up_write(&lgr
->rmbs_lock
);
642 /* send ADD LINK request or response */
643 int smc_llc_send_add_link(struct smc_link
*link
, u8 mac
[], u8 gid
[],
644 struct smc_link
*link_new
,
645 enum smc_llc_reqresp reqresp
)
647 struct smc_llc_msg_add_link_v2_ext
*ext
= NULL
;
648 struct smc_llc_msg_add_link
*addllc
;
649 struct smc_wr_tx_pend_priv
*pend
;
650 int len
= sizeof(*addllc
);
653 if (!smc_wr_tx_link_hold(link
))
655 if (link
->lgr
->smc_version
== SMC_V2
) {
656 struct smc_wr_v2_buf
*wr_buf
;
658 rc
= smc_llc_add_pending_send_v2(link
, &wr_buf
, &pend
);
661 addllc
= (struct smc_llc_msg_add_link
*)wr_buf
;
662 ext
= (struct smc_llc_msg_add_link_v2_ext
*)
663 &wr_buf
->raw
[sizeof(*addllc
)];
664 memset(ext
, 0, SMC_WR_TX_SIZE
);
666 struct smc_wr_buf
*wr_buf
;
668 rc
= smc_llc_add_pending_send(link
, &wr_buf
, &pend
);
671 addllc
= (struct smc_llc_msg_add_link
*)wr_buf
;
674 memset(addllc
, 0, sizeof(*addllc
));
675 addllc
->hd
.common
.llc_type
= SMC_LLC_ADD_LINK
;
676 if (reqresp
== SMC_LLC_RESP
)
677 addllc
->hd
.flags
|= SMC_LLC_FLAG_RESP
;
678 memcpy(addllc
->sender_mac
, mac
, ETH_ALEN
);
679 memcpy(addllc
->sender_gid
, gid
, SMC_GID_SIZE
);
681 addllc
->link_num
= link_new
->link_id
;
682 hton24(addllc
->sender_qp_num
, link_new
->roce_qp
->qp_num
);
683 hton24(addllc
->initial_psn
, link_new
->psn_initial
);
684 if (reqresp
== SMC_LLC_REQ
)
685 addllc
->qp_mtu
= link_new
->path_mtu
;
687 addllc
->qp_mtu
= min(link_new
->path_mtu
,
691 len
+= smc_llc_fill_ext_v2(ext
, link
, link_new
);
692 smc_llc_init_msg_hdr(&addllc
->hd
, link
->lgr
, len
);
693 /* send llc message */
694 if (link
->lgr
->smc_version
== SMC_V2
)
695 rc
= smc_wr_tx_v2_send(link
, pend
, len
);
697 rc
= smc_wr_tx_send(link
, pend
);
699 smc_wr_tx_link_put(link
);
703 /* send DELETE LINK request or response */
704 int smc_llc_send_delete_link(struct smc_link
*link
, u8 link_del_id
,
705 enum smc_llc_reqresp reqresp
, bool orderly
,
708 struct smc_llc_msg_del_link
*delllc
;
709 struct smc_wr_tx_pend_priv
*pend
;
710 struct smc_wr_buf
*wr_buf
;
713 if (!smc_wr_tx_link_hold(link
))
715 rc
= smc_llc_add_pending_send(link
, &wr_buf
, &pend
);
718 delllc
= (struct smc_llc_msg_del_link
*)wr_buf
;
720 memset(delllc
, 0, sizeof(*delllc
));
721 delllc
->hd
.common
.llc_type
= SMC_LLC_DELETE_LINK
;
722 smc_llc_init_msg_hdr(&delllc
->hd
, link
->lgr
, sizeof(*delllc
));
723 if (reqresp
== SMC_LLC_RESP
)
724 delllc
->hd
.flags
|= SMC_LLC_FLAG_RESP
;
726 delllc
->hd
.flags
|= SMC_LLC_FLAG_DEL_LINK_ORDERLY
;
728 delllc
->link_num
= link_del_id
;
730 delllc
->hd
.flags
|= SMC_LLC_FLAG_DEL_LINK_ALL
;
731 delllc
->reason
= htonl(reason
);
732 /* send llc message */
733 rc
= smc_wr_tx_send(link
, pend
);
735 smc_wr_tx_link_put(link
);
739 /* send LLC test link request */
740 static int smc_llc_send_test_link(struct smc_link
*link
, u8 user_data
[16])
742 struct smc_llc_msg_test_link
*testllc
;
743 struct smc_wr_tx_pend_priv
*pend
;
744 struct smc_wr_buf
*wr_buf
;
747 if (!smc_wr_tx_link_hold(link
))
749 rc
= smc_llc_add_pending_send(link
, &wr_buf
, &pend
);
752 testllc
= (struct smc_llc_msg_test_link
*)wr_buf
;
753 memset(testllc
, 0, sizeof(*testllc
));
754 testllc
->hd
.common
.llc_type
= SMC_LLC_TEST_LINK
;
755 smc_llc_init_msg_hdr(&testllc
->hd
, link
->lgr
, sizeof(*testllc
));
756 memcpy(testllc
->user_data
, user_data
, sizeof(testllc
->user_data
));
757 /* send llc message */
758 rc
= smc_wr_tx_send(link
, pend
);
760 smc_wr_tx_link_put(link
);
764 /* schedule an llc send on link, may wait for buffers */
765 static int smc_llc_send_message(struct smc_link
*link
, void *llcbuf
)
767 struct smc_wr_tx_pend_priv
*pend
;
768 struct smc_wr_buf
*wr_buf
;
771 if (!smc_wr_tx_link_hold(link
))
773 rc
= smc_llc_add_pending_send(link
, &wr_buf
, &pend
);
776 memcpy(wr_buf
, llcbuf
, sizeof(union smc_llc_msg
));
777 rc
= smc_wr_tx_send(link
, pend
);
779 smc_wr_tx_link_put(link
);
783 /* schedule an llc send on link, may wait for buffers,
784 * and wait for send completion notification.
785 * @return 0 on success
787 static int smc_llc_send_message_wait(struct smc_link
*link
, void *llcbuf
)
789 struct smc_wr_tx_pend_priv
*pend
;
790 struct smc_wr_buf
*wr_buf
;
793 if (!smc_wr_tx_link_hold(link
))
795 rc
= smc_llc_add_pending_send(link
, &wr_buf
, &pend
);
798 memcpy(wr_buf
, llcbuf
, sizeof(union smc_llc_msg
));
799 rc
= smc_wr_tx_send_wait(link
, pend
, SMC_LLC_WAIT_TIME
);
801 smc_wr_tx_link_put(link
);
805 /********************************* receive ***********************************/
807 static int smc_llc_alloc_alt_link(struct smc_link_group
*lgr
,
808 enum smc_lgr_type lgr_new_t
)
812 if (lgr
->type
== SMC_LGR_SYMMETRIC
||
813 (lgr
->type
!= SMC_LGR_SINGLE
&&
814 (lgr_new_t
== SMC_LGR_ASYMMETRIC_LOCAL
||
815 lgr_new_t
== SMC_LGR_ASYMMETRIC_PEER
)))
818 if (lgr_new_t
== SMC_LGR_ASYMMETRIC_LOCAL
||
819 lgr_new_t
== SMC_LGR_ASYMMETRIC_PEER
) {
820 for (i
= SMC_LINKS_PER_LGR_MAX
- 1; i
>= 0; i
--)
821 if (lgr
->lnk
[i
].state
== SMC_LNK_UNUSED
)
824 for (i
= 0; i
< SMC_LINKS_PER_LGR_MAX
; i
++)
825 if (lgr
->lnk
[i
].state
== SMC_LNK_UNUSED
)
831 /* send one add_link_continue msg */
832 static int smc_llc_add_link_cont(struct smc_link
*link
,
833 struct smc_link
*link_new
, u8
*num_rkeys_todo
,
834 int *buf_lst
, struct smc_buf_desc
**buf_pos
)
836 struct smc_llc_msg_add_link_cont
*addc_llc
;
837 struct smc_link_group
*lgr
= link
->lgr
;
838 int prim_lnk_idx
, lnk_idx
, i
, rc
;
839 struct smc_wr_tx_pend_priv
*pend
;
840 struct smc_wr_buf
*wr_buf
;
841 struct smc_buf_desc
*rmb
;
844 if (!smc_wr_tx_link_hold(link
))
846 rc
= smc_llc_add_pending_send(link
, &wr_buf
, &pend
);
849 addc_llc
= (struct smc_llc_msg_add_link_cont
*)wr_buf
;
850 memset(addc_llc
, 0, sizeof(*addc_llc
));
852 prim_lnk_idx
= link
->link_idx
;
853 lnk_idx
= link_new
->link_idx
;
854 addc_llc
->link_num
= link_new
->link_id
;
855 addc_llc
->num_rkeys
= *num_rkeys_todo
;
857 for (i
= 0; i
< min_t(u8
, n
, SMC_LLC_RKEYS_PER_CONT_MSG
); i
++) {
858 while (*buf_pos
&& !(*buf_pos
)->used
)
859 *buf_pos
= smc_llc_get_next_rmb(lgr
, buf_lst
, *buf_pos
);
861 addc_llc
->num_rkeys
= addc_llc
->num_rkeys
-
868 addc_llc
->rt
[i
].rmb_key
= htonl(rmb
->mr
[prim_lnk_idx
]->rkey
);
869 addc_llc
->rt
[i
].rmb_key_new
= htonl(rmb
->mr
[lnk_idx
]->rkey
);
870 addc_llc
->rt
[i
].rmb_vaddr_new
= rmb
->is_vm
?
871 cpu_to_be64((uintptr_t)rmb
->cpu_addr
) :
872 cpu_to_be64((u64
)sg_dma_address(rmb
->sgt
[lnk_idx
].sgl
));
875 *buf_pos
= smc_llc_get_next_rmb(lgr
, buf_lst
, *buf_pos
);
877 addc_llc
->hd
.common
.llc_type
= SMC_LLC_ADD_LINK_CONT
;
878 addc_llc
->hd
.length
= sizeof(struct smc_llc_msg_add_link_cont
);
879 if (lgr
->role
== SMC_CLNT
)
880 addc_llc
->hd
.flags
|= SMC_LLC_FLAG_RESP
;
881 rc
= smc_wr_tx_send(link
, pend
);
883 smc_wr_tx_link_put(link
);
887 static int smc_llc_cli_rkey_exchange(struct smc_link
*link
,
888 struct smc_link
*link_new
)
890 struct smc_llc_msg_add_link_cont
*addc_llc
;
891 struct smc_link_group
*lgr
= link
->lgr
;
892 u8 max
, num_rkeys_send
, num_rkeys_recv
;
893 struct smc_llc_qentry
*qentry
;
894 struct smc_buf_desc
*buf_pos
;
899 down_write(&lgr
->rmbs_lock
);
900 num_rkeys_send
= lgr
->conns_num
;
901 buf_pos
= smc_llc_get_first_rmb(lgr
, &buf_lst
);
903 qentry
= smc_llc_wait(lgr
, NULL
, SMC_LLC_WAIT_TIME
,
904 SMC_LLC_ADD_LINK_CONT
);
909 addc_llc
= &qentry
->msg
.add_link_cont
;
910 num_rkeys_recv
= addc_llc
->num_rkeys
;
911 max
= min_t(u8
, num_rkeys_recv
, SMC_LLC_RKEYS_PER_CONT_MSG
);
912 for (i
= 0; i
< max
; i
++) {
913 smc_rtoken_set(lgr
, link
->link_idx
, link_new
->link_idx
,
914 addc_llc
->rt
[i
].rmb_key
,
915 addc_llc
->rt
[i
].rmb_vaddr_new
,
916 addc_llc
->rt
[i
].rmb_key_new
);
919 smc_llc_flow_qentry_del(&lgr
->llc_flow_lcl
);
920 rc
= smc_llc_add_link_cont(link
, link_new
, &num_rkeys_send
,
924 } while (num_rkeys_send
|| num_rkeys_recv
);
926 up_write(&lgr
->rmbs_lock
);
930 /* prepare and send an add link reject response */
931 static int smc_llc_cli_add_link_reject(struct smc_llc_qentry
*qentry
)
933 qentry
->msg
.raw
.hdr
.flags
|= SMC_LLC_FLAG_RESP
;
934 qentry
->msg
.raw
.hdr
.flags
|= SMC_LLC_FLAG_ADD_LNK_REJ
;
935 qentry
->msg
.raw
.hdr
.add_link_rej_rsn
= SMC_LLC_REJ_RSN_NO_ALT_PATH
;
936 smc_llc_init_msg_hdr(&qentry
->msg
.raw
.hdr
, qentry
->link
->lgr
,
937 sizeof(qentry
->msg
));
938 return smc_llc_send_message(qentry
->link
, &qentry
->msg
);
941 static int smc_llc_cli_conf_link(struct smc_link
*link
,
942 struct smc_init_info
*ini
,
943 struct smc_link
*link_new
,
944 enum smc_lgr_type lgr_new_t
)
946 struct smc_link_group
*lgr
= link
->lgr
;
947 struct smc_llc_qentry
*qentry
= NULL
;
950 /* receive CONFIRM LINK request over RoCE fabric */
951 qentry
= smc_llc_wait(lgr
, NULL
, SMC_LLC_WAIT_FIRST_TIME
, 0);
953 rc
= smc_llc_send_delete_link(link
, link_new
->link_id
,
955 SMC_LLC_DEL_LOST_PATH
);
958 if (qentry
->msg
.raw
.hdr
.common
.llc_type
!= SMC_LLC_CONFIRM_LINK
) {
959 /* received DELETE_LINK instead */
960 qentry
->msg
.raw
.hdr
.flags
|= SMC_LLC_FLAG_RESP
;
961 smc_llc_send_message(link
, &qentry
->msg
);
962 smc_llc_flow_qentry_del(&lgr
->llc_flow_lcl
);
965 smc_llc_save_peer_uid(qentry
);
966 smc_llc_flow_qentry_del(&lgr
->llc_flow_lcl
);
968 rc
= smc_ib_modify_qp_rts(link_new
);
970 smc_llc_send_delete_link(link
, link_new
->link_id
, SMC_LLC_REQ
,
971 false, SMC_LLC_DEL_LOST_PATH
);
974 smc_wr_remember_qp_attr(link_new
);
976 rc
= smcr_buf_reg_lgr(link_new
);
978 smc_llc_send_delete_link(link
, link_new
->link_id
, SMC_LLC_REQ
,
979 false, SMC_LLC_DEL_LOST_PATH
);
983 /* send CONFIRM LINK response over RoCE fabric */
984 rc
= smc_llc_send_confirm_link(link_new
, SMC_LLC_RESP
);
986 smc_llc_send_delete_link(link
, link_new
->link_id
, SMC_LLC_REQ
,
987 false, SMC_LLC_DEL_LOST_PATH
);
990 smc_llc_link_active(link_new
);
991 if (lgr_new_t
== SMC_LGR_ASYMMETRIC_LOCAL
||
992 lgr_new_t
== SMC_LGR_ASYMMETRIC_PEER
)
993 smcr_lgr_set_type_asym(lgr
, lgr_new_t
, link_new
->link_idx
);
995 smcr_lgr_set_type(lgr
, lgr_new_t
);
999 static void smc_llc_save_add_link_rkeys(struct smc_link
*link
,
1000 struct smc_link
*link_new
)
1002 struct smc_llc_msg_add_link_v2_ext
*ext
;
1003 struct smc_link_group
*lgr
= link
->lgr
;
1006 ext
= (struct smc_llc_msg_add_link_v2_ext
*)((u8
*)lgr
->wr_rx_buf_v2
+
1008 max
= min_t(u8
, ext
->num_rkeys
, SMC_LLC_RKEYS_PER_MSG_V2
);
1009 down_write(&lgr
->rmbs_lock
);
1010 for (i
= 0; i
< max
; i
++) {
1011 smc_rtoken_set(lgr
, link
->link_idx
, link_new
->link_idx
,
1013 ext
->rt
[i
].rmb_vaddr_new
,
1014 ext
->rt
[i
].rmb_key_new
);
1016 up_write(&lgr
->rmbs_lock
);
1019 static void smc_llc_save_add_link_info(struct smc_link
*link
,
1020 struct smc_llc_msg_add_link
*add_llc
)
1022 link
->peer_qpn
= ntoh24(add_llc
->sender_qp_num
);
1023 memcpy(link
->peer_gid
, add_llc
->sender_gid
, SMC_GID_SIZE
);
1024 memcpy(link
->peer_mac
, add_llc
->sender_mac
, ETH_ALEN
);
1025 link
->peer_psn
= ntoh24(add_llc
->initial_psn
);
1026 link
->peer_mtu
= add_llc
->qp_mtu
;
1029 /* as an SMC client, process an add link request */
1030 int smc_llc_cli_add_link(struct smc_link
*link
, struct smc_llc_qentry
*qentry
)
1032 struct smc_llc_msg_add_link
*llc
= &qentry
->msg
.add_link
;
1033 enum smc_lgr_type lgr_new_t
= SMC_LGR_SYMMETRIC
;
1034 struct smc_link_group
*lgr
= smc_get_lgr(link
);
1035 struct smc_init_info
*ini
= NULL
;
1036 struct smc_link
*lnk_new
= NULL
;
1037 int lnk_idx
, rc
= 0;
1042 ini
= kzalloc(sizeof(*ini
), GFP_KERNEL
);
1048 if (lgr
->type
== SMC_LGR_SINGLE
&& lgr
->max_links
<= 1) {
1053 ini
->vlan_id
= lgr
->vlan_id
;
1054 if (lgr
->smc_version
== SMC_V2
) {
1055 ini
->check_smcrv2
= true;
1056 ini
->smcrv2
.saddr
= lgr
->saddr
;
1057 ini
->smcrv2
.daddr
= smc_ib_gid_to_ipv4(llc
->sender_gid
);
1059 smc_pnet_find_alt_roce(lgr
, ini
, link
->smcibdev
);
1060 if (!memcmp(llc
->sender_gid
, link
->peer_gid
, SMC_GID_SIZE
) &&
1061 (lgr
->smc_version
== SMC_V2
||
1062 !memcmp(llc
->sender_mac
, link
->peer_mac
, ETH_ALEN
))) {
1063 if (!ini
->ib_dev
&& !ini
->smcrv2
.ib_dev_v2
)
1065 lgr_new_t
= SMC_LGR_ASYMMETRIC_PEER
;
1067 if (lgr
->smc_version
== SMC_V2
&& !ini
->smcrv2
.ib_dev_v2
) {
1068 lgr_new_t
= SMC_LGR_ASYMMETRIC_LOCAL
;
1069 ini
->smcrv2
.ib_dev_v2
= link
->smcibdev
;
1070 ini
->smcrv2
.ib_port_v2
= link
->ibport
;
1071 } else if (lgr
->smc_version
< SMC_V2
&& !ini
->ib_dev
) {
1072 lgr_new_t
= SMC_LGR_ASYMMETRIC_LOCAL
;
1073 ini
->ib_dev
= link
->smcibdev
;
1074 ini
->ib_port
= link
->ibport
;
1076 lnk_idx
= smc_llc_alloc_alt_link(lgr
, lgr_new_t
);
1079 lnk_new
= &lgr
->lnk
[lnk_idx
];
1080 rc
= smcr_link_init(lgr
, lnk_new
, lnk_idx
, ini
);
1083 smc_llc_save_add_link_info(lnk_new
, llc
);
1084 lnk_new
->link_id
= llc
->link_num
; /* SMC server assigns link id */
1085 smc_llc_link_set_uid(lnk_new
);
1087 rc
= smc_ib_ready_link(lnk_new
);
1091 rc
= smcr_buf_map_lgr(lnk_new
);
1095 rc
= smc_llc_send_add_link(link
,
1096 lnk_new
->smcibdev
->mac
[lnk_new
->ibport
- 1],
1097 lnk_new
->gid
, lnk_new
, SMC_LLC_RESP
);
1100 if (lgr
->smc_version
== SMC_V2
) {
1101 smc_llc_save_add_link_rkeys(link
, lnk_new
);
1103 rc
= smc_llc_cli_rkey_exchange(link
, lnk_new
);
1109 rc
= smc_llc_cli_conf_link(link
, ini
, lnk_new
, lgr_new_t
);
1113 lnk_new
->state
= SMC_LNK_INACTIVE
;
1114 smcr_link_clear(lnk_new
, false);
1116 smc_llc_cli_add_link_reject(qentry
);
1123 static void smc_llc_send_request_add_link(struct smc_link
*link
)
1125 struct smc_llc_msg_req_add_link_v2
*llc
;
1126 struct smc_wr_tx_pend_priv
*pend
;
1127 struct smc_wr_v2_buf
*wr_buf
;
1128 struct smc_gidlist gidlist
;
1131 if (!smc_wr_tx_link_hold(link
))
1133 if (link
->lgr
->type
== SMC_LGR_SYMMETRIC
||
1134 link
->lgr
->type
== SMC_LGR_ASYMMETRIC_PEER
)
1137 smc_fill_gid_list(link
->lgr
, &gidlist
, link
->smcibdev
, link
->gid
);
1138 if (gidlist
.len
<= 1)
1141 rc
= smc_llc_add_pending_send_v2(link
, &wr_buf
, &pend
);
1144 llc
= (struct smc_llc_msg_req_add_link_v2
*)wr_buf
;
1145 memset(llc
, 0, SMC_WR_TX_SIZE
);
1147 llc
->hd
.common
.llc_type
= SMC_LLC_REQ_ADD_LINK
;
1148 for (i
= 0; i
< gidlist
.len
; i
++)
1149 memcpy(llc
->gid
[i
], gidlist
.list
[i
], sizeof(gidlist
.list
[0]));
1150 llc
->gid_cnt
= gidlist
.len
;
1151 len
= sizeof(*llc
) + (gidlist
.len
* sizeof(gidlist
.list
[0]));
1152 smc_llc_init_msg_hdr(&llc
->hd
, link
->lgr
, len
);
1153 rc
= smc_wr_tx_v2_send(link
, pend
, len
);
1155 /* set REQ_ADD_LINK flow and wait for response from peer */
1156 link
->lgr
->llc_flow_lcl
.type
= SMC_LLC_FLOW_REQ_ADD_LINK
;
1158 smc_wr_tx_link_put(link
);
1161 /* as an SMC client, invite server to start the add_link processing */
1162 static void smc_llc_cli_add_link_invite(struct smc_link
*link
,
1163 struct smc_llc_qentry
*qentry
)
1165 struct smc_link_group
*lgr
= smc_get_lgr(link
);
1166 struct smc_init_info
*ini
= NULL
;
1168 if (lgr
->smc_version
== SMC_V2
) {
1169 smc_llc_send_request_add_link(link
);
1173 if (lgr
->type
== SMC_LGR_SYMMETRIC
||
1174 lgr
->type
== SMC_LGR_ASYMMETRIC_PEER
)
1177 if (lgr
->type
== SMC_LGR_SINGLE
&& lgr
->max_links
<= 1)
1180 ini
= kzalloc(sizeof(*ini
), GFP_KERNEL
);
1184 ini
->vlan_id
= lgr
->vlan_id
;
1185 smc_pnet_find_alt_roce(lgr
, ini
, link
->smcibdev
);
1189 smc_llc_send_add_link(link
, ini
->ib_dev
->mac
[ini
->ib_port
- 1],
1190 ini
->ib_gid
, NULL
, SMC_LLC_REQ
);
1196 static bool smc_llc_is_empty_llc_message(union smc_llc_msg
*llc
)
1200 for (i
= 0; i
< ARRAY_SIZE(llc
->raw
.data
); i
++)
1201 if (llc
->raw
.data
[i
])
1206 static bool smc_llc_is_local_add_link(union smc_llc_msg
*llc
)
1208 if (llc
->raw
.hdr
.common
.llc_type
== SMC_LLC_ADD_LINK
&&
1209 smc_llc_is_empty_llc_message(llc
))
1214 static void smc_llc_process_cli_add_link(struct smc_link_group
*lgr
)
1216 struct smc_llc_qentry
*qentry
;
1218 qentry
= smc_llc_flow_qentry_clr(&lgr
->llc_flow_lcl
);
1220 down_write(&lgr
->llc_conf_mutex
);
1221 if (smc_llc_is_local_add_link(&qentry
->msg
))
1222 smc_llc_cli_add_link_invite(qentry
->link
, qentry
);
1224 smc_llc_cli_add_link(qentry
->link
, qentry
);
1225 up_write(&lgr
->llc_conf_mutex
);
1228 static int smc_llc_active_link_count(struct smc_link_group
*lgr
)
1230 int i
, link_count
= 0;
1232 for (i
= 0; i
< SMC_LINKS_PER_LGR_MAX
; i
++) {
1233 if (!smc_link_active(&lgr
->lnk
[i
]))
1240 /* find the asymmetric link when 3 links are established */
1241 static struct smc_link
*smc_llc_find_asym_link(struct smc_link_group
*lgr
)
1243 int asym_idx
= -ENOENT
;
1247 /* determine asymmetric link */
1249 for (i
= 0; i
< SMC_LINKS_PER_LGR_MAX
; i
++) {
1250 for (j
= i
+ 1; j
< SMC_LINKS_PER_LGR_MAX
; j
++) {
1251 if (!smc_link_usable(&lgr
->lnk
[i
]) ||
1252 !smc_link_usable(&lgr
->lnk
[j
]))
1254 if (!memcmp(lgr
->lnk
[i
].gid
, lgr
->lnk
[j
].gid
,
1256 found
= true; /* asym_lnk is i or j */
1264 goto out
; /* no asymmetric link */
1265 for (k
= 0; k
< SMC_LINKS_PER_LGR_MAX
; k
++) {
1266 if (!smc_link_usable(&lgr
->lnk
[k
]))
1269 !memcmp(lgr
->lnk
[i
].peer_gid
, lgr
->lnk
[k
].peer_gid
,
1275 !memcmp(lgr
->lnk
[j
].peer_gid
, lgr
->lnk
[k
].peer_gid
,
1282 return (asym_idx
< 0) ? NULL
: &lgr
->lnk
[asym_idx
];
1285 static void smc_llc_delete_asym_link(struct smc_link_group
*lgr
)
1287 struct smc_link
*lnk_new
= NULL
, *lnk_asym
;
1288 struct smc_llc_qentry
*qentry
;
1291 lnk_asym
= smc_llc_find_asym_link(lgr
);
1293 return; /* no asymmetric link */
1294 if (!smc_link_downing(&lnk_asym
->state
))
1296 lnk_new
= smc_switch_conns(lgr
, lnk_asym
, false);
1297 smc_wr_tx_wait_no_pending_sends(lnk_asym
);
1300 /* change flow type from ADD_LINK into DEL_LINK */
1301 lgr
->llc_flow_lcl
.type
= SMC_LLC_FLOW_DEL_LINK
;
1302 rc
= smc_llc_send_delete_link(lnk_new
, lnk_asym
->link_id
, SMC_LLC_REQ
,
1303 true, SMC_LLC_DEL_NO_ASYM_NEEDED
);
1305 smcr_link_down_cond(lnk_new
);
1308 qentry
= smc_llc_wait(lgr
, lnk_new
, SMC_LLC_WAIT_TIME
,
1309 SMC_LLC_DELETE_LINK
);
1311 smcr_link_down_cond(lnk_new
);
1314 smc_llc_flow_qentry_del(&lgr
->llc_flow_lcl
);
1316 smcr_link_clear(lnk_asym
, true);
1319 static int smc_llc_srv_rkey_exchange(struct smc_link
*link
,
1320 struct smc_link
*link_new
)
1322 struct smc_llc_msg_add_link_cont
*addc_llc
;
1323 struct smc_link_group
*lgr
= link
->lgr
;
1324 u8 max
, num_rkeys_send
, num_rkeys_recv
;
1325 struct smc_llc_qentry
*qentry
= NULL
;
1326 struct smc_buf_desc
*buf_pos
;
1331 down_write(&lgr
->rmbs_lock
);
1332 num_rkeys_send
= lgr
->conns_num
;
1333 buf_pos
= smc_llc_get_first_rmb(lgr
, &buf_lst
);
1335 smc_llc_add_link_cont(link
, link_new
, &num_rkeys_send
,
1336 &buf_lst
, &buf_pos
);
1337 qentry
= smc_llc_wait(lgr
, link
, SMC_LLC_WAIT_TIME
,
1338 SMC_LLC_ADD_LINK_CONT
);
1343 addc_llc
= &qentry
->msg
.add_link_cont
;
1344 num_rkeys_recv
= addc_llc
->num_rkeys
;
1345 max
= min_t(u8
, num_rkeys_recv
, SMC_LLC_RKEYS_PER_CONT_MSG
);
1346 for (i
= 0; i
< max
; i
++) {
1347 smc_rtoken_set(lgr
, link
->link_idx
, link_new
->link_idx
,
1348 addc_llc
->rt
[i
].rmb_key
,
1349 addc_llc
->rt
[i
].rmb_vaddr_new
,
1350 addc_llc
->rt
[i
].rmb_key_new
);
1353 smc_llc_flow_qentry_del(&lgr
->llc_flow_lcl
);
1354 } while (num_rkeys_send
|| num_rkeys_recv
);
1356 up_write(&lgr
->rmbs_lock
);
1360 static int smc_llc_srv_conf_link(struct smc_link
*link
,
1361 struct smc_link
*link_new
,
1362 enum smc_lgr_type lgr_new_t
)
1364 struct smc_link_group
*lgr
= link
->lgr
;
1365 struct smc_llc_qentry
*qentry
= NULL
;
1368 /* send CONFIRM LINK request over the RoCE fabric */
1369 rc
= smc_llc_send_confirm_link(link_new
, SMC_LLC_REQ
);
1372 /* receive CONFIRM LINK response over the RoCE fabric */
1373 qentry
= smc_llc_wait(lgr
, link
, SMC_LLC_WAIT_FIRST_TIME
, 0);
1375 qentry
->msg
.raw
.hdr
.common
.llc_type
!= SMC_LLC_CONFIRM_LINK
) {
1376 /* send DELETE LINK */
1377 smc_llc_send_delete_link(link
, link_new
->link_id
, SMC_LLC_REQ
,
1378 false, SMC_LLC_DEL_LOST_PATH
);
1380 smc_llc_flow_qentry_del(&lgr
->llc_flow_lcl
);
1383 smc_llc_save_peer_uid(qentry
);
1384 smc_llc_link_active(link_new
);
1385 if (lgr_new_t
== SMC_LGR_ASYMMETRIC_LOCAL
||
1386 lgr_new_t
== SMC_LGR_ASYMMETRIC_PEER
)
1387 smcr_lgr_set_type_asym(lgr
, lgr_new_t
, link_new
->link_idx
);
1389 smcr_lgr_set_type(lgr
, lgr_new_t
);
1390 smc_llc_flow_qentry_del(&lgr
->llc_flow_lcl
);
1394 static void smc_llc_send_req_add_link_response(struct smc_llc_qentry
*qentry
)
1396 qentry
->msg
.raw
.hdr
.flags
|= SMC_LLC_FLAG_RESP
;
1397 smc_llc_init_msg_hdr(&qentry
->msg
.raw
.hdr
, qentry
->link
->lgr
,
1398 sizeof(qentry
->msg
));
1399 memset(&qentry
->msg
.raw
.data
, 0, sizeof(qentry
->msg
.raw
.data
));
1400 smc_llc_send_message(qentry
->link
, &qentry
->msg
);
1403 int smc_llc_srv_add_link(struct smc_link
*link
,
1404 struct smc_llc_qentry
*req_qentry
)
1406 enum smc_lgr_type lgr_new_t
= SMC_LGR_SYMMETRIC
;
1407 struct smc_link_group
*lgr
= link
->lgr
;
1408 struct smc_llc_msg_add_link
*add_llc
;
1409 struct smc_llc_qentry
*qentry
= NULL
;
1410 bool send_req_add_link_resp
= false;
1411 struct smc_link
*link_new
= NULL
;
1412 struct smc_init_info
*ini
= NULL
;
1413 int lnk_idx
, rc
= 0;
1416 req_qentry
->msg
.raw
.hdr
.common
.llc_type
== SMC_LLC_REQ_ADD_LINK
)
1417 send_req_add_link_resp
= true;
1419 ini
= kzalloc(sizeof(*ini
), GFP_KERNEL
);
1425 if (lgr
->type
== SMC_LGR_SINGLE
&& lgr
->max_links
<= 1) {
1430 /* ignore client add link recommendation, start new flow */
1431 ini
->vlan_id
= lgr
->vlan_id
;
1432 if (lgr
->smc_version
== SMC_V2
) {
1433 ini
->check_smcrv2
= true;
1434 ini
->smcrv2
.saddr
= lgr
->saddr
;
1435 if (send_req_add_link_resp
) {
1436 struct smc_llc_msg_req_add_link_v2
*req_add
=
1437 &req_qentry
->msg
.req_add_link
;
1439 ini
->smcrv2
.daddr
= smc_ib_gid_to_ipv4(req_add
->gid
[0]);
1442 smc_pnet_find_alt_roce(lgr
, ini
, link
->smcibdev
);
1443 if (lgr
->smc_version
== SMC_V2
&& !ini
->smcrv2
.ib_dev_v2
) {
1444 lgr_new_t
= SMC_LGR_ASYMMETRIC_LOCAL
;
1445 ini
->smcrv2
.ib_dev_v2
= link
->smcibdev
;
1446 ini
->smcrv2
.ib_port_v2
= link
->ibport
;
1447 } else if (lgr
->smc_version
< SMC_V2
&& !ini
->ib_dev
) {
1448 lgr_new_t
= SMC_LGR_ASYMMETRIC_LOCAL
;
1449 ini
->ib_dev
= link
->smcibdev
;
1450 ini
->ib_port
= link
->ibport
;
1452 lnk_idx
= smc_llc_alloc_alt_link(lgr
, lgr_new_t
);
1458 rc
= smcr_link_init(lgr
, &lgr
->lnk
[lnk_idx
], lnk_idx
, ini
);
1461 link_new
= &lgr
->lnk
[lnk_idx
];
1463 rc
= smcr_buf_map_lgr(link_new
);
1467 rc
= smc_llc_send_add_link(link
,
1468 link_new
->smcibdev
->mac
[link_new
->ibport
-1],
1469 link_new
->gid
, link_new
, SMC_LLC_REQ
);
1472 send_req_add_link_resp
= false;
1473 /* receive ADD LINK response over the RoCE fabric */
1474 qentry
= smc_llc_wait(lgr
, link
, SMC_LLC_WAIT_TIME
, SMC_LLC_ADD_LINK
);
1479 add_llc
= &qentry
->msg
.add_link
;
1480 if (add_llc
->hd
.flags
& SMC_LLC_FLAG_ADD_LNK_REJ
) {
1481 smc_llc_flow_qentry_del(&lgr
->llc_flow_lcl
);
1485 if (lgr
->type
== SMC_LGR_SINGLE
&&
1486 (!memcmp(add_llc
->sender_gid
, link
->peer_gid
, SMC_GID_SIZE
) &&
1487 (lgr
->smc_version
== SMC_V2
||
1488 !memcmp(add_llc
->sender_mac
, link
->peer_mac
, ETH_ALEN
)))) {
1489 lgr_new_t
= SMC_LGR_ASYMMETRIC_PEER
;
1491 smc_llc_save_add_link_info(link_new
, add_llc
);
1492 smc_llc_flow_qentry_del(&lgr
->llc_flow_lcl
);
1494 rc
= smc_ib_ready_link(link_new
);
1497 rc
= smcr_buf_reg_lgr(link_new
);
1500 if (lgr
->smc_version
== SMC_V2
) {
1501 smc_llc_save_add_link_rkeys(link
, link_new
);
1503 rc
= smc_llc_srv_rkey_exchange(link
, link_new
);
1507 rc
= smc_llc_srv_conf_link(link
, link_new
, lgr_new_t
);
1514 link_new
->state
= SMC_LNK_INACTIVE
;
1515 smcr_link_clear(link_new
, false);
1519 if (send_req_add_link_resp
)
1520 smc_llc_send_req_add_link_response(req_qentry
);
1524 static void smc_llc_process_srv_add_link(struct smc_link_group
*lgr
)
1526 struct smc_link
*link
= lgr
->llc_flow_lcl
.qentry
->link
;
1527 struct smc_llc_qentry
*qentry
;
1530 qentry
= smc_llc_flow_qentry_clr(&lgr
->llc_flow_lcl
);
1532 down_write(&lgr
->llc_conf_mutex
);
1533 rc
= smc_llc_srv_add_link(link
, qentry
);
1534 if (!rc
&& lgr
->type
== SMC_LGR_SYMMETRIC
) {
1535 /* delete any asymmetric link */
1536 smc_llc_delete_asym_link(lgr
);
1538 up_write(&lgr
->llc_conf_mutex
);
1542 /* enqueue a local add_link req to trigger a new add_link flow */
1543 void smc_llc_add_link_local(struct smc_link
*link
)
1545 struct smc_llc_msg_add_link add_llc
= {};
1547 add_llc
.hd
.common
.llc_type
= SMC_LLC_ADD_LINK
;
1548 smc_llc_init_msg_hdr(&add_llc
.hd
, link
->lgr
, sizeof(add_llc
));
1549 /* no dev and port needed */
1550 smc_llc_enqueue(link
, (union smc_llc_msg
*)&add_llc
);
1553 /* worker to process an add link message */
1554 static void smc_llc_add_link_work(struct work_struct
*work
)
1556 struct smc_link_group
*lgr
= container_of(work
, struct smc_link_group
,
1559 if (list_empty(&lgr
->list
)) {
1560 /* link group is terminating */
1561 smc_llc_flow_qentry_del(&lgr
->llc_flow_lcl
);
1565 if (lgr
->role
== SMC_CLNT
)
1566 smc_llc_process_cli_add_link(lgr
);
1568 smc_llc_process_srv_add_link(lgr
);
1570 if (lgr
->llc_flow_lcl
.type
!= SMC_LLC_FLOW_REQ_ADD_LINK
)
1571 smc_llc_flow_stop(lgr
, &lgr
->llc_flow_lcl
);
1574 /* enqueue a local del_link msg to trigger a new del_link flow,
1575 * called only for role SMC_SERV
1577 void smc_llc_srv_delete_link_local(struct smc_link
*link
, u8 del_link_id
)
1579 struct smc_llc_msg_del_link del_llc
= {};
1581 del_llc
.hd
.common
.llc_type
= SMC_LLC_DELETE_LINK
;
1582 smc_llc_init_msg_hdr(&del_llc
.hd
, link
->lgr
, sizeof(del_llc
));
1583 del_llc
.link_num
= del_link_id
;
1584 del_llc
.reason
= htonl(SMC_LLC_DEL_LOST_PATH
);
1585 del_llc
.hd
.flags
|= SMC_LLC_FLAG_DEL_LINK_ORDERLY
;
1586 smc_llc_enqueue(link
, (union smc_llc_msg
*)&del_llc
);
1589 static void smc_llc_process_cli_delete_link(struct smc_link_group
*lgr
)
1591 struct smc_link
*lnk_del
= NULL
, *lnk_asym
, *lnk
;
1592 struct smc_llc_msg_del_link
*del_llc
;
1593 struct smc_llc_qentry
*qentry
;
1597 qentry
= smc_llc_flow_qentry_clr(&lgr
->llc_flow_lcl
);
1599 del_llc
= &qentry
->msg
.delete_link
;
1601 if (del_llc
->hd
.flags
& SMC_LLC_FLAG_DEL_LINK_ALL
) {
1602 smc_lgr_terminate_sched(lgr
);
1605 down_write(&lgr
->llc_conf_mutex
);
1606 /* delete single link */
1607 for (lnk_idx
= 0; lnk_idx
< SMC_LINKS_PER_LGR_MAX
; lnk_idx
++) {
1608 if (lgr
->lnk
[lnk_idx
].link_id
!= del_llc
->link_num
)
1610 lnk_del
= &lgr
->lnk
[lnk_idx
];
1613 del_llc
->hd
.flags
|= SMC_LLC_FLAG_RESP
;
1615 /* link was not found */
1616 del_llc
->reason
= htonl(SMC_LLC_DEL_NOLNK
);
1617 smc_llc_send_message(lnk
, &qentry
->msg
);
1620 lnk_asym
= smc_llc_find_asym_link(lgr
);
1622 del_llc
->reason
= 0;
1623 smc_llc_send_message(lnk
, &qentry
->msg
); /* response */
1625 if (smc_link_downing(&lnk_del
->state
))
1626 smc_switch_conns(lgr
, lnk_del
, false);
1627 smcr_link_clear(lnk_del
, true);
1629 active_links
= smc_llc_active_link_count(lgr
);
1630 if (lnk_del
== lnk_asym
) {
1631 /* expected deletion of asym link, don't change lgr state */
1632 } else if (active_links
== 1) {
1633 smcr_lgr_set_type(lgr
, SMC_LGR_SINGLE
);
1634 } else if (!active_links
) {
1635 smcr_lgr_set_type(lgr
, SMC_LGR_NONE
);
1636 smc_lgr_terminate_sched(lgr
);
1639 up_write(&lgr
->llc_conf_mutex
);
1644 /* try to send a DELETE LINK ALL request on any active link,
1645 * waiting for send completion
1647 void smc_llc_send_link_delete_all(struct smc_link_group
*lgr
, bool ord
, u32 rsn
)
1649 struct smc_llc_msg_del_link delllc
= {};
1652 delllc
.hd
.common
.llc_type
= SMC_LLC_DELETE_LINK
;
1653 smc_llc_init_msg_hdr(&delllc
.hd
, lgr
, sizeof(delllc
));
1655 delllc
.hd
.flags
|= SMC_LLC_FLAG_DEL_LINK_ORDERLY
;
1656 delllc
.hd
.flags
|= SMC_LLC_FLAG_DEL_LINK_ALL
;
1657 delllc
.reason
= htonl(rsn
);
1659 for (i
= 0; i
< SMC_LINKS_PER_LGR_MAX
; i
++) {
1660 if (!smc_link_sendable(&lgr
->lnk
[i
]))
1662 if (!smc_llc_send_message_wait(&lgr
->lnk
[i
], &delllc
))
1667 static void smc_llc_process_srv_delete_link(struct smc_link_group
*lgr
)
1669 struct smc_llc_msg_del_link
*del_llc
;
1670 struct smc_link
*lnk
, *lnk_del
;
1671 struct smc_llc_qentry
*qentry
;
1675 down_write(&lgr
->llc_conf_mutex
);
1676 qentry
= smc_llc_flow_qentry_clr(&lgr
->llc_flow_lcl
);
1678 del_llc
= &qentry
->msg
.delete_link
;
1680 if (qentry
->msg
.delete_link
.hd
.flags
& SMC_LLC_FLAG_DEL_LINK_ALL
) {
1681 /* delete entire lgr */
1682 smc_llc_send_link_delete_all(lgr
, true, ntohl(
1683 qentry
->msg
.delete_link
.reason
));
1684 smc_lgr_terminate_sched(lgr
);
1687 /* delete single link */
1689 for (i
= 0; i
< SMC_LINKS_PER_LGR_MAX
; i
++) {
1690 if (lgr
->lnk
[i
].link_id
== del_llc
->link_num
) {
1691 lnk_del
= &lgr
->lnk
[i
];
1696 goto out
; /* asymmetric link already deleted */
1698 if (smc_link_downing(&lnk_del
->state
)) {
1699 if (smc_switch_conns(lgr
, lnk_del
, false))
1700 smc_wr_tx_wait_no_pending_sends(lnk_del
);
1702 if (!list_empty(&lgr
->list
)) {
1703 /* qentry is either a request from peer (send it back to
1704 * initiate the DELETE_LINK processing), or a locally
1705 * enqueued DELETE_LINK request (forward it)
1707 if (!smc_llc_send_message(lnk
, &qentry
->msg
)) {
1708 struct smc_llc_qentry
*qentry2
;
1710 qentry2
= smc_llc_wait(lgr
, lnk
, SMC_LLC_WAIT_TIME
,
1711 SMC_LLC_DELETE_LINK
);
1713 smc_llc_flow_qentry_del(&lgr
->llc_flow_lcl
);
1716 smcr_link_clear(lnk_del
, true);
1718 active_links
= smc_llc_active_link_count(lgr
);
1719 if (active_links
== 1) {
1720 smcr_lgr_set_type(lgr
, SMC_LGR_SINGLE
);
1721 } else if (!active_links
) {
1722 smcr_lgr_set_type(lgr
, SMC_LGR_NONE
);
1723 smc_lgr_terminate_sched(lgr
);
1726 if (lgr
->type
== SMC_LGR_SINGLE
&& !list_empty(&lgr
->list
)) {
1727 /* trigger setup of asymm alt link */
1728 smc_llc_add_link_local(lnk
);
1731 up_write(&lgr
->llc_conf_mutex
);
1735 static void smc_llc_delete_link_work(struct work_struct
*work
)
1737 struct smc_link_group
*lgr
= container_of(work
, struct smc_link_group
,
1740 if (list_empty(&lgr
->list
)) {
1741 /* link group is terminating */
1742 smc_llc_flow_qentry_del(&lgr
->llc_flow_lcl
);
1746 if (lgr
->role
== SMC_CLNT
)
1747 smc_llc_process_cli_delete_link(lgr
);
1749 smc_llc_process_srv_delete_link(lgr
);
1751 smc_llc_flow_stop(lgr
, &lgr
->llc_flow_lcl
);
1754 /* process a confirm_rkey request from peer, remote flow */
1755 static void smc_llc_rmt_conf_rkey(struct smc_link_group
*lgr
)
1757 struct smc_llc_msg_confirm_rkey
*llc
;
1758 struct smc_llc_qentry
*qentry
;
1759 struct smc_link
*link
;
1764 qentry
= lgr
->llc_flow_rmt
.qentry
;
1765 llc
= &qentry
->msg
.confirm_rkey
;
1766 link
= qentry
->link
;
1768 num_entries
= llc
->rtoken
[0].num_rkeys
;
1769 if (num_entries
> SMC_LLC_RKEYS_PER_MSG
)
1771 /* first rkey entry is for receiving link */
1772 rk_idx
= smc_rtoken_add(link
,
1773 llc
->rtoken
[0].rmb_vaddr
,
1774 llc
->rtoken
[0].rmb_key
);
1778 for (i
= 1; i
<= min_t(u8
, num_entries
, SMC_LLC_RKEYS_PER_MSG
- 1); i
++)
1779 smc_rtoken_set2(lgr
, rk_idx
, llc
->rtoken
[i
].link_id
,
1780 llc
->rtoken
[i
].rmb_vaddr
,
1781 llc
->rtoken
[i
].rmb_key
);
1782 /* max links is 3 so there is no need to support conf_rkey_cont msgs */
1785 llc
->hd
.flags
|= SMC_LLC_FLAG_RKEY_NEG
;
1786 llc
->hd
.flags
|= SMC_LLC_FLAG_RKEY_RETRY
;
1788 llc
->hd
.flags
|= SMC_LLC_FLAG_RESP
;
1789 smc_llc_init_msg_hdr(&llc
->hd
, link
->lgr
, sizeof(*llc
));
1790 smc_llc_send_message(link
, &qentry
->msg
);
1791 smc_llc_flow_qentry_del(&lgr
->llc_flow_rmt
);
1794 /* process a delete_rkey request from peer, remote flow */
1795 static void smc_llc_rmt_delete_rkey(struct smc_link_group
*lgr
)
1797 struct smc_llc_msg_delete_rkey
*llc
;
1798 struct smc_llc_qentry
*qentry
;
1799 struct smc_link
*link
;
1803 qentry
= lgr
->llc_flow_rmt
.qentry
;
1804 llc
= &qentry
->msg
.delete_rkey
;
1805 link
= qentry
->link
;
1807 if (lgr
->smc_version
== SMC_V2
) {
1808 struct smc_llc_msg_delete_rkey_v2
*llcv2
;
1810 memcpy(lgr
->wr_rx_buf_v2
, llc
, sizeof(*llc
));
1811 llcv2
= (struct smc_llc_msg_delete_rkey_v2
*)lgr
->wr_rx_buf_v2
;
1812 llcv2
->num_inval_rkeys
= 0;
1814 max
= min_t(u8
, llcv2
->num_rkeys
, SMC_LLC_RKEYS_PER_MSG_V2
);
1815 for (i
= 0; i
< max
; i
++) {
1816 if (smc_rtoken_delete(link
, llcv2
->rkey
[i
]))
1817 llcv2
->num_inval_rkeys
++;
1819 memset(&llc
->rkey
[0], 0, sizeof(llc
->rkey
));
1820 memset(&llc
->reserved2
, 0, sizeof(llc
->reserved2
));
1821 smc_llc_init_msg_hdr(&llc
->hd
, link
->lgr
, sizeof(*llc
));
1822 if (llcv2
->num_inval_rkeys
) {
1823 llc
->hd
.flags
|= SMC_LLC_FLAG_RKEY_NEG
;
1824 llc
->err_mask
= llcv2
->num_inval_rkeys
;
1829 max
= min_t(u8
, llc
->num_rkeys
, SMC_LLC_DEL_RKEY_MAX
);
1830 for (i
= 0; i
< max
; i
++) {
1831 if (smc_rtoken_delete(link
, llc
->rkey
[i
]))
1832 err_mask
|= 1 << (SMC_LLC_DEL_RKEY_MAX
- 1 - i
);
1835 llc
->hd
.flags
|= SMC_LLC_FLAG_RKEY_NEG
;
1836 llc
->err_mask
= err_mask
;
1839 llc
->hd
.flags
|= SMC_LLC_FLAG_RESP
;
1840 smc_llc_send_message(link
, &qentry
->msg
);
1841 smc_llc_flow_qentry_del(&lgr
->llc_flow_rmt
);
1844 static void smc_llc_protocol_violation(struct smc_link_group
*lgr
, u8 type
)
1846 pr_warn_ratelimited("smc: SMC-R lg %*phN net %llu LLC protocol violation: "
1847 "llc_type %d\n", SMC_LGR_ID_SIZE
, &lgr
->id
,
1848 lgr
->net
->net_cookie
, type
);
1849 smc_llc_set_termination_rsn(lgr
, SMC_LLC_DEL_PROT_VIOL
);
1850 smc_lgr_terminate_sched(lgr
);
1853 /* flush the llc event queue */
1854 static void smc_llc_event_flush(struct smc_link_group
*lgr
)
1856 struct smc_llc_qentry
*qentry
, *q
;
1858 spin_lock_bh(&lgr
->llc_event_q_lock
);
1859 list_for_each_entry_safe(qentry
, q
, &lgr
->llc_event_q
, list
) {
1860 list_del_init(&qentry
->list
);
1863 spin_unlock_bh(&lgr
->llc_event_q_lock
);
1866 static void smc_llc_event_handler(struct smc_llc_qentry
*qentry
)
1868 union smc_llc_msg
*llc
= &qentry
->msg
;
1869 struct smc_link
*link
= qentry
->link
;
1870 struct smc_link_group
*lgr
= link
->lgr
;
1872 if (!smc_link_usable(link
))
1875 switch (llc
->raw
.hdr
.common
.llc_type
) {
1876 case SMC_LLC_TEST_LINK
:
1877 llc
->test_link
.hd
.flags
|= SMC_LLC_FLAG_RESP
;
1878 smc_llc_send_message(link
, llc
);
1880 case SMC_LLC_ADD_LINK
:
1881 if (list_empty(&lgr
->list
))
1882 goto out
; /* lgr is terminating */
1883 if (lgr
->role
== SMC_CLNT
) {
1884 if (smc_llc_is_local_add_link(llc
)) {
1885 if (lgr
->llc_flow_lcl
.type
==
1886 SMC_LLC_FLOW_ADD_LINK
)
1887 break; /* add_link in progress */
1888 if (smc_llc_flow_start(&lgr
->llc_flow_lcl
,
1890 schedule_work(&lgr
->llc_add_link_work
);
1894 if (lgr
->llc_flow_lcl
.type
== SMC_LLC_FLOW_ADD_LINK
&&
1895 !lgr
->llc_flow_lcl
.qentry
) {
1896 /* a flow is waiting for this message */
1897 smc_llc_flow_qentry_set(&lgr
->llc_flow_lcl
,
1899 wake_up(&lgr
->llc_msg_waiter
);
1902 if (lgr
->llc_flow_lcl
.type
==
1903 SMC_LLC_FLOW_REQ_ADD_LINK
) {
1904 /* server started add_link processing */
1905 lgr
->llc_flow_lcl
.type
= SMC_LLC_FLOW_ADD_LINK
;
1906 smc_llc_flow_qentry_set(&lgr
->llc_flow_lcl
,
1908 schedule_work(&lgr
->llc_add_link_work
);
1911 if (smc_llc_flow_start(&lgr
->llc_flow_lcl
, qentry
)) {
1912 schedule_work(&lgr
->llc_add_link_work
);
1914 } else if (smc_llc_flow_start(&lgr
->llc_flow_lcl
, qentry
)) {
1915 /* as smc server, handle client suggestion */
1916 schedule_work(&lgr
->llc_add_link_work
);
1919 case SMC_LLC_CONFIRM_LINK
:
1920 case SMC_LLC_ADD_LINK_CONT
:
1921 if (lgr
->llc_flow_lcl
.type
!= SMC_LLC_FLOW_NONE
) {
1922 /* a flow is waiting for this message */
1923 smc_llc_flow_qentry_set(&lgr
->llc_flow_lcl
, qentry
);
1924 wake_up(&lgr
->llc_msg_waiter
);
1928 case SMC_LLC_DELETE_LINK
:
1929 if (lgr
->llc_flow_lcl
.type
== SMC_LLC_FLOW_ADD_LINK
&&
1930 !lgr
->llc_flow_lcl
.qentry
) {
1931 /* DEL LINK REQ during ADD LINK SEQ */
1932 smc_llc_flow_qentry_set(&lgr
->llc_flow_lcl
, qentry
);
1933 wake_up(&lgr
->llc_msg_waiter
);
1934 } else if (smc_llc_flow_start(&lgr
->llc_flow_lcl
, qentry
)) {
1935 schedule_work(&lgr
->llc_del_link_work
);
1938 case SMC_LLC_CONFIRM_RKEY
:
1939 /* new request from remote, assign to remote flow */
1940 if (smc_llc_flow_start(&lgr
->llc_flow_rmt
, qentry
)) {
1941 /* process here, does not wait for more llc msgs */
1942 smc_llc_rmt_conf_rkey(lgr
);
1943 smc_llc_flow_stop(lgr
, &lgr
->llc_flow_rmt
);
1946 case SMC_LLC_CONFIRM_RKEY_CONT
:
1947 /* not used because max links is 3, and 3 rkeys fit into
1948 * one CONFIRM_RKEY message
1951 case SMC_LLC_DELETE_RKEY
:
1952 /* new request from remote, assign to remote flow */
1953 if (smc_llc_flow_start(&lgr
->llc_flow_rmt
, qentry
)) {
1954 /* process here, does not wait for more llc msgs */
1955 smc_llc_rmt_delete_rkey(lgr
);
1956 smc_llc_flow_stop(lgr
, &lgr
->llc_flow_rmt
);
1959 case SMC_LLC_REQ_ADD_LINK
:
1960 /* handle response here, smc_llc_flow_stop() cannot be called
1961 * in tasklet context
1963 if (lgr
->role
== SMC_CLNT
&&
1964 lgr
->llc_flow_lcl
.type
== SMC_LLC_FLOW_REQ_ADD_LINK
&&
1965 (llc
->raw
.hdr
.flags
& SMC_LLC_FLAG_RESP
)) {
1966 smc_llc_flow_stop(link
->lgr
, &lgr
->llc_flow_lcl
);
1967 } else if (lgr
->role
== SMC_SERV
) {
1968 if (smc_llc_flow_start(&lgr
->llc_flow_lcl
, qentry
)) {
1969 /* as smc server, handle client suggestion */
1970 lgr
->llc_flow_lcl
.type
= SMC_LLC_FLOW_ADD_LINK
;
1971 schedule_work(&lgr
->llc_add_link_work
);
1977 smc_llc_protocol_violation(lgr
, llc
->raw
.hdr
.common
.type
);
1984 /* worker to process llc messages on the event queue */
1985 static void smc_llc_event_work(struct work_struct
*work
)
1987 struct smc_link_group
*lgr
= container_of(work
, struct smc_link_group
,
1989 struct smc_llc_qentry
*qentry
;
1991 if (!lgr
->llc_flow_lcl
.type
&& lgr
->delayed_event
) {
1992 qentry
= lgr
->delayed_event
;
1993 lgr
->delayed_event
= NULL
;
1994 if (smc_link_usable(qentry
->link
))
1995 smc_llc_event_handler(qentry
);
2001 spin_lock_bh(&lgr
->llc_event_q_lock
);
2002 if (!list_empty(&lgr
->llc_event_q
)) {
2003 qentry
= list_first_entry(&lgr
->llc_event_q
,
2004 struct smc_llc_qentry
, list
);
2005 list_del_init(&qentry
->list
);
2006 spin_unlock_bh(&lgr
->llc_event_q_lock
);
2007 smc_llc_event_handler(qentry
);
2010 spin_unlock_bh(&lgr
->llc_event_q_lock
);
2013 /* process llc responses in tasklet context */
2014 static void smc_llc_rx_response(struct smc_link
*link
,
2015 struct smc_llc_qentry
*qentry
)
2017 enum smc_llc_flowtype flowtype
= link
->lgr
->llc_flow_lcl
.type
;
2018 struct smc_llc_flow
*flow
= &link
->lgr
->llc_flow_lcl
;
2019 u8 llc_type
= qentry
->msg
.raw
.hdr
.common
.llc_type
;
2022 case SMC_LLC_TEST_LINK
:
2023 if (smc_link_active(link
))
2024 complete(&link
->llc_testlink_resp
);
2026 case SMC_LLC_ADD_LINK
:
2027 case SMC_LLC_ADD_LINK_CONT
:
2028 case SMC_LLC_CONFIRM_LINK
:
2029 if (flowtype
!= SMC_LLC_FLOW_ADD_LINK
|| flow
->qentry
)
2030 break; /* drop out-of-flow response */
2032 case SMC_LLC_DELETE_LINK
:
2033 if (flowtype
!= SMC_LLC_FLOW_DEL_LINK
|| flow
->qentry
)
2034 break; /* drop out-of-flow response */
2036 case SMC_LLC_CONFIRM_RKEY
:
2037 case SMC_LLC_DELETE_RKEY
:
2038 if (flowtype
!= SMC_LLC_FLOW_RKEY
|| flow
->qentry
)
2039 break; /* drop out-of-flow response */
2041 case SMC_LLC_CONFIRM_RKEY_CONT
:
2042 /* not used because max links is 3 */
2045 smc_llc_protocol_violation(link
->lgr
,
2046 qentry
->msg
.raw
.hdr
.common
.type
);
2052 /* assign responses to the local flow, we requested them */
2053 smc_llc_flow_qentry_set(&link
->lgr
->llc_flow_lcl
, qentry
);
2054 wake_up(&link
->lgr
->llc_msg_waiter
);
2057 static void smc_llc_enqueue(struct smc_link
*link
, union smc_llc_msg
*llc
)
2059 struct smc_link_group
*lgr
= link
->lgr
;
2060 struct smc_llc_qentry
*qentry
;
2061 unsigned long flags
;
2063 qentry
= kmalloc(sizeof(*qentry
), GFP_ATOMIC
);
2066 qentry
->link
= link
;
2067 INIT_LIST_HEAD(&qentry
->list
);
2068 memcpy(&qentry
->msg
, llc
, sizeof(union smc_llc_msg
));
2070 /* process responses immediately */
2071 if ((llc
->raw
.hdr
.flags
& SMC_LLC_FLAG_RESP
) &&
2072 llc
->raw
.hdr
.common
.llc_type
!= SMC_LLC_REQ_ADD_LINK
) {
2073 smc_llc_rx_response(link
, qentry
);
2077 /* add requests to event queue */
2078 spin_lock_irqsave(&lgr
->llc_event_q_lock
, flags
);
2079 list_add_tail(&qentry
->list
, &lgr
->llc_event_q
);
2080 spin_unlock_irqrestore(&lgr
->llc_event_q_lock
, flags
);
2081 queue_work(system_highpri_wq
, &lgr
->llc_event_work
);
2084 /* copy received msg and add it to the event queue */
2085 static void smc_llc_rx_handler(struct ib_wc
*wc
, void *buf
)
2087 struct smc_link
*link
= (struct smc_link
*)wc
->qp
->qp_context
;
2088 union smc_llc_msg
*llc
= buf
;
2090 if (wc
->byte_len
< sizeof(*llc
))
2091 return; /* short message */
2092 if (!llc
->raw
.hdr
.common
.llc_version
) {
2093 if (llc
->raw
.hdr
.length
!= sizeof(*llc
))
2094 return; /* invalid message */
2096 if (llc
->raw
.hdr
.length_v2
< sizeof(*llc
))
2097 return; /* invalid message */
2100 smc_llc_enqueue(link
, llc
);
2103 /***************************** worker, utils *********************************/
2105 static void smc_llc_testlink_work(struct work_struct
*work
)
2107 struct smc_link
*link
= container_of(to_delayed_work(work
),
2108 struct smc_link
, llc_testlink_wrk
);
2109 unsigned long next_interval
;
2110 unsigned long expire_time
;
2111 u8 user_data
[16] = { 0 };
2114 if (!smc_link_active(link
))
2115 return; /* don't reschedule worker */
2116 expire_time
= link
->wr_rx_tstamp
+ link
->llc_testlink_time
;
2117 if (time_is_after_jiffies(expire_time
)) {
2118 next_interval
= expire_time
- jiffies
;
2121 reinit_completion(&link
->llc_testlink_resp
);
2122 smc_llc_send_test_link(link
, user_data
);
2123 /* receive TEST LINK response over RoCE fabric */
2124 rc
= wait_for_completion_interruptible_timeout(&link
->llc_testlink_resp
,
2126 if (!smc_link_active(link
))
2127 return; /* link state changed */
2129 smcr_link_down_cond_sched(link
);
2132 next_interval
= link
->llc_testlink_time
;
2134 schedule_delayed_work(&link
->llc_testlink_wrk
, next_interval
);
2137 void smc_llc_lgr_init(struct smc_link_group
*lgr
, struct smc_sock
*smc
)
2139 struct net
*net
= sock_net(smc
->clcsock
->sk
);
2141 INIT_WORK(&lgr
->llc_event_work
, smc_llc_event_work
);
2142 INIT_WORK(&lgr
->llc_add_link_work
, smc_llc_add_link_work
);
2143 INIT_WORK(&lgr
->llc_del_link_work
, smc_llc_delete_link_work
);
2144 INIT_LIST_HEAD(&lgr
->llc_event_q
);
2145 spin_lock_init(&lgr
->llc_event_q_lock
);
2146 spin_lock_init(&lgr
->llc_flow_lock
);
2147 init_waitqueue_head(&lgr
->llc_flow_waiter
);
2148 init_waitqueue_head(&lgr
->llc_msg_waiter
);
2149 init_rwsem(&lgr
->llc_conf_mutex
);
2150 lgr
->llc_testlink_time
= READ_ONCE(net
->smc
.sysctl_smcr_testlink_time
);
2153 /* called after lgr was removed from lgr_list */
2154 void smc_llc_lgr_clear(struct smc_link_group
*lgr
)
2156 smc_llc_event_flush(lgr
);
2157 wake_up_all(&lgr
->llc_flow_waiter
);
2158 wake_up_all(&lgr
->llc_msg_waiter
);
2159 cancel_work_sync(&lgr
->llc_event_work
);
2160 cancel_work_sync(&lgr
->llc_add_link_work
);
2161 cancel_work_sync(&lgr
->llc_del_link_work
);
2162 if (lgr
->delayed_event
) {
2163 kfree(lgr
->delayed_event
);
2164 lgr
->delayed_event
= NULL
;
2168 int smc_llc_link_init(struct smc_link
*link
)
2170 init_completion(&link
->llc_testlink_resp
);
2171 INIT_DELAYED_WORK(&link
->llc_testlink_wrk
, smc_llc_testlink_work
);
2175 void smc_llc_link_active(struct smc_link
*link
)
2177 pr_warn_ratelimited("smc: SMC-R lg %*phN net %llu link added: id %*phN, "
2178 "peerid %*phN, ibdev %s, ibport %d\n",
2179 SMC_LGR_ID_SIZE
, &link
->lgr
->id
,
2180 link
->lgr
->net
->net_cookie
,
2181 SMC_LGR_ID_SIZE
, &link
->link_uid
,
2182 SMC_LGR_ID_SIZE
, &link
->peer_link_uid
,
2183 link
->smcibdev
->ibdev
->name
, link
->ibport
);
2184 link
->state
= SMC_LNK_ACTIVE
;
2185 if (link
->lgr
->llc_testlink_time
) {
2186 link
->llc_testlink_time
= link
->lgr
->llc_testlink_time
;
2187 schedule_delayed_work(&link
->llc_testlink_wrk
,
2188 link
->llc_testlink_time
);
2192 /* called in worker context */
2193 void smc_llc_link_clear(struct smc_link
*link
, bool log
)
2196 pr_warn_ratelimited("smc: SMC-R lg %*phN net %llu link removed: id %*phN"
2197 ", peerid %*phN, ibdev %s, ibport %d\n",
2198 SMC_LGR_ID_SIZE
, &link
->lgr
->id
,
2199 link
->lgr
->net
->net_cookie
,
2200 SMC_LGR_ID_SIZE
, &link
->link_uid
,
2201 SMC_LGR_ID_SIZE
, &link
->peer_link_uid
,
2202 link
->smcibdev
->ibdev
->name
, link
->ibport
);
2203 complete(&link
->llc_testlink_resp
);
2204 cancel_delayed_work_sync(&link
->llc_testlink_wrk
);
2207 /* register a new rtoken at the remote peer (for all links) */
2208 int smc_llc_do_confirm_rkey(struct smc_link
*send_link
,
2209 struct smc_buf_desc
*rmb_desc
)
2211 struct smc_link_group
*lgr
= send_link
->lgr
;
2212 struct smc_llc_qentry
*qentry
= NULL
;
2215 rc
= smc_llc_send_confirm_rkey(send_link
, rmb_desc
);
2218 /* receive CONFIRM RKEY response from server over RoCE fabric */
2219 qentry
= smc_llc_wait(lgr
, send_link
, SMC_LLC_WAIT_TIME
,
2220 SMC_LLC_CONFIRM_RKEY
);
2221 if (!qentry
|| (qentry
->msg
.raw
.hdr
.flags
& SMC_LLC_FLAG_RKEY_NEG
))
2225 smc_llc_flow_qentry_del(&lgr
->llc_flow_lcl
);
2229 /* unregister an rtoken at the remote peer */
2230 int smc_llc_do_delete_rkey(struct smc_link_group
*lgr
,
2231 struct smc_buf_desc
*rmb_desc
)
2233 struct smc_llc_qentry
*qentry
= NULL
;
2234 struct smc_link
*send_link
;
2237 send_link
= smc_llc_usable_link(lgr
);
2241 /* protected by llc_flow control */
2242 rc
= smc_llc_send_delete_rkey(send_link
, rmb_desc
);
2245 /* receive DELETE RKEY response from server over RoCE fabric */
2246 qentry
= smc_llc_wait(lgr
, send_link
, SMC_LLC_WAIT_TIME
,
2247 SMC_LLC_DELETE_RKEY
);
2248 if (!qentry
|| (qentry
->msg
.raw
.hdr
.flags
& SMC_LLC_FLAG_RKEY_NEG
))
2252 smc_llc_flow_qentry_del(&lgr
->llc_flow_lcl
);
2256 void smc_llc_link_set_uid(struct smc_link
*link
)
2260 link_uid
= htonl(*((u32
*)link
->lgr
->id
) + link
->link_id
);
2261 memcpy(link
->link_uid
, &link_uid
, SMC_LGR_ID_SIZE
);
2264 /* save peers link user id, used for debug purposes */
2265 void smc_llc_save_peer_uid(struct smc_llc_qentry
*qentry
)
2267 memcpy(qentry
->link
->peer_link_uid
, qentry
->msg
.confirm_link
.link_uid
,
2271 /* evaluate confirm link request or response */
2272 int smc_llc_eval_conf_link(struct smc_llc_qentry
*qentry
,
2273 enum smc_llc_reqresp type
)
2275 if (type
== SMC_LLC_REQ
) { /* SMC server assigns link_id */
2276 qentry
->link
->link_id
= qentry
->msg
.confirm_link
.link_num
;
2277 smc_llc_link_set_uid(qentry
->link
);
2279 if (!(qentry
->msg
.raw
.hdr
.flags
& SMC_LLC_FLAG_NO_RMBE_EYEC
))
2284 /***************************** init, exit, misc ******************************/
2286 static struct smc_wr_rx_handler smc_llc_rx_handlers
[] = {
2288 .handler
= smc_llc_rx_handler
,
2289 .type
= SMC_LLC_CONFIRM_LINK
2292 .handler
= smc_llc_rx_handler
,
2293 .type
= SMC_LLC_TEST_LINK
2296 .handler
= smc_llc_rx_handler
,
2297 .type
= SMC_LLC_ADD_LINK
2300 .handler
= smc_llc_rx_handler
,
2301 .type
= SMC_LLC_ADD_LINK_CONT
2304 .handler
= smc_llc_rx_handler
,
2305 .type
= SMC_LLC_DELETE_LINK
2308 .handler
= smc_llc_rx_handler
,
2309 .type
= SMC_LLC_CONFIRM_RKEY
2312 .handler
= smc_llc_rx_handler
,
2313 .type
= SMC_LLC_CONFIRM_RKEY_CONT
2316 .handler
= smc_llc_rx_handler
,
2317 .type
= SMC_LLC_DELETE_RKEY
2321 .handler
= smc_llc_rx_handler
,
2322 .type
= SMC_LLC_CONFIRM_LINK_V2
2325 .handler
= smc_llc_rx_handler
,
2326 .type
= SMC_LLC_TEST_LINK_V2
2329 .handler
= smc_llc_rx_handler
,
2330 .type
= SMC_LLC_ADD_LINK_V2
2333 .handler
= smc_llc_rx_handler
,
2334 .type
= SMC_LLC_DELETE_LINK_V2
2337 .handler
= smc_llc_rx_handler
,
2338 .type
= SMC_LLC_REQ_ADD_LINK_V2
2341 .handler
= smc_llc_rx_handler
,
2342 .type
= SMC_LLC_CONFIRM_RKEY_V2
2345 .handler
= smc_llc_rx_handler
,
2346 .type
= SMC_LLC_DELETE_RKEY_V2
2353 int __init
smc_llc_init(void)
2355 struct smc_wr_rx_handler
*handler
;
2358 for (handler
= smc_llc_rx_handlers
; handler
->handler
; handler
++) {
2359 INIT_HLIST_NODE(&handler
->list
);
2360 rc
= smc_wr_rx_register_handler(handler
);