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