1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (c) 2016 HGST, a Western Digital Company. |
4 | */ |
5 | #include <rdma/ib_verbs.h> |
6 | #include <rdma/mr_pool.h> |
7 | |
8 | struct ib_mr *ib_mr_pool_get(struct ib_qp *qp, struct list_head *list) |
9 | { |
10 | struct ib_mr *mr; |
11 | unsigned long flags; |
12 | |
13 | spin_lock_irqsave(&qp->mr_lock, flags); |
14 | mr = list_first_entry_or_null(list, struct ib_mr, qp_entry); |
15 | if (mr) { |
16 | list_del(entry: &mr->qp_entry); |
17 | qp->mrs_used++; |
18 | } |
19 | spin_unlock_irqrestore(lock: &qp->mr_lock, flags); |
20 | |
21 | return mr; |
22 | } |
23 | EXPORT_SYMBOL(ib_mr_pool_get); |
24 | |
25 | void ib_mr_pool_put(struct ib_qp *qp, struct list_head *list, struct ib_mr *mr) |
26 | { |
27 | unsigned long flags; |
28 | |
29 | spin_lock_irqsave(&qp->mr_lock, flags); |
30 | list_add(new: &mr->qp_entry, head: list); |
31 | qp->mrs_used--; |
32 | spin_unlock_irqrestore(lock: &qp->mr_lock, flags); |
33 | } |
34 | EXPORT_SYMBOL(ib_mr_pool_put); |
35 | |
36 | int ib_mr_pool_init(struct ib_qp *qp, struct list_head *list, int nr, |
37 | enum ib_mr_type type, u32 max_num_sg, u32 max_num_meta_sg) |
38 | { |
39 | struct ib_mr *mr; |
40 | unsigned long flags; |
41 | int ret, i; |
42 | |
43 | for (i = 0; i < nr; i++) { |
44 | if (type == IB_MR_TYPE_INTEGRITY) |
45 | mr = ib_alloc_mr_integrity(pd: qp->pd, max_num_data_sg: max_num_sg, |
46 | max_num_meta_sg); |
47 | else |
48 | mr = ib_alloc_mr(pd: qp->pd, mr_type: type, max_num_sg); |
49 | if (IS_ERR(ptr: mr)) { |
50 | ret = PTR_ERR(ptr: mr); |
51 | goto out; |
52 | } |
53 | |
54 | spin_lock_irqsave(&qp->mr_lock, flags); |
55 | list_add_tail(new: &mr->qp_entry, head: list); |
56 | spin_unlock_irqrestore(lock: &qp->mr_lock, flags); |
57 | } |
58 | |
59 | return 0; |
60 | out: |
61 | ib_mr_pool_destroy(qp, list); |
62 | return ret; |
63 | } |
64 | EXPORT_SYMBOL(ib_mr_pool_init); |
65 | |
66 | void ib_mr_pool_destroy(struct ib_qp *qp, struct list_head *list) |
67 | { |
68 | struct ib_mr *mr; |
69 | unsigned long flags; |
70 | |
71 | spin_lock_irqsave(&qp->mr_lock, flags); |
72 | while (!list_empty(head: list)) { |
73 | mr = list_first_entry(list, struct ib_mr, qp_entry); |
74 | list_del(entry: &mr->qp_entry); |
75 | |
76 | spin_unlock_irqrestore(lock: &qp->mr_lock, flags); |
77 | ib_dereg_mr(mr); |
78 | spin_lock_irqsave(&qp->mr_lock, flags); |
79 | } |
80 | spin_unlock_irqrestore(lock: &qp->mr_lock, flags); |
81 | } |
82 | EXPORT_SYMBOL(ib_mr_pool_destroy); |
83 | |