net/smc: process confirm/delete rkey messages
[platform/kernel/linux-rpi.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  *  For now, we only support the necessary "confirm link" functionality
8  *  which happens for the first RoCE link after successful CLC handshake.
9  *
10  *  Copyright IBM Corp. 2016
11  *
12  *  Author(s):  Klaus Wacker <Klaus.Wacker@de.ibm.com>
13  *              Ursula Braun <ubraun@linux.vnet.ibm.com>
14  */
15
16 #include <net/tcp.h>
17 #include <rdma/ib_verbs.h>
18
19 #include "smc.h"
20 #include "smc_core.h"
21 #include "smc_clc.h"
22 #include "smc_llc.h"
23
24 #define SMC_LLC_DATA_LEN                40
25
26 struct smc_llc_hdr {
27         struct smc_wr_rx_hdr common;
28         u8 length;      /* 44 */
29         u8 reserved;
30         u8 flags;
31 };
32
33 struct smc_llc_msg_confirm_link {       /* type 0x01 */
34         struct smc_llc_hdr hd;
35         u8 sender_mac[ETH_ALEN];
36         u8 sender_gid[SMC_GID_SIZE];
37         u8 sender_qp_num[3];
38         u8 link_num;
39         u8 link_uid[SMC_LGR_ID_SIZE];
40         u8 max_links;
41         u8 reserved[9];
42 };
43
44 struct smc_llc_msg_test_link {          /* type 0x07 */
45         struct smc_llc_hdr hd;
46         u8 user_data[16];
47         u8 reserved[24];
48 };
49
50 struct smc_rmb_rtoken {
51         union {
52                 u8 num_rkeys;   /* first rtoken byte of CONFIRM LINK msg */
53                                 /* is actually the num of rtokens, first */
54                                 /* rtoken is always for the current link */
55                 u8 link_id;     /* link id of the rtoken */
56         };
57         __be32 rmb_key;
58         __be64 rmb_vaddr;
59 } __packed;                     /* format defined in RFC7609 */
60
61 #define SMC_LLC_RKEYS_PER_MSG   3
62
63 struct smc_llc_msg_confirm_rkey {       /* type 0x06 */
64         struct smc_llc_hdr hd;
65         struct smc_rmb_rtoken rtoken[SMC_LLC_RKEYS_PER_MSG];
66         u8 reserved;
67 };
68
69 struct smc_llc_msg_confirm_rkey_cont {  /* type 0x08 */
70         struct smc_llc_hdr hd;
71         u8 num_rkeys;
72         struct smc_rmb_rtoken rtoken[SMC_LLC_RKEYS_PER_MSG];
73 };
74
75 #define SMC_LLC_DEL_RKEY_MAX    8
76 #define SMC_LLC_FLAG_RKEY_NEG   0x20
77
78 struct smc_llc_msg_delete_rkey {        /* type 0x09 */
79         struct smc_llc_hdr hd;
80         u8 num_rkeys;
81         u8 err_mask;
82         u8 reserved[2];
83         __be32 rkey[8];
84         u8 reserved2[4];
85 };
86
87 union smc_llc_msg {
88         struct smc_llc_msg_confirm_link confirm_link;
89
90         struct smc_llc_msg_confirm_rkey confirm_rkey;
91         struct smc_llc_msg_confirm_rkey_cont confirm_rkey_cont;
92         struct smc_llc_msg_delete_rkey delete_rkey;
93
94         struct smc_llc_msg_test_link test_link;
95         struct {
96                 struct smc_llc_hdr hdr;
97                 u8 data[SMC_LLC_DATA_LEN];
98         } raw;
99 };
100
101 #define SMC_LLC_FLAG_RESP               0x80
102
103 /********************************** send *************************************/
104
105 struct smc_llc_tx_pend {
106 };
107
108 /* handler for send/transmission completion of an LLC msg */
109 static void smc_llc_tx_handler(struct smc_wr_tx_pend_priv *pend,
110                                struct smc_link *link,
111                                enum ib_wc_status wc_status)
112 {
113         /* future work: handle wc_status error for recovery and failover */
114 }
115
116 /**
117  * smc_llc_add_pending_send() - add LLC control message to pending WQE transmits
118  * @link: Pointer to SMC link used for sending LLC control message.
119  * @wr_buf: Out variable returning pointer to work request payload buffer.
120  * @pend: Out variable returning pointer to private pending WR tracking.
121  *        It's the context the transmit complete handler will get.
122  *
123  * Reserves and pre-fills an entry for a pending work request send/tx.
124  * Used by mid-level smc_llc_send_msg() to prepare for later actual send/tx.
125  * Can sleep due to smc_get_ctrl_buf (if not in softirq context).
126  *
127  * Return: 0 on success, otherwise an error value.
128  */
129 static int smc_llc_add_pending_send(struct smc_link *link,
130                                     struct smc_wr_buf **wr_buf,
131                                     struct smc_wr_tx_pend_priv **pend)
132 {
133         int rc;
134
135         rc = smc_wr_tx_get_free_slot(link, smc_llc_tx_handler, wr_buf, pend);
136         if (rc < 0)
137                 return rc;
138         BUILD_BUG_ON_MSG(
139                 sizeof(union smc_llc_msg) > SMC_WR_BUF_SIZE,
140                 "must increase SMC_WR_BUF_SIZE to at least sizeof(struct smc_llc_msg)");
141         BUILD_BUG_ON_MSG(
142                 sizeof(union smc_llc_msg) != SMC_WR_TX_SIZE,
143                 "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()");
144         BUILD_BUG_ON_MSG(
145                 sizeof(struct smc_llc_tx_pend) > SMC_WR_TX_PEND_PRIV_SIZE,
146                 "must increase SMC_WR_TX_PEND_PRIV_SIZE to at least sizeof(struct smc_llc_tx_pend)");
147         return 0;
148 }
149
150 /* high-level API to send LLC confirm link */
151 int smc_llc_send_confirm_link(struct smc_link *link, u8 mac[],
152                               union ib_gid *gid,
153                               enum smc_llc_reqresp reqresp)
154 {
155         struct smc_link_group *lgr = container_of(link, struct smc_link_group,
156                                                   lnk[SMC_SINGLE_LINK]);
157         struct smc_llc_msg_confirm_link *confllc;
158         struct smc_wr_tx_pend_priv *pend;
159         struct smc_wr_buf *wr_buf;
160         int rc;
161
162         rc = smc_llc_add_pending_send(link, &wr_buf, &pend);
163         if (rc)
164                 return rc;
165         confllc = (struct smc_llc_msg_confirm_link *)wr_buf;
166         memset(confllc, 0, sizeof(*confllc));
167         confllc->hd.common.type = SMC_LLC_CONFIRM_LINK;
168         confllc->hd.length = sizeof(struct smc_llc_msg_confirm_link);
169         if (reqresp == SMC_LLC_RESP)
170                 confllc->hd.flags |= SMC_LLC_FLAG_RESP;
171         memcpy(confllc->sender_mac, mac, ETH_ALEN);
172         memcpy(confllc->sender_gid, gid, SMC_GID_SIZE);
173         hton24(confllc->sender_qp_num, link->roce_qp->qp_num);
174         /* confllc->link_num = SMC_SINGLE_LINK; already done by memset above */
175         memcpy(confllc->link_uid, lgr->id, SMC_LGR_ID_SIZE);
176         confllc->max_links = SMC_LINKS_PER_LGR_MAX;
177         /* send llc message */
178         rc = smc_wr_tx_send(link, pend);
179         return rc;
180 }
181
182 /* send LLC test link request or response */
183 int smc_llc_send_test_link(struct smc_link *link, u8 user_data[16],
184                            enum smc_llc_reqresp reqresp)
185 {
186         struct smc_llc_msg_test_link *testllc;
187         struct smc_wr_tx_pend_priv *pend;
188         struct smc_wr_buf *wr_buf;
189         int rc;
190
191         rc = smc_llc_add_pending_send(link, &wr_buf, &pend);
192         if (rc)
193                 return rc;
194         testllc = (struct smc_llc_msg_test_link *)wr_buf;
195         memset(testllc, 0, sizeof(*testllc));
196         testllc->hd.common.type = SMC_LLC_TEST_LINK;
197         testllc->hd.length = sizeof(struct smc_llc_msg_test_link);
198         if (reqresp == SMC_LLC_RESP)
199                 testllc->hd.flags |= SMC_LLC_FLAG_RESP;
200         memcpy(testllc->user_data, user_data, sizeof(testllc->user_data));
201         /* send llc message */
202         rc = smc_wr_tx_send(link, pend);
203         return rc;
204 }
205
206 /* send a prepared message */
207 static int smc_llc_send_message(struct smc_link *link, void *llcbuf, int llclen)
208 {
209         struct smc_wr_tx_pend_priv *pend;
210         struct smc_wr_buf *wr_buf;
211         int rc;
212
213         rc = smc_llc_add_pending_send(link, &wr_buf, &pend);
214         if (rc)
215                 return rc;
216         memcpy(wr_buf, llcbuf, llclen);
217         /* send llc message */
218         rc = smc_wr_tx_send(link, pend);
219         return rc;
220 }
221
222 /********************************* receive ***********************************/
223
224 static void smc_llc_rx_confirm_link(struct smc_link *link,
225                                     struct smc_llc_msg_confirm_link *llc)
226 {
227         struct smc_link_group *lgr;
228
229         lgr = container_of(link, struct smc_link_group, lnk[SMC_SINGLE_LINK]);
230         if (llc->hd.flags & SMC_LLC_FLAG_RESP) {
231                 if (lgr->role == SMC_SERV)
232                         complete(&link->llc_confirm_resp);
233         } else {
234                 if (lgr->role == SMC_CLNT) {
235                         link->link_id = llc->link_num;
236                         complete(&link->llc_confirm);
237                 }
238         }
239 }
240
241 static void smc_llc_rx_test_link(struct smc_link *link,
242                                  struct smc_llc_msg_test_link *llc)
243 {
244         if (llc->hd.flags & SMC_LLC_FLAG_RESP) {
245                 /* unused as long as we don't send this type of msg */
246         } else {
247                 smc_llc_send_test_link(link, llc->user_data, SMC_LLC_RESP);
248         }
249 }
250
251 static void smc_llc_rx_confirm_rkey(struct smc_link *link,
252                                     struct smc_llc_msg_confirm_rkey *llc)
253 {
254         struct smc_link_group *lgr;
255         int rc;
256
257         lgr = container_of(link, struct smc_link_group, lnk[SMC_SINGLE_LINK]);
258
259         if (llc->hd.flags & SMC_LLC_FLAG_RESP) {
260                 /* unused as long as we don't send this type of msg */
261         } else {
262                 rc = smc_rtoken_add(lgr,
263                                     llc->rtoken[0].rmb_vaddr,
264                                     llc->rtoken[0].rmb_key);
265
266                 /* ignore rtokens for other links, we have only one link */
267
268                 llc->hd.flags |= SMC_LLC_FLAG_RESP;
269                 if (rc < 0)
270                         llc->hd.flags |= SMC_LLC_FLAG_RKEY_NEG;
271                 smc_llc_send_message(link, (void *)llc, sizeof(*llc));
272         }
273 }
274
275 static void smc_llc_rx_confirm_rkey_cont(struct smc_link *link,
276                                       struct smc_llc_msg_confirm_rkey_cont *llc)
277 {
278         if (llc->hd.flags & SMC_LLC_FLAG_RESP) {
279                 /* unused as long as we don't send this type of msg */
280         } else {
281                 /* ignore rtokens for other links, we have only one link */
282                 llc->hd.flags |= SMC_LLC_FLAG_RESP;
283                 smc_llc_send_message(link, (void *)llc, sizeof(*llc));
284         }
285 }
286
287 static void smc_llc_rx_delete_rkey(struct smc_link *link,
288                                    struct smc_llc_msg_delete_rkey *llc)
289 {
290         struct smc_link_group *lgr;
291         u8 err_mask = 0;
292         int i, max;
293
294         lgr = container_of(link, struct smc_link_group, lnk[SMC_SINGLE_LINK]);
295
296         if (llc->hd.flags & SMC_LLC_FLAG_RESP) {
297                 /* unused as long as we don't send this type of msg */
298         } else {
299                 max = min_t(u8, llc->num_rkeys, SMC_LLC_DEL_RKEY_MAX);
300                 for (i = 0; i < max; i++) {
301                         if (smc_rtoken_delete(lgr, llc->rkey[i]))
302                                 err_mask |= 1 << (SMC_LLC_DEL_RKEY_MAX - 1 - i);
303                 }
304
305                 if (err_mask) {
306                         llc->hd.flags |= SMC_LLC_FLAG_RKEY_NEG;
307                         llc->err_mask = err_mask;
308                 }
309
310                 llc->hd.flags |= SMC_LLC_FLAG_RESP;
311                 smc_llc_send_message(link, (void *)llc, sizeof(*llc));
312         }
313 }
314
315 static void smc_llc_rx_handler(struct ib_wc *wc, void *buf)
316 {
317         struct smc_link *link = (struct smc_link *)wc->qp->qp_context;
318         union smc_llc_msg *llc = buf;
319
320         if (wc->byte_len < sizeof(*llc))
321                 return; /* short message */
322         if (llc->raw.hdr.length != sizeof(*llc))
323                 return; /* invalid message */
324
325         switch (llc->raw.hdr.common.type) {
326         case SMC_LLC_TEST_LINK:
327                 smc_llc_rx_test_link(link, &llc->test_link);
328                 break;
329         case SMC_LLC_CONFIRM_LINK:
330                 smc_llc_rx_confirm_link(link, &llc->confirm_link);
331                 break;
332         case SMC_LLC_CONFIRM_RKEY:
333                 smc_llc_rx_confirm_rkey(link, &llc->confirm_rkey);
334                 break;
335         case SMC_LLC_CONFIRM_RKEY_CONT:
336                 smc_llc_rx_confirm_rkey_cont(link, &llc->confirm_rkey_cont);
337                 break;
338         case SMC_LLC_DELETE_RKEY:
339                 smc_llc_rx_delete_rkey(link, &llc->delete_rkey);
340                 break;
341         }
342 }
343
344 /***************************** init, exit, misc ******************************/
345
346 static struct smc_wr_rx_handler smc_llc_rx_handlers[] = {
347         {
348                 .handler        = smc_llc_rx_handler,
349                 .type           = SMC_LLC_CONFIRM_LINK
350         },
351         {
352                 .handler        = smc_llc_rx_handler,
353                 .type           = SMC_LLC_TEST_LINK
354         },
355         {
356                 .handler        = smc_llc_rx_handler,
357                 .type           = SMC_LLC_CONFIRM_RKEY
358         },
359         {
360                 .handler        = smc_llc_rx_handler,
361                 .type           = SMC_LLC_CONFIRM_RKEY_CONT
362         },
363         {
364                 .handler        = smc_llc_rx_handler,
365                 .type           = SMC_LLC_DELETE_RKEY
366         },
367         {
368                 .handler        = NULL,
369         }
370 };
371
372 int __init smc_llc_init(void)
373 {
374         struct smc_wr_rx_handler *handler;
375         int rc = 0;
376
377         for (handler = smc_llc_rx_handlers; handler->handler; handler++) {
378                 INIT_HLIST_NODE(&handler->list);
379                 rc = smc_wr_rx_register_handler(handler);
380                 if (rc)
381                         break;
382         }
383         return rc;
384 }