1 | /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ |
2 | /* |
3 | * Copyright(c) 2017 Intel Corporation. |
4 | */ |
5 | |
6 | #ifndef _HFI1_EXP_RCV_H |
7 | #define _HFI1_EXP_RCV_H |
8 | #include "hfi.h" |
9 | |
10 | #define EXP_TID_SET_EMPTY(set) (set.count == 0 && list_empty(&set.list)) |
11 | |
12 | #define EXP_TID_TIDLEN_MASK 0x7FFULL |
13 | #define EXP_TID_TIDLEN_SHIFT 0 |
14 | #define EXP_TID_TIDCTRL_MASK 0x3ULL |
15 | #define EXP_TID_TIDCTRL_SHIFT 20 |
16 | #define EXP_TID_TIDIDX_MASK 0x3FFULL |
17 | #define EXP_TID_TIDIDX_SHIFT 22 |
18 | #define EXP_TID_GET(tid, field) \ |
19 | (((tid) >> EXP_TID_TID##field##_SHIFT) & EXP_TID_TID##field##_MASK) |
20 | |
21 | #define EXP_TID_SET(field, value) \ |
22 | (((value) & EXP_TID_TID##field##_MASK) << \ |
23 | EXP_TID_TID##field##_SHIFT) |
24 | #define EXP_TID_CLEAR(tid, field) ({ \ |
25 | (tid) &= ~(EXP_TID_TID##field##_MASK << \ |
26 | EXP_TID_TID##field##_SHIFT); \ |
27 | }) |
28 | #define EXP_TID_RESET(tid, field, value) do { \ |
29 | EXP_TID_CLEAR(tid, field); \ |
30 | (tid) |= EXP_TID_SET(field, (value)); \ |
31 | } while (0) |
32 | |
33 | /* |
34 | * Define fields in the KDETH header so we can update the header |
35 | * template. |
36 | */ |
37 | #define KDETH_OFFSET_SHIFT 0 |
38 | #define KDETH_OFFSET_MASK 0x7fff |
39 | #define KDETH_OM_SHIFT 15 |
40 | #define KDETH_OM_MASK 0x1 |
41 | #define KDETH_TID_SHIFT 16 |
42 | #define KDETH_TID_MASK 0x3ff |
43 | #define KDETH_TIDCTRL_SHIFT 26 |
44 | #define KDETH_TIDCTRL_MASK 0x3 |
45 | #define KDETH_INTR_SHIFT 28 |
46 | #define KDETH_INTR_MASK 0x1 |
47 | #define KDETH_SH_SHIFT 29 |
48 | #define KDETH_SH_MASK 0x1 |
49 | #define KDETH_KVER_SHIFT 30 |
50 | #define KDETH_KVER_MASK 0x3 |
51 | #define KDETH_JKEY_SHIFT 0x0 |
52 | #define KDETH_JKEY_MASK 0xff |
53 | #define KDETH_HCRC_UPPER_SHIFT 16 |
54 | #define KDETH_HCRC_UPPER_MASK 0xff |
55 | #define KDETH_HCRC_LOWER_SHIFT 24 |
56 | #define KDETH_HCRC_LOWER_MASK 0xff |
57 | |
58 | #define KDETH_GET(val, field) \ |
59 | (((le32_to_cpu((val))) >> KDETH_##field##_SHIFT) & KDETH_##field##_MASK) |
60 | #define KDETH_SET(dw, field, val) do { \ |
61 | u32 dwval = le32_to_cpu(dw); \ |
62 | dwval &= ~(KDETH_##field##_MASK << KDETH_##field##_SHIFT); \ |
63 | dwval |= (((val) & KDETH_##field##_MASK) << \ |
64 | KDETH_##field##_SHIFT); \ |
65 | dw = cpu_to_le32(dwval); \ |
66 | } while (0) |
67 | |
68 | #define KDETH_RESET(dw, field, val) ({ dw = 0; KDETH_SET(dw, field, val); }) |
69 | |
70 | /* KDETH OM multipliers and switch over point */ |
71 | #define KDETH_OM_SMALL 4 |
72 | #define KDETH_OM_SMALL_SHIFT 2 |
73 | #define KDETH_OM_LARGE 64 |
74 | #define KDETH_OM_LARGE_SHIFT 6 |
75 | #define KDETH_OM_MAX_SIZE (1 << ((KDETH_OM_LARGE / KDETH_OM_SMALL) + 1)) |
76 | |
77 | struct tid_group { |
78 | struct list_head list; |
79 | u32 base; |
80 | u8 size; |
81 | u8 used; |
82 | u8 map; |
83 | }; |
84 | |
85 | /* |
86 | * Write an "empty" RcvArray entry. |
87 | * This function exists so the TID registaration code can use it |
88 | * to write to unused/unneeded entries and still take advantage |
89 | * of the WC performance improvements. The HFI will ignore this |
90 | * write to the RcvArray entry. |
91 | */ |
92 | static inline void rcv_array_wc_fill(struct hfi1_devdata *dd, u32 index) |
93 | { |
94 | /* |
95 | * Doing the WC fill writes only makes sense if the device is |
96 | * present and the RcvArray has been mapped as WC memory. |
97 | */ |
98 | if ((dd->flags & HFI1_PRESENT) && dd->rcvarray_wc) { |
99 | writeq(val: 0, addr: dd->rcvarray_wc + (index * 8)); |
100 | if ((index & 3) == 3) |
101 | flush_wc(); |
102 | } |
103 | } |
104 | |
105 | static inline void tid_group_add_tail(struct tid_group *grp, |
106 | struct exp_tid_set *set) |
107 | { |
108 | list_add_tail(new: &grp->list, head: &set->list); |
109 | set->count++; |
110 | } |
111 | |
112 | static inline void tid_group_remove(struct tid_group *grp, |
113 | struct exp_tid_set *set) |
114 | { |
115 | list_del_init(entry: &grp->list); |
116 | set->count--; |
117 | } |
118 | |
119 | static inline void tid_group_move(struct tid_group *group, |
120 | struct exp_tid_set *s1, |
121 | struct exp_tid_set *s2) |
122 | { |
123 | tid_group_remove(grp: group, set: s1); |
124 | tid_group_add_tail(grp: group, set: s2); |
125 | } |
126 | |
127 | static inline struct tid_group *tid_group_pop(struct exp_tid_set *set) |
128 | { |
129 | struct tid_group *grp = |
130 | list_first_entry(&set->list, struct tid_group, list); |
131 | list_del_init(entry: &grp->list); |
132 | set->count--; |
133 | return grp; |
134 | } |
135 | |
136 | static inline u32 create_tid(u32 rcventry, u32 npages) |
137 | { |
138 | u32 pair = rcventry & ~0x1; |
139 | |
140 | return EXP_TID_SET(IDX, pair >> 1) | |
141 | EXP_TID_SET(CTRL, 1 << (rcventry - pair)) | |
142 | EXP_TID_SET(LEN, npages); |
143 | } |
144 | |
145 | /** |
146 | * hfi1_tid_group_to_idx - convert an index to a group |
147 | * @rcd - the receive context |
148 | * @grp - the group pointer |
149 | */ |
150 | static inline u16 |
151 | hfi1_tid_group_to_idx(struct hfi1_ctxtdata *rcd, struct tid_group *grp) |
152 | { |
153 | return grp - &rcd->groups[0]; |
154 | } |
155 | |
156 | /** |
157 | * hfi1_idx_to_tid_group - convert a group to an index |
158 | * @rcd - the receive context |
159 | * @idx - the index |
160 | */ |
161 | static inline struct tid_group * |
162 | hfi1_idx_to_tid_group(struct hfi1_ctxtdata *rcd, u16 idx) |
163 | { |
164 | return &rcd->groups[idx]; |
165 | } |
166 | |
167 | int hfi1_alloc_ctxt_rcv_groups(struct hfi1_ctxtdata *rcd); |
168 | void hfi1_free_ctxt_rcv_groups(struct hfi1_ctxtdata *rcd); |
169 | void hfi1_exp_tid_group_init(struct hfi1_ctxtdata *rcd); |
170 | |
171 | #endif /* _HFI1_EXP_RCV_H */ |
172 | |