9f99292ab5cedb90f042e68729533f3343182e70
[linux-block.git] / drivers / net / ethernet / mellanox / mlx5 / core / pagealloc.c
1 /*
2  * Copyright (c) 2013-2015, Mellanox Technologies. All rights reserved.
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/highmem.h>
34 #include <linux/kernel.h>
35 #include <linux/delay.h>
36 #include <linux/mlx5/driver.h>
37 #include <linux/xarray.h>
38 #include "mlx5_core.h"
39 #include "lib/eq.h"
40 #include "lib/tout.h"
41
42 enum {
43         MLX5_PAGES_CANT_GIVE    = 0,
44         MLX5_PAGES_GIVE         = 1,
45         MLX5_PAGES_TAKE         = 2
46 };
47
48 struct mlx5_pages_req {
49         struct mlx5_core_dev *dev;
50         u16     func_id;
51         u8      ec_function;
52         s32     npages;
53         struct work_struct work;
54         u8      release_all;
55 };
56
57 struct fw_page {
58         struct rb_node          rb_node;
59         u64                     addr;
60         struct page            *page;
61         u32                     function;
62         unsigned long           bitmask;
63         struct list_head        list;
64         unsigned int free_count;
65 };
66
67 enum {
68         MLX5_MAX_RECLAIM_TIME_MILI      = 5000,
69         MLX5_NUM_4K_IN_PAGE             = PAGE_SIZE / MLX5_ADAPTER_PAGE_SIZE,
70 };
71
72 static u32 get_function(u16 func_id, bool ec_function)
73 {
74         return (u32)func_id | (ec_function << 16);
75 }
76
77 static u16 func_id_to_type(struct mlx5_core_dev *dev, u16 func_id, bool ec_function)
78 {
79         if (!func_id)
80                 return mlx5_core_is_ecpf(dev) && !ec_function ? MLX5_HOST_PF : MLX5_PF;
81
82         return MLX5_VF;
83 }
84
85 static struct rb_root *page_root_per_function(struct mlx5_core_dev *dev, u32 function)
86 {
87         struct rb_root *root;
88         int err;
89
90         root = xa_load(&dev->priv.page_root_xa, function);
91         if (root)
92                 return root;
93
94         root = kzalloc(sizeof(*root), GFP_KERNEL);
95         if (!root)
96                 return ERR_PTR(-ENOMEM);
97
98         err = xa_insert(&dev->priv.page_root_xa, function, root, GFP_KERNEL);
99         if (err) {
100                 kfree(root);
101                 return ERR_PTR(err);
102         }
103
104         *root = RB_ROOT;
105
106         return root;
107 }
108
109 static int insert_page(struct mlx5_core_dev *dev, u64 addr, struct page *page, u32 function)
110 {
111         struct rb_node *parent = NULL;
112         struct rb_root *root;
113         struct rb_node **new;
114         struct fw_page *nfp;
115         struct fw_page *tfp;
116         int i;
117
118         root = page_root_per_function(dev, function);
119         if (IS_ERR(root))
120                 return PTR_ERR(root);
121
122         new = &root->rb_node;
123
124         while (*new) {
125                 parent = *new;
126                 tfp = rb_entry(parent, struct fw_page, rb_node);
127                 if (tfp->addr < addr)
128                         new = &parent->rb_left;
129                 else if (tfp->addr > addr)
130                         new = &parent->rb_right;
131                 else
132                         return -EEXIST;
133         }
134
135         nfp = kzalloc(sizeof(*nfp), GFP_KERNEL);
136         if (!nfp)
137                 return -ENOMEM;
138
139         nfp->addr = addr;
140         nfp->page = page;
141         nfp->function = function;
142         nfp->free_count = MLX5_NUM_4K_IN_PAGE;
143         for (i = 0; i < MLX5_NUM_4K_IN_PAGE; i++)
144                 set_bit(i, &nfp->bitmask);
145
146         rb_link_node(&nfp->rb_node, parent, new);
147         rb_insert_color(&nfp->rb_node, root);
148         list_add(&nfp->list, &dev->priv.free_list);
149
150         return 0;
151 }
152
153 static struct fw_page *find_fw_page(struct mlx5_core_dev *dev, u64 addr,
154                                     u32 function)
155 {
156         struct fw_page *result = NULL;
157         struct rb_root *root;
158         struct rb_node *tmp;
159         struct fw_page *tfp;
160
161         root = xa_load(&dev->priv.page_root_xa, function);
162         if (WARN_ON_ONCE(!root))
163                 return NULL;
164
165         tmp = root->rb_node;
166
167         while (tmp) {
168                 tfp = rb_entry(tmp, struct fw_page, rb_node);
169                 if (tfp->addr < addr) {
170                         tmp = tmp->rb_left;
171                 } else if (tfp->addr > addr) {
172                         tmp = tmp->rb_right;
173                 } else {
174                         result = tfp;
175                         break;
176                 }
177         }
178
179         return result;
180 }
181
182 static int mlx5_cmd_query_pages(struct mlx5_core_dev *dev, u16 *func_id,
183                                 s32 *npages, int boot)
184 {
185         u32 out[MLX5_ST_SZ_DW(query_pages_out)] = {};
186         u32 in[MLX5_ST_SZ_DW(query_pages_in)] = {};
187         int err;
188
189         MLX5_SET(query_pages_in, in, opcode, MLX5_CMD_OP_QUERY_PAGES);
190         MLX5_SET(query_pages_in, in, op_mod, boot ?
191                  MLX5_QUERY_PAGES_IN_OP_MOD_BOOT_PAGES :
192                  MLX5_QUERY_PAGES_IN_OP_MOD_INIT_PAGES);
193         MLX5_SET(query_pages_in, in, embedded_cpu_function, mlx5_core_is_ecpf(dev));
194
195         err = mlx5_cmd_exec_inout(dev, query_pages, in, out);
196         if (err)
197                 return err;
198
199         *npages = MLX5_GET(query_pages_out, out, num_pages);
200         *func_id = MLX5_GET(query_pages_out, out, function_id);
201
202         return err;
203 }
204
205 static int alloc_4k(struct mlx5_core_dev *dev, u64 *addr, u32 function)
206 {
207         struct fw_page *fp = NULL;
208         struct fw_page *iter;
209         unsigned n;
210
211         list_for_each_entry(iter, &dev->priv.free_list, list) {
212                 if (iter->function != function)
213                         continue;
214                 fp = iter;
215         }
216
217         if (list_empty(&dev->priv.free_list) || !fp)
218                 return -ENOMEM;
219
220         n = find_first_bit(&fp->bitmask, 8 * sizeof(fp->bitmask));
221         if (n >= MLX5_NUM_4K_IN_PAGE) {
222                 mlx5_core_warn(dev, "alloc 4k bug\n");
223                 return -ENOENT;
224         }
225         clear_bit(n, &fp->bitmask);
226         fp->free_count--;
227         if (!fp->free_count)
228                 list_del(&fp->list);
229
230         *addr = fp->addr + n * MLX5_ADAPTER_PAGE_SIZE;
231
232         return 0;
233 }
234
235 #define MLX5_U64_4K_PAGE_MASK ((~(u64)0U) << PAGE_SHIFT)
236
237 static void free_fwp(struct mlx5_core_dev *dev, struct fw_page *fwp,
238                      bool in_free_list)
239 {
240         struct rb_root *root;
241
242         root = xa_load(&dev->priv.page_root_xa, fwp->function);
243         if (WARN_ON_ONCE(!root))
244                 return;
245
246         rb_erase(&fwp->rb_node, root);
247         if (in_free_list)
248                 list_del(&fwp->list);
249         dma_unmap_page(mlx5_core_dma_dev(dev), fwp->addr & MLX5_U64_4K_PAGE_MASK,
250                        PAGE_SIZE, DMA_BIDIRECTIONAL);
251         __free_page(fwp->page);
252         kfree(fwp);
253 }
254
255 static void free_4k(struct mlx5_core_dev *dev, u64 addr, u32 function)
256 {
257         struct fw_page *fwp;
258         int n;
259
260         fwp = find_fw_page(dev, addr & MLX5_U64_4K_PAGE_MASK, function);
261         if (!fwp) {
262                 mlx5_core_warn_rl(dev, "page not found\n");
263                 return;
264         }
265         n = (addr & ~MLX5_U64_4K_PAGE_MASK) >> MLX5_ADAPTER_PAGE_SHIFT;
266         fwp->free_count++;
267         set_bit(n, &fwp->bitmask);
268         if (fwp->free_count == MLX5_NUM_4K_IN_PAGE)
269                 free_fwp(dev, fwp, fwp->free_count != 1);
270         else if (fwp->free_count == 1)
271                 list_add(&fwp->list, &dev->priv.free_list);
272 }
273
274 static int alloc_system_page(struct mlx5_core_dev *dev, u32 function)
275 {
276         struct device *device = mlx5_core_dma_dev(dev);
277         int nid = dev_to_node(device);
278         struct page *page;
279         u64 zero_addr = 1;
280         u64 addr;
281         int err;
282
283         page = alloc_pages_node(nid, GFP_HIGHUSER, 0);
284         if (!page) {
285                 mlx5_core_warn(dev, "failed to allocate page\n");
286                 return -ENOMEM;
287         }
288 map:
289         addr = dma_map_page(device, page, 0, PAGE_SIZE, DMA_BIDIRECTIONAL);
290         if (dma_mapping_error(device, addr)) {
291                 mlx5_core_warn(dev, "failed dma mapping page\n");
292                 err = -ENOMEM;
293                 goto err_mapping;
294         }
295
296         /* Firmware doesn't support page with physical address 0 */
297         if (addr == 0) {
298                 zero_addr = addr;
299                 goto map;
300         }
301
302         err = insert_page(dev, addr, page, function);
303         if (err) {
304                 mlx5_core_err(dev, "failed to track allocated page\n");
305                 dma_unmap_page(device, addr, PAGE_SIZE, DMA_BIDIRECTIONAL);
306         }
307
308 err_mapping:
309         if (err)
310                 __free_page(page);
311
312         if (zero_addr == 0)
313                 dma_unmap_page(device, zero_addr, PAGE_SIZE,
314                                DMA_BIDIRECTIONAL);
315
316         return err;
317 }
318
319 static void page_notify_fail(struct mlx5_core_dev *dev, u16 func_id,
320                              bool ec_function)
321 {
322         u32 in[MLX5_ST_SZ_DW(manage_pages_in)] = {};
323         int err;
324
325         MLX5_SET(manage_pages_in, in, opcode, MLX5_CMD_OP_MANAGE_PAGES);
326         MLX5_SET(manage_pages_in, in, op_mod, MLX5_PAGES_CANT_GIVE);
327         MLX5_SET(manage_pages_in, in, function_id, func_id);
328         MLX5_SET(manage_pages_in, in, embedded_cpu_function, ec_function);
329
330         err = mlx5_cmd_exec_in(dev, manage_pages, in);
331         if (err)
332                 mlx5_core_warn(dev, "page notify failed func_id(%d) err(%d)\n",
333                                func_id, err);
334 }
335
336 static int give_pages(struct mlx5_core_dev *dev, u16 func_id, int npages,
337                       int event, bool ec_function)
338 {
339         u32 function = get_function(func_id, ec_function);
340         u32 out[MLX5_ST_SZ_DW(manage_pages_out)] = {0};
341         int inlen = MLX5_ST_SZ_BYTES(manage_pages_in);
342         int notify_fail = event;
343         u16 func_type;
344         u64 addr;
345         int err;
346         u32 *in;
347         int i;
348
349         inlen += npages * MLX5_FLD_SZ_BYTES(manage_pages_in, pas[0]);
350         in = kvzalloc(inlen, GFP_KERNEL);
351         if (!in) {
352                 err = -ENOMEM;
353                 mlx5_core_warn(dev, "vzalloc failed %d\n", inlen);
354                 goto out_free;
355         }
356
357         for (i = 0; i < npages; i++) {
358 retry:
359                 err = alloc_4k(dev, &addr, function);
360                 if (err) {
361                         if (err == -ENOMEM)
362                                 err = alloc_system_page(dev, function);
363                         if (err) {
364                                 dev->priv.fw_pages_alloc_failed += (npages - i);
365                                 goto out_4k;
366                         }
367
368                         goto retry;
369                 }
370                 MLX5_ARRAY_SET64(manage_pages_in, in, pas, i, addr);
371         }
372
373         MLX5_SET(manage_pages_in, in, opcode, MLX5_CMD_OP_MANAGE_PAGES);
374         MLX5_SET(manage_pages_in, in, op_mod, MLX5_PAGES_GIVE);
375         MLX5_SET(manage_pages_in, in, function_id, func_id);
376         MLX5_SET(manage_pages_in, in, input_num_entries, npages);
377         MLX5_SET(manage_pages_in, in, embedded_cpu_function, ec_function);
378
379         err = mlx5_cmd_do(dev, in, inlen, out, sizeof(out));
380         if (err == -EREMOTEIO) {
381                 notify_fail = 0;
382                 /* if triggered by FW and failed by FW ignore */
383                 if (event) {
384                         err = 0;
385                         goto out_dropped;
386                 }
387         }
388         err = mlx5_cmd_check(dev, err, in, out);
389         if (err) {
390                 mlx5_core_warn(dev, "func_id 0x%x, npages %d, err %d\n",
391                                func_id, npages, err);
392                 goto out_dropped;
393         }
394
395         func_type = func_id_to_type(dev, func_id, ec_function);
396         dev->priv.page_counters[func_type] += npages;
397         dev->priv.fw_pages += npages;
398
399         mlx5_core_dbg(dev, "npages %d, ec_function %d, func_id 0x%x, err %d\n",
400                       npages, ec_function, func_id, err);
401
402         kvfree(in);
403         return 0;
404
405 out_dropped:
406         dev->priv.give_pages_dropped += npages;
407 out_4k:
408         for (i--; i >= 0; i--)
409                 free_4k(dev, MLX5_GET64(manage_pages_in, in, pas[i]), function);
410 out_free:
411         kvfree(in);
412         if (notify_fail)
413                 page_notify_fail(dev, func_id, ec_function);
414         return err;
415 }
416
417 static void release_all_pages(struct mlx5_core_dev *dev, u16 func_id,
418                               bool ec_function)
419 {
420         u32 function = get_function(func_id, ec_function);
421         struct rb_root *root;
422         struct rb_node *p;
423         int npages = 0;
424         u16 func_type;
425
426         root = xa_load(&dev->priv.page_root_xa, function);
427         if (WARN_ON_ONCE(!root))
428                 return;
429
430         p = rb_first(root);
431         while (p) {
432                 struct fw_page *fwp = rb_entry(p, struct fw_page, rb_node);
433
434                 p = rb_next(p);
435                 npages += (MLX5_NUM_4K_IN_PAGE - fwp->free_count);
436                 free_fwp(dev, fwp, fwp->free_count);
437         }
438
439         func_type = func_id_to_type(dev, func_id, ec_function);
440         dev->priv.page_counters[func_type] -= npages;
441         dev->priv.fw_pages -= npages;
442
443         mlx5_core_dbg(dev, "npages %d, ec_function %d, func_id 0x%x\n",
444                       npages, ec_function, func_id);
445 }
446
447 static u32 fwp_fill_manage_pages_out(struct fw_page *fwp, u32 *out, u32 index,
448                                      u32 npages)
449 {
450         u32 pages_set = 0;
451         unsigned int n;
452
453         for_each_clear_bit(n, &fwp->bitmask, MLX5_NUM_4K_IN_PAGE) {
454                 MLX5_ARRAY_SET64(manage_pages_out, out, pas, index + pages_set,
455                                  fwp->addr + (n * MLX5_ADAPTER_PAGE_SIZE));
456                 pages_set++;
457
458                 if (!--npages)
459                         break;
460         }
461
462         return pages_set;
463 }
464
465 static int reclaim_pages_cmd(struct mlx5_core_dev *dev,
466                              u32 *in, int in_size, u32 *out, int out_size)
467 {
468         struct rb_root *root;
469         struct fw_page *fwp;
470         struct rb_node *p;
471         bool ec_function;
472         u32 func_id;
473         u32 npages;
474         u32 i = 0;
475
476         if (!mlx5_cmd_is_down(dev))
477                 return mlx5_cmd_do(dev, in, in_size, out, out_size);
478
479         /* No hard feelings, we want our pages back! */
480         npages = MLX5_GET(manage_pages_in, in, input_num_entries);
481         func_id = MLX5_GET(manage_pages_in, in, function_id);
482         ec_function = MLX5_GET(manage_pages_in, in, embedded_cpu_function);
483
484         root = xa_load(&dev->priv.page_root_xa, get_function(func_id, ec_function));
485         if (WARN_ON_ONCE(!root))
486                 return -EEXIST;
487
488         p = rb_first(root);
489         while (p && i < npages) {
490                 fwp = rb_entry(p, struct fw_page, rb_node);
491                 p = rb_next(p);
492
493                 i += fwp_fill_manage_pages_out(fwp, out, i, npages - i);
494         }
495
496         MLX5_SET(manage_pages_out, out, output_num_entries, i);
497         return 0;
498 }
499
500 static int reclaim_pages(struct mlx5_core_dev *dev, u16 func_id, int npages,
501                          int *nclaimed, bool event, bool ec_function)
502 {
503         u32 function = get_function(func_id, ec_function);
504         int outlen = MLX5_ST_SZ_BYTES(manage_pages_out);
505         u32 in[MLX5_ST_SZ_DW(manage_pages_in)] = {};
506         int num_claimed;
507         u16 func_type;
508         u32 *out;
509         int err;
510         int i;
511
512         if (nclaimed)
513                 *nclaimed = 0;
514
515         outlen += npages * MLX5_FLD_SZ_BYTES(manage_pages_out, pas[0]);
516         out = kvzalloc(outlen, GFP_KERNEL);
517         if (!out)
518                 return -ENOMEM;
519
520         MLX5_SET(manage_pages_in, in, opcode, MLX5_CMD_OP_MANAGE_PAGES);
521         MLX5_SET(manage_pages_in, in, op_mod, MLX5_PAGES_TAKE);
522         MLX5_SET(manage_pages_in, in, function_id, func_id);
523         MLX5_SET(manage_pages_in, in, input_num_entries, npages);
524         MLX5_SET(manage_pages_in, in, embedded_cpu_function, ec_function);
525
526         mlx5_core_dbg(dev, "func 0x%x, npages %d, outlen %d\n",
527                       func_id, npages, outlen);
528         err = reclaim_pages_cmd(dev, in, sizeof(in), out, outlen);
529         if (err) {
530                 npages = MLX5_GET(manage_pages_in, in, input_num_entries);
531                 dev->priv.reclaim_pages_discard += npages;
532         }
533         /* if triggered by FW event and failed by FW then ignore */
534         if (event && err == -EREMOTEIO) {
535                 err = 0;
536                 goto out_free;
537         }
538
539         err = mlx5_cmd_check(dev, err, in, out);
540         if (err) {
541                 mlx5_core_err(dev, "failed reclaiming pages: err %d\n", err);
542                 goto out_free;
543         }
544
545         num_claimed = MLX5_GET(manage_pages_out, out, output_num_entries);
546         if (num_claimed > npages) {
547                 mlx5_core_warn(dev, "fw returned %d, driver asked %d => corruption\n",
548                                num_claimed, npages);
549                 err = -EINVAL;
550                 goto out_free;
551         }
552
553         for (i = 0; i < num_claimed; i++)
554                 free_4k(dev, MLX5_GET64(manage_pages_out, out, pas[i]), function);
555
556         if (nclaimed)
557                 *nclaimed = num_claimed;
558
559         func_type = func_id_to_type(dev, func_id, ec_function);
560         dev->priv.page_counters[func_type] -= num_claimed;
561         dev->priv.fw_pages -= num_claimed;
562
563 out_free:
564         kvfree(out);
565         return err;
566 }
567
568 static void pages_work_handler(struct work_struct *work)
569 {
570         struct mlx5_pages_req *req = container_of(work, struct mlx5_pages_req, work);
571         struct mlx5_core_dev *dev = req->dev;
572         int err = 0;
573
574         if (req->release_all)
575                 release_all_pages(dev, req->func_id, req->ec_function);
576         else if (req->npages < 0)
577                 err = reclaim_pages(dev, req->func_id, -1 * req->npages, NULL,
578                                     true, req->ec_function);
579         else if (req->npages > 0)
580                 err = give_pages(dev, req->func_id, req->npages, 1, req->ec_function);
581
582         if (err)
583                 mlx5_core_warn(dev, "%s fail %d\n",
584                                req->npages < 0 ? "reclaim" : "give", err);
585
586         kfree(req);
587 }
588
589 enum {
590         EC_FUNCTION_MASK = 0x8000,
591         RELEASE_ALL_PAGES_MASK = 0x4000,
592 };
593
594 static int req_pages_handler(struct notifier_block *nb,
595                              unsigned long type, void *data)
596 {
597         struct mlx5_pages_req *req;
598         struct mlx5_core_dev *dev;
599         struct mlx5_priv *priv;
600         struct mlx5_eqe *eqe;
601         bool ec_function;
602         bool release_all;
603         u16 func_id;
604         s32 npages;
605
606         priv = mlx5_nb_cof(nb, struct mlx5_priv, pg_nb);
607         dev  = container_of(priv, struct mlx5_core_dev, priv);
608         eqe  = data;
609
610         func_id = be16_to_cpu(eqe->data.req_pages.func_id);
611         npages  = be32_to_cpu(eqe->data.req_pages.num_pages);
612         ec_function = be16_to_cpu(eqe->data.req_pages.ec_function) & EC_FUNCTION_MASK;
613         release_all = be16_to_cpu(eqe->data.req_pages.ec_function) &
614                       RELEASE_ALL_PAGES_MASK;
615         mlx5_core_dbg(dev, "page request for func 0x%x, npages %d, release_all %d\n",
616                       func_id, npages, release_all);
617         req = kzalloc(sizeof(*req), GFP_ATOMIC);
618         if (!req) {
619                 mlx5_core_warn(dev, "failed to allocate pages request\n");
620                 return NOTIFY_DONE;
621         }
622
623         req->dev = dev;
624         req->func_id = func_id;
625         req->npages = npages;
626         req->ec_function = ec_function;
627         req->release_all = release_all;
628         INIT_WORK(&req->work, pages_work_handler);
629         queue_work(dev->priv.pg_wq, &req->work);
630         return NOTIFY_OK;
631 }
632
633 int mlx5_satisfy_startup_pages(struct mlx5_core_dev *dev, int boot)
634 {
635         u16 func_id;
636         s32 npages;
637         int err;
638
639         err = mlx5_cmd_query_pages(dev, &func_id, &npages, boot);
640         if (err)
641                 return err;
642
643         mlx5_core_dbg(dev, "requested %d %s pages for func_id 0x%x\n",
644                       npages, boot ? "boot" : "init", func_id);
645
646         return give_pages(dev, func_id, npages, 0, mlx5_core_is_ecpf(dev));
647 }
648
649 enum {
650         MLX5_BLKS_FOR_RECLAIM_PAGES = 12
651 };
652
653 static int optimal_reclaimed_pages(void)
654 {
655         struct mlx5_cmd_prot_block *block;
656         struct mlx5_cmd_layout *lay;
657         int ret;
658
659         ret = (sizeof(lay->out) + MLX5_BLKS_FOR_RECLAIM_PAGES * sizeof(block->data) -
660                MLX5_ST_SZ_BYTES(manage_pages_out)) /
661                MLX5_FLD_SZ_BYTES(manage_pages_out, pas[0]);
662
663         return ret;
664 }
665
666 static int mlx5_reclaim_root_pages(struct mlx5_core_dev *dev,
667                                    struct rb_root *root, u16 func_id)
668 {
669         u64 recl_pages_to_jiffies = msecs_to_jiffies(mlx5_tout_ms(dev, RECLAIM_PAGES));
670         unsigned long end = jiffies + recl_pages_to_jiffies;
671
672         while (!RB_EMPTY_ROOT(root)) {
673                 int nclaimed;
674                 int err;
675
676                 err = reclaim_pages(dev, func_id, optimal_reclaimed_pages(),
677                                     &nclaimed, false, mlx5_core_is_ecpf(dev));
678                 if (err) {
679                         mlx5_core_warn(dev, "failed reclaiming pages (%d) for func id 0x%x\n",
680                                        err, func_id);
681                         return err;
682                 }
683
684                 if (nclaimed)
685                         end = jiffies + recl_pages_to_jiffies;
686
687                 if (time_after(jiffies, end)) {
688                         mlx5_core_warn(dev, "FW did not return all pages. giving up...\n");
689                         break;
690                 }
691         }
692
693         return 0;
694 }
695
696 int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev)
697 {
698         struct rb_root *root;
699         unsigned long id;
700         void *entry;
701
702         xa_for_each(&dev->priv.page_root_xa, id, entry) {
703                 root = entry;
704                 mlx5_reclaim_root_pages(dev, root, id);
705                 xa_erase(&dev->priv.page_root_xa, id);
706                 kfree(root);
707         }
708
709         WARN_ON(!xa_empty(&dev->priv.page_root_xa));
710
711         WARN(dev->priv.fw_pages,
712              "FW pages counter is %d after reclaiming all pages\n",
713              dev->priv.fw_pages);
714         WARN(dev->priv.page_counters[MLX5_VF],
715              "VFs FW pages counter is %d after reclaiming all pages\n",
716              dev->priv.page_counters[MLX5_VF]);
717         WARN(dev->priv.page_counters[MLX5_HOST_PF],
718              "External host PF FW pages counter is %d after reclaiming all pages\n",
719              dev->priv.page_counters[MLX5_HOST_PF]);
720
721         return 0;
722 }
723
724 int mlx5_pagealloc_init(struct mlx5_core_dev *dev)
725 {
726         INIT_LIST_HEAD(&dev->priv.free_list);
727         dev->priv.pg_wq = create_singlethread_workqueue("mlx5_page_allocator");
728         if (!dev->priv.pg_wq)
729                 return -ENOMEM;
730
731         xa_init(&dev->priv.page_root_xa);
732         mlx5_pages_debugfs_init(dev);
733
734         return 0;
735 }
736
737 void mlx5_pagealloc_cleanup(struct mlx5_core_dev *dev)
738 {
739         mlx5_pages_debugfs_cleanup(dev);
740         xa_destroy(&dev->priv.page_root_xa);
741         destroy_workqueue(dev->priv.pg_wq);
742 }
743
744 void mlx5_pagealloc_start(struct mlx5_core_dev *dev)
745 {
746         MLX5_NB_INIT(&dev->priv.pg_nb, req_pages_handler, PAGE_REQUEST);
747         mlx5_eq_notifier_register(dev, &dev->priv.pg_nb);
748 }
749
750 void mlx5_pagealloc_stop(struct mlx5_core_dev *dev)
751 {
752         mlx5_eq_notifier_unregister(dev, &dev->priv.pg_nb);
753         flush_workqueue(dev->priv.pg_wq);
754 }
755
756 int mlx5_wait_for_pages(struct mlx5_core_dev *dev, int *pages)
757 {
758         u64 recl_vf_pages_to_jiffies = msecs_to_jiffies(mlx5_tout_ms(dev, RECLAIM_VFS_PAGES));
759         unsigned long end = jiffies + recl_vf_pages_to_jiffies;
760         int prev_pages = *pages;
761
762         /* In case of internal error we will free the pages manually later */
763         if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
764                 mlx5_core_warn(dev, "Skipping wait for vf pages stage");
765                 return 0;
766         }
767
768         mlx5_core_dbg(dev, "Waiting for %d pages\n", prev_pages);
769         while (*pages) {
770                 if (time_after(jiffies, end)) {
771                         mlx5_core_warn(dev, "aborting while there are %d pending pages\n", *pages);
772                         return -ETIMEDOUT;
773                 }
774                 if (*pages < prev_pages) {
775                         end = jiffies + recl_vf_pages_to_jiffies;
776                         prev_pages = *pages;
777                 }
778                 msleep(50);
779         }
780
781         mlx5_core_dbg(dev, "All pages received\n");
782         return 0;
783 }