xref: /linux/drivers/net/ethernet/qlogic/qed/qed_ooo.c (revision 1d6cff4fca4366d0529dbce170e0f33cfe213790)
1*1d6cff4fSYuval Mintz /* QLogic qed NIC Driver
2*1d6cff4fSYuval Mintz  * Copyright (c) 2015 QLogic Corporation
3*1d6cff4fSYuval Mintz  *
4*1d6cff4fSYuval Mintz  * This software is available under the terms of the GNU General Public License
5*1d6cff4fSYuval Mintz  * (GPL) Version 2, available from the file COPYING in the main directory of
6*1d6cff4fSYuval Mintz  * this source tree.
7*1d6cff4fSYuval Mintz  */
8*1d6cff4fSYuval Mintz 
9*1d6cff4fSYuval Mintz #include <linux/types.h>
10*1d6cff4fSYuval Mintz #include <linux/dma-mapping.h>
11*1d6cff4fSYuval Mintz #include <linux/kernel.h>
12*1d6cff4fSYuval Mintz #include <linux/list.h>
13*1d6cff4fSYuval Mintz #include <linux/pci.h>
14*1d6cff4fSYuval Mintz #include <linux/slab.h>
15*1d6cff4fSYuval Mintz #include <linux/string.h>
16*1d6cff4fSYuval Mintz #include "qed.h"
17*1d6cff4fSYuval Mintz #include "qed_iscsi.h"
18*1d6cff4fSYuval Mintz #include "qed_ll2.h"
19*1d6cff4fSYuval Mintz #include "qed_ooo.h"
20*1d6cff4fSYuval Mintz 
21*1d6cff4fSYuval Mintz static struct qed_ooo_archipelago
22*1d6cff4fSYuval Mintz *qed_ooo_seek_archipelago(struct qed_hwfn *p_hwfn,
23*1d6cff4fSYuval Mintz 			  struct qed_ooo_info
24*1d6cff4fSYuval Mintz 			  *p_ooo_info,
25*1d6cff4fSYuval Mintz 			  u32 cid)
26*1d6cff4fSYuval Mintz {
27*1d6cff4fSYuval Mintz 	struct qed_ooo_archipelago *p_archipelago = NULL;
28*1d6cff4fSYuval Mintz 
29*1d6cff4fSYuval Mintz 	list_for_each_entry(p_archipelago,
30*1d6cff4fSYuval Mintz 			    &p_ooo_info->archipelagos_list, list_entry) {
31*1d6cff4fSYuval Mintz 		if (p_archipelago->cid == cid)
32*1d6cff4fSYuval Mintz 			return p_archipelago;
33*1d6cff4fSYuval Mintz 	}
34*1d6cff4fSYuval Mintz 
35*1d6cff4fSYuval Mintz 	return NULL;
36*1d6cff4fSYuval Mintz }
37*1d6cff4fSYuval Mintz 
38*1d6cff4fSYuval Mintz static struct qed_ooo_isle *qed_ooo_seek_isle(struct qed_hwfn *p_hwfn,
39*1d6cff4fSYuval Mintz 					      struct qed_ooo_info *p_ooo_info,
40*1d6cff4fSYuval Mintz 					      u32 cid, u8 isle)
41*1d6cff4fSYuval Mintz {
42*1d6cff4fSYuval Mintz 	struct qed_ooo_archipelago *p_archipelago = NULL;
43*1d6cff4fSYuval Mintz 	struct qed_ooo_isle *p_isle = NULL;
44*1d6cff4fSYuval Mintz 	u8 the_num_of_isle = 1;
45*1d6cff4fSYuval Mintz 
46*1d6cff4fSYuval Mintz 	p_archipelago = qed_ooo_seek_archipelago(p_hwfn, p_ooo_info, cid);
47*1d6cff4fSYuval Mintz 	if (!p_archipelago) {
48*1d6cff4fSYuval Mintz 		DP_NOTICE(p_hwfn,
49*1d6cff4fSYuval Mintz 			  "Connection %d is not found in OOO list\n", cid);
50*1d6cff4fSYuval Mintz 		return NULL;
51*1d6cff4fSYuval Mintz 	}
52*1d6cff4fSYuval Mintz 
53*1d6cff4fSYuval Mintz 	list_for_each_entry(p_isle, &p_archipelago->isles_list, list_entry) {
54*1d6cff4fSYuval Mintz 		if (the_num_of_isle == isle)
55*1d6cff4fSYuval Mintz 			return p_isle;
56*1d6cff4fSYuval Mintz 		the_num_of_isle++;
57*1d6cff4fSYuval Mintz 	}
58*1d6cff4fSYuval Mintz 
59*1d6cff4fSYuval Mintz 	return NULL;
60*1d6cff4fSYuval Mintz }
61*1d6cff4fSYuval Mintz 
62*1d6cff4fSYuval Mintz void qed_ooo_save_history_entry(struct qed_hwfn *p_hwfn,
63*1d6cff4fSYuval Mintz 				struct qed_ooo_info *p_ooo_info,
64*1d6cff4fSYuval Mintz 				struct ooo_opaque *p_cqe)
65*1d6cff4fSYuval Mintz {
66*1d6cff4fSYuval Mintz 	struct qed_ooo_history *p_history = &p_ooo_info->ooo_history;
67*1d6cff4fSYuval Mintz 
68*1d6cff4fSYuval Mintz 	if (p_history->head_idx == p_history->num_of_cqes)
69*1d6cff4fSYuval Mintz 		p_history->head_idx = 0;
70*1d6cff4fSYuval Mintz 	p_history->p_cqes[p_history->head_idx] = *p_cqe;
71*1d6cff4fSYuval Mintz 	p_history->head_idx++;
72*1d6cff4fSYuval Mintz }
73*1d6cff4fSYuval Mintz 
74*1d6cff4fSYuval Mintz struct qed_ooo_info *qed_ooo_alloc(struct qed_hwfn *p_hwfn)
75*1d6cff4fSYuval Mintz {
76*1d6cff4fSYuval Mintz 	struct qed_ooo_info *p_ooo_info;
77*1d6cff4fSYuval Mintz 	u16 max_num_archipelagos = 0;
78*1d6cff4fSYuval Mintz 	u16 max_num_isles = 0;
79*1d6cff4fSYuval Mintz 	u32 i;
80*1d6cff4fSYuval Mintz 
81*1d6cff4fSYuval Mintz 	if (p_hwfn->hw_info.personality != QED_PCI_ISCSI) {
82*1d6cff4fSYuval Mintz 		DP_NOTICE(p_hwfn,
83*1d6cff4fSYuval Mintz 			  "Failed to allocate qed_ooo_info: unknown personality\n");
84*1d6cff4fSYuval Mintz 		return NULL;
85*1d6cff4fSYuval Mintz 	}
86*1d6cff4fSYuval Mintz 
87*1d6cff4fSYuval Mintz 	max_num_archipelagos = p_hwfn->pf_params.iscsi_pf_params.num_cons;
88*1d6cff4fSYuval Mintz 	max_num_isles = QED_MAX_NUM_ISLES + max_num_archipelagos;
89*1d6cff4fSYuval Mintz 
90*1d6cff4fSYuval Mintz 	if (!max_num_archipelagos) {
91*1d6cff4fSYuval Mintz 		DP_NOTICE(p_hwfn,
92*1d6cff4fSYuval Mintz 			  "Failed to allocate qed_ooo_info: unknown amount of connections\n");
93*1d6cff4fSYuval Mintz 		return NULL;
94*1d6cff4fSYuval Mintz 	}
95*1d6cff4fSYuval Mintz 
96*1d6cff4fSYuval Mintz 	p_ooo_info = kzalloc(sizeof(*p_ooo_info), GFP_KERNEL);
97*1d6cff4fSYuval Mintz 	if (!p_ooo_info)
98*1d6cff4fSYuval Mintz 		return NULL;
99*1d6cff4fSYuval Mintz 
100*1d6cff4fSYuval Mintz 	INIT_LIST_HEAD(&p_ooo_info->free_buffers_list);
101*1d6cff4fSYuval Mintz 	INIT_LIST_HEAD(&p_ooo_info->ready_buffers_list);
102*1d6cff4fSYuval Mintz 	INIT_LIST_HEAD(&p_ooo_info->free_isles_list);
103*1d6cff4fSYuval Mintz 	INIT_LIST_HEAD(&p_ooo_info->free_archipelagos_list);
104*1d6cff4fSYuval Mintz 	INIT_LIST_HEAD(&p_ooo_info->archipelagos_list);
105*1d6cff4fSYuval Mintz 
106*1d6cff4fSYuval Mintz 	p_ooo_info->p_isles_mem = kcalloc(max_num_isles,
107*1d6cff4fSYuval Mintz 					  sizeof(struct qed_ooo_isle),
108*1d6cff4fSYuval Mintz 					  GFP_KERNEL);
109*1d6cff4fSYuval Mintz 	if (!p_ooo_info->p_isles_mem)
110*1d6cff4fSYuval Mintz 		goto no_isles_mem;
111*1d6cff4fSYuval Mintz 
112*1d6cff4fSYuval Mintz 	for (i = 0; i < max_num_isles; i++) {
113*1d6cff4fSYuval Mintz 		INIT_LIST_HEAD(&p_ooo_info->p_isles_mem[i].buffers_list);
114*1d6cff4fSYuval Mintz 		list_add_tail(&p_ooo_info->p_isles_mem[i].list_entry,
115*1d6cff4fSYuval Mintz 			      &p_ooo_info->free_isles_list);
116*1d6cff4fSYuval Mintz 	}
117*1d6cff4fSYuval Mintz 
118*1d6cff4fSYuval Mintz 	p_ooo_info->p_archipelagos_mem =
119*1d6cff4fSYuval Mintz 				kcalloc(max_num_archipelagos,
120*1d6cff4fSYuval Mintz 					sizeof(struct qed_ooo_archipelago),
121*1d6cff4fSYuval Mintz 					GFP_KERNEL);
122*1d6cff4fSYuval Mintz 	if (!p_ooo_info->p_archipelagos_mem)
123*1d6cff4fSYuval Mintz 		goto no_archipelagos_mem;
124*1d6cff4fSYuval Mintz 
125*1d6cff4fSYuval Mintz 	for (i = 0; i < max_num_archipelagos; i++) {
126*1d6cff4fSYuval Mintz 		INIT_LIST_HEAD(&p_ooo_info->p_archipelagos_mem[i].isles_list);
127*1d6cff4fSYuval Mintz 		list_add_tail(&p_ooo_info->p_archipelagos_mem[i].list_entry,
128*1d6cff4fSYuval Mintz 			      &p_ooo_info->free_archipelagos_list);
129*1d6cff4fSYuval Mintz 	}
130*1d6cff4fSYuval Mintz 
131*1d6cff4fSYuval Mintz 	p_ooo_info->ooo_history.p_cqes =
132*1d6cff4fSYuval Mintz 				kcalloc(QED_MAX_NUM_OOO_HISTORY_ENTRIES,
133*1d6cff4fSYuval Mintz 					sizeof(struct ooo_opaque),
134*1d6cff4fSYuval Mintz 					GFP_KERNEL);
135*1d6cff4fSYuval Mintz 	if (!p_ooo_info->ooo_history.p_cqes)
136*1d6cff4fSYuval Mintz 		goto no_history_mem;
137*1d6cff4fSYuval Mintz 
138*1d6cff4fSYuval Mintz 	return p_ooo_info;
139*1d6cff4fSYuval Mintz 
140*1d6cff4fSYuval Mintz no_history_mem:
141*1d6cff4fSYuval Mintz 	kfree(p_ooo_info->p_archipelagos_mem);
142*1d6cff4fSYuval Mintz no_archipelagos_mem:
143*1d6cff4fSYuval Mintz 	kfree(p_ooo_info->p_isles_mem);
144*1d6cff4fSYuval Mintz no_isles_mem:
145*1d6cff4fSYuval Mintz 	kfree(p_ooo_info);
146*1d6cff4fSYuval Mintz 	return NULL;
147*1d6cff4fSYuval Mintz }
148*1d6cff4fSYuval Mintz 
149*1d6cff4fSYuval Mintz void qed_ooo_release_connection_isles(struct qed_hwfn *p_hwfn,
150*1d6cff4fSYuval Mintz 				      struct qed_ooo_info *p_ooo_info, u32 cid)
151*1d6cff4fSYuval Mintz {
152*1d6cff4fSYuval Mintz 	struct qed_ooo_archipelago *p_archipelago;
153*1d6cff4fSYuval Mintz 	struct qed_ooo_buffer *p_buffer;
154*1d6cff4fSYuval Mintz 	struct qed_ooo_isle *p_isle;
155*1d6cff4fSYuval Mintz 	bool b_found = false;
156*1d6cff4fSYuval Mintz 
157*1d6cff4fSYuval Mintz 	if (list_empty(&p_ooo_info->archipelagos_list))
158*1d6cff4fSYuval Mintz 		return;
159*1d6cff4fSYuval Mintz 
160*1d6cff4fSYuval Mintz 	list_for_each_entry(p_archipelago,
161*1d6cff4fSYuval Mintz 			    &p_ooo_info->archipelagos_list, list_entry) {
162*1d6cff4fSYuval Mintz 		if (p_archipelago->cid == cid) {
163*1d6cff4fSYuval Mintz 			list_del(&p_archipelago->list_entry);
164*1d6cff4fSYuval Mintz 			b_found = true;
165*1d6cff4fSYuval Mintz 			break;
166*1d6cff4fSYuval Mintz 		}
167*1d6cff4fSYuval Mintz 	}
168*1d6cff4fSYuval Mintz 
169*1d6cff4fSYuval Mintz 	if (!b_found)
170*1d6cff4fSYuval Mintz 		return;
171*1d6cff4fSYuval Mintz 
172*1d6cff4fSYuval Mintz 	while (!list_empty(&p_archipelago->isles_list)) {
173*1d6cff4fSYuval Mintz 		p_isle = list_first_entry(&p_archipelago->isles_list,
174*1d6cff4fSYuval Mintz 					  struct qed_ooo_isle, list_entry);
175*1d6cff4fSYuval Mintz 
176*1d6cff4fSYuval Mintz 		list_del(&p_isle->list_entry);
177*1d6cff4fSYuval Mintz 
178*1d6cff4fSYuval Mintz 		while (!list_empty(&p_isle->buffers_list)) {
179*1d6cff4fSYuval Mintz 			p_buffer = list_first_entry(&p_isle->buffers_list,
180*1d6cff4fSYuval Mintz 						    struct qed_ooo_buffer,
181*1d6cff4fSYuval Mintz 						    list_entry);
182*1d6cff4fSYuval Mintz 
183*1d6cff4fSYuval Mintz 			if (!p_buffer)
184*1d6cff4fSYuval Mintz 				break;
185*1d6cff4fSYuval Mintz 
186*1d6cff4fSYuval Mintz 			list_del(&p_buffer->list_entry);
187*1d6cff4fSYuval Mintz 			list_add_tail(&p_buffer->list_entry,
188*1d6cff4fSYuval Mintz 				      &p_ooo_info->free_buffers_list);
189*1d6cff4fSYuval Mintz 		}
190*1d6cff4fSYuval Mintz 		list_add_tail(&p_isle->list_entry,
191*1d6cff4fSYuval Mintz 			      &p_ooo_info->free_isles_list);
192*1d6cff4fSYuval Mintz 	}
193*1d6cff4fSYuval Mintz 
194*1d6cff4fSYuval Mintz 	list_add_tail(&p_archipelago->list_entry,
195*1d6cff4fSYuval Mintz 		      &p_ooo_info->free_archipelagos_list);
196*1d6cff4fSYuval Mintz }
197*1d6cff4fSYuval Mintz 
198*1d6cff4fSYuval Mintz void qed_ooo_release_all_isles(struct qed_hwfn *p_hwfn,
199*1d6cff4fSYuval Mintz 			       struct qed_ooo_info *p_ooo_info)
200*1d6cff4fSYuval Mintz {
201*1d6cff4fSYuval Mintz 	struct qed_ooo_archipelago *p_arch;
202*1d6cff4fSYuval Mintz 	struct qed_ooo_buffer *p_buffer;
203*1d6cff4fSYuval Mintz 	struct qed_ooo_isle *p_isle;
204*1d6cff4fSYuval Mintz 
205*1d6cff4fSYuval Mintz 	while (!list_empty(&p_ooo_info->archipelagos_list)) {
206*1d6cff4fSYuval Mintz 		p_arch = list_first_entry(&p_ooo_info->archipelagos_list,
207*1d6cff4fSYuval Mintz 					  struct qed_ooo_archipelago,
208*1d6cff4fSYuval Mintz 					  list_entry);
209*1d6cff4fSYuval Mintz 
210*1d6cff4fSYuval Mintz 		list_del(&p_arch->list_entry);
211*1d6cff4fSYuval Mintz 
212*1d6cff4fSYuval Mintz 		while (!list_empty(&p_arch->isles_list)) {
213*1d6cff4fSYuval Mintz 			p_isle = list_first_entry(&p_arch->isles_list,
214*1d6cff4fSYuval Mintz 						  struct qed_ooo_isle,
215*1d6cff4fSYuval Mintz 						  list_entry);
216*1d6cff4fSYuval Mintz 
217*1d6cff4fSYuval Mintz 			list_del(&p_isle->list_entry);
218*1d6cff4fSYuval Mintz 
219*1d6cff4fSYuval Mintz 			while (!list_empty(&p_isle->buffers_list)) {
220*1d6cff4fSYuval Mintz 				p_buffer =
221*1d6cff4fSYuval Mintz 				    list_first_entry(&p_isle->buffers_list,
222*1d6cff4fSYuval Mintz 						     struct qed_ooo_buffer,
223*1d6cff4fSYuval Mintz 						     list_entry);
224*1d6cff4fSYuval Mintz 
225*1d6cff4fSYuval Mintz 				if (!p_buffer)
226*1d6cff4fSYuval Mintz 					break;
227*1d6cff4fSYuval Mintz 
228*1d6cff4fSYuval Mintz 			list_del(&p_buffer->list_entry);
229*1d6cff4fSYuval Mintz 				list_add_tail(&p_buffer->list_entry,
230*1d6cff4fSYuval Mintz 					      &p_ooo_info->free_buffers_list);
231*1d6cff4fSYuval Mintz 			}
232*1d6cff4fSYuval Mintz 			list_add_tail(&p_isle->list_entry,
233*1d6cff4fSYuval Mintz 				      &p_ooo_info->free_isles_list);
234*1d6cff4fSYuval Mintz 		}
235*1d6cff4fSYuval Mintz 		list_add_tail(&p_arch->list_entry,
236*1d6cff4fSYuval Mintz 			      &p_ooo_info->free_archipelagos_list);
237*1d6cff4fSYuval Mintz 	}
238*1d6cff4fSYuval Mintz 	if (!list_empty(&p_ooo_info->ready_buffers_list))
239*1d6cff4fSYuval Mintz 		list_splice_tail_init(&p_ooo_info->ready_buffers_list,
240*1d6cff4fSYuval Mintz 				      &p_ooo_info->free_buffers_list);
241*1d6cff4fSYuval Mintz }
242*1d6cff4fSYuval Mintz 
243*1d6cff4fSYuval Mintz void qed_ooo_setup(struct qed_hwfn *p_hwfn, struct qed_ooo_info *p_ooo_info)
244*1d6cff4fSYuval Mintz {
245*1d6cff4fSYuval Mintz 	qed_ooo_release_all_isles(p_hwfn, p_ooo_info);
246*1d6cff4fSYuval Mintz 	memset(p_ooo_info->ooo_history.p_cqes, 0,
247*1d6cff4fSYuval Mintz 	       p_ooo_info->ooo_history.num_of_cqes *
248*1d6cff4fSYuval Mintz 	       sizeof(struct ooo_opaque));
249*1d6cff4fSYuval Mintz 	p_ooo_info->ooo_history.head_idx = 0;
250*1d6cff4fSYuval Mintz }
251*1d6cff4fSYuval Mintz 
252*1d6cff4fSYuval Mintz void qed_ooo_free(struct qed_hwfn *p_hwfn, struct qed_ooo_info *p_ooo_info)
253*1d6cff4fSYuval Mintz {
254*1d6cff4fSYuval Mintz 	struct qed_ooo_buffer *p_buffer;
255*1d6cff4fSYuval Mintz 
256*1d6cff4fSYuval Mintz 	qed_ooo_release_all_isles(p_hwfn, p_ooo_info);
257*1d6cff4fSYuval Mintz 	while (!list_empty(&p_ooo_info->free_buffers_list)) {
258*1d6cff4fSYuval Mintz 		p_buffer = list_first_entry(&p_ooo_info->free_buffers_list,
259*1d6cff4fSYuval Mintz 					    struct qed_ooo_buffer, list_entry);
260*1d6cff4fSYuval Mintz 
261*1d6cff4fSYuval Mintz 		if (!p_buffer)
262*1d6cff4fSYuval Mintz 			break;
263*1d6cff4fSYuval Mintz 
264*1d6cff4fSYuval Mintz 		list_del(&p_buffer->list_entry);
265*1d6cff4fSYuval Mintz 		dma_free_coherent(&p_hwfn->cdev->pdev->dev,
266*1d6cff4fSYuval Mintz 				  p_buffer->rx_buffer_size,
267*1d6cff4fSYuval Mintz 				  p_buffer->rx_buffer_virt_addr,
268*1d6cff4fSYuval Mintz 				  p_buffer->rx_buffer_phys_addr);
269*1d6cff4fSYuval Mintz 		kfree(p_buffer);
270*1d6cff4fSYuval Mintz 	}
271*1d6cff4fSYuval Mintz 
272*1d6cff4fSYuval Mintz 	kfree(p_ooo_info->p_isles_mem);
273*1d6cff4fSYuval Mintz 	kfree(p_ooo_info->p_archipelagos_mem);
274*1d6cff4fSYuval Mintz 	kfree(p_ooo_info->ooo_history.p_cqes);
275*1d6cff4fSYuval Mintz 	kfree(p_ooo_info);
276*1d6cff4fSYuval Mintz }
277*1d6cff4fSYuval Mintz 
278*1d6cff4fSYuval Mintz void qed_ooo_put_free_buffer(struct qed_hwfn *p_hwfn,
279*1d6cff4fSYuval Mintz 			     struct qed_ooo_info *p_ooo_info,
280*1d6cff4fSYuval Mintz 			     struct qed_ooo_buffer *p_buffer)
281*1d6cff4fSYuval Mintz {
282*1d6cff4fSYuval Mintz 	list_add_tail(&p_buffer->list_entry, &p_ooo_info->free_buffers_list);
283*1d6cff4fSYuval Mintz }
284*1d6cff4fSYuval Mintz 
285*1d6cff4fSYuval Mintz struct qed_ooo_buffer *qed_ooo_get_free_buffer(struct qed_hwfn *p_hwfn,
286*1d6cff4fSYuval Mintz 					       struct qed_ooo_info *p_ooo_info)
287*1d6cff4fSYuval Mintz {
288*1d6cff4fSYuval Mintz 	struct qed_ooo_buffer *p_buffer = NULL;
289*1d6cff4fSYuval Mintz 
290*1d6cff4fSYuval Mintz 	if (!list_empty(&p_ooo_info->free_buffers_list)) {
291*1d6cff4fSYuval Mintz 		p_buffer = list_first_entry(&p_ooo_info->free_buffers_list,
292*1d6cff4fSYuval Mintz 					    struct qed_ooo_buffer, list_entry);
293*1d6cff4fSYuval Mintz 
294*1d6cff4fSYuval Mintz 		list_del(&p_buffer->list_entry);
295*1d6cff4fSYuval Mintz 	}
296*1d6cff4fSYuval Mintz 
297*1d6cff4fSYuval Mintz 	return p_buffer;
298*1d6cff4fSYuval Mintz }
299*1d6cff4fSYuval Mintz 
300*1d6cff4fSYuval Mintz void qed_ooo_put_ready_buffer(struct qed_hwfn *p_hwfn,
301*1d6cff4fSYuval Mintz 			      struct qed_ooo_info *p_ooo_info,
302*1d6cff4fSYuval Mintz 			      struct qed_ooo_buffer *p_buffer, u8 on_tail)
303*1d6cff4fSYuval Mintz {
304*1d6cff4fSYuval Mintz 	if (on_tail)
305*1d6cff4fSYuval Mintz 		list_add_tail(&p_buffer->list_entry,
306*1d6cff4fSYuval Mintz 			      &p_ooo_info->ready_buffers_list);
307*1d6cff4fSYuval Mintz 	else
308*1d6cff4fSYuval Mintz 		list_add(&p_buffer->list_entry,
309*1d6cff4fSYuval Mintz 			 &p_ooo_info->ready_buffers_list);
310*1d6cff4fSYuval Mintz }
311*1d6cff4fSYuval Mintz 
312*1d6cff4fSYuval Mintz struct qed_ooo_buffer *qed_ooo_get_ready_buffer(struct qed_hwfn *p_hwfn,
313*1d6cff4fSYuval Mintz 						struct qed_ooo_info *p_ooo_info)
314*1d6cff4fSYuval Mintz {
315*1d6cff4fSYuval Mintz 	struct qed_ooo_buffer *p_buffer = NULL;
316*1d6cff4fSYuval Mintz 
317*1d6cff4fSYuval Mintz 	if (!list_empty(&p_ooo_info->ready_buffers_list)) {
318*1d6cff4fSYuval Mintz 		p_buffer = list_first_entry(&p_ooo_info->ready_buffers_list,
319*1d6cff4fSYuval Mintz 					    struct qed_ooo_buffer, list_entry);
320*1d6cff4fSYuval Mintz 
321*1d6cff4fSYuval Mintz 		list_del(&p_buffer->list_entry);
322*1d6cff4fSYuval Mintz 	}
323*1d6cff4fSYuval Mintz 
324*1d6cff4fSYuval Mintz 	return p_buffer;
325*1d6cff4fSYuval Mintz }
326*1d6cff4fSYuval Mintz 
327*1d6cff4fSYuval Mintz void qed_ooo_delete_isles(struct qed_hwfn *p_hwfn,
328*1d6cff4fSYuval Mintz 			  struct qed_ooo_info *p_ooo_info,
329*1d6cff4fSYuval Mintz 			  u32 cid, u8 drop_isle, u8 drop_size)
330*1d6cff4fSYuval Mintz {
331*1d6cff4fSYuval Mintz 	struct qed_ooo_archipelago *p_archipelago = NULL;
332*1d6cff4fSYuval Mintz 	struct qed_ooo_isle *p_isle = NULL;
333*1d6cff4fSYuval Mintz 	u8 isle_idx;
334*1d6cff4fSYuval Mintz 
335*1d6cff4fSYuval Mintz 	p_archipelago = qed_ooo_seek_archipelago(p_hwfn, p_ooo_info, cid);
336*1d6cff4fSYuval Mintz 	for (isle_idx = 0; isle_idx < drop_size; isle_idx++) {
337*1d6cff4fSYuval Mintz 		p_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid, drop_isle);
338*1d6cff4fSYuval Mintz 		if (!p_isle) {
339*1d6cff4fSYuval Mintz 			DP_NOTICE(p_hwfn,
340*1d6cff4fSYuval Mintz 				  "Isle %d is not found(cid %d)\n",
341*1d6cff4fSYuval Mintz 				  drop_isle, cid);
342*1d6cff4fSYuval Mintz 			return;
343*1d6cff4fSYuval Mintz 		}
344*1d6cff4fSYuval Mintz 		if (list_empty(&p_isle->buffers_list))
345*1d6cff4fSYuval Mintz 			DP_NOTICE(p_hwfn,
346*1d6cff4fSYuval Mintz 				  "Isle %d is empty(cid %d)\n", drop_isle, cid);
347*1d6cff4fSYuval Mintz 		else
348*1d6cff4fSYuval Mintz 			list_splice_tail_init(&p_isle->buffers_list,
349*1d6cff4fSYuval Mintz 					      &p_ooo_info->free_buffers_list);
350*1d6cff4fSYuval Mintz 
351*1d6cff4fSYuval Mintz 		list_del(&p_isle->list_entry);
352*1d6cff4fSYuval Mintz 		p_ooo_info->cur_isles_number--;
353*1d6cff4fSYuval Mintz 		list_add(&p_isle->list_entry, &p_ooo_info->free_isles_list);
354*1d6cff4fSYuval Mintz 	}
355*1d6cff4fSYuval Mintz 
356*1d6cff4fSYuval Mintz 	if (list_empty(&p_archipelago->isles_list)) {
357*1d6cff4fSYuval Mintz 		list_del(&p_archipelago->list_entry);
358*1d6cff4fSYuval Mintz 		list_add(&p_archipelago->list_entry,
359*1d6cff4fSYuval Mintz 			 &p_ooo_info->free_archipelagos_list);
360*1d6cff4fSYuval Mintz 	}
361*1d6cff4fSYuval Mintz }
362*1d6cff4fSYuval Mintz 
363*1d6cff4fSYuval Mintz void qed_ooo_add_new_isle(struct qed_hwfn *p_hwfn,
364*1d6cff4fSYuval Mintz 			  struct qed_ooo_info *p_ooo_info,
365*1d6cff4fSYuval Mintz 			  u32 cid, u8 ooo_isle,
366*1d6cff4fSYuval Mintz 			  struct qed_ooo_buffer *p_buffer)
367*1d6cff4fSYuval Mintz {
368*1d6cff4fSYuval Mintz 	struct qed_ooo_archipelago *p_archipelago = NULL;
369*1d6cff4fSYuval Mintz 	struct qed_ooo_isle *p_prev_isle = NULL;
370*1d6cff4fSYuval Mintz 	struct qed_ooo_isle *p_isle = NULL;
371*1d6cff4fSYuval Mintz 
372*1d6cff4fSYuval Mintz 	if (ooo_isle > 1) {
373*1d6cff4fSYuval Mintz 		p_prev_isle = qed_ooo_seek_isle(p_hwfn,
374*1d6cff4fSYuval Mintz 						p_ooo_info, cid, ooo_isle - 1);
375*1d6cff4fSYuval Mintz 		if (!p_prev_isle) {
376*1d6cff4fSYuval Mintz 			DP_NOTICE(p_hwfn,
377*1d6cff4fSYuval Mintz 				  "Isle %d is not found(cid %d)\n",
378*1d6cff4fSYuval Mintz 				  ooo_isle - 1, cid);
379*1d6cff4fSYuval Mintz 			return;
380*1d6cff4fSYuval Mintz 		}
381*1d6cff4fSYuval Mintz 	}
382*1d6cff4fSYuval Mintz 	p_archipelago = qed_ooo_seek_archipelago(p_hwfn, p_ooo_info, cid);
383*1d6cff4fSYuval Mintz 	if (!p_archipelago && (ooo_isle != 1)) {
384*1d6cff4fSYuval Mintz 		DP_NOTICE(p_hwfn,
385*1d6cff4fSYuval Mintz 			  "Connection %d is not found in OOO list\n", cid);
386*1d6cff4fSYuval Mintz 		return;
387*1d6cff4fSYuval Mintz 	}
388*1d6cff4fSYuval Mintz 
389*1d6cff4fSYuval Mintz 	if (!list_empty(&p_ooo_info->free_isles_list)) {
390*1d6cff4fSYuval Mintz 		p_isle = list_first_entry(&p_ooo_info->free_isles_list,
391*1d6cff4fSYuval Mintz 					  struct qed_ooo_isle, list_entry);
392*1d6cff4fSYuval Mintz 
393*1d6cff4fSYuval Mintz 		list_del(&p_isle->list_entry);
394*1d6cff4fSYuval Mintz 		if (!list_empty(&p_isle->buffers_list)) {
395*1d6cff4fSYuval Mintz 			DP_NOTICE(p_hwfn, "Free isle is not empty\n");
396*1d6cff4fSYuval Mintz 			INIT_LIST_HEAD(&p_isle->buffers_list);
397*1d6cff4fSYuval Mintz 		}
398*1d6cff4fSYuval Mintz 	} else {
399*1d6cff4fSYuval Mintz 		DP_NOTICE(p_hwfn, "No more free isles\n");
400*1d6cff4fSYuval Mintz 		return;
401*1d6cff4fSYuval Mintz 	}
402*1d6cff4fSYuval Mintz 
403*1d6cff4fSYuval Mintz 	if (!p_archipelago &&
404*1d6cff4fSYuval Mintz 	    !list_empty(&p_ooo_info->free_archipelagos_list)) {
405*1d6cff4fSYuval Mintz 		p_archipelago =
406*1d6cff4fSYuval Mintz 		    list_first_entry(&p_ooo_info->free_archipelagos_list,
407*1d6cff4fSYuval Mintz 				     struct qed_ooo_archipelago, list_entry);
408*1d6cff4fSYuval Mintz 
409*1d6cff4fSYuval Mintz 		list_del(&p_archipelago->list_entry);
410*1d6cff4fSYuval Mintz 		if (!list_empty(&p_archipelago->isles_list)) {
411*1d6cff4fSYuval Mintz 			DP_NOTICE(p_hwfn,
412*1d6cff4fSYuval Mintz 				  "Free OOO connection is not empty\n");
413*1d6cff4fSYuval Mintz 			INIT_LIST_HEAD(&p_archipelago->isles_list);
414*1d6cff4fSYuval Mintz 		}
415*1d6cff4fSYuval Mintz 		p_archipelago->cid = cid;
416*1d6cff4fSYuval Mintz 		list_add(&p_archipelago->list_entry,
417*1d6cff4fSYuval Mintz 			 &p_ooo_info->archipelagos_list);
418*1d6cff4fSYuval Mintz 	} else if (!p_archipelago) {
419*1d6cff4fSYuval Mintz 		DP_NOTICE(p_hwfn, "No more free OOO connections\n");
420*1d6cff4fSYuval Mintz 		list_add(&p_isle->list_entry,
421*1d6cff4fSYuval Mintz 			 &p_ooo_info->free_isles_list);
422*1d6cff4fSYuval Mintz 		list_add(&p_buffer->list_entry,
423*1d6cff4fSYuval Mintz 			 &p_ooo_info->free_buffers_list);
424*1d6cff4fSYuval Mintz 		return;
425*1d6cff4fSYuval Mintz 	}
426*1d6cff4fSYuval Mintz 
427*1d6cff4fSYuval Mintz 	list_add(&p_buffer->list_entry, &p_isle->buffers_list);
428*1d6cff4fSYuval Mintz 	p_ooo_info->cur_isles_number++;
429*1d6cff4fSYuval Mintz 	p_ooo_info->gen_isles_number++;
430*1d6cff4fSYuval Mintz 
431*1d6cff4fSYuval Mintz 	if (p_ooo_info->cur_isles_number > p_ooo_info->max_isles_number)
432*1d6cff4fSYuval Mintz 		p_ooo_info->max_isles_number = p_ooo_info->cur_isles_number;
433*1d6cff4fSYuval Mintz 
434*1d6cff4fSYuval Mintz 	if (!p_prev_isle)
435*1d6cff4fSYuval Mintz 		list_add(&p_isle->list_entry, &p_archipelago->isles_list);
436*1d6cff4fSYuval Mintz 	else
437*1d6cff4fSYuval Mintz 		list_add(&p_isle->list_entry, &p_prev_isle->list_entry);
438*1d6cff4fSYuval Mintz }
439*1d6cff4fSYuval Mintz 
440*1d6cff4fSYuval Mintz void qed_ooo_add_new_buffer(struct qed_hwfn *p_hwfn,
441*1d6cff4fSYuval Mintz 			    struct qed_ooo_info *p_ooo_info,
442*1d6cff4fSYuval Mintz 			    u32 cid,
443*1d6cff4fSYuval Mintz 			    u8 ooo_isle,
444*1d6cff4fSYuval Mintz 			    struct qed_ooo_buffer *p_buffer, u8 buffer_side)
445*1d6cff4fSYuval Mintz {
446*1d6cff4fSYuval Mintz 	struct qed_ooo_isle *p_isle = NULL;
447*1d6cff4fSYuval Mintz 
448*1d6cff4fSYuval Mintz 	p_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid, ooo_isle);
449*1d6cff4fSYuval Mintz 	if (!p_isle) {
450*1d6cff4fSYuval Mintz 		DP_NOTICE(p_hwfn,
451*1d6cff4fSYuval Mintz 			  "Isle %d is not found(cid %d)\n", ooo_isle, cid);
452*1d6cff4fSYuval Mintz 		return;
453*1d6cff4fSYuval Mintz 	}
454*1d6cff4fSYuval Mintz 
455*1d6cff4fSYuval Mintz 	if (buffer_side == QED_OOO_LEFT_BUF)
456*1d6cff4fSYuval Mintz 		list_add(&p_buffer->list_entry, &p_isle->buffers_list);
457*1d6cff4fSYuval Mintz 	else
458*1d6cff4fSYuval Mintz 		list_add_tail(&p_buffer->list_entry, &p_isle->buffers_list);
459*1d6cff4fSYuval Mintz }
460*1d6cff4fSYuval Mintz 
461*1d6cff4fSYuval Mintz void qed_ooo_join_isles(struct qed_hwfn *p_hwfn,
462*1d6cff4fSYuval Mintz 			struct qed_ooo_info *p_ooo_info, u32 cid, u8 left_isle)
463*1d6cff4fSYuval Mintz {
464*1d6cff4fSYuval Mintz 	struct qed_ooo_archipelago *p_archipelago = NULL;
465*1d6cff4fSYuval Mintz 	struct qed_ooo_isle *p_right_isle = NULL;
466*1d6cff4fSYuval Mintz 	struct qed_ooo_isle *p_left_isle = NULL;
467*1d6cff4fSYuval Mintz 
468*1d6cff4fSYuval Mintz 	p_right_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid,
469*1d6cff4fSYuval Mintz 					 left_isle + 1);
470*1d6cff4fSYuval Mintz 	if (!p_right_isle) {
471*1d6cff4fSYuval Mintz 		DP_NOTICE(p_hwfn,
472*1d6cff4fSYuval Mintz 			  "Right isle %d is not found(cid %d)\n",
473*1d6cff4fSYuval Mintz 			  left_isle + 1, cid);
474*1d6cff4fSYuval Mintz 		return;
475*1d6cff4fSYuval Mintz 	}
476*1d6cff4fSYuval Mintz 
477*1d6cff4fSYuval Mintz 	p_archipelago = qed_ooo_seek_archipelago(p_hwfn, p_ooo_info, cid);
478*1d6cff4fSYuval Mintz 	list_del(&p_right_isle->list_entry);
479*1d6cff4fSYuval Mintz 	p_ooo_info->cur_isles_number--;
480*1d6cff4fSYuval Mintz 	if (left_isle) {
481*1d6cff4fSYuval Mintz 		p_left_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid,
482*1d6cff4fSYuval Mintz 						left_isle);
483*1d6cff4fSYuval Mintz 		if (!p_left_isle) {
484*1d6cff4fSYuval Mintz 			DP_NOTICE(p_hwfn,
485*1d6cff4fSYuval Mintz 				  "Left isle %d is not found(cid %d)\n",
486*1d6cff4fSYuval Mintz 				  left_isle, cid);
487*1d6cff4fSYuval Mintz 			return;
488*1d6cff4fSYuval Mintz 		}
489*1d6cff4fSYuval Mintz 		list_splice_tail_init(&p_right_isle->buffers_list,
490*1d6cff4fSYuval Mintz 				      &p_left_isle->buffers_list);
491*1d6cff4fSYuval Mintz 	} else {
492*1d6cff4fSYuval Mintz 		list_splice_tail_init(&p_right_isle->buffers_list,
493*1d6cff4fSYuval Mintz 				      &p_ooo_info->ready_buffers_list);
494*1d6cff4fSYuval Mintz 		if (list_empty(&p_archipelago->isles_list)) {
495*1d6cff4fSYuval Mintz 			list_del(&p_archipelago->list_entry);
496*1d6cff4fSYuval Mintz 			list_add(&p_archipelago->list_entry,
497*1d6cff4fSYuval Mintz 				 &p_ooo_info->free_archipelagos_list);
498*1d6cff4fSYuval Mintz 		}
499*1d6cff4fSYuval Mintz 	}
500*1d6cff4fSYuval Mintz 	list_add_tail(&p_right_isle->list_entry, &p_ooo_info->free_isles_list);
501*1d6cff4fSYuval Mintz }
502