net/smc: enqueue local LLC messages
[linux-2.6-microblaze.git] / net / smc / smc_llc.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *  Shared Memory Communications over RDMA (SMC-R) and RoCE
4  *
5  *  Link Layer Control (LLC)
6  *
7  *  Copyright IBM Corp. 2016
8  *
9  *  Author(s):  Klaus Wacker <Klaus.Wacker@de.ibm.com>
10  *              Ursula Braun <ubraun@linux.vnet.ibm.com>
11  */
12
13 #include <net/tcp.h>
14 #include <rdma/ib_verbs.h>
15
16 #include "smc.h"
17 #include "smc_core.h"
18 #include "smc_clc.h"
19 #include "smc_llc.h"
20 #include "smc_pnet.h"
21
22 #define SMC_LLC_DATA_LEN                40
23
24 struct smc_llc_hdr {
25         struct smc_wr_rx_hdr common;
26         u8 length;      /* 44 */
27 #if defined(__BIG_ENDIAN_BITFIELD)
28         u8 reserved:4,
29            add_link_rej_rsn:4;
30 #elif defined(__LITTLE_ENDIAN_BITFIELD)
31         u8 add_link_rej_rsn:4,
32            reserved:4;
33 #endif
34         u8 flags;
35 };
36
37 #define SMC_LLC_FLAG_NO_RMBE_EYEC       0x03
38
39 struct smc_llc_msg_confirm_link {       /* type 0x01 */
40         struct smc_llc_hdr hd;
41         u8 sender_mac[ETH_ALEN];
42         u8 sender_gid[SMC_GID_SIZE];
43         u8 sender_qp_num[3];
44         u8 link_num;
45         u8 link_uid[SMC_LGR_ID_SIZE];
46         u8 max_links;
47         u8 reserved[9];
48 };
49
50 #define SMC_LLC_FLAG_ADD_LNK_REJ        0x40
51 #define SMC_LLC_REJ_RSN_NO_ALT_PATH     1
52
53 #define SMC_LLC_ADD_LNK_MAX_LINKS       2
54
55 struct smc_llc_msg_add_link {           /* type 0x02 */
56         struct smc_llc_hdr hd;
57         u8 sender_mac[ETH_ALEN];
58         u8 reserved2[2];
59         u8 sender_gid[SMC_GID_SIZE];
60         u8 sender_qp_num[3];
61         u8 link_num;
62 #if defined(__BIG_ENDIAN_BITFIELD)
63         u8 reserved3 : 4,
64            qp_mtu   : 4;
65 #elif defined(__LITTLE_ENDIAN_BITFIELD)
66         u8 qp_mtu   : 4,
67            reserved3 : 4;
68 #endif
69         u8 initial_psn[3];
70         u8 reserved[8];
71 };
72
73 struct smc_llc_msg_add_link_cont_rt {
74         __be32 rmb_key;
75         __be32 rmb_key_new;
76         __be64 rmb_vaddr_new;
77 };
78
79 #define SMC_LLC_RKEYS_PER_CONT_MSG      2
80
81 struct smc_llc_msg_add_link_cont {      /* type 0x03 */
82         struct smc_llc_hdr hd;
83         u8 link_num;
84         u8 num_rkeys;
85         u8 reserved2[2];
86         struct smc_llc_msg_add_link_cont_rt rt[SMC_LLC_RKEYS_PER_CONT_MSG];
87         u8 reserved[4];
88 } __packed;                     /* format defined in RFC7609 */
89
90 #define SMC_LLC_FLAG_DEL_LINK_ALL       0x40
91 #define SMC_LLC_FLAG_DEL_LINK_ORDERLY   0x20
92
93 struct smc_llc_msg_del_link {           /* type 0x04 */
94         struct smc_llc_hdr hd;
95         u8 link_num;
96         __be32 reason;
97         u8 reserved[35];
98 } __packed;                     /* format defined in RFC7609 */
99
100 struct smc_llc_msg_test_link {          /* type 0x07 */
101         struct smc_llc_hdr hd;
102         u8 user_data[16];
103         u8 reserved[24];
104 };
105
106 struct smc_rmb_rtoken {
107         union {
108                 u8 num_rkeys;   /* first rtoken byte of CONFIRM LINK msg */
109                                 /* is actually the num of rtokens, first */
110                                 /* rtoken is always for the current link */
111                 u8 link_id;     /* link id of the rtoken */
112         };
113         __be32 rmb_key;
114         __be64 rmb_vaddr;
115 } __packed;                     /* format defined in RFC7609 */
116
117 #define SMC_LLC_RKEYS_PER_MSG   3
118
119 struct smc_llc_msg_confirm_rkey {       /* type 0x06 */
120         struct smc_llc_hdr hd;
121         struct smc_rmb_rtoken rtoken[SMC_LLC_RKEYS_PER_MSG];
122         u8 reserved;
123 };
124
125 #define SMC_LLC_DEL_RKEY_MAX    8
126 #define SMC_LLC_FLAG_RKEY_RETRY 0x10
127 #define SMC_LLC_FLAG_RKEY_NEG   0x20
128
129 struct smc_llc_msg_delete_rkey {        /* type 0x09 */
130         struct smc_llc_hdr hd;
131         u8 num_rkeys;
132         u8 err_mask;
133         u8 reserved[2];
134         __be32 rkey[8];
135         u8 reserved2[4];
136 };
137
138 union smc_llc_msg {
139         struct smc_llc_msg_confirm_link confirm_link;
140         struct smc_llc_msg_add_link add_link;
141         struct smc_llc_msg_add_link_cont add_link_cont;
142         struct smc_llc_msg_del_link delete_link;
143
144         struct smc_llc_msg_confirm_rkey confirm_rkey;
145         struct smc_llc_msg_delete_rkey delete_rkey;
146
147         struct smc_llc_msg_test_link test_link;
148         struct {
149                 struct smc_llc_hdr hdr;
150                 u8 data[SMC_LLC_DATA_LEN];
151         } raw;
152 };
153
154 #define SMC_LLC_FLAG_RESP               0x80
155
156 struct smc_llc_qentry {
157         struct list_head list;
158         struct smc_link *link;
159         union smc_llc_msg msg;
160 };
161
162 static void smc_llc_enqueue(struct smc_link *link, union smc_llc_msg *llc);
163
164 struct smc_llc_qentry *smc_llc_flow_qentry_clr(struct smc_llc_flow *flow)
165 {
166         struct smc_llc_qentry *qentry = flow->qentry;
167
168         flow->qentry = NULL;
169         return qentry;
170 }
171
172 void smc_llc_flow_qentry_del(struct smc_llc_flow *flow)
173 {
174         struct smc_llc_qentry *qentry;
175
176         if (flow->qentry) {
177                 qentry = flow->qentry;
178                 flow->qentry = NULL;
179                 kfree(qentry);
180         }
181 }
182
183 static inline void smc_llc_flow_qentry_set(struct smc_llc_flow *flow,
184                                            struct smc_llc_qentry *qentry)
185 {
186         flow->qentry = qentry;
187 }
188
189 /* try to start a new llc flow, initiated by an incoming llc msg */
190 static bool smc_llc_flow_start(struct smc_llc_flow *flow,
191                                struct smc_llc_qentry *qentry)
192 {
193         struct smc_link_group *lgr = qentry->link->lgr;
194
195         spin_lock_bh(&lgr->llc_flow_lock);
196         if (flow->type) {
197                 /* a flow is already active */
198                 if ((qentry->msg.raw.hdr.common.type == SMC_LLC_ADD_LINK ||
199                      qentry->msg.raw.hdr.common.type == SMC_LLC_DELETE_LINK) &&
200                     !lgr->delayed_event) {
201                         lgr->delayed_event = qentry;
202                 } else {
203                         /* forget this llc request */
204                         kfree(qentry);
205                 }
206                 spin_unlock_bh(&lgr->llc_flow_lock);
207                 return false;
208         }
209         switch (qentry->msg.raw.hdr.common.type) {
210         case SMC_LLC_ADD_LINK:
211                 flow->type = SMC_LLC_FLOW_ADD_LINK;
212                 break;
213         case SMC_LLC_DELETE_LINK:
214                 flow->type = SMC_LLC_FLOW_DEL_LINK;
215                 break;
216         case SMC_LLC_CONFIRM_RKEY:
217         case SMC_LLC_DELETE_RKEY:
218                 flow->type = SMC_LLC_FLOW_RKEY;
219                 break;
220         default:
221                 flow->type = SMC_LLC_FLOW_NONE;
222         }
223         if (qentry == lgr->delayed_event)
224                 lgr->delayed_event = NULL;
225         spin_unlock_bh(&lgr->llc_flow_lock);
226         smc_llc_flow_qentry_set(flow, qentry);
227         return true;
228 }
229
230 /* start a new local llc flow, wait till current flow finished */
231 int smc_llc_flow_initiate(struct smc_link_group *lgr,
232                           enum smc_llc_flowtype type)
233 {
234         enum smc_llc_flowtype allowed_remote = SMC_LLC_FLOW_NONE;
235         int rc;
236
237         /* all flows except confirm_rkey and delete_rkey are exclusive,
238          * confirm/delete rkey flows can run concurrently (local and remote)
239          */
240         if (type == SMC_LLC_FLOW_RKEY)
241                 allowed_remote = SMC_LLC_FLOW_RKEY;
242 again:
243         if (list_empty(&lgr->list))
244                 return -ENODEV;
245         spin_lock_bh(&lgr->llc_flow_lock);
246         if (lgr->llc_flow_lcl.type == SMC_LLC_FLOW_NONE &&
247             (lgr->llc_flow_rmt.type == SMC_LLC_FLOW_NONE ||
248              lgr->llc_flow_rmt.type == allowed_remote)) {
249                 lgr->llc_flow_lcl.type = type;
250                 spin_unlock_bh(&lgr->llc_flow_lock);
251                 return 0;
252         }
253         spin_unlock_bh(&lgr->llc_flow_lock);
254         rc = wait_event_interruptible_timeout(lgr->llc_waiter,
255                         (lgr->llc_flow_lcl.type == SMC_LLC_FLOW_NONE &&
256                          (lgr->llc_flow_rmt.type == SMC_LLC_FLOW_NONE ||
257                           lgr->llc_flow_rmt.type == allowed_remote)),
258                         SMC_LLC_WAIT_TIME);
259         if (!rc)
260                 return -ETIMEDOUT;
261         goto again;
262 }
263
264 /* finish the current llc flow */
265 void smc_llc_flow_stop(struct smc_link_group *lgr, struct smc_llc_flow *flow)
266 {
267         spin_lock_bh(&lgr->llc_flow_lock);
268         memset(flow, 0, sizeof(*flow));
269         flow->type = SMC_LLC_FLOW_NONE;
270         spin_unlock_bh(&lgr->llc_flow_lock);
271         if (!list_empty(&lgr->list) && lgr->delayed_event &&
272             flow == &lgr->llc_flow_lcl)
273                 schedule_work(&lgr->llc_event_work);
274         else
275                 wake_up_interruptible(&lgr->llc_waiter);
276 }
277
278 /* lnk is optional and used for early wakeup when link goes down, useful in
279  * cases where we wait for a response on the link after we sent a request
280  */
281 struct smc_llc_qentry *smc_llc_wait(struct smc_link_group *lgr,
282                                     struct smc_link *lnk,
283                                     int time_out, u8 exp_msg)
284 {
285         struct smc_llc_flow *flow = &lgr->llc_flow_lcl;
286
287         wait_event_interruptible_timeout(lgr->llc_waiter,
288                                          (flow->qentry ||
289                                           (lnk && !smc_link_usable(lnk)) ||
290                                           list_empty(&lgr->list)),
291                                          time_out);
292         if (!flow->qentry ||
293             (lnk && !smc_link_usable(lnk)) || list_empty(&lgr->list)) {
294                 smc_llc_flow_qentry_del(flow);
295                 goto out;
296         }
297         if (exp_msg && flow->qentry->msg.raw.hdr.common.type != exp_msg) {
298                 if (exp_msg == SMC_LLC_ADD_LINK &&
299                     flow->qentry->msg.raw.hdr.common.type ==
300                     SMC_LLC_DELETE_LINK) {
301                         /* flow_start will delay the unexpected msg */
302                         smc_llc_flow_start(&lgr->llc_flow_lcl,
303                                            smc_llc_flow_qentry_clr(flow));
304                         return NULL;
305                 }
306                 smc_llc_flow_qentry_del(flow);
307         }
308 out:
309         return flow->qentry;
310 }
311
312 /********************************** send *************************************/
313
314 struct smc_llc_tx_pend {
315 };
316
317 /* handler for send/transmission completion of an LLC msg */
318 static void smc_llc_tx_handler(struct smc_wr_tx_pend_priv *pend,
319                                struct smc_link *link,
320                                enum ib_wc_status wc_status)
321 {
322         /* future work: handle wc_status error for recovery and failover */
323 }
324
325 /**
326  * smc_llc_add_pending_send() - add LLC control message to pending WQE transmits
327  * @link: Pointer to SMC link used for sending LLC control message.
328  * @wr_buf: Out variable returning pointer to work request payload buffer.
329  * @pend: Out variable returning pointer to private pending WR tracking.
330  *        It's the context the transmit complete handler will get.
331  *
332  * Reserves and pre-fills an entry for a pending work request send/tx.
333  * Used by mid-level smc_llc_send_msg() to prepare for later actual send/tx.
334  * Can sleep due to smc_get_ctrl_buf (if not in softirq context).
335  *
336  * Return: 0 on success, otherwise an error value.
337  */
338 static int smc_llc_add_pending_send(struct smc_link *link,
339                                     struct smc_wr_buf **wr_buf,
340                                     struct smc_wr_tx_pend_priv **pend)
341 {
342         int rc;
343
344         rc = smc_wr_tx_get_free_slot(link, smc_llc_tx_handler, wr_buf, NULL,
345                                      pend);
346         if (rc < 0)
347                 return rc;
348         BUILD_BUG_ON_MSG(
349                 sizeof(union smc_llc_msg) > SMC_WR_BUF_SIZE,
350                 "must increase SMC_WR_BUF_SIZE to at least sizeof(struct smc_llc_msg)");
351         BUILD_BUG_ON_MSG(
352                 sizeof(union smc_llc_msg) != SMC_WR_TX_SIZE,
353                 "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()");
354         BUILD_BUG_ON_MSG(
355                 sizeof(struct smc_llc_tx_pend) > SMC_WR_TX_PEND_PRIV_SIZE,
356                 "must increase SMC_WR_TX_PEND_PRIV_SIZE to at least sizeof(struct smc_llc_tx_pend)");
357         return 0;
358 }
359
360 /* high-level API to send LLC confirm link */
361 int smc_llc_send_confirm_link(struct smc_link *link,
362                               enum smc_llc_reqresp reqresp)
363 {
364         struct smc_link_group *lgr = smc_get_lgr(link);
365         struct smc_llc_msg_confirm_link *confllc;
366         struct smc_wr_tx_pend_priv *pend;
367         struct smc_wr_buf *wr_buf;
368         int rc;
369
370         rc = smc_llc_add_pending_send(link, &wr_buf, &pend);
371         if (rc)
372                 return rc;
373         confllc = (struct smc_llc_msg_confirm_link *)wr_buf;
374         memset(confllc, 0, sizeof(*confllc));
375         confllc->hd.common.type = SMC_LLC_CONFIRM_LINK;
376         confllc->hd.length = sizeof(struct smc_llc_msg_confirm_link);
377         confllc->hd.flags |= SMC_LLC_FLAG_NO_RMBE_EYEC;
378         if (reqresp == SMC_LLC_RESP)
379                 confllc->hd.flags |= SMC_LLC_FLAG_RESP;
380         memcpy(confllc->sender_mac, link->smcibdev->mac[link->ibport - 1],
381                ETH_ALEN);
382         memcpy(confllc->sender_gid, link->gid, SMC_GID_SIZE);
383         hton24(confllc->sender_qp_num, link->roce_qp->qp_num);
384         confllc->link_num = link->link_id;
385         memcpy(confllc->link_uid, lgr->id, SMC_LGR_ID_SIZE);
386         confllc->max_links = SMC_LLC_ADD_LNK_MAX_LINKS;
387         /* send llc message */
388         rc = smc_wr_tx_send(link, pend);
389         return rc;
390 }
391
392 /* send LLC confirm rkey request */
393 static int smc_llc_send_confirm_rkey(struct smc_link *send_link,
394                                      struct smc_buf_desc *rmb_desc)
395 {
396         struct smc_llc_msg_confirm_rkey *rkeyllc;
397         struct smc_wr_tx_pend_priv *pend;
398         struct smc_wr_buf *wr_buf;
399         struct smc_link *link;
400         int i, rc, rtok_ix;
401
402         rc = smc_llc_add_pending_send(send_link, &wr_buf, &pend);
403         if (rc)
404                 return rc;
405         rkeyllc = (struct smc_llc_msg_confirm_rkey *)wr_buf;
406         memset(rkeyllc, 0, sizeof(*rkeyllc));
407         rkeyllc->hd.common.type = SMC_LLC_CONFIRM_RKEY;
408         rkeyllc->hd.length = sizeof(struct smc_llc_msg_confirm_rkey);
409
410         rtok_ix = 1;
411         for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
412                 link = &send_link->lgr->lnk[i];
413                 if (link->state == SMC_LNK_ACTIVE && link != send_link) {
414                         rkeyllc->rtoken[rtok_ix].link_id = link->link_id;
415                         rkeyllc->rtoken[rtok_ix].rmb_key =
416                                 htonl(rmb_desc->mr_rx[link->link_idx]->rkey);
417                         rkeyllc->rtoken[rtok_ix].rmb_vaddr = cpu_to_be64(
418                                 (u64)sg_dma_address(
419                                         rmb_desc->sgt[link->link_idx].sgl));
420                         rtok_ix++;
421                 }
422         }
423         /* rkey of send_link is in rtoken[0] */
424         rkeyllc->rtoken[0].num_rkeys = rtok_ix - 1;
425         rkeyllc->rtoken[0].rmb_key =
426                 htonl(rmb_desc->mr_rx[send_link->link_idx]->rkey);
427         rkeyllc->rtoken[0].rmb_vaddr = cpu_to_be64(
428                 (u64)sg_dma_address(rmb_desc->sgt[send_link->link_idx].sgl));
429         /* send llc message */
430         rc = smc_wr_tx_send(send_link, pend);
431         return rc;
432 }
433
434 /* send LLC delete rkey request */
435 static int smc_llc_send_delete_rkey(struct smc_link *link,
436                                     struct smc_buf_desc *rmb_desc)
437 {
438         struct smc_llc_msg_delete_rkey *rkeyllc;
439         struct smc_wr_tx_pend_priv *pend;
440         struct smc_wr_buf *wr_buf;
441         int rc;
442
443         rc = smc_llc_add_pending_send(link, &wr_buf, &pend);
444         if (rc)
445                 return rc;
446         rkeyllc = (struct smc_llc_msg_delete_rkey *)wr_buf;
447         memset(rkeyllc, 0, sizeof(*rkeyllc));
448         rkeyllc->hd.common.type = SMC_LLC_DELETE_RKEY;
449         rkeyllc->hd.length = sizeof(struct smc_llc_msg_delete_rkey);
450         rkeyllc->num_rkeys = 1;
451         rkeyllc->rkey[0] = htonl(rmb_desc->mr_rx[link->link_idx]->rkey);
452         /* send llc message */
453         rc = smc_wr_tx_send(link, pend);
454         return rc;
455 }
456
457 /* send ADD LINK request or response */
458 int smc_llc_send_add_link(struct smc_link *link, u8 mac[], u8 gid[],
459                           struct smc_link *link_new,
460                           enum smc_llc_reqresp reqresp)
461 {
462         struct smc_llc_msg_add_link *addllc;
463         struct smc_wr_tx_pend_priv *pend;
464         struct smc_wr_buf *wr_buf;
465         int rc;
466
467         rc = smc_llc_add_pending_send(link, &wr_buf, &pend);
468         if (rc)
469                 return rc;
470         addllc = (struct smc_llc_msg_add_link *)wr_buf;
471
472         memset(addllc, 0, sizeof(*addllc));
473         addllc->hd.common.type = SMC_LLC_ADD_LINK;
474         addllc->hd.length = sizeof(struct smc_llc_msg_add_link);
475         if (reqresp == SMC_LLC_RESP)
476                 addllc->hd.flags |= SMC_LLC_FLAG_RESP;
477         memcpy(addllc->sender_mac, mac, ETH_ALEN);
478         memcpy(addllc->sender_gid, gid, SMC_GID_SIZE);
479         if (link_new) {
480                 addllc->link_num = link_new->link_id;
481                 hton24(addllc->sender_qp_num, link_new->roce_qp->qp_num);
482                 hton24(addllc->initial_psn, link_new->psn_initial);
483                 if (reqresp == SMC_LLC_REQ)
484                         addllc->qp_mtu = link_new->path_mtu;
485                 else
486                         addllc->qp_mtu = min(link_new->path_mtu,
487                                              link_new->peer_mtu);
488         }
489         /* send llc message */
490         rc = smc_wr_tx_send(link, pend);
491         return rc;
492 }
493
494 /* send DELETE LINK request or response */
495 int smc_llc_send_delete_link(struct smc_link *link, u8 link_del_id,
496                              enum smc_llc_reqresp reqresp, bool orderly,
497                              u32 reason)
498 {
499         struct smc_llc_msg_del_link *delllc;
500         struct smc_wr_tx_pend_priv *pend;
501         struct smc_wr_buf *wr_buf;
502         int rc;
503
504         rc = smc_llc_add_pending_send(link, &wr_buf, &pend);
505         if (rc)
506                 return rc;
507         delllc = (struct smc_llc_msg_del_link *)wr_buf;
508
509         memset(delllc, 0, sizeof(*delllc));
510         delllc->hd.common.type = SMC_LLC_DELETE_LINK;
511         delllc->hd.length = sizeof(struct smc_llc_msg_del_link);
512         if (reqresp == SMC_LLC_RESP)
513                 delllc->hd.flags |= SMC_LLC_FLAG_RESP;
514         if (orderly)
515                 delllc->hd.flags |= SMC_LLC_FLAG_DEL_LINK_ORDERLY;
516         if (link_del_id)
517                 delllc->link_num = link_del_id;
518         else
519                 delllc->hd.flags |= SMC_LLC_FLAG_DEL_LINK_ALL;
520         delllc->reason = htonl(reason);
521         /* send llc message */
522         rc = smc_wr_tx_send(link, pend);
523         return rc;
524 }
525
526 /* send LLC test link request */
527 static int smc_llc_send_test_link(struct smc_link *link, u8 user_data[16])
528 {
529         struct smc_llc_msg_test_link *testllc;
530         struct smc_wr_tx_pend_priv *pend;
531         struct smc_wr_buf *wr_buf;
532         int rc;
533
534         rc = smc_llc_add_pending_send(link, &wr_buf, &pend);
535         if (rc)
536                 return rc;
537         testllc = (struct smc_llc_msg_test_link *)wr_buf;
538         memset(testllc, 0, sizeof(*testllc));
539         testllc->hd.common.type = SMC_LLC_TEST_LINK;
540         testllc->hd.length = sizeof(struct smc_llc_msg_test_link);
541         memcpy(testllc->user_data, user_data, sizeof(testllc->user_data));
542         /* send llc message */
543         rc = smc_wr_tx_send(link, pend);
544         return rc;
545 }
546
547 /* schedule an llc send on link, may wait for buffers */
548 static int smc_llc_send_message(struct smc_link *link, void *llcbuf)
549 {
550         struct smc_wr_tx_pend_priv *pend;
551         struct smc_wr_buf *wr_buf;
552         int rc;
553
554         if (!smc_link_usable(link))
555                 return -ENOLINK;
556         rc = smc_llc_add_pending_send(link, &wr_buf, &pend);
557         if (rc)
558                 return rc;
559         memcpy(wr_buf, llcbuf, sizeof(union smc_llc_msg));
560         return smc_wr_tx_send(link, pend);
561 }
562
563 /********************************* receive ***********************************/
564
565 static int smc_llc_alloc_alt_link(struct smc_link_group *lgr,
566                                   enum smc_lgr_type lgr_new_t)
567 {
568         int i;
569
570         if (lgr->type == SMC_LGR_SYMMETRIC ||
571             (lgr->type != SMC_LGR_SINGLE &&
572              (lgr_new_t == SMC_LGR_ASYMMETRIC_LOCAL ||
573               lgr_new_t == SMC_LGR_ASYMMETRIC_PEER)))
574                 return -EMLINK;
575
576         if (lgr_new_t == SMC_LGR_ASYMMETRIC_LOCAL ||
577             lgr_new_t == SMC_LGR_ASYMMETRIC_PEER) {
578                 for (i = SMC_LINKS_PER_LGR_MAX - 1; i >= 0; i--)
579                         if (lgr->lnk[i].state == SMC_LNK_UNUSED)
580                                 return i;
581         } else {
582                 for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++)
583                         if (lgr->lnk[i].state == SMC_LNK_UNUSED)
584                                 return i;
585         }
586         return -EMLINK;
587 }
588
589 /* return first buffer from any of the next buf lists */
590 static struct smc_buf_desc *_smc_llc_get_next_rmb(struct smc_link_group *lgr,
591                                                   int *buf_lst)
592 {
593         struct smc_buf_desc *buf_pos;
594
595         while (*buf_lst < SMC_RMBE_SIZES) {
596                 buf_pos = list_first_entry_or_null(&lgr->rmbs[*buf_lst],
597                                                    struct smc_buf_desc, list);
598                 if (buf_pos)
599                         return buf_pos;
600                 (*buf_lst)++;
601         }
602         return NULL;
603 }
604
605 /* return next rmb from buffer lists */
606 static struct smc_buf_desc *smc_llc_get_next_rmb(struct smc_link_group *lgr,
607                                                  int *buf_lst,
608                                                  struct smc_buf_desc *buf_pos)
609 {
610         struct smc_buf_desc *buf_next;
611
612         if (!buf_pos || list_is_last(&buf_pos->list, &lgr->rmbs[*buf_lst])) {
613                 (*buf_lst)++;
614                 return _smc_llc_get_next_rmb(lgr, buf_lst);
615         }
616         buf_next = list_next_entry(buf_pos, list);
617         return buf_next;
618 }
619
620 static struct smc_buf_desc *smc_llc_get_first_rmb(struct smc_link_group *lgr,
621                                                   int *buf_lst)
622 {
623         *buf_lst = 0;
624         return smc_llc_get_next_rmb(lgr, buf_lst, NULL);
625 }
626
627 /* send one add_link_continue msg */
628 static int smc_llc_add_link_cont(struct smc_link *link,
629                                  struct smc_link *link_new, u8 *num_rkeys_todo,
630                                  int *buf_lst, struct smc_buf_desc **buf_pos)
631 {
632         struct smc_llc_msg_add_link_cont *addc_llc;
633         struct smc_link_group *lgr = link->lgr;
634         int prim_lnk_idx, lnk_idx, i, rc;
635         struct smc_wr_tx_pend_priv *pend;
636         struct smc_wr_buf *wr_buf;
637         struct smc_buf_desc *rmb;
638         u8 n;
639
640         rc = smc_llc_add_pending_send(link, &wr_buf, &pend);
641         if (rc)
642                 return rc;
643         addc_llc = (struct smc_llc_msg_add_link_cont *)wr_buf;
644         memset(addc_llc, 0, sizeof(*addc_llc));
645
646         prim_lnk_idx = link->link_idx;
647         lnk_idx = link_new->link_idx;
648         addc_llc->link_num = link_new->link_id;
649         addc_llc->num_rkeys = *num_rkeys_todo;
650         n = *num_rkeys_todo;
651         for (i = 0; i < min_t(u8, n, SMC_LLC_RKEYS_PER_CONT_MSG); i++) {
652                 if (!*buf_pos) {
653                         addc_llc->num_rkeys = addc_llc->num_rkeys -
654                                               *num_rkeys_todo;
655                         *num_rkeys_todo = 0;
656                         break;
657                 }
658                 rmb = *buf_pos;
659
660                 addc_llc->rt[i].rmb_key = htonl(rmb->mr_rx[prim_lnk_idx]->rkey);
661                 addc_llc->rt[i].rmb_key_new = htonl(rmb->mr_rx[lnk_idx]->rkey);
662                 addc_llc->rt[i].rmb_vaddr_new =
663                         cpu_to_be64((u64)sg_dma_address(rmb->sgt[lnk_idx].sgl));
664
665                 (*num_rkeys_todo)--;
666                 *buf_pos = smc_llc_get_next_rmb(lgr, buf_lst, *buf_pos);
667                 while (*buf_pos && !(*buf_pos)->used)
668                         *buf_pos = smc_llc_get_next_rmb(lgr, buf_lst, *buf_pos);
669         }
670         addc_llc->hd.common.type = SMC_LLC_ADD_LINK_CONT;
671         addc_llc->hd.length = sizeof(struct smc_llc_msg_add_link_cont);
672         if (lgr->role == SMC_CLNT)
673                 addc_llc->hd.flags |= SMC_LLC_FLAG_RESP;
674         return smc_wr_tx_send(link, pend);
675 }
676
677 static int smc_llc_cli_rkey_exchange(struct smc_link *link,
678                                      struct smc_link *link_new)
679 {
680         struct smc_llc_msg_add_link_cont *addc_llc;
681         struct smc_link_group *lgr = link->lgr;
682         u8 max, num_rkeys_send, num_rkeys_recv;
683         struct smc_llc_qentry *qentry;
684         struct smc_buf_desc *buf_pos;
685         int buf_lst;
686         int rc = 0;
687         int i;
688
689         mutex_lock(&lgr->rmbs_lock);
690         num_rkeys_send = lgr->conns_num;
691         buf_pos = smc_llc_get_first_rmb(lgr, &buf_lst);
692         do {
693                 qentry = smc_llc_wait(lgr, NULL, SMC_LLC_WAIT_TIME,
694                                       SMC_LLC_ADD_LINK_CONT);
695                 if (!qentry) {
696                         rc = -ETIMEDOUT;
697                         break;
698                 }
699                 addc_llc = &qentry->msg.add_link_cont;
700                 num_rkeys_recv = addc_llc->num_rkeys;
701                 max = min_t(u8, num_rkeys_recv, SMC_LLC_RKEYS_PER_CONT_MSG);
702                 for (i = 0; i < max; i++) {
703                         smc_rtoken_set(lgr, link->link_idx, link_new->link_idx,
704                                        addc_llc->rt[i].rmb_key,
705                                        addc_llc->rt[i].rmb_vaddr_new,
706                                        addc_llc->rt[i].rmb_key_new);
707                         num_rkeys_recv--;
708                 }
709                 smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
710                 rc = smc_llc_add_link_cont(link, link_new, &num_rkeys_send,
711                                            &buf_lst, &buf_pos);
712                 if (rc)
713                         break;
714         } while (num_rkeys_send || num_rkeys_recv);
715
716         mutex_unlock(&lgr->rmbs_lock);
717         return rc;
718 }
719
720 /* prepare and send an add link reject response */
721 static int smc_llc_cli_add_link_reject(struct smc_llc_qentry *qentry)
722 {
723         qentry->msg.raw.hdr.flags |= SMC_LLC_FLAG_RESP;
724         qentry->msg.raw.hdr.flags |= SMC_LLC_FLAG_ADD_LNK_REJ;
725         qentry->msg.raw.hdr.add_link_rej_rsn = SMC_LLC_REJ_RSN_NO_ALT_PATH;
726         return smc_llc_send_message(qentry->link, &qentry->msg);
727 }
728
729 static int smc_llc_cli_conf_link(struct smc_link *link,
730                                  struct smc_init_info *ini,
731                                  struct smc_link *link_new,
732                                  enum smc_lgr_type lgr_new_t)
733 {
734         struct smc_link_group *lgr = link->lgr;
735         struct smc_llc_msg_del_link *del_llc;
736         struct smc_llc_qentry *qentry = NULL;
737         int rc = 0;
738
739         /* receive CONFIRM LINK request over RoCE fabric */
740         qentry = smc_llc_wait(lgr, NULL, SMC_LLC_WAIT_FIRST_TIME, 0);
741         if (!qentry) {
742                 rc = smc_llc_send_delete_link(link, link_new->link_id,
743                                               SMC_LLC_REQ, false,
744                                               SMC_LLC_DEL_LOST_PATH);
745                 return -ENOLINK;
746         }
747         if (qentry->msg.raw.hdr.common.type != SMC_LLC_CONFIRM_LINK) {
748                 /* received DELETE_LINK instead */
749                 del_llc = &qentry->msg.delete_link;
750                 qentry->msg.raw.hdr.flags |= SMC_LLC_FLAG_RESP;
751                 smc_llc_send_message(link, &qentry->msg);
752                 smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
753                 return -ENOLINK;
754         }
755         smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
756
757         rc = smc_ib_modify_qp_rts(link_new);
758         if (rc) {
759                 smc_llc_send_delete_link(link, link_new->link_id, SMC_LLC_REQ,
760                                          false, SMC_LLC_DEL_LOST_PATH);
761                 return -ENOLINK;
762         }
763         smc_wr_remember_qp_attr(link_new);
764
765         rc = smcr_buf_reg_lgr(link_new);
766         if (rc) {
767                 smc_llc_send_delete_link(link, link_new->link_id, SMC_LLC_REQ,
768                                          false, SMC_LLC_DEL_LOST_PATH);
769                 return -ENOLINK;
770         }
771
772         /* send CONFIRM LINK response over RoCE fabric */
773         rc = smc_llc_send_confirm_link(link_new, SMC_LLC_RESP);
774         if (rc) {
775                 smc_llc_send_delete_link(link, link_new->link_id, SMC_LLC_REQ,
776                                          false, SMC_LLC_DEL_LOST_PATH);
777                 return -ENOLINK;
778         }
779         smc_llc_link_active(link_new);
780         lgr->type = lgr_new_t;
781         return 0;
782 }
783
784 static void smc_llc_save_add_link_info(struct smc_link *link,
785                                        struct smc_llc_msg_add_link *add_llc)
786 {
787         link->peer_qpn = ntoh24(add_llc->sender_qp_num);
788         memcpy(link->peer_gid, add_llc->sender_gid, SMC_GID_SIZE);
789         memcpy(link->peer_mac, add_llc->sender_mac, ETH_ALEN);
790         link->peer_psn = ntoh24(add_llc->initial_psn);
791         link->peer_mtu = add_llc->qp_mtu;
792 }
793
794 /* as an SMC client, process an add link request */
795 int smc_llc_cli_add_link(struct smc_link *link, struct smc_llc_qentry *qentry)
796 {
797         struct smc_llc_msg_add_link *llc = &qentry->msg.add_link;
798         enum smc_lgr_type lgr_new_t = SMC_LGR_SYMMETRIC;
799         struct smc_link_group *lgr = smc_get_lgr(link);
800         struct smc_link *lnk_new = NULL;
801         struct smc_init_info ini;
802         int lnk_idx, rc = 0;
803
804         ini.vlan_id = lgr->vlan_id;
805         smc_pnet_find_alt_roce(lgr, &ini, link->smcibdev);
806         if (!memcmp(llc->sender_gid, link->peer_gid, SMC_GID_SIZE) &&
807             !memcmp(llc->sender_mac, link->peer_mac, ETH_ALEN)) {
808                 if (!ini.ib_dev)
809                         goto out_reject;
810                 lgr_new_t = SMC_LGR_ASYMMETRIC_PEER;
811         }
812         if (!ini.ib_dev) {
813                 lgr_new_t = SMC_LGR_ASYMMETRIC_LOCAL;
814                 ini.ib_dev = link->smcibdev;
815                 ini.ib_port = link->ibport;
816         }
817         lnk_idx = smc_llc_alloc_alt_link(lgr, lgr_new_t);
818         if (lnk_idx < 0)
819                 goto out_reject;
820         lnk_new = &lgr->lnk[lnk_idx];
821         rc = smcr_link_init(lgr, lnk_new, lnk_idx, &ini);
822         if (rc)
823                 goto out_reject;
824         smc_llc_save_add_link_info(lnk_new, llc);
825         lnk_new->link_id = llc->link_num;
826
827         rc = smc_ib_ready_link(lnk_new);
828         if (rc)
829                 goto out_clear_lnk;
830
831         rc = smcr_buf_map_lgr(lnk_new);
832         if (rc)
833                 goto out_clear_lnk;
834
835         rc = smc_llc_send_add_link(link,
836                                    lnk_new->smcibdev->mac[ini.ib_port - 1],
837                                    lnk_new->gid, lnk_new, SMC_LLC_RESP);
838         if (rc)
839                 goto out_clear_lnk;
840         rc = smc_llc_cli_rkey_exchange(link, lnk_new);
841         if (rc) {
842                 rc = 0;
843                 goto out_clear_lnk;
844         }
845         rc = smc_llc_cli_conf_link(link, &ini, lnk_new, lgr_new_t);
846         if (!rc)
847                 goto out;
848 out_clear_lnk:
849         smcr_link_clear(lnk_new);
850 out_reject:
851         smc_llc_cli_add_link_reject(qentry);
852 out:
853         kfree(qentry);
854         return rc;
855 }
856
857 static void smc_llc_process_cli_add_link(struct smc_link_group *lgr)
858 {
859         struct smc_llc_qentry *qentry;
860
861         qentry = smc_llc_flow_qentry_clr(&lgr->llc_flow_lcl);
862
863         mutex_lock(&lgr->llc_conf_mutex);
864         smc_llc_cli_add_link(qentry->link, qentry);
865         mutex_unlock(&lgr->llc_conf_mutex);
866 }
867
868 static int smc_llc_active_link_count(struct smc_link_group *lgr)
869 {
870         int i, link_count = 0;
871
872         for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
873                 if (!smc_link_usable(&lgr->lnk[i]))
874                         continue;
875                 link_count++;
876         }
877         return link_count;
878 }
879
880 /* find the asymmetric link when 3 links are established  */
881 static struct smc_link *smc_llc_find_asym_link(struct smc_link_group *lgr)
882 {
883         int asym_idx = -ENOENT;
884         int i, j, k;
885         bool found;
886
887         /* determine asymmetric link */
888         found = false;
889         for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
890                 for (j = i + 1; j < SMC_LINKS_PER_LGR_MAX; j++) {
891                         if (!smc_link_usable(&lgr->lnk[i]) ||
892                             !smc_link_usable(&lgr->lnk[j]))
893                                 continue;
894                         if (!memcmp(lgr->lnk[i].gid, lgr->lnk[j].gid,
895                                     SMC_GID_SIZE)) {
896                                 found = true;   /* asym_lnk is i or j */
897                                 break;
898                         }
899                 }
900                 if (found)
901                         break;
902         }
903         if (!found)
904                 goto out; /* no asymmetric link */
905         for (k = 0; k < SMC_LINKS_PER_LGR_MAX; k++) {
906                 if (!smc_link_usable(&lgr->lnk[k]))
907                         continue;
908                 if (k != i &&
909                     !memcmp(lgr->lnk[i].peer_gid, lgr->lnk[k].peer_gid,
910                             SMC_GID_SIZE)) {
911                         asym_idx = i;
912                         break;
913                 }
914                 if (k != j &&
915                     !memcmp(lgr->lnk[j].peer_gid, lgr->lnk[k].peer_gid,
916                             SMC_GID_SIZE)) {
917                         asym_idx = j;
918                         break;
919                 }
920         }
921 out:
922         return (asym_idx < 0) ? NULL : &lgr->lnk[asym_idx];
923 }
924
925 static void smc_llc_delete_asym_link(struct smc_link_group *lgr)
926 {
927         struct smc_link *lnk_new = NULL, *lnk_asym;
928         struct smc_llc_qentry *qentry;
929         int rc;
930
931         lnk_asym = smc_llc_find_asym_link(lgr);
932         if (!lnk_asym)
933                 return; /* no asymmetric link */
934         if (!smc_link_downing(&lnk_asym->state))
935                 return;
936         /* tbd: lnk_new = smc_switch_conns(lgr, lnk_asym, false); */
937         smc_wr_tx_wait_no_pending_sends(lnk_asym);
938         if (!lnk_new)
939                 goto out_free;
940         /* change flow type from ADD_LINK into DEL_LINK */
941         lgr->llc_flow_lcl.type = SMC_LLC_FLOW_DEL_LINK;
942         rc = smc_llc_send_delete_link(lnk_new, lnk_asym->link_id, SMC_LLC_REQ,
943                                       true, SMC_LLC_DEL_NO_ASYM_NEEDED);
944         if (rc) {
945                 smcr_link_down_cond(lnk_new);
946                 goto out_free;
947         }
948         qentry = smc_llc_wait(lgr, lnk_new, SMC_LLC_WAIT_TIME,
949                               SMC_LLC_DELETE_LINK);
950         if (!qentry) {
951                 smcr_link_down_cond(lnk_new);
952                 goto out_free;
953         }
954         smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
955 out_free:
956         smcr_link_clear(lnk_asym);
957 }
958
959 static int smc_llc_srv_rkey_exchange(struct smc_link *link,
960                                      struct smc_link *link_new)
961 {
962         struct smc_llc_msg_add_link_cont *addc_llc;
963         struct smc_link_group *lgr = link->lgr;
964         u8 max, num_rkeys_send, num_rkeys_recv;
965         struct smc_llc_qentry *qentry = NULL;
966         struct smc_buf_desc *buf_pos;
967         int buf_lst;
968         int rc = 0;
969         int i;
970
971         mutex_lock(&lgr->rmbs_lock);
972         num_rkeys_send = lgr->conns_num;
973         buf_pos = smc_llc_get_first_rmb(lgr, &buf_lst);
974         do {
975                 smc_llc_add_link_cont(link, link_new, &num_rkeys_send,
976                                       &buf_lst, &buf_pos);
977                 qentry = smc_llc_wait(lgr, link, SMC_LLC_WAIT_TIME,
978                                       SMC_LLC_ADD_LINK_CONT);
979                 if (!qentry) {
980                         rc = -ETIMEDOUT;
981                         goto out;
982                 }
983                 addc_llc = &qentry->msg.add_link_cont;
984                 num_rkeys_recv = addc_llc->num_rkeys;
985                 max = min_t(u8, num_rkeys_recv, SMC_LLC_RKEYS_PER_CONT_MSG);
986                 for (i = 0; i < max; i++) {
987                         smc_rtoken_set(lgr, link->link_idx, link_new->link_idx,
988                                        addc_llc->rt[i].rmb_key,
989                                        addc_llc->rt[i].rmb_vaddr_new,
990                                        addc_llc->rt[i].rmb_key_new);
991                         num_rkeys_recv--;
992                 }
993                 smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
994         } while (num_rkeys_send || num_rkeys_recv);
995 out:
996         mutex_unlock(&lgr->rmbs_lock);
997         return rc;
998 }
999
1000 static int smc_llc_srv_conf_link(struct smc_link *link,
1001                                  struct smc_link *link_new,
1002                                  enum smc_lgr_type lgr_new_t)
1003 {
1004         struct smc_link_group *lgr = link->lgr;
1005         struct smc_llc_qentry *qentry = NULL;
1006         int rc;
1007
1008         /* send CONFIRM LINK request over the RoCE fabric */
1009         rc = smc_llc_send_confirm_link(link_new, SMC_LLC_REQ);
1010         if (rc)
1011                 return -ENOLINK;
1012         /* receive CONFIRM LINK response over the RoCE fabric */
1013         qentry = smc_llc_wait(lgr, link, SMC_LLC_WAIT_FIRST_TIME,
1014                               SMC_LLC_CONFIRM_LINK);
1015         if (!qentry) {
1016                 /* send DELETE LINK */
1017                 smc_llc_send_delete_link(link, link_new->link_id, SMC_LLC_REQ,
1018                                          false, SMC_LLC_DEL_LOST_PATH);
1019                 return -ENOLINK;
1020         }
1021         smc_llc_link_active(link_new);
1022         lgr->type = lgr_new_t;
1023         smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
1024         return 0;
1025 }
1026
1027 int smc_llc_srv_add_link(struct smc_link *link)
1028 {
1029         enum smc_lgr_type lgr_new_t = SMC_LGR_SYMMETRIC;
1030         struct smc_link_group *lgr = link->lgr;
1031         struct smc_llc_msg_add_link *add_llc;
1032         struct smc_llc_qentry *qentry = NULL;
1033         struct smc_link *link_new;
1034         struct smc_init_info ini;
1035         int lnk_idx, rc = 0;
1036
1037         /* ignore client add link recommendation, start new flow */
1038         ini.vlan_id = lgr->vlan_id;
1039         smc_pnet_find_alt_roce(lgr, &ini, link->smcibdev);
1040         if (!ini.ib_dev) {
1041                 lgr_new_t = SMC_LGR_ASYMMETRIC_LOCAL;
1042                 ini.ib_dev = link->smcibdev;
1043                 ini.ib_port = link->ibport;
1044         }
1045         lnk_idx = smc_llc_alloc_alt_link(lgr, lgr_new_t);
1046         if (lnk_idx < 0)
1047                 return 0;
1048
1049         rc = smcr_link_init(lgr, &lgr->lnk[lnk_idx], lnk_idx, &ini);
1050         if (rc)
1051                 return rc;
1052         link_new = &lgr->lnk[lnk_idx];
1053         rc = smc_llc_send_add_link(link,
1054                                    link_new->smcibdev->mac[ini.ib_port - 1],
1055                                    link_new->gid, link_new, SMC_LLC_REQ);
1056         if (rc)
1057                 goto out_err;
1058         /* receive ADD LINK response over the RoCE fabric */
1059         qentry = smc_llc_wait(lgr, link, SMC_LLC_WAIT_TIME, SMC_LLC_ADD_LINK);
1060         if (!qentry) {
1061                 rc = -ETIMEDOUT;
1062                 goto out_err;
1063         }
1064         add_llc = &qentry->msg.add_link;
1065         if (add_llc->hd.flags & SMC_LLC_FLAG_ADD_LNK_REJ) {
1066                 smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
1067                 rc = -ENOLINK;
1068                 goto out_err;
1069         }
1070         if (lgr->type == SMC_LGR_SINGLE &&
1071             (!memcmp(add_llc->sender_gid, link->peer_gid, SMC_GID_SIZE) &&
1072              !memcmp(add_llc->sender_mac, link->peer_mac, ETH_ALEN))) {
1073                 lgr_new_t = SMC_LGR_ASYMMETRIC_PEER;
1074         }
1075         smc_llc_save_add_link_info(link_new, add_llc);
1076         smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
1077
1078         rc = smc_ib_ready_link(link_new);
1079         if (rc)
1080                 goto out_err;
1081         rc = smcr_buf_map_lgr(link_new);
1082         if (rc)
1083                 goto out_err;
1084         rc = smcr_buf_reg_lgr(link_new);
1085         if (rc)
1086                 goto out_err;
1087         rc = smc_llc_srv_rkey_exchange(link, link_new);
1088         if (rc)
1089                 goto out_err;
1090         rc = smc_llc_srv_conf_link(link, link_new, lgr_new_t);
1091         if (rc)
1092                 goto out_err;
1093         return 0;
1094 out_err:
1095         smcr_link_clear(link_new);
1096         return rc;
1097 }
1098
1099 static void smc_llc_process_srv_add_link(struct smc_link_group *lgr)
1100 {
1101         struct smc_link *link = lgr->llc_flow_lcl.qentry->link;
1102         int rc;
1103
1104         smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
1105
1106         mutex_lock(&lgr->llc_conf_mutex);
1107         rc = smc_llc_srv_add_link(link);
1108         if (!rc && lgr->type == SMC_LGR_SYMMETRIC) {
1109                 /* delete any asymmetric link */
1110                 smc_llc_delete_asym_link(lgr);
1111         }
1112         mutex_unlock(&lgr->llc_conf_mutex);
1113 }
1114
1115 /* enqueue a local add_link req to trigger a new add_link flow, only as SERV */
1116 void smc_llc_srv_add_link_local(struct smc_link *link)
1117 {
1118         struct smc_llc_msg_add_link add_llc = {0};
1119
1120         add_llc.hd.length = sizeof(add_llc);
1121         add_llc.hd.common.type = SMC_LLC_ADD_LINK;
1122         /* no dev and port needed, we as server ignore client data anyway */
1123         smc_llc_enqueue(link, (union smc_llc_msg *)&add_llc);
1124 }
1125
1126 /* worker to process an add link message */
1127 static void smc_llc_add_link_work(struct work_struct *work)
1128 {
1129         struct smc_link_group *lgr = container_of(work, struct smc_link_group,
1130                                                   llc_add_link_work);
1131
1132         if (list_empty(&lgr->list)) {
1133                 /* link group is terminating */
1134                 smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
1135                 goto out;
1136         }
1137
1138         if (lgr->role == SMC_CLNT)
1139                 smc_llc_process_cli_add_link(lgr);
1140         else
1141                 smc_llc_process_srv_add_link(lgr);
1142 out:
1143         smc_llc_flow_stop(lgr, &lgr->llc_flow_lcl);
1144 }
1145
1146 /* enqueue a local del_link msg to trigger a new del_link flow,
1147  * called only for role SMC_SERV
1148  */
1149 void smc_llc_srv_delete_link_local(struct smc_link *link, u8 del_link_id)
1150 {
1151         struct smc_llc_msg_del_link del_llc = {0};
1152
1153         del_llc.hd.length = sizeof(del_llc);
1154         del_llc.hd.common.type = SMC_LLC_DELETE_LINK;
1155         del_llc.link_num = del_link_id;
1156         del_llc.reason = htonl(SMC_LLC_DEL_LOST_PATH);
1157         del_llc.hd.flags |= SMC_LLC_FLAG_DEL_LINK_ORDERLY;
1158         smc_llc_enqueue(link, (union smc_llc_msg *)&del_llc);
1159 }
1160
1161 static void smc_llc_process_cli_delete_link(struct smc_link_group *lgr)
1162 {
1163         struct smc_link *lnk_del = NULL, *lnk_asym, *lnk;
1164         struct smc_llc_msg_del_link *del_llc;
1165         struct smc_llc_qentry *qentry;
1166         int active_links;
1167         int lnk_idx;
1168
1169         qentry = smc_llc_flow_qentry_clr(&lgr->llc_flow_lcl);
1170         lnk = qentry->link;
1171         del_llc = &qentry->msg.delete_link;
1172
1173         if (del_llc->hd.flags & SMC_LLC_FLAG_DEL_LINK_ALL) {
1174                 smc_lgr_terminate_sched(lgr);
1175                 goto out;
1176         }
1177         mutex_lock(&lgr->llc_conf_mutex);
1178         /* delete single link */
1179         for (lnk_idx = 0; lnk_idx < SMC_LINKS_PER_LGR_MAX; lnk_idx++) {
1180                 if (lgr->lnk[lnk_idx].link_id != del_llc->link_num)
1181                         continue;
1182                 lnk_del = &lgr->lnk[lnk_idx];
1183                 break;
1184         }
1185         del_llc->hd.flags |= SMC_LLC_FLAG_RESP;
1186         if (!lnk_del) {
1187                 /* link was not found */
1188                 del_llc->reason = htonl(SMC_LLC_DEL_NOLNK);
1189                 smc_llc_send_message(lnk, &qentry->msg);
1190                 goto out_unlock;
1191         }
1192         lnk_asym = smc_llc_find_asym_link(lgr);
1193
1194         del_llc->reason = 0;
1195         smc_llc_send_message(lnk, &qentry->msg); /* response */
1196
1197         if (smc_link_downing(&lnk_del->state)) {
1198                 /* tbd: call smc_switch_conns(lgr, lnk_del, false); */
1199                 smc_wr_tx_wait_no_pending_sends(lnk_del);
1200         }
1201         smcr_link_clear(lnk_del);
1202
1203         active_links = smc_llc_active_link_count(lgr);
1204         if (lnk_del == lnk_asym) {
1205                 /* expected deletion of asym link, don't change lgr state */
1206         } else if (active_links == 1) {
1207                 lgr->type = SMC_LGR_SINGLE;
1208         } else if (!active_links) {
1209                 lgr->type = SMC_LGR_NONE;
1210                 smc_lgr_terminate_sched(lgr);
1211         }
1212 out_unlock:
1213         mutex_unlock(&lgr->llc_conf_mutex);
1214 out:
1215         kfree(qentry);
1216 }
1217
1218 static void smc_llc_process_srv_delete_link(struct smc_link_group *lgr)
1219 {
1220         struct smc_llc_msg_del_link *del_llc;
1221         struct smc_link *lnk, *lnk_del;
1222         struct smc_llc_qentry *qentry;
1223         int active_links;
1224         int i;
1225
1226         mutex_lock(&lgr->llc_conf_mutex);
1227         qentry = smc_llc_flow_qentry_clr(&lgr->llc_flow_lcl);
1228         lnk = qentry->link;
1229         del_llc = &qentry->msg.delete_link;
1230
1231         if (qentry->msg.delete_link.hd.flags & SMC_LLC_FLAG_DEL_LINK_ALL) {
1232                 /* delete entire lgr */
1233                 smc_lgr_terminate_sched(lgr);
1234                 goto out;
1235         }
1236         /* delete single link */
1237         lnk_del = NULL;
1238         for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
1239                 if (lgr->lnk[i].link_id == del_llc->link_num) {
1240                         lnk_del = &lgr->lnk[i];
1241                         break;
1242                 }
1243         }
1244         if (!lnk_del)
1245                 goto out; /* asymmetric link already deleted */
1246
1247         if (smc_link_downing(&lnk_del->state)) {
1248                 /* tbd: call smc_switch_conns(lgr, lnk_del, false); */
1249                 smc_wr_tx_wait_no_pending_sends(lnk_del);
1250         }
1251         if (!list_empty(&lgr->list)) {
1252                 /* qentry is either a request from peer (send it back to
1253                  * initiate the DELETE_LINK processing), or a locally
1254                  * enqueued DELETE_LINK request (forward it)
1255                  */
1256                 if (!smc_llc_send_message(lnk, &qentry->msg)) {
1257                         struct smc_llc_msg_del_link *del_llc_resp;
1258                         struct smc_llc_qentry *qentry2;
1259
1260                         qentry2 = smc_llc_wait(lgr, lnk, SMC_LLC_WAIT_TIME,
1261                                                SMC_LLC_DELETE_LINK);
1262                         if (!qentry2) {
1263                         } else {
1264                                 del_llc_resp = &qentry2->msg.delete_link;
1265                                 smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
1266                         }
1267                 }
1268         }
1269         smcr_link_clear(lnk_del);
1270
1271         active_links = smc_llc_active_link_count(lgr);
1272         if (active_links == 1) {
1273                 lgr->type = SMC_LGR_SINGLE;
1274         } else if (!active_links) {
1275                 lgr->type = SMC_LGR_NONE;
1276                 smc_lgr_terminate_sched(lgr);
1277         }
1278
1279         if (lgr->type == SMC_LGR_SINGLE && !list_empty(&lgr->list)) {
1280                 /* trigger setup of asymm alt link */
1281                 smc_llc_srv_add_link_local(lnk);
1282         }
1283 out:
1284         mutex_unlock(&lgr->llc_conf_mutex);
1285         kfree(qentry);
1286 }
1287
1288 static void smc_llc_delete_link_work(struct work_struct *work)
1289 {
1290         struct smc_link_group *lgr = container_of(work, struct smc_link_group,
1291                                                   llc_del_link_work);
1292
1293         if (list_empty(&lgr->list)) {
1294                 /* link group is terminating */
1295                 smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
1296                 goto out;
1297         }
1298
1299         if (lgr->role == SMC_CLNT)
1300                 smc_llc_process_cli_delete_link(lgr);
1301         else
1302                 smc_llc_process_srv_delete_link(lgr);
1303 out:
1304         smc_llc_flow_stop(lgr, &lgr->llc_flow_lcl);
1305 }
1306
1307 /* process a confirm_rkey request from peer, remote flow */
1308 static void smc_llc_rmt_conf_rkey(struct smc_link_group *lgr)
1309 {
1310         struct smc_llc_msg_confirm_rkey *llc;
1311         struct smc_llc_qentry *qentry;
1312         struct smc_link *link;
1313         int num_entries;
1314         int rk_idx;
1315         int i;
1316
1317         qentry = lgr->llc_flow_rmt.qentry;
1318         llc = &qentry->msg.confirm_rkey;
1319         link = qentry->link;
1320
1321         num_entries = llc->rtoken[0].num_rkeys;
1322         /* first rkey entry is for receiving link */
1323         rk_idx = smc_rtoken_add(link,
1324                                 llc->rtoken[0].rmb_vaddr,
1325                                 llc->rtoken[0].rmb_key);
1326         if (rk_idx < 0)
1327                 goto out_err;
1328
1329         for (i = 1; i <= min_t(u8, num_entries, SMC_LLC_RKEYS_PER_MSG - 1); i++)
1330                 smc_rtoken_set2(lgr, rk_idx, llc->rtoken[i].link_id,
1331                                 llc->rtoken[i].rmb_vaddr,
1332                                 llc->rtoken[i].rmb_key);
1333         /* max links is 3 so there is no need to support conf_rkey_cont msgs */
1334         goto out;
1335 out_err:
1336         llc->hd.flags |= SMC_LLC_FLAG_RKEY_NEG;
1337         llc->hd.flags |= SMC_LLC_FLAG_RKEY_RETRY;
1338 out:
1339         llc->hd.flags |= SMC_LLC_FLAG_RESP;
1340         smc_llc_send_message(link, &qentry->msg);
1341         smc_llc_flow_qentry_del(&lgr->llc_flow_rmt);
1342 }
1343
1344 /* process a delete_rkey request from peer, remote flow */
1345 static void smc_llc_rmt_delete_rkey(struct smc_link_group *lgr)
1346 {
1347         struct smc_llc_msg_delete_rkey *llc;
1348         struct smc_llc_qentry *qentry;
1349         struct smc_link *link;
1350         u8 err_mask = 0;
1351         int i, max;
1352
1353         qentry = lgr->llc_flow_rmt.qentry;
1354         llc = &qentry->msg.delete_rkey;
1355         link = qentry->link;
1356
1357         max = min_t(u8, llc->num_rkeys, SMC_LLC_DEL_RKEY_MAX);
1358         for (i = 0; i < max; i++) {
1359                 if (smc_rtoken_delete(link, llc->rkey[i]))
1360                         err_mask |= 1 << (SMC_LLC_DEL_RKEY_MAX - 1 - i);
1361         }
1362         if (err_mask) {
1363                 llc->hd.flags |= SMC_LLC_FLAG_RKEY_NEG;
1364                 llc->err_mask = err_mask;
1365         }
1366         llc->hd.flags |= SMC_LLC_FLAG_RESP;
1367         smc_llc_send_message(link, &qentry->msg);
1368         smc_llc_flow_qentry_del(&lgr->llc_flow_rmt);
1369 }
1370
1371 /* flush the llc event queue */
1372 static void smc_llc_event_flush(struct smc_link_group *lgr)
1373 {
1374         struct smc_llc_qentry *qentry, *q;
1375
1376         spin_lock_bh(&lgr->llc_event_q_lock);
1377         list_for_each_entry_safe(qentry, q, &lgr->llc_event_q, list) {
1378                 list_del_init(&qentry->list);
1379                 kfree(qentry);
1380         }
1381         spin_unlock_bh(&lgr->llc_event_q_lock);
1382 }
1383
1384 static void smc_llc_event_handler(struct smc_llc_qentry *qentry)
1385 {
1386         union smc_llc_msg *llc = &qentry->msg;
1387         struct smc_link *link = qentry->link;
1388         struct smc_link_group *lgr = link->lgr;
1389
1390         if (!smc_link_usable(link))
1391                 goto out;
1392
1393         switch (llc->raw.hdr.common.type) {
1394         case SMC_LLC_TEST_LINK:
1395                 llc->test_link.hd.flags |= SMC_LLC_FLAG_RESP;
1396                 smc_llc_send_message(link, llc);
1397                 break;
1398         case SMC_LLC_ADD_LINK:
1399                 if (list_empty(&lgr->list))
1400                         goto out;       /* lgr is terminating */
1401                 if (lgr->role == SMC_CLNT) {
1402                         if (lgr->llc_flow_lcl.type == SMC_LLC_FLOW_ADD_LINK) {
1403                                 /* a flow is waiting for this message */
1404                                 smc_llc_flow_qentry_set(&lgr->llc_flow_lcl,
1405                                                         qentry);
1406                                 wake_up_interruptible(&lgr->llc_waiter);
1407                         } else if (smc_llc_flow_start(&lgr->llc_flow_lcl,
1408                                                       qentry)) {
1409                                 schedule_work(&lgr->llc_add_link_work);
1410                         }
1411                 } else if (smc_llc_flow_start(&lgr->llc_flow_lcl, qentry)) {
1412                         /* as smc server, handle client suggestion */
1413                         schedule_work(&lgr->llc_add_link_work);
1414                 }
1415                 return;
1416         case SMC_LLC_CONFIRM_LINK:
1417         case SMC_LLC_ADD_LINK_CONT:
1418                 if (lgr->llc_flow_lcl.type != SMC_LLC_FLOW_NONE) {
1419                         /* a flow is waiting for this message */
1420                         smc_llc_flow_qentry_set(&lgr->llc_flow_lcl, qentry);
1421                         wake_up_interruptible(&lgr->llc_waiter);
1422                         return;
1423                 }
1424                 break;
1425         case SMC_LLC_DELETE_LINK:
1426                 if (lgr->role == SMC_CLNT) {
1427                         /* server requests to delete this link, send response */
1428                         if (lgr->llc_flow_lcl.type != SMC_LLC_FLOW_NONE) {
1429                                 /* DEL LINK REQ during ADD LINK SEQ */
1430                                 smc_llc_flow_qentry_set(&lgr->llc_flow_lcl,
1431                                                         qentry);
1432                                 wake_up_interruptible(&lgr->llc_waiter);
1433                         } else if (smc_llc_flow_start(&lgr->llc_flow_lcl,
1434                                                       qentry)) {
1435                                 schedule_work(&lgr->llc_del_link_work);
1436                         }
1437                 } else {
1438                         if (lgr->llc_flow_lcl.type == SMC_LLC_FLOW_ADD_LINK &&
1439                             !lgr->llc_flow_lcl.qentry) {
1440                                 /* DEL LINK REQ during ADD LINK SEQ */
1441                                 smc_llc_flow_qentry_set(&lgr->llc_flow_lcl,
1442                                                         qentry);
1443                                 wake_up_interruptible(&lgr->llc_waiter);
1444                         } else if (smc_llc_flow_start(&lgr->llc_flow_lcl,
1445                                                       qentry)) {
1446                                 schedule_work(&lgr->llc_del_link_work);
1447                         }
1448                 }
1449                 return;
1450         case SMC_LLC_CONFIRM_RKEY:
1451                 /* new request from remote, assign to remote flow */
1452                 if (smc_llc_flow_start(&lgr->llc_flow_rmt, qentry)) {
1453                         /* process here, does not wait for more llc msgs */
1454                         smc_llc_rmt_conf_rkey(lgr);
1455                         smc_llc_flow_stop(lgr, &lgr->llc_flow_rmt);
1456                 }
1457                 return;
1458         case SMC_LLC_CONFIRM_RKEY_CONT:
1459                 /* not used because max links is 3, and 3 rkeys fit into
1460                  * one CONFIRM_RKEY message
1461                  */
1462                 break;
1463         case SMC_LLC_DELETE_RKEY:
1464                 /* new request from remote, assign to remote flow */
1465                 if (smc_llc_flow_start(&lgr->llc_flow_rmt, qentry)) {
1466                         /* process here, does not wait for more llc msgs */
1467                         smc_llc_rmt_delete_rkey(lgr);
1468                         smc_llc_flow_stop(lgr, &lgr->llc_flow_rmt);
1469                 }
1470                 return;
1471         }
1472 out:
1473         kfree(qentry);
1474 }
1475
1476 /* worker to process llc messages on the event queue */
1477 static void smc_llc_event_work(struct work_struct *work)
1478 {
1479         struct smc_link_group *lgr = container_of(work, struct smc_link_group,
1480                                                   llc_event_work);
1481         struct smc_llc_qentry *qentry;
1482
1483         if (!lgr->llc_flow_lcl.type && lgr->delayed_event) {
1484                 if (smc_link_usable(lgr->delayed_event->link)) {
1485                         smc_llc_event_handler(lgr->delayed_event);
1486                 } else {
1487                         qentry = lgr->delayed_event;
1488                         lgr->delayed_event = NULL;
1489                         kfree(qentry);
1490                 }
1491         }
1492
1493 again:
1494         spin_lock_bh(&lgr->llc_event_q_lock);
1495         if (!list_empty(&lgr->llc_event_q)) {
1496                 qentry = list_first_entry(&lgr->llc_event_q,
1497                                           struct smc_llc_qentry, list);
1498                 list_del_init(&qentry->list);
1499                 spin_unlock_bh(&lgr->llc_event_q_lock);
1500                 smc_llc_event_handler(qentry);
1501                 goto again;
1502         }
1503         spin_unlock_bh(&lgr->llc_event_q_lock);
1504 }
1505
1506 /* process llc responses in tasklet context */
1507 static void smc_llc_rx_response(struct smc_link *link,
1508                                 struct smc_llc_qentry *qentry)
1509 {
1510         u8 llc_type = qentry->msg.raw.hdr.common.type;
1511
1512         switch (llc_type) {
1513         case SMC_LLC_TEST_LINK:
1514                 if (link->state == SMC_LNK_ACTIVE)
1515                         complete(&link->llc_testlink_resp);
1516                 break;
1517         case SMC_LLC_ADD_LINK:
1518         case SMC_LLC_DELETE_LINK:
1519         case SMC_LLC_CONFIRM_LINK:
1520         case SMC_LLC_ADD_LINK_CONT:
1521         case SMC_LLC_CONFIRM_RKEY:
1522         case SMC_LLC_DELETE_RKEY:
1523                 /* assign responses to the local flow, we requested them */
1524                 smc_llc_flow_qentry_set(&link->lgr->llc_flow_lcl, qentry);
1525                 wake_up_interruptible(&link->lgr->llc_waiter);
1526                 return;
1527         case SMC_LLC_CONFIRM_RKEY_CONT:
1528                 /* not used because max links is 3 */
1529                 break;
1530         }
1531         kfree(qentry);
1532 }
1533
1534 static void smc_llc_enqueue(struct smc_link *link, union smc_llc_msg *llc)
1535 {
1536         struct smc_link_group *lgr = link->lgr;
1537         struct smc_llc_qentry *qentry;
1538         unsigned long flags;
1539
1540         qentry = kmalloc(sizeof(*qentry), GFP_ATOMIC);
1541         if (!qentry)
1542                 return;
1543         qentry->link = link;
1544         INIT_LIST_HEAD(&qentry->list);
1545         memcpy(&qentry->msg, llc, sizeof(union smc_llc_msg));
1546
1547         /* process responses immediately */
1548         if (llc->raw.hdr.flags & SMC_LLC_FLAG_RESP) {
1549                 smc_llc_rx_response(link, qentry);
1550                 return;
1551         }
1552
1553         /* add requests to event queue */
1554         spin_lock_irqsave(&lgr->llc_event_q_lock, flags);
1555         list_add_tail(&qentry->list, &lgr->llc_event_q);
1556         spin_unlock_irqrestore(&lgr->llc_event_q_lock, flags);
1557         schedule_work(&link->lgr->llc_event_work);
1558 }
1559
1560 /* copy received msg and add it to the event queue */
1561 static void smc_llc_rx_handler(struct ib_wc *wc, void *buf)
1562 {
1563         struct smc_link *link = (struct smc_link *)wc->qp->qp_context;
1564         union smc_llc_msg *llc = buf;
1565
1566         if (wc->byte_len < sizeof(*llc))
1567                 return; /* short message */
1568         if (llc->raw.hdr.length != sizeof(*llc))
1569                 return; /* invalid message */
1570
1571         smc_llc_enqueue(link, llc);
1572 }
1573
1574 /***************************** worker, utils *********************************/
1575
1576 static void smc_llc_testlink_work(struct work_struct *work)
1577 {
1578         struct smc_link *link = container_of(to_delayed_work(work),
1579                                              struct smc_link, llc_testlink_wrk);
1580         unsigned long next_interval;
1581         unsigned long expire_time;
1582         u8 user_data[16] = { 0 };
1583         int rc;
1584
1585         if (link->state != SMC_LNK_ACTIVE)
1586                 return;         /* don't reschedule worker */
1587         expire_time = link->wr_rx_tstamp + link->llc_testlink_time;
1588         if (time_is_after_jiffies(expire_time)) {
1589                 next_interval = expire_time - jiffies;
1590                 goto out;
1591         }
1592         reinit_completion(&link->llc_testlink_resp);
1593         smc_llc_send_test_link(link, user_data);
1594         /* receive TEST LINK response over RoCE fabric */
1595         rc = wait_for_completion_interruptible_timeout(&link->llc_testlink_resp,
1596                                                        SMC_LLC_WAIT_TIME);
1597         if (link->state != SMC_LNK_ACTIVE)
1598                 return;         /* link state changed */
1599         if (rc <= 0) {
1600                 smcr_link_down_cond_sched(link);
1601                 return;
1602         }
1603         next_interval = link->llc_testlink_time;
1604 out:
1605         schedule_delayed_work(&link->llc_testlink_wrk, next_interval);
1606 }
1607
1608 void smc_llc_lgr_init(struct smc_link_group *lgr, struct smc_sock *smc)
1609 {
1610         struct net *net = sock_net(smc->clcsock->sk);
1611
1612         INIT_WORK(&lgr->llc_event_work, smc_llc_event_work);
1613         INIT_WORK(&lgr->llc_add_link_work, smc_llc_add_link_work);
1614         INIT_WORK(&lgr->llc_del_link_work, smc_llc_delete_link_work);
1615         INIT_LIST_HEAD(&lgr->llc_event_q);
1616         spin_lock_init(&lgr->llc_event_q_lock);
1617         spin_lock_init(&lgr->llc_flow_lock);
1618         init_waitqueue_head(&lgr->llc_waiter);
1619         mutex_init(&lgr->llc_conf_mutex);
1620         lgr->llc_testlink_time = net->ipv4.sysctl_tcp_keepalive_time;
1621 }
1622
1623 /* called after lgr was removed from lgr_list */
1624 void smc_llc_lgr_clear(struct smc_link_group *lgr)
1625 {
1626         smc_llc_event_flush(lgr);
1627         wake_up_interruptible_all(&lgr->llc_waiter);
1628         cancel_work_sync(&lgr->llc_event_work);
1629         cancel_work_sync(&lgr->llc_add_link_work);
1630         cancel_work_sync(&lgr->llc_del_link_work);
1631         if (lgr->delayed_event) {
1632                 kfree(lgr->delayed_event);
1633                 lgr->delayed_event = NULL;
1634         }
1635 }
1636
1637 int smc_llc_link_init(struct smc_link *link)
1638 {
1639         init_completion(&link->llc_testlink_resp);
1640         INIT_DELAYED_WORK(&link->llc_testlink_wrk, smc_llc_testlink_work);
1641         return 0;
1642 }
1643
1644 void smc_llc_link_active(struct smc_link *link)
1645 {
1646         link->state = SMC_LNK_ACTIVE;
1647         if (link->lgr->llc_testlink_time) {
1648                 link->llc_testlink_time = link->lgr->llc_testlink_time * HZ;
1649                 schedule_delayed_work(&link->llc_testlink_wrk,
1650                                       link->llc_testlink_time);
1651         }
1652 }
1653
1654 /* called in worker context */
1655 void smc_llc_link_clear(struct smc_link *link)
1656 {
1657         complete(&link->llc_testlink_resp);
1658         cancel_delayed_work_sync(&link->llc_testlink_wrk);
1659         smc_wr_wakeup_reg_wait(link);
1660         smc_wr_wakeup_tx_wait(link);
1661 }
1662
1663 /* register a new rtoken at the remote peer (for all links) */
1664 int smc_llc_do_confirm_rkey(struct smc_link *send_link,
1665                             struct smc_buf_desc *rmb_desc)
1666 {
1667         struct smc_link_group *lgr = send_link->lgr;
1668         struct smc_llc_qentry *qentry = NULL;
1669         int rc = 0;
1670
1671         rc = smc_llc_send_confirm_rkey(send_link, rmb_desc);
1672         if (rc)
1673                 goto out;
1674         /* receive CONFIRM RKEY response from server over RoCE fabric */
1675         qentry = smc_llc_wait(lgr, send_link, SMC_LLC_WAIT_TIME,
1676                               SMC_LLC_CONFIRM_RKEY);
1677         if (!qentry || (qentry->msg.raw.hdr.flags & SMC_LLC_FLAG_RKEY_NEG))
1678                 rc = -EFAULT;
1679 out:
1680         if (qentry)
1681                 smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
1682         return rc;
1683 }
1684
1685 /* unregister an rtoken at the remote peer */
1686 int smc_llc_do_delete_rkey(struct smc_link_group *lgr,
1687                            struct smc_buf_desc *rmb_desc)
1688 {
1689         struct smc_llc_qentry *qentry = NULL;
1690         struct smc_link *send_link;
1691         int rc = 0;
1692
1693         send_link = smc_llc_usable_link(lgr);
1694         if (!send_link)
1695                 return -ENOLINK;
1696
1697         /* protected by llc_flow control */
1698         rc = smc_llc_send_delete_rkey(send_link, rmb_desc);
1699         if (rc)
1700                 goto out;
1701         /* receive DELETE RKEY response from server over RoCE fabric */
1702         qentry = smc_llc_wait(lgr, send_link, SMC_LLC_WAIT_TIME,
1703                               SMC_LLC_DELETE_RKEY);
1704         if (!qentry || (qentry->msg.raw.hdr.flags & SMC_LLC_FLAG_RKEY_NEG))
1705                 rc = -EFAULT;
1706 out:
1707         if (qentry)
1708                 smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
1709         return rc;
1710 }
1711
1712 /* evaluate confirm link request or response */
1713 int smc_llc_eval_conf_link(struct smc_llc_qentry *qentry,
1714                            enum smc_llc_reqresp type)
1715 {
1716         if (type == SMC_LLC_REQ)        /* SMC server assigns link_id */
1717                 qentry->link->link_id = qentry->msg.confirm_link.link_num;
1718         if (!(qentry->msg.raw.hdr.flags & SMC_LLC_FLAG_NO_RMBE_EYEC))
1719                 return -ENOTSUPP;
1720         return 0;
1721 }
1722
1723 /***************************** init, exit, misc ******************************/
1724
1725 static struct smc_wr_rx_handler smc_llc_rx_handlers[] = {
1726         {
1727                 .handler        = smc_llc_rx_handler,
1728                 .type           = SMC_LLC_CONFIRM_LINK
1729         },
1730         {
1731                 .handler        = smc_llc_rx_handler,
1732                 .type           = SMC_LLC_TEST_LINK
1733         },
1734         {
1735                 .handler        = smc_llc_rx_handler,
1736                 .type           = SMC_LLC_ADD_LINK
1737         },
1738         {
1739                 .handler        = smc_llc_rx_handler,
1740                 .type           = SMC_LLC_ADD_LINK_CONT
1741         },
1742         {
1743                 .handler        = smc_llc_rx_handler,
1744                 .type           = SMC_LLC_DELETE_LINK
1745         },
1746         {
1747                 .handler        = smc_llc_rx_handler,
1748                 .type           = SMC_LLC_CONFIRM_RKEY
1749         },
1750         {
1751                 .handler        = smc_llc_rx_handler,
1752                 .type           = SMC_LLC_CONFIRM_RKEY_CONT
1753         },
1754         {
1755                 .handler        = smc_llc_rx_handler,
1756                 .type           = SMC_LLC_DELETE_RKEY
1757         },
1758         {
1759                 .handler        = NULL,
1760         }
1761 };
1762
1763 int __init smc_llc_init(void)
1764 {
1765         struct smc_wr_rx_handler *handler;
1766         int rc = 0;
1767
1768         for (handler = smc_llc_rx_handlers; handler->handler; handler++) {
1769                 INIT_HLIST_NODE(&handler->list);
1770                 rc = smc_wr_rx_register_handler(handler);
1771                 if (rc)
1772                         break;
1773         }
1774         return rc;
1775 }