1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2 /* QLogic qed NIC Driver
3 * Copyright (c) 2015-2017 QLogic Corporation
4 * Copyright (c) 2019-2020 Marvell International Ltd.
7 #include <linux/types.h>
8 #include <linux/dma-mapping.h>
9 #include <linux/kernel.h>
10 #include <linux/list.h>
11 #include <linux/pci.h>
12 #include <linux/slab.h>
13 #include <linux/string.h>
15 #include "qed_iscsi.h"
19 #include "qed_nvmetcp.h"
20 static struct qed_ooo_archipelago
21 *qed_ooo_seek_archipelago(struct qed_hwfn
*p_hwfn
,
26 u32 idx
= (cid
& 0xffff) - p_ooo_info
->cid_base
;
27 struct qed_ooo_archipelago
*p_archipelago
;
29 if (unlikely(idx
>= p_ooo_info
->max_num_archipelagos
))
32 p_archipelago
= &p_ooo_info
->p_archipelagos_mem
[idx
];
34 if (unlikely(list_empty(&p_archipelago
->isles_list
)))
40 static struct qed_ooo_isle
*qed_ooo_seek_isle(struct qed_hwfn
*p_hwfn
,
41 struct qed_ooo_info
*p_ooo_info
,
44 struct qed_ooo_archipelago
*p_archipelago
= NULL
;
45 struct qed_ooo_isle
*p_isle
= NULL
;
46 u8 the_num_of_isle
= 1;
48 p_archipelago
= qed_ooo_seek_archipelago(p_hwfn
, p_ooo_info
, cid
);
49 if (unlikely(!p_archipelago
)) {
51 "Connection %d is not found in OOO list\n", cid
);
55 list_for_each_entry(p_isle
, &p_archipelago
->isles_list
, list_entry
) {
56 if (the_num_of_isle
== isle
)
64 void qed_ooo_save_history_entry(struct qed_hwfn
*p_hwfn
,
65 struct qed_ooo_info
*p_ooo_info
,
66 struct ooo_opaque
*p_cqe
)
68 struct qed_ooo_history
*p_history
= &p_ooo_info
->ooo_history
;
70 if (p_history
->head_idx
== p_history
->num_of_cqes
)
71 p_history
->head_idx
= 0;
72 p_history
->p_cqes
[p_history
->head_idx
] = *p_cqe
;
73 p_history
->head_idx
++;
76 int qed_ooo_alloc(struct qed_hwfn
*p_hwfn
)
78 u16 max_num_archipelagos
= 0, cid_base
;
79 struct qed_ooo_info
*p_ooo_info
;
80 enum protocol_type proto
;
81 u16 max_num_isles
= 0;
84 switch (p_hwfn
->hw_info
.personality
) {
87 proto
= PROTOCOLID_TCP_ULP
;
89 case QED_PCI_ETH_RDMA
:
90 case QED_PCI_ETH_IWARP
:
91 proto
= PROTOCOLID_IWARP
;
95 "Failed to allocate qed_ooo_info: unknown personality\n");
99 max_num_archipelagos
= (u16
)qed_cxt_get_proto_cid_count(p_hwfn
, proto
,
101 max_num_isles
= QED_MAX_NUM_ISLES
+ max_num_archipelagos
;
102 cid_base
= (u16
)qed_cxt_get_proto_cid_start(p_hwfn
, proto
);
104 if (!max_num_archipelagos
) {
106 "Failed to allocate qed_ooo_info: unknown amount of connections\n");
110 p_ooo_info
= kzalloc(sizeof(*p_ooo_info
), GFP_KERNEL
);
114 p_ooo_info
->cid_base
= cid_base
;
115 p_ooo_info
->max_num_archipelagos
= max_num_archipelagos
;
117 INIT_LIST_HEAD(&p_ooo_info
->free_buffers_list
);
118 INIT_LIST_HEAD(&p_ooo_info
->ready_buffers_list
);
119 INIT_LIST_HEAD(&p_ooo_info
->free_isles_list
);
121 p_ooo_info
->p_isles_mem
= kcalloc(max_num_isles
,
122 sizeof(struct qed_ooo_isle
),
124 if (!p_ooo_info
->p_isles_mem
)
127 for (i
= 0; i
< max_num_isles
; i
++) {
128 INIT_LIST_HEAD(&p_ooo_info
->p_isles_mem
[i
].buffers_list
);
129 list_add_tail(&p_ooo_info
->p_isles_mem
[i
].list_entry
,
130 &p_ooo_info
->free_isles_list
);
133 p_ooo_info
->p_archipelagos_mem
=
134 kcalloc(max_num_archipelagos
,
135 sizeof(struct qed_ooo_archipelago
),
137 if (!p_ooo_info
->p_archipelagos_mem
)
138 goto no_archipelagos_mem
;
140 for (i
= 0; i
< max_num_archipelagos
; i
++)
141 INIT_LIST_HEAD(&p_ooo_info
->p_archipelagos_mem
[i
].isles_list
);
143 p_ooo_info
->ooo_history
.p_cqes
=
144 kcalloc(QED_MAX_NUM_OOO_HISTORY_ENTRIES
,
145 sizeof(struct ooo_opaque
),
147 if (!p_ooo_info
->ooo_history
.p_cqes
)
150 p_ooo_info
->ooo_history
.num_of_cqes
= QED_MAX_NUM_OOO_HISTORY_ENTRIES
;
152 p_hwfn
->p_ooo_info
= p_ooo_info
;
156 kfree(p_ooo_info
->p_archipelagos_mem
);
158 kfree(p_ooo_info
->p_isles_mem
);
164 void qed_ooo_release_connection_isles(struct qed_hwfn
*p_hwfn
,
165 struct qed_ooo_info
*p_ooo_info
, u32 cid
)
167 struct qed_ooo_archipelago
*p_archipelago
;
168 struct qed_ooo_buffer
*p_buffer
;
169 struct qed_ooo_isle
*p_isle
;
171 p_archipelago
= qed_ooo_seek_archipelago(p_hwfn
, p_ooo_info
, cid
);
175 while (!list_empty(&p_archipelago
->isles_list
)) {
176 p_isle
= list_first_entry(&p_archipelago
->isles_list
,
177 struct qed_ooo_isle
, list_entry
);
179 list_del(&p_isle
->list_entry
);
181 while (!list_empty(&p_isle
->buffers_list
)) {
182 p_buffer
= list_first_entry(&p_isle
->buffers_list
,
183 struct qed_ooo_buffer
,
189 list_move_tail(&p_buffer
->list_entry
,
190 &p_ooo_info
->free_buffers_list
);
192 list_add_tail(&p_isle
->list_entry
,
193 &p_ooo_info
->free_isles_list
);
197 void qed_ooo_release_all_isles(struct qed_hwfn
*p_hwfn
,
198 struct qed_ooo_info
*p_ooo_info
)
200 struct qed_ooo_archipelago
*p_archipelago
;
201 struct qed_ooo_buffer
*p_buffer
;
202 struct qed_ooo_isle
*p_isle
;
205 for (i
= 0; i
< p_ooo_info
->max_num_archipelagos
; i
++) {
206 p_archipelago
= &(p_ooo_info
->p_archipelagos_mem
[i
]);
208 while (!list_empty(&p_archipelago
->isles_list
)) {
209 p_isle
= list_first_entry(&p_archipelago
->isles_list
,
213 list_del(&p_isle
->list_entry
);
215 while (!list_empty(&p_isle
->buffers_list
)) {
217 list_first_entry(&p_isle
->buffers_list
,
218 struct qed_ooo_buffer
,
224 list_move_tail(&p_buffer
->list_entry
,
225 &p_ooo_info
->free_buffers_list
);
227 list_add_tail(&p_isle
->list_entry
,
228 &p_ooo_info
->free_isles_list
);
231 if (!list_empty(&p_ooo_info
->ready_buffers_list
))
232 list_splice_tail_init(&p_ooo_info
->ready_buffers_list
,
233 &p_ooo_info
->free_buffers_list
);
236 void qed_ooo_setup(struct qed_hwfn
*p_hwfn
)
238 qed_ooo_release_all_isles(p_hwfn
, p_hwfn
->p_ooo_info
);
239 memset(p_hwfn
->p_ooo_info
->ooo_history
.p_cqes
, 0,
240 p_hwfn
->p_ooo_info
->ooo_history
.num_of_cqes
*
241 sizeof(struct ooo_opaque
));
242 p_hwfn
->p_ooo_info
->ooo_history
.head_idx
= 0;
245 void qed_ooo_free(struct qed_hwfn
*p_hwfn
)
247 struct qed_ooo_info
*p_ooo_info
= p_hwfn
->p_ooo_info
;
248 struct qed_ooo_buffer
*p_buffer
;
253 qed_ooo_release_all_isles(p_hwfn
, p_ooo_info
);
254 while (!list_empty(&p_ooo_info
->free_buffers_list
)) {
255 p_buffer
= list_first_entry(&p_ooo_info
->free_buffers_list
,
256 struct qed_ooo_buffer
, list_entry
);
261 list_del(&p_buffer
->list_entry
);
262 dma_free_coherent(&p_hwfn
->cdev
->pdev
->dev
,
263 p_buffer
->rx_buffer_size
,
264 p_buffer
->rx_buffer_virt_addr
,
265 p_buffer
->rx_buffer_phys_addr
);
269 kfree(p_ooo_info
->p_isles_mem
);
270 kfree(p_ooo_info
->p_archipelagos_mem
);
271 kfree(p_ooo_info
->ooo_history
.p_cqes
);
273 p_hwfn
->p_ooo_info
= NULL
;
276 void qed_ooo_put_free_buffer(struct qed_hwfn
*p_hwfn
,
277 struct qed_ooo_info
*p_ooo_info
,
278 struct qed_ooo_buffer
*p_buffer
)
280 list_add_tail(&p_buffer
->list_entry
, &p_ooo_info
->free_buffers_list
);
283 struct qed_ooo_buffer
*qed_ooo_get_free_buffer(struct qed_hwfn
*p_hwfn
,
284 struct qed_ooo_info
*p_ooo_info
)
286 struct qed_ooo_buffer
*p_buffer
= NULL
;
288 if (!list_empty(&p_ooo_info
->free_buffers_list
)) {
289 p_buffer
= list_first_entry(&p_ooo_info
->free_buffers_list
,
290 struct qed_ooo_buffer
, list_entry
);
292 list_del(&p_buffer
->list_entry
);
298 void qed_ooo_put_ready_buffer(struct qed_hwfn
*p_hwfn
,
299 struct qed_ooo_info
*p_ooo_info
,
300 struct qed_ooo_buffer
*p_buffer
, u8 on_tail
)
303 list_add_tail(&p_buffer
->list_entry
,
304 &p_ooo_info
->ready_buffers_list
);
306 list_add(&p_buffer
->list_entry
,
307 &p_ooo_info
->ready_buffers_list
);
310 struct qed_ooo_buffer
*qed_ooo_get_ready_buffer(struct qed_hwfn
*p_hwfn
,
311 struct qed_ooo_info
*p_ooo_info
)
313 struct qed_ooo_buffer
*p_buffer
= NULL
;
315 if (!list_empty(&p_ooo_info
->ready_buffers_list
)) {
316 p_buffer
= list_first_entry(&p_ooo_info
->ready_buffers_list
,
317 struct qed_ooo_buffer
, list_entry
);
319 list_del(&p_buffer
->list_entry
);
325 void qed_ooo_delete_isles(struct qed_hwfn
*p_hwfn
,
326 struct qed_ooo_info
*p_ooo_info
,
327 u32 cid
, u8 drop_isle
, u8 drop_size
)
329 struct qed_ooo_isle
*p_isle
= NULL
;
332 for (isle_idx
= 0; isle_idx
< drop_size
; isle_idx
++) {
333 p_isle
= qed_ooo_seek_isle(p_hwfn
, p_ooo_info
, cid
, drop_isle
);
336 "Isle %d is not found(cid %d)\n",
340 if (list_empty(&p_isle
->buffers_list
))
342 "Isle %d is empty(cid %d)\n", drop_isle
, cid
);
344 list_splice_tail_init(&p_isle
->buffers_list
,
345 &p_ooo_info
->free_buffers_list
);
347 list_del(&p_isle
->list_entry
);
348 p_ooo_info
->cur_isles_number
--;
349 list_add(&p_isle
->list_entry
, &p_ooo_info
->free_isles_list
);
353 void qed_ooo_add_new_isle(struct qed_hwfn
*p_hwfn
,
354 struct qed_ooo_info
*p_ooo_info
,
355 u32 cid
, u8 ooo_isle
,
356 struct qed_ooo_buffer
*p_buffer
)
358 struct qed_ooo_archipelago
*p_archipelago
= NULL
;
359 struct qed_ooo_isle
*p_prev_isle
= NULL
;
360 struct qed_ooo_isle
*p_isle
= NULL
;
363 p_prev_isle
= qed_ooo_seek_isle(p_hwfn
,
364 p_ooo_info
, cid
, ooo_isle
- 1);
365 if (unlikely(!p_prev_isle
)) {
367 "Isle %d is not found(cid %d)\n",
372 p_archipelago
= qed_ooo_seek_archipelago(p_hwfn
, p_ooo_info
, cid
);
373 if (unlikely(!p_archipelago
&& ooo_isle
!= 1)) {
375 "Connection %d is not found in OOO list\n", cid
);
379 if (!list_empty(&p_ooo_info
->free_isles_list
)) {
380 p_isle
= list_first_entry(&p_ooo_info
->free_isles_list
,
381 struct qed_ooo_isle
, list_entry
);
383 list_del(&p_isle
->list_entry
);
384 if (unlikely(!list_empty(&p_isle
->buffers_list
))) {
385 DP_NOTICE(p_hwfn
, "Free isle is not empty\n");
386 INIT_LIST_HEAD(&p_isle
->buffers_list
);
389 DP_NOTICE(p_hwfn
, "No more free isles\n");
393 if (!p_archipelago
) {
394 u32 idx
= (cid
& 0xffff) - p_ooo_info
->cid_base
;
396 p_archipelago
= &p_ooo_info
->p_archipelagos_mem
[idx
];
399 list_add(&p_buffer
->list_entry
, &p_isle
->buffers_list
);
400 p_ooo_info
->cur_isles_number
++;
401 p_ooo_info
->gen_isles_number
++;
403 if (p_ooo_info
->cur_isles_number
> p_ooo_info
->max_isles_number
)
404 p_ooo_info
->max_isles_number
= p_ooo_info
->cur_isles_number
;
407 list_add(&p_isle
->list_entry
, &p_archipelago
->isles_list
);
409 list_add(&p_isle
->list_entry
, &p_prev_isle
->list_entry
);
412 void qed_ooo_add_new_buffer(struct qed_hwfn
*p_hwfn
,
413 struct qed_ooo_info
*p_ooo_info
,
416 struct qed_ooo_buffer
*p_buffer
, u8 buffer_side
)
418 struct qed_ooo_isle
*p_isle
= NULL
;
420 p_isle
= qed_ooo_seek_isle(p_hwfn
, p_ooo_info
, cid
, ooo_isle
);
421 if (unlikely(!p_isle
)) {
423 "Isle %d is not found(cid %d)\n", ooo_isle
, cid
);
427 if (unlikely(buffer_side
== QED_OOO_LEFT_BUF
))
428 list_add(&p_buffer
->list_entry
, &p_isle
->buffers_list
);
430 list_add_tail(&p_buffer
->list_entry
, &p_isle
->buffers_list
);
433 void qed_ooo_join_isles(struct qed_hwfn
*p_hwfn
,
434 struct qed_ooo_info
*p_ooo_info
, u32 cid
, u8 left_isle
)
436 struct qed_ooo_isle
*p_right_isle
= NULL
;
437 struct qed_ooo_isle
*p_left_isle
= NULL
;
439 p_right_isle
= qed_ooo_seek_isle(p_hwfn
, p_ooo_info
, cid
,
441 if (unlikely(!p_right_isle
)) {
443 "Right isle %d is not found(cid %d)\n",
448 list_del(&p_right_isle
->list_entry
);
449 p_ooo_info
->cur_isles_number
--;
451 p_left_isle
= qed_ooo_seek_isle(p_hwfn
, p_ooo_info
, cid
,
453 if (unlikely(!p_left_isle
)) {
455 "Left isle %d is not found(cid %d)\n",
459 list_splice_tail_init(&p_right_isle
->buffers_list
,
460 &p_left_isle
->buffers_list
);
462 list_splice_tail_init(&p_right_isle
->buffers_list
,
463 &p_ooo_info
->ready_buffers_list
);
465 list_add_tail(&p_right_isle
->list_entry
, &p_ooo_info
->free_isles_list
);