Merge branch 'for-linus-4.11' of git://git.kernel.org/pub/scm/linux/kernel/git/mason...
[sfrench/cifs-2.6.git] / drivers / infiniband / hw / bnxt_re / qplib_sp.c
1 /*
2  * Broadcom NetXtreme-E RoCE driver.
3  *
4  * Copyright (c) 2016 - 2017, Broadcom. All rights reserved.  The term
5  * Broadcom refers to Broadcom Limited and/or its subsidiaries.
6  *
7  * This software is available to you under a choice of one of two
8  * licenses.  You may choose to be licensed under the terms of the GNU
9  * General Public License (GPL) Version 2, available from the file
10  * COPYING in the main directory of this source tree, or the
11  * BSD license below:
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  *
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in
21  *    the documentation and/or other materials provided with the
22  *    distribution.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
25  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
26  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
28  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
31  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
33  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
34  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  *
36  * Description: Slow Path Operators
37  */
38
39 #include <linux/interrupt.h>
40 #include <linux/spinlock.h>
41 #include <linux/sched.h>
42 #include <linux/pci.h>
43
44 #include "roce_hsi.h"
45
46 #include "qplib_res.h"
47 #include "qplib_rcfw.h"
48 #include "qplib_sp.h"
49
50 const struct bnxt_qplib_gid bnxt_qplib_gid_zero = {{ 0, 0, 0, 0, 0, 0, 0, 0,
51                                                      0, 0, 0, 0, 0, 0, 0, 0 } };
52
53 /* Device */
54 int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw,
55                             struct bnxt_qplib_dev_attr *attr)
56 {
57         struct cmdq_query_func req;
58         struct creq_query_func_resp *resp;
59         struct creq_query_func_resp_sb *sb;
60         u16 cmd_flags = 0;
61         u32 temp;
62         u8 *tqm_alloc;
63         int i;
64
65         RCFW_CMD_PREP(req, QUERY_FUNC, cmd_flags);
66
67         req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS;
68         resp = (struct creq_query_func_resp *)
69                 bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void **)&sb,
70                                              0);
71         if (!resp) {
72                 dev_err(&rcfw->pdev->dev, "QPLIB: SP: QUERY_FUNC send failed");
73                 return -EINVAL;
74         }
75         if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
76                 /* Cmd timed out */
77                 dev_err(&rcfw->pdev->dev, "QPLIB: SP: QUERY_FUNC timed out");
78                 return -ETIMEDOUT;
79         }
80         if (resp->status ||
81             le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
82                 dev_err(&rcfw->pdev->dev, "QPLIB: SP: QUERY_FUNC failed ");
83                 dev_err(&rcfw->pdev->dev,
84                         "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
85                         resp->status, le16_to_cpu(req.cookie),
86                         le16_to_cpu(resp->cookie));
87                 return -EINVAL;
88         }
89         /* Extract the context from the side buffer */
90         attr->max_qp = le32_to_cpu(sb->max_qp);
91         attr->max_qp_rd_atom =
92                 sb->max_qp_rd_atom > BNXT_QPLIB_MAX_OUT_RD_ATOM ?
93                 BNXT_QPLIB_MAX_OUT_RD_ATOM : sb->max_qp_rd_atom;
94         attr->max_qp_init_rd_atom =
95                 sb->max_qp_init_rd_atom > BNXT_QPLIB_MAX_OUT_RD_ATOM ?
96                 BNXT_QPLIB_MAX_OUT_RD_ATOM : sb->max_qp_init_rd_atom;
97         attr->max_qp_wqes = le16_to_cpu(sb->max_qp_wr);
98         attr->max_qp_sges = sb->max_sge;
99         attr->max_cq = le32_to_cpu(sb->max_cq);
100         attr->max_cq_wqes = le32_to_cpu(sb->max_cqe);
101         attr->max_cq_sges = attr->max_qp_sges;
102         attr->max_mr = le32_to_cpu(sb->max_mr);
103         attr->max_mw = le32_to_cpu(sb->max_mw);
104
105         attr->max_mr_size = le64_to_cpu(sb->max_mr_size);
106         attr->max_pd = 64 * 1024;
107         attr->max_raw_ethy_qp = le32_to_cpu(sb->max_raw_eth_qp);
108         attr->max_ah = le32_to_cpu(sb->max_ah);
109
110         attr->max_fmr = le32_to_cpu(sb->max_fmr);
111         attr->max_map_per_fmr = sb->max_map_per_fmr;
112
113         attr->max_srq = le16_to_cpu(sb->max_srq);
114         attr->max_srq_wqes = le32_to_cpu(sb->max_srq_wr) - 1;
115         attr->max_srq_sges = sb->max_srq_sge;
116         /* Bono only reports 1 PKEY for now, but it can support > 1 */
117         attr->max_pkey = le32_to_cpu(sb->max_pkeys);
118
119         attr->max_inline_data = le32_to_cpu(sb->max_inline_data);
120         attr->l2_db_size = (sb->l2_db_space_size + 1) * PAGE_SIZE;
121         attr->max_sgid = le32_to_cpu(sb->max_gid);
122
123         strlcpy(attr->fw_ver, "20.6.28.0", sizeof(attr->fw_ver));
124
125         for (i = 0; i < MAX_TQM_ALLOC_REQ / 4; i++) {
126                 temp = le32_to_cpu(sb->tqm_alloc_reqs[i]);
127                 tqm_alloc = (u8 *)&temp;
128                 attr->tqm_alloc_reqs[i * 4] = *tqm_alloc;
129                 attr->tqm_alloc_reqs[i * 4 + 1] = *(++tqm_alloc);
130                 attr->tqm_alloc_reqs[i * 4 + 2] = *(++tqm_alloc);
131                 attr->tqm_alloc_reqs[i * 4 + 3] = *(++tqm_alloc);
132         }
133         return 0;
134 }
135
136 /* SGID */
137 int bnxt_qplib_get_sgid(struct bnxt_qplib_res *res,
138                         struct bnxt_qplib_sgid_tbl *sgid_tbl, int index,
139                         struct bnxt_qplib_gid *gid)
140 {
141         if (index > sgid_tbl->max) {
142                 dev_err(&res->pdev->dev,
143                         "QPLIB: Index %d exceeded SGID table max (%d)",
144                         index, sgid_tbl->max);
145                 return -EINVAL;
146         }
147         memcpy(gid, &sgid_tbl->tbl[index], sizeof(*gid));
148         return 0;
149 }
150
151 int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
152                         struct bnxt_qplib_gid *gid, bool update)
153 {
154         struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl,
155                                                    struct bnxt_qplib_res,
156                                                    sgid_tbl);
157         struct bnxt_qplib_rcfw *rcfw = res->rcfw;
158         int index;
159
160         if (!sgid_tbl) {
161                 dev_err(&res->pdev->dev, "QPLIB: SGID table not allocated");
162                 return -EINVAL;
163         }
164         /* Do we need a sgid_lock here? */
165         if (!sgid_tbl->active) {
166                 dev_err(&res->pdev->dev,
167                         "QPLIB: SGID table has no active entries");
168                 return -ENOMEM;
169         }
170         for (index = 0; index < sgid_tbl->max; index++) {
171                 if (!memcmp(&sgid_tbl->tbl[index], gid, sizeof(*gid)))
172                         break;
173         }
174         if (index == sgid_tbl->max) {
175                 dev_warn(&res->pdev->dev, "GID not found in the SGID table");
176                 return 0;
177         }
178         /* Remove GID from the SGID table */
179         if (update) {
180                 struct cmdq_delete_gid req;
181                 struct creq_delete_gid_resp *resp;
182                 u16 cmd_flags = 0;
183
184                 RCFW_CMD_PREP(req, DELETE_GID, cmd_flags);
185                 if (sgid_tbl->hw_id[index] == 0xFFFF) {
186                         dev_err(&res->pdev->dev,
187                                 "QPLIB: GID entry contains an invalid HW id");
188                         return -EINVAL;
189                 }
190                 req.gid_index = cpu_to_le16(sgid_tbl->hw_id[index]);
191                 resp = (struct creq_delete_gid_resp *)
192                         bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, NULL,
193                                                      0);
194                 if (!resp) {
195                         dev_err(&res->pdev->dev,
196                                 "QPLIB: SP: DELETE_GID send failed");
197                         return -EINVAL;
198                 }
199                 if (!bnxt_qplib_rcfw_wait_for_resp(rcfw,
200                                                    le16_to_cpu(req.cookie))) {
201                         /* Cmd timed out */
202                         dev_err(&res->pdev->dev,
203                                 "QPLIB: SP: DELETE_GID timed out");
204                         return -ETIMEDOUT;
205                 }
206                 if (resp->status ||
207                     le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
208                         dev_err(&res->pdev->dev,
209                                 "QPLIB: SP: DELETE_GID failed ");
210                         dev_err(&res->pdev->dev,
211                                 "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
212                                 resp->status, le16_to_cpu(req.cookie),
213                                 le16_to_cpu(resp->cookie));
214                         return -EINVAL;
215                 }
216         }
217         memcpy(&sgid_tbl->tbl[index], &bnxt_qplib_gid_zero,
218                sizeof(bnxt_qplib_gid_zero));
219         sgid_tbl->active--;
220         dev_dbg(&res->pdev->dev,
221                 "QPLIB: SGID deleted hw_id[0x%x] = 0x%x active = 0x%x",
222                  index, sgid_tbl->hw_id[index], sgid_tbl->active);
223         sgid_tbl->hw_id[index] = (u16)-1;
224
225         /* unlock */
226         return 0;
227 }
228
229 int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
230                         struct bnxt_qplib_gid *gid, u8 *smac, u16 vlan_id,
231                         bool update, u32 *index)
232 {
233         struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl,
234                                                    struct bnxt_qplib_res,
235                                                    sgid_tbl);
236         struct bnxt_qplib_rcfw *rcfw = res->rcfw;
237         int i, free_idx, rc = 0;
238
239         if (!sgid_tbl) {
240                 dev_err(&res->pdev->dev, "QPLIB: SGID table not allocated");
241                 return -EINVAL;
242         }
243         /* Do we need a sgid_lock here? */
244         if (sgid_tbl->active == sgid_tbl->max) {
245                 dev_err(&res->pdev->dev, "QPLIB: SGID table is full");
246                 return -ENOMEM;
247         }
248         free_idx = sgid_tbl->max;
249         for (i = 0; i < sgid_tbl->max; i++) {
250                 if (!memcmp(&sgid_tbl->tbl[i], gid, sizeof(*gid))) {
251                         dev_dbg(&res->pdev->dev,
252                                 "QPLIB: SGID entry already exist in entry %d!",
253                                 i);
254                         *index = i;
255                         return -EALREADY;
256                 } else if (!memcmp(&sgid_tbl->tbl[i], &bnxt_qplib_gid_zero,
257                                    sizeof(bnxt_qplib_gid_zero)) &&
258                            free_idx == sgid_tbl->max) {
259                         free_idx = i;
260                 }
261         }
262         if (free_idx == sgid_tbl->max) {
263                 dev_err(&res->pdev->dev,
264                         "QPLIB: SGID table is FULL but count is not MAX??");
265                 return -ENOMEM;
266         }
267         if (update) {
268                 struct cmdq_add_gid req;
269                 struct creq_add_gid_resp *resp;
270                 u16 cmd_flags = 0;
271                 u32 temp32[4];
272                 u16 temp16[3];
273
274                 RCFW_CMD_PREP(req, ADD_GID, cmd_flags);
275
276                 memcpy(temp32, gid->data, sizeof(struct bnxt_qplib_gid));
277                 req.gid[0] = cpu_to_be32(temp32[3]);
278                 req.gid[1] = cpu_to_be32(temp32[2]);
279                 req.gid[2] = cpu_to_be32(temp32[1]);
280                 req.gid[3] = cpu_to_be32(temp32[0]);
281                 if (vlan_id != 0xFFFF)
282                         req.vlan = cpu_to_le16((vlan_id &
283                                         CMDQ_ADD_GID_VLAN_VLAN_ID_MASK) |
284                                         CMDQ_ADD_GID_VLAN_TPID_TPID_8100 |
285                                         CMDQ_ADD_GID_VLAN_VLAN_EN);
286
287                 /* MAC in network format */
288                 memcpy(temp16, smac, 6);
289                 req.src_mac[0] = cpu_to_be16(temp16[0]);
290                 req.src_mac[1] = cpu_to_be16(temp16[1]);
291                 req.src_mac[2] = cpu_to_be16(temp16[2]);
292
293                 resp = (struct creq_add_gid_resp *)
294                         bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
295                                                      NULL, 0);
296                 if (!resp) {
297                         dev_err(&res->pdev->dev,
298                                 "QPLIB: SP: ADD_GID send failed");
299                         return -EINVAL;
300                 }
301                 if (!bnxt_qplib_rcfw_wait_for_resp(rcfw,
302                                                    le16_to_cpu(req.cookie))) {
303                         /* Cmd timed out */
304                         dev_err(&res->pdev->dev,
305                                 "QPIB: SP: ADD_GID timed out");
306                         return -ETIMEDOUT;
307                 }
308                 if (resp->status ||
309                     le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
310                         dev_err(&res->pdev->dev, "QPLIB: SP: ADD_GID failed ");
311                         dev_err(&res->pdev->dev,
312                                 "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
313                                 resp->status, le16_to_cpu(req.cookie),
314                                 le16_to_cpu(resp->cookie));
315                         return -EINVAL;
316                 }
317                 sgid_tbl->hw_id[free_idx] = le32_to_cpu(resp->xid);
318         }
319         /* Add GID to the sgid_tbl */
320         memcpy(&sgid_tbl->tbl[free_idx], gid, sizeof(*gid));
321         sgid_tbl->active++;
322         dev_dbg(&res->pdev->dev,
323                 "QPLIB: SGID added hw_id[0x%x] = 0x%x active = 0x%x",
324                  free_idx, sgid_tbl->hw_id[free_idx], sgid_tbl->active);
325
326         *index = free_idx;
327         /* unlock */
328         return rc;
329 }
330
331 /* pkeys */
332 int bnxt_qplib_get_pkey(struct bnxt_qplib_res *res,
333                         struct bnxt_qplib_pkey_tbl *pkey_tbl, u16 index,
334                         u16 *pkey)
335 {
336         if (index == 0xFFFF) {
337                 *pkey = 0xFFFF;
338                 return 0;
339         }
340         if (index > pkey_tbl->max) {
341                 dev_err(&res->pdev->dev,
342                         "QPLIB: Index %d exceeded PKEY table max (%d)",
343                         index, pkey_tbl->max);
344                 return -EINVAL;
345         }
346         memcpy(pkey, &pkey_tbl->tbl[index], sizeof(*pkey));
347         return 0;
348 }
349
350 int bnxt_qplib_del_pkey(struct bnxt_qplib_res *res,
351                         struct bnxt_qplib_pkey_tbl *pkey_tbl, u16 *pkey,
352                         bool update)
353 {
354         int i, rc = 0;
355
356         if (!pkey_tbl) {
357                 dev_err(&res->pdev->dev, "QPLIB: PKEY table not allocated");
358                 return -EINVAL;
359         }
360
361         /* Do we need a pkey_lock here? */
362         if (!pkey_tbl->active) {
363                 dev_err(&res->pdev->dev,
364                         "QPLIB: PKEY table has no active entries");
365                 return -ENOMEM;
366         }
367         for (i = 0; i < pkey_tbl->max; i++) {
368                 if (!memcmp(&pkey_tbl->tbl[i], pkey, sizeof(*pkey)))
369                         break;
370         }
371         if (i == pkey_tbl->max) {
372                 dev_err(&res->pdev->dev,
373                         "QPLIB: PKEY 0x%04x not found in the pkey table",
374                         *pkey);
375                 return -ENOMEM;
376         }
377         memset(&pkey_tbl->tbl[i], 0, sizeof(*pkey));
378         pkey_tbl->active--;
379
380         /* unlock */
381         return rc;
382 }
383
384 int bnxt_qplib_add_pkey(struct bnxt_qplib_res *res,
385                         struct bnxt_qplib_pkey_tbl *pkey_tbl, u16 *pkey,
386                         bool update)
387 {
388         int i, free_idx, rc = 0;
389
390         if (!pkey_tbl) {
391                 dev_err(&res->pdev->dev, "QPLIB: PKEY table not allocated");
392                 return -EINVAL;
393         }
394
395         /* Do we need a pkey_lock here? */
396         if (pkey_tbl->active == pkey_tbl->max) {
397                 dev_err(&res->pdev->dev, "QPLIB: PKEY table is full");
398                 return -ENOMEM;
399         }
400         free_idx = pkey_tbl->max;
401         for (i = 0; i < pkey_tbl->max; i++) {
402                 if (!memcmp(&pkey_tbl->tbl[i], pkey, sizeof(*pkey)))
403                         return -EALREADY;
404                 else if (!pkey_tbl->tbl[i] && free_idx == pkey_tbl->max)
405                         free_idx = i;
406         }
407         if (free_idx == pkey_tbl->max) {
408                 dev_err(&res->pdev->dev,
409                         "QPLIB: PKEY table is FULL but count is not MAX??");
410                 return -ENOMEM;
411         }
412         /* Add PKEY to the pkey_tbl */
413         memcpy(&pkey_tbl->tbl[free_idx], pkey, sizeof(*pkey));
414         pkey_tbl->active++;
415
416         /* unlock */
417         return rc;
418 }
419
420 /* AH */
421 int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah)
422 {
423         struct bnxt_qplib_rcfw *rcfw = res->rcfw;
424         struct cmdq_create_ah req;
425         struct creq_create_ah_resp *resp;
426         u16 cmd_flags = 0;
427         u32 temp32[4];
428         u16 temp16[3];
429
430         RCFW_CMD_PREP(req, CREATE_AH, cmd_flags);
431
432         memcpy(temp32, ah->dgid.data, sizeof(struct bnxt_qplib_gid));
433         req.dgid[0] = cpu_to_le32(temp32[0]);
434         req.dgid[1] = cpu_to_le32(temp32[1]);
435         req.dgid[2] = cpu_to_le32(temp32[2]);
436         req.dgid[3] = cpu_to_le32(temp32[3]);
437
438         req.type = ah->nw_type;
439         req.hop_limit = ah->hop_limit;
440         req.sgid_index = cpu_to_le16(res->sgid_tbl.hw_id[ah->sgid_index]);
441         req.dest_vlan_id_flow_label = cpu_to_le32((ah->flow_label &
442                                         CMDQ_CREATE_AH_FLOW_LABEL_MASK) |
443                                         CMDQ_CREATE_AH_DEST_VLAN_ID_MASK);
444         req.pd_id = cpu_to_le32(ah->pd->id);
445         req.traffic_class = ah->traffic_class;
446
447         /* MAC in network format */
448         memcpy(temp16, ah->dmac, 6);
449         req.dest_mac[0] = cpu_to_le16(temp16[0]);
450         req.dest_mac[1] = cpu_to_le16(temp16[1]);
451         req.dest_mac[2] = cpu_to_le16(temp16[2]);
452
453         resp = (struct creq_create_ah_resp *)
454                         bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
455                                                      NULL, 1);
456         if (!resp) {
457                 dev_err(&rcfw->pdev->dev, "QPLIB: SP: CREATE_AH send failed");
458                 return -EINVAL;
459         }
460         if (!bnxt_qplib_rcfw_block_for_resp(rcfw, le16_to_cpu(req.cookie))) {
461                 /* Cmd timed out */
462                 dev_err(&rcfw->pdev->dev, "QPLIB: SP: CREATE_AH timed out");
463                 return -ETIMEDOUT;
464         }
465         if (resp->status ||
466             le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
467                 dev_err(&rcfw->pdev->dev, "QPLIB: SP: CREATE_AH failed ");
468                 dev_err(&rcfw->pdev->dev,
469                         "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
470                         resp->status, le16_to_cpu(req.cookie),
471                         le16_to_cpu(resp->cookie));
472                 return -EINVAL;
473         }
474         ah->id = le32_to_cpu(resp->xid);
475         return 0;
476 }
477
478 int bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah)
479 {
480         struct bnxt_qplib_rcfw *rcfw = res->rcfw;
481         struct cmdq_destroy_ah req;
482         struct creq_destroy_ah_resp *resp;
483         u16 cmd_flags = 0;
484
485         /* Clean up the AH table in the device */
486         RCFW_CMD_PREP(req, DESTROY_AH, cmd_flags);
487
488         req.ah_cid = cpu_to_le32(ah->id);
489
490         resp = (struct creq_destroy_ah_resp *)
491                         bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
492                                                      NULL, 1);
493         if (!resp) {
494                 dev_err(&rcfw->pdev->dev, "QPLIB: SP: DESTROY_AH send failed");
495                 return -EINVAL;
496         }
497         if (!bnxt_qplib_rcfw_block_for_resp(rcfw, le16_to_cpu(req.cookie))) {
498                 /* Cmd timed out */
499                 dev_err(&rcfw->pdev->dev, "QPLIB: SP: DESTROY_AH timed out");
500                 return -ETIMEDOUT;
501         }
502         if (resp->status ||
503             le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
504                 dev_err(&rcfw->pdev->dev, "QPLIB: SP: DESTROY_AH failed ");
505                 dev_err(&rcfw->pdev->dev,
506                         "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
507                         resp->status, le16_to_cpu(req.cookie),
508                         le16_to_cpu(resp->cookie));
509                 return -EINVAL;
510         }
511         return 0;
512 }
513
514 /* MRW */
515 int bnxt_qplib_free_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw)
516 {
517         struct bnxt_qplib_rcfw *rcfw = res->rcfw;
518         struct cmdq_deallocate_key req;
519         struct creq_deallocate_key_resp *resp;
520         u16 cmd_flags = 0;
521
522         if (mrw->lkey == 0xFFFFFFFF) {
523                 dev_info(&res->pdev->dev,
524                          "QPLIB: SP: Free a reserved lkey MRW");
525                 return 0;
526         }
527
528         RCFW_CMD_PREP(req, DEALLOCATE_KEY, cmd_flags);
529
530         req.mrw_flags = mrw->type;
531
532         if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1)  ||
533             (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A) ||
534             (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B))
535                 req.key = cpu_to_le32(mrw->rkey);
536         else
537                 req.key = cpu_to_le32(mrw->lkey);
538
539         resp = (struct creq_deallocate_key_resp *)
540                         bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
541                                                      NULL, 0);
542         if (!resp) {
543                 dev_err(&res->pdev->dev, "QPLIB: SP: FREE_MR send failed");
544                 return -EINVAL;
545         }
546         if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
547                 /* Cmd timed out */
548                 dev_err(&res->pdev->dev, "QPLIB: SP: FREE_MR timed out");
549                 return -ETIMEDOUT;
550         }
551         if (resp->status ||
552             le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
553                 dev_err(&res->pdev->dev, "QPLIB: SP: FREE_MR failed ");
554                 dev_err(&res->pdev->dev,
555                         "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
556                         resp->status, le16_to_cpu(req.cookie),
557                         le16_to_cpu(resp->cookie));
558                 return -EINVAL;
559         }
560         /* Free the qplib's MRW memory */
561         if (mrw->hwq.max_elements)
562                 bnxt_qplib_free_hwq(res->pdev, &mrw->hwq);
563
564         return 0;
565 }
566
567 int bnxt_qplib_alloc_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw)
568 {
569         struct bnxt_qplib_rcfw *rcfw = res->rcfw;
570         struct cmdq_allocate_mrw req;
571         struct creq_allocate_mrw_resp *resp;
572         u16 cmd_flags = 0;
573         unsigned long tmp;
574
575         RCFW_CMD_PREP(req, ALLOCATE_MRW, cmd_flags);
576
577         req.pd_id = cpu_to_le32(mrw->pd->id);
578         req.mrw_flags = mrw->type;
579         if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR &&
580              mrw->flags & BNXT_QPLIB_FR_PMR) ||
581             mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A ||
582             mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B)
583                 req.access = CMDQ_ALLOCATE_MRW_ACCESS_CONSUMER_OWNED_KEY;
584         tmp = (unsigned long)mrw;
585         req.mrw_handle = cpu_to_le64(tmp);
586
587         resp = (struct creq_allocate_mrw_resp *)
588                         bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
589                                                      NULL, 0);
590         if (!resp) {
591                 dev_err(&rcfw->pdev->dev, "QPLIB: SP: ALLOC_MRW send failed");
592                 return -EINVAL;
593         }
594         if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
595                 /* Cmd timed out */
596                 dev_err(&rcfw->pdev->dev, "QPLIB: SP: ALLOC_MRW timed out");
597                 return -ETIMEDOUT;
598         }
599         if (resp->status ||
600             le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
601                 dev_err(&rcfw->pdev->dev, "QPLIB: SP: ALLOC_MRW failed ");
602                 dev_err(&rcfw->pdev->dev,
603                         "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
604                         resp->status, le16_to_cpu(req.cookie),
605                         le16_to_cpu(resp->cookie));
606                 return -EINVAL;
607         }
608         if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1)  ||
609             (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A) ||
610             (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B))
611                 mrw->rkey = le32_to_cpu(resp->xid);
612         else
613                 mrw->lkey = le32_to_cpu(resp->xid);
614         return 0;
615 }
616
617 int bnxt_qplib_dereg_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw,
618                          bool block)
619 {
620         struct bnxt_qplib_rcfw *rcfw = res->rcfw;
621         struct cmdq_deregister_mr req;
622         struct creq_deregister_mr_resp *resp;
623         u16 cmd_flags = 0;
624         int rc;
625
626         RCFW_CMD_PREP(req, DEREGISTER_MR, cmd_flags);
627
628         req.lkey = cpu_to_le32(mrw->lkey);
629         resp = (struct creq_deregister_mr_resp *)
630                         bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
631                                                      NULL, block);
632         if (!resp) {
633                 dev_err(&rcfw->pdev->dev, "QPLIB: SP: DEREG_MR send failed");
634                 return -EINVAL;
635         }
636         if (block)
637                 rc = bnxt_qplib_rcfw_block_for_resp(rcfw,
638                                                     le16_to_cpu(req.cookie));
639         else
640                 rc = bnxt_qplib_rcfw_wait_for_resp(rcfw,
641                                                    le16_to_cpu(req.cookie));
642         if (!rc) {
643                 /* Cmd timed out */
644                 dev_err(&res->pdev->dev, "QPLIB: SP: DEREG_MR timed out");
645                 return -ETIMEDOUT;
646         }
647         if (resp->status ||
648             le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
649                 dev_err(&rcfw->pdev->dev, "QPLIB: SP: DEREG_MR failed ");
650                 dev_err(&rcfw->pdev->dev,
651                         "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
652                         resp->status, le16_to_cpu(req.cookie),
653                         le16_to_cpu(resp->cookie));
654                 return -EINVAL;
655         }
656
657         /* Free the qplib's MR memory */
658         if (mrw->hwq.max_elements) {
659                 mrw->va = 0;
660                 mrw->total_size = 0;
661                 bnxt_qplib_free_hwq(res->pdev, &mrw->hwq);
662         }
663
664         return 0;
665 }
666
667 int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr,
668                       u64 *pbl_tbl, int num_pbls, bool block)
669 {
670         struct bnxt_qplib_rcfw *rcfw = res->rcfw;
671         struct cmdq_register_mr req;
672         struct creq_register_mr_resp *resp;
673         u16 cmd_flags = 0, level;
674         int pg_ptrs, pages, i, rc;
675         dma_addr_t **pbl_ptr;
676         u32 pg_size;
677
678         if (num_pbls) {
679                 pg_ptrs = roundup_pow_of_two(num_pbls);
680                 pages = pg_ptrs >> MAX_PBL_LVL_1_PGS_SHIFT;
681                 if (!pages)
682                         pages++;
683
684                 if (pages > MAX_PBL_LVL_1_PGS) {
685                         dev_err(&res->pdev->dev, "QPLIB: SP: Reg MR pages ");
686                         dev_err(&res->pdev->dev,
687                                 "requested (0x%x) exceeded max (0x%x)",
688                                 pages, MAX_PBL_LVL_1_PGS);
689                         return -ENOMEM;
690                 }
691                 /* Free the hwq if it already exist, must be a rereg */
692                 if (mr->hwq.max_elements)
693                         bnxt_qplib_free_hwq(res->pdev, &mr->hwq);
694
695                 mr->hwq.max_elements = pages;
696                 rc = bnxt_qplib_alloc_init_hwq(res->pdev, &mr->hwq, NULL, 0,
697                                                &mr->hwq.max_elements,
698                                                PAGE_SIZE, 0, PAGE_SIZE,
699                                                HWQ_TYPE_CTX);
700                 if (rc) {
701                         dev_err(&res->pdev->dev,
702                                 "SP: Reg MR memory allocation failed");
703                         return -ENOMEM;
704                 }
705                 /* Write to the hwq */
706                 pbl_ptr = (dma_addr_t **)mr->hwq.pbl_ptr;
707                 for (i = 0; i < num_pbls; i++)
708                         pbl_ptr[PTR_PG(i)][PTR_IDX(i)] =
709                                 (pbl_tbl[i] & PAGE_MASK) | PTU_PTE_VALID;
710         }
711
712         RCFW_CMD_PREP(req, REGISTER_MR, cmd_flags);
713
714         /* Configure the request */
715         if (mr->hwq.level == PBL_LVL_MAX) {
716                 level = 0;
717                 req.pbl = 0;
718                 pg_size = PAGE_SIZE;
719         } else {
720                 level = mr->hwq.level + 1;
721                 req.pbl = cpu_to_le64(mr->hwq.pbl[PBL_LVL_0].pg_map_arr[0]);
722                 pg_size = mr->hwq.pbl[PBL_LVL_0].pg_size;
723         }
724         req.log2_pg_size_lvl = (level << CMDQ_REGISTER_MR_LVL_SFT) |
725                                ((ilog2(pg_size) <<
726                                  CMDQ_REGISTER_MR_LOG2_PG_SIZE_SFT) &
727                                 CMDQ_REGISTER_MR_LOG2_PG_SIZE_MASK);
728         req.access = (mr->flags & 0xFFFF);
729         req.va = cpu_to_le64(mr->va);
730         req.key = cpu_to_le32(mr->lkey);
731         req.mr_size = cpu_to_le64(mr->total_size);
732
733         resp = (struct creq_register_mr_resp *)
734                         bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
735                                                      NULL, block);
736         if (!resp) {
737                 dev_err(&res->pdev->dev, "SP: REG_MR send failed");
738                 rc = -EINVAL;
739                 goto fail;
740         }
741         if (block)
742                 rc = bnxt_qplib_rcfw_block_for_resp(rcfw,
743                                                     le16_to_cpu(req.cookie));
744         else
745                 rc = bnxt_qplib_rcfw_wait_for_resp(rcfw,
746                                                    le16_to_cpu(req.cookie));
747         if (!rc) {
748                 /* Cmd timed out */
749                 dev_err(&res->pdev->dev, "SP: REG_MR timed out");
750                 rc = -ETIMEDOUT;
751                 goto fail;
752         }
753         if (resp->status ||
754             le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
755                 dev_err(&res->pdev->dev, "QPLIB: SP: REG_MR failed ");
756                 dev_err(&res->pdev->dev,
757                         "QPLIB: SP: with status 0x%x cmdq 0x%x resp 0x%x",
758                         resp->status, le16_to_cpu(req.cookie),
759                         le16_to_cpu(resp->cookie));
760                 rc = -EINVAL;
761                 goto fail;
762         }
763         return 0;
764
765 fail:
766         if (mr->hwq.max_elements)
767                 bnxt_qplib_free_hwq(res->pdev, &mr->hwq);
768         return rc;
769 }
770
771 int bnxt_qplib_alloc_fast_reg_page_list(struct bnxt_qplib_res *res,
772                                         struct bnxt_qplib_frpl *frpl,
773                                         int max_pg_ptrs)
774 {
775         int pg_ptrs, pages, rc;
776
777         /* Re-calculate the max to fit the HWQ allocation model */
778         pg_ptrs = roundup_pow_of_two(max_pg_ptrs);
779         pages = pg_ptrs >> MAX_PBL_LVL_1_PGS_SHIFT;
780         if (!pages)
781                 pages++;
782
783         if (pages > MAX_PBL_LVL_1_PGS)
784                 return -ENOMEM;
785
786         frpl->hwq.max_elements = pages;
787         rc = bnxt_qplib_alloc_init_hwq(res->pdev, &frpl->hwq, NULL, 0,
788                                        &frpl->hwq.max_elements, PAGE_SIZE, 0,
789                                        PAGE_SIZE, HWQ_TYPE_CTX);
790         if (!rc)
791                 frpl->max_pg_ptrs = pg_ptrs;
792
793         return rc;
794 }
795
796 int bnxt_qplib_free_fast_reg_page_list(struct bnxt_qplib_res *res,
797                                        struct bnxt_qplib_frpl *frpl)
798 {
799         bnxt_qplib_free_hwq(res->pdev, &frpl->hwq);
800         return 0;
801 }
802
803 int bnxt_qplib_map_tc2cos(struct bnxt_qplib_res *res, u16 *cids)
804 {
805         struct bnxt_qplib_rcfw *rcfw = res->rcfw;
806         struct cmdq_map_tc_to_cos req;
807         struct creq_map_tc_to_cos_resp *resp;
808         u16 cmd_flags = 0;
809         int tleft;
810
811         RCFW_CMD_PREP(req, MAP_TC_TO_COS, cmd_flags);
812         req.cos0 = cpu_to_le16(cids[0]);
813         req.cos1 = cpu_to_le16(cids[1]);
814
815         resp = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, NULL, 0);
816         if (!resp) {
817                 dev_err(&res->pdev->dev, "QPLIB: SP: MAP_TC2COS send failed");
818                 return -EINVAL;
819         }
820
821         tleft = bnxt_qplib_rcfw_block_for_resp(rcfw, le16_to_cpu(req.cookie));
822         if (!tleft) {
823                 dev_err(&res->pdev->dev, "QPLIB: SP: MAP_TC2COS timed out");
824                 return -ETIMEDOUT;
825         }
826
827         if (resp->status ||
828             le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
829                 dev_err(&res->pdev->dev, "QPLIB: SP: MAP_TC2COS failed ");
830                 dev_err(&res->pdev->dev,
831                         "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
832                         resp->status, le16_to_cpu(req.cookie),
833                         le16_to_cpu(resp->cookie));
834                 return -EINVAL;
835         }
836
837         return 0;
838 }