1/*-
2 * Copyright (c) 2013-2015, Mellanox Technologies, Ltd.  All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 *
25 * $FreeBSD$
26 */
27
28#include <dev/mlx5/driver.h>
29#include "wq.h"
30#include "mlx5_core.h"
31
32u32 mlx5_wq_cyc_get_size(struct mlx5_wq_cyc *wq)
33{
34	return (u32)wq->sz_m1 + 1;
35}
36
37u32 mlx5_cqwq_get_size(struct mlx5_cqwq *wq)
38{
39	return wq->sz_m1 + 1;
40}
41
42u32 mlx5_wq_ll_get_size(struct mlx5_wq_ll *wq)
43{
44	return (u32)wq->sz_m1 + 1;
45}
46
47static u32 mlx5_wq_cyc_get_byte_size(struct mlx5_wq_cyc *wq)
48{
49	return mlx5_wq_cyc_get_size(wq) << wq->log_stride;
50}
51
52static u32 mlx5_cqwq_get_byte_size(struct mlx5_cqwq *wq)
53{
54	return mlx5_cqwq_get_size(wq) << wq->log_stride;
55}
56
57static u32 mlx5_wq_ll_get_byte_size(struct mlx5_wq_ll *wq)
58{
59	return mlx5_wq_ll_get_size(wq) << wq->log_stride;
60}
61
62int mlx5_wq_cyc_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
63		       void *wqc, struct mlx5_wq_cyc *wq,
64		       struct mlx5_wq_ctrl *wq_ctrl)
65{
66	int max_direct = param->linear ? INT_MAX : 0;
67	int err;
68
69	wq->log_stride = MLX5_GET(wq, wqc, log_wq_stride);
70	wq->sz_m1 = (1 << MLX5_GET(wq, wqc, log_wq_sz)) - 1;
71
72	err = mlx5_db_alloc_node(mdev, &wq_ctrl->db, param->db_numa_node);
73	if (err) {
74		mlx5_core_warn(mdev, "mlx5_db_alloc() failed, %d\n", err);
75		return err;
76	}
77
78	err = mlx5_buf_alloc_node(mdev, mlx5_wq_cyc_get_byte_size(wq),
79				  max_direct, &wq_ctrl->buf,
80				  param->buf_numa_node);
81	if (err) {
82		mlx5_core_warn(mdev, "mlx5_buf_alloc() failed, %d\n", err);
83		goto err_db_free;
84	}
85
86	wq->buf = wq_ctrl->buf.direct.buf;
87	wq->db  = wq_ctrl->db.db;
88
89	wq_ctrl->mdev = mdev;
90
91	return 0;
92
93err_db_free:
94	mlx5_db_free(mdev, &wq_ctrl->db);
95
96	return err;
97}
98
99int mlx5_cqwq_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
100		     void *cqc, struct mlx5_cqwq *wq,
101		     struct mlx5_wq_ctrl *wq_ctrl)
102{
103	int max_direct = param->linear ? INT_MAX : 0;
104	int err;
105
106	wq->log_stride = 6 + MLX5_GET(cqc, cqc, cqe_sz);
107	wq->log_sz = MLX5_GET(cqc, cqc, log_cq_size);
108	wq->sz_m1 = (1 << wq->log_sz) - 1;
109
110	err = mlx5_db_alloc_node(mdev, &wq_ctrl->db, param->db_numa_node);
111	if (err) {
112		mlx5_core_warn(mdev, "mlx5_db_alloc() failed, %d\n", err);
113		return err;
114	}
115
116	err = mlx5_buf_alloc_node(mdev, mlx5_cqwq_get_byte_size(wq),
117				  max_direct, &wq_ctrl->buf,
118				  param->buf_numa_node);
119	if (err) {
120		mlx5_core_warn(mdev, "mlx5_buf_alloc() failed, %d\n", err);
121		goto err_db_free;
122	}
123
124	wq->buf = wq_ctrl->buf.direct.buf;
125	wq->db  = wq_ctrl->db.db;
126
127	wq_ctrl->mdev = mdev;
128
129	return 0;
130
131err_db_free:
132	mlx5_db_free(mdev, &wq_ctrl->db);
133
134	return err;
135}
136
137int mlx5_wq_ll_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
138		      void *wqc, struct mlx5_wq_ll *wq,
139		      struct mlx5_wq_ctrl *wq_ctrl)
140{
141	struct mlx5_wqe_srq_next_seg *next_seg;
142	int max_direct = param->linear ? INT_MAX : 0;
143	int err;
144	int i;
145
146	wq->log_stride = MLX5_GET(wq, wqc, log_wq_stride);
147	wq->sz_m1 = (1 << MLX5_GET(wq, wqc, log_wq_sz)) - 1;
148
149	err = mlx5_db_alloc_node(mdev, &wq_ctrl->db, param->db_numa_node);
150	if (err) {
151		mlx5_core_warn(mdev, "mlx5_db_alloc() failed, %d\n", err);
152		return err;
153	}
154
155	err = mlx5_buf_alloc_node(mdev, mlx5_wq_ll_get_byte_size(wq),
156				  max_direct, &wq_ctrl->buf,
157				  param->buf_numa_node);
158	if (err) {
159		mlx5_core_warn(mdev, "mlx5_buf_alloc() failed, %d\n", err);
160		goto err_db_free;
161	}
162
163	wq->buf = wq_ctrl->buf.direct.buf;
164	wq->db  = wq_ctrl->db.db;
165
166	for (i = 0; i < wq->sz_m1; i++) {
167		next_seg = mlx5_wq_ll_get_wqe(wq, i);
168		next_seg->next_wqe_index = cpu_to_be16(i + 1);
169	}
170	next_seg = mlx5_wq_ll_get_wqe(wq, i);
171	wq->tail_next = &next_seg->next_wqe_index;
172
173	wq_ctrl->mdev = mdev;
174
175	return 0;
176
177err_db_free:
178	mlx5_db_free(mdev, &wq_ctrl->db);
179
180	return err;
181}
182
183void mlx5_wq_destroy(struct mlx5_wq_ctrl *wq_ctrl)
184{
185	mlx5_buf_free(wq_ctrl->mdev, &wq_ctrl->buf);
186	mlx5_db_free(wq_ctrl->mdev, &wq_ctrl->db);
187}
188