1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2 /* QLogic qed NIC Driver
3 * Copyright (c) 2015-2017 QLogic Corporation
6 #include <linux/types.h>
7 #include <linux/dma-mapping.h>
8 #include <linux/kernel.h>
9 #include <linux/list.h>
10 #include <linux/pci.h>
11 #include <linux/slab.h>
12 #include <linux/string.h>
14 #include "qed_iscsi.h"
19 static struct qed_ooo_archipelago
20 *qed_ooo_seek_archipelago(struct qed_hwfn *p_hwfn,
25 u32 idx = (cid & 0xffff) - p_ooo_info->cid_base;
26 struct qed_ooo_archipelago *p_archipelago;
28 if (idx >= p_ooo_info->max_num_archipelagos)
31 p_archipelago = &p_ooo_info->p_archipelagos_mem[idx];
33 if (list_empty(&p_archipelago->isles_list))
39 static struct qed_ooo_isle *qed_ooo_seek_isle(struct qed_hwfn *p_hwfn,
40 struct qed_ooo_info *p_ooo_info,
43 struct qed_ooo_archipelago *p_archipelago = NULL;
44 struct qed_ooo_isle *p_isle = NULL;
45 u8 the_num_of_isle = 1;
47 p_archipelago = qed_ooo_seek_archipelago(p_hwfn, p_ooo_info, cid);
50 "Connection %d is not found in OOO list\n", cid);
54 list_for_each_entry(p_isle, &p_archipelago->isles_list, list_entry) {
55 if (the_num_of_isle == isle)
63 void qed_ooo_save_history_entry(struct qed_hwfn *p_hwfn,
64 struct qed_ooo_info *p_ooo_info,
65 struct ooo_opaque *p_cqe)
67 struct qed_ooo_history *p_history = &p_ooo_info->ooo_history;
69 if (p_history->head_idx == p_history->num_of_cqes)
70 p_history->head_idx = 0;
71 p_history->p_cqes[p_history->head_idx] = *p_cqe;
72 p_history->head_idx++;
75 int qed_ooo_alloc(struct qed_hwfn *p_hwfn)
77 u16 max_num_archipelagos = 0, cid_base;
78 struct qed_ooo_info *p_ooo_info;
79 enum protocol_type proto;
80 u16 max_num_isles = 0;
83 switch (p_hwfn->hw_info.personality) {
85 proto = PROTOCOLID_ISCSI;
87 case QED_PCI_ETH_RDMA:
88 case QED_PCI_ETH_IWARP:
89 proto = PROTOCOLID_IWARP;
93 "Failed to allocate qed_ooo_info: unknown personality\n");
97 max_num_archipelagos = (u16)qed_cxt_get_proto_cid_count(p_hwfn, proto,
99 max_num_isles = QED_MAX_NUM_ISLES + max_num_archipelagos;
100 cid_base = (u16)qed_cxt_get_proto_cid_start(p_hwfn, proto);
102 if (!max_num_archipelagos) {
104 "Failed to allocate qed_ooo_info: unknown amount of connections\n");
108 p_ooo_info = kzalloc(sizeof(*p_ooo_info), GFP_KERNEL);
112 p_ooo_info->cid_base = cid_base;
113 p_ooo_info->max_num_archipelagos = max_num_archipelagos;
115 INIT_LIST_HEAD(&p_ooo_info->free_buffers_list);
116 INIT_LIST_HEAD(&p_ooo_info->ready_buffers_list);
117 INIT_LIST_HEAD(&p_ooo_info->free_isles_list);
119 p_ooo_info->p_isles_mem = kcalloc(max_num_isles,
120 sizeof(struct qed_ooo_isle),
122 if (!p_ooo_info->p_isles_mem)
125 for (i = 0; i < max_num_isles; i++) {
126 INIT_LIST_HEAD(&p_ooo_info->p_isles_mem[i].buffers_list);
127 list_add_tail(&p_ooo_info->p_isles_mem[i].list_entry,
128 &p_ooo_info->free_isles_list);
131 p_ooo_info->p_archipelagos_mem =
132 kcalloc(max_num_archipelagos,
133 sizeof(struct qed_ooo_archipelago),
135 if (!p_ooo_info->p_archipelagos_mem)
136 goto no_archipelagos_mem;
138 for (i = 0; i < max_num_archipelagos; i++)
139 INIT_LIST_HEAD(&p_ooo_info->p_archipelagos_mem[i].isles_list);
141 p_ooo_info->ooo_history.p_cqes =
142 kcalloc(QED_MAX_NUM_OOO_HISTORY_ENTRIES,
143 sizeof(struct ooo_opaque),
145 if (!p_ooo_info->ooo_history.p_cqes)
148 p_ooo_info->ooo_history.num_of_cqes = QED_MAX_NUM_OOO_HISTORY_ENTRIES;
150 p_hwfn->p_ooo_info = p_ooo_info;
154 kfree(p_ooo_info->p_archipelagos_mem);
156 kfree(p_ooo_info->p_isles_mem);
162 void qed_ooo_release_connection_isles(struct qed_hwfn *p_hwfn,
163 struct qed_ooo_info *p_ooo_info, u32 cid)
165 struct qed_ooo_archipelago *p_archipelago;
166 struct qed_ooo_buffer *p_buffer;
167 struct qed_ooo_isle *p_isle;
169 p_archipelago = qed_ooo_seek_archipelago(p_hwfn, p_ooo_info, cid);
173 while (!list_empty(&p_archipelago->isles_list)) {
174 p_isle = list_first_entry(&p_archipelago->isles_list,
175 struct qed_ooo_isle, list_entry);
177 list_del(&p_isle->list_entry);
179 while (!list_empty(&p_isle->buffers_list)) {
180 p_buffer = list_first_entry(&p_isle->buffers_list,
181 struct qed_ooo_buffer,
187 list_move_tail(&p_buffer->list_entry,
188 &p_ooo_info->free_buffers_list);
190 list_add_tail(&p_isle->list_entry,
191 &p_ooo_info->free_isles_list);
195 void qed_ooo_release_all_isles(struct qed_hwfn *p_hwfn,
196 struct qed_ooo_info *p_ooo_info)
198 struct qed_ooo_archipelago *p_archipelago;
199 struct qed_ooo_buffer *p_buffer;
200 struct qed_ooo_isle *p_isle;
203 for (i = 0; i < p_ooo_info->max_num_archipelagos; i++) {
204 p_archipelago = &(p_ooo_info->p_archipelagos_mem[i]);
206 while (!list_empty(&p_archipelago->isles_list)) {
207 p_isle = list_first_entry(&p_archipelago->isles_list,
211 list_del(&p_isle->list_entry);
213 while (!list_empty(&p_isle->buffers_list)) {
215 list_first_entry(&p_isle->buffers_list,
216 struct qed_ooo_buffer,
222 list_move_tail(&p_buffer->list_entry,
223 &p_ooo_info->free_buffers_list);
225 list_add_tail(&p_isle->list_entry,
226 &p_ooo_info->free_isles_list);
229 if (!list_empty(&p_ooo_info->ready_buffers_list))
230 list_splice_tail_init(&p_ooo_info->ready_buffers_list,
231 &p_ooo_info->free_buffers_list);
234 void qed_ooo_setup(struct qed_hwfn *p_hwfn)
236 qed_ooo_release_all_isles(p_hwfn, p_hwfn->p_ooo_info);
237 memset(p_hwfn->p_ooo_info->ooo_history.p_cqes, 0,
238 p_hwfn->p_ooo_info->ooo_history.num_of_cqes *
239 sizeof(struct ooo_opaque));
240 p_hwfn->p_ooo_info->ooo_history.head_idx = 0;
243 void qed_ooo_free(struct qed_hwfn *p_hwfn)
245 struct qed_ooo_info *p_ooo_info = p_hwfn->p_ooo_info;
246 struct qed_ooo_buffer *p_buffer;
251 qed_ooo_release_all_isles(p_hwfn, p_ooo_info);
252 while (!list_empty(&p_ooo_info->free_buffers_list)) {
253 p_buffer = list_first_entry(&p_ooo_info->free_buffers_list,
254 struct qed_ooo_buffer, list_entry);
259 list_del(&p_buffer->list_entry);
260 dma_free_coherent(&p_hwfn->cdev->pdev->dev,
261 p_buffer->rx_buffer_size,
262 p_buffer->rx_buffer_virt_addr,
263 p_buffer->rx_buffer_phys_addr);
267 kfree(p_ooo_info->p_isles_mem);
268 kfree(p_ooo_info->p_archipelagos_mem);
269 kfree(p_ooo_info->ooo_history.p_cqes);
271 p_hwfn->p_ooo_info = NULL;
274 void qed_ooo_put_free_buffer(struct qed_hwfn *p_hwfn,
275 struct qed_ooo_info *p_ooo_info,
276 struct qed_ooo_buffer *p_buffer)
278 list_add_tail(&p_buffer->list_entry, &p_ooo_info->free_buffers_list);
281 struct qed_ooo_buffer *qed_ooo_get_free_buffer(struct qed_hwfn *p_hwfn,
282 struct qed_ooo_info *p_ooo_info)
284 struct qed_ooo_buffer *p_buffer = NULL;
286 if (!list_empty(&p_ooo_info->free_buffers_list)) {
287 p_buffer = list_first_entry(&p_ooo_info->free_buffers_list,
288 struct qed_ooo_buffer, list_entry);
290 list_del(&p_buffer->list_entry);
296 void qed_ooo_put_ready_buffer(struct qed_hwfn *p_hwfn,
297 struct qed_ooo_info *p_ooo_info,
298 struct qed_ooo_buffer *p_buffer, u8 on_tail)
301 list_add_tail(&p_buffer->list_entry,
302 &p_ooo_info->ready_buffers_list);
304 list_add(&p_buffer->list_entry,
305 &p_ooo_info->ready_buffers_list);
308 struct qed_ooo_buffer *qed_ooo_get_ready_buffer(struct qed_hwfn *p_hwfn,
309 struct qed_ooo_info *p_ooo_info)
311 struct qed_ooo_buffer *p_buffer = NULL;
313 if (!list_empty(&p_ooo_info->ready_buffers_list)) {
314 p_buffer = list_first_entry(&p_ooo_info->ready_buffers_list,
315 struct qed_ooo_buffer, list_entry);
317 list_del(&p_buffer->list_entry);
323 void qed_ooo_delete_isles(struct qed_hwfn *p_hwfn,
324 struct qed_ooo_info *p_ooo_info,
325 u32 cid, u8 drop_isle, u8 drop_size)
327 struct qed_ooo_isle *p_isle = NULL;
330 for (isle_idx = 0; isle_idx < drop_size; isle_idx++) {
331 p_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid, drop_isle);
334 "Isle %d is not found(cid %d)\n",
338 if (list_empty(&p_isle->buffers_list))
340 "Isle %d is empty(cid %d)\n", drop_isle, cid);
342 list_splice_tail_init(&p_isle->buffers_list,
343 &p_ooo_info->free_buffers_list);
345 list_del(&p_isle->list_entry);
346 p_ooo_info->cur_isles_number--;
347 list_add(&p_isle->list_entry, &p_ooo_info->free_isles_list);
351 void qed_ooo_add_new_isle(struct qed_hwfn *p_hwfn,
352 struct qed_ooo_info *p_ooo_info,
353 u32 cid, u8 ooo_isle,
354 struct qed_ooo_buffer *p_buffer)
356 struct qed_ooo_archipelago *p_archipelago = NULL;
357 struct qed_ooo_isle *p_prev_isle = NULL;
358 struct qed_ooo_isle *p_isle = NULL;
361 p_prev_isle = qed_ooo_seek_isle(p_hwfn,
362 p_ooo_info, cid, ooo_isle - 1);
365 "Isle %d is not found(cid %d)\n",
370 p_archipelago = qed_ooo_seek_archipelago(p_hwfn, p_ooo_info, cid);
371 if (!p_archipelago && (ooo_isle != 1)) {
373 "Connection %d is not found in OOO list\n", cid);
377 if (!list_empty(&p_ooo_info->free_isles_list)) {
378 p_isle = list_first_entry(&p_ooo_info->free_isles_list,
379 struct qed_ooo_isle, list_entry);
381 list_del(&p_isle->list_entry);
382 if (!list_empty(&p_isle->buffers_list)) {
383 DP_NOTICE(p_hwfn, "Free isle is not empty\n");
384 INIT_LIST_HEAD(&p_isle->buffers_list);
387 DP_NOTICE(p_hwfn, "No more free isles\n");
391 if (!p_archipelago) {
392 u32 idx = (cid & 0xffff) - p_ooo_info->cid_base;
394 p_archipelago = &p_ooo_info->p_archipelagos_mem[idx];
397 list_add(&p_buffer->list_entry, &p_isle->buffers_list);
398 p_ooo_info->cur_isles_number++;
399 p_ooo_info->gen_isles_number++;
401 if (p_ooo_info->cur_isles_number > p_ooo_info->max_isles_number)
402 p_ooo_info->max_isles_number = p_ooo_info->cur_isles_number;
405 list_add(&p_isle->list_entry, &p_archipelago->isles_list);
407 list_add(&p_isle->list_entry, &p_prev_isle->list_entry);
410 void qed_ooo_add_new_buffer(struct qed_hwfn *p_hwfn,
411 struct qed_ooo_info *p_ooo_info,
414 struct qed_ooo_buffer *p_buffer, u8 buffer_side)
416 struct qed_ooo_isle *p_isle = NULL;
418 p_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid, ooo_isle);
421 "Isle %d is not found(cid %d)\n", ooo_isle, cid);
425 if (buffer_side == QED_OOO_LEFT_BUF)
426 list_add(&p_buffer->list_entry, &p_isle->buffers_list);
428 list_add_tail(&p_buffer->list_entry, &p_isle->buffers_list);
431 void qed_ooo_join_isles(struct qed_hwfn *p_hwfn,
432 struct qed_ooo_info *p_ooo_info, u32 cid, u8 left_isle)
434 struct qed_ooo_isle *p_right_isle = NULL;
435 struct qed_ooo_isle *p_left_isle = NULL;
437 p_right_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid,
441 "Right isle %d is not found(cid %d)\n",
446 list_del(&p_right_isle->list_entry);
447 p_ooo_info->cur_isles_number--;
449 p_left_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid,
453 "Left isle %d is not found(cid %d)\n",
457 list_splice_tail_init(&p_right_isle->buffers_list,
458 &p_left_isle->buffers_list);
460 list_splice_tail_init(&p_right_isle->buffers_list,
461 &p_ooo_info->ready_buffers_list);
463 list_add_tail(&p_right_isle->list_entry, &p_ooo_info->free_isles_list);