1
2
3
4
5
6
7
8
9
10
11
12
13#ifndef __CXGB4PPM_H__
14#define __CXGB4PPM_H__
15
16#include <linux/kernel.h>
17#include <linux/errno.h>
18#include <linux/types.h>
19#include <linux/debugfs.h>
20#include <linux/list.h>
21#include <linux/netdevice.h>
22#include <linux/scatterlist.h>
23#include <linux/skbuff.h>
24#include <linux/vmalloc.h>
25#include <linux/bitmap.h>
26
27struct cxgbi_pagepod_hdr {
28 u32 vld_tid;
29 u32 pgsz_tag_clr;
30 u32 max_offset;
31 u32 page_offset;
32 u64 rsvd;
33};
34
35#define PPOD_PAGES_MAX 4
36struct cxgbi_pagepod {
37 struct cxgbi_pagepod_hdr hdr;
38 u64 addr[PPOD_PAGES_MAX + 1];
39};
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56#define DDP_PGIDX_MAX 4
57#define DDP_PGSZ_BASE_SHIFT 12
58
59struct cxgbi_task_tag_info {
60 unsigned char flags;
61#define CXGBI_PPOD_INFO_FLAG_VALID 0x1
62#define CXGBI_PPOD_INFO_FLAG_MAPPED 0x2
63 unsigned char cid;
64 unsigned short pg_shift;
65 unsigned int npods;
66 unsigned int idx;
67 unsigned int tag;
68 struct cxgbi_pagepod_hdr hdr;
69 int nents;
70 int nr_pages;
71 struct scatterlist *sgl;
72};
73
74struct cxgbi_tag_format {
75 unsigned char pgsz_order[DDP_PGIDX_MAX];
76 unsigned char pgsz_idx_dflt;
77 unsigned char free_bits:4;
78 unsigned char color_bits:4;
79 unsigned char idx_bits;
80 unsigned char rsvd_bits;
81 unsigned int no_ddp_mask;
82 unsigned int idx_mask;
83 unsigned int color_mask;
84 unsigned int idx_clr_mask;
85 unsigned int rsvd_mask;
86};
87
88struct cxgbi_ppod_data {
89 unsigned char pg_idx:2;
90 unsigned char color:6;
91 unsigned char chan_id;
92 unsigned short npods;
93 unsigned long caller_data;
94};
95
96
97struct cxgbi_ppm_pool {
98 unsigned int base;
99 unsigned int next;
100 spinlock_t lock;
101 unsigned long bmap[0];
102} ____cacheline_aligned_in_smp;
103
104struct cxgbi_ppm {
105 struct kref refcnt;
106 struct net_device *ndev;
107 struct pci_dev *pdev;
108 void *lldev;
109 void **ppm_pp;
110 struct cxgbi_tag_format tformat;
111 unsigned int ppmax;
112 unsigned int llimit;
113 unsigned int base_idx;
114
115 unsigned int pool_rsvd;
116 unsigned int pool_index_max;
117 struct cxgbi_ppm_pool __percpu *pool;
118
119 spinlock_t map_lock;
120 unsigned int bmap_index_max;
121 unsigned int next;
122 unsigned long *ppod_bmap;
123 struct cxgbi_ppod_data ppod_data[0];
124};
125
126#define DDP_THRESHOLD 512
127
128#define PPOD_PAGES_SHIFT 2
129
130#define IPPOD_SIZE sizeof(struct cxgbi_pagepod)
131#define PPOD_SIZE_SHIFT 6
132
133
134#define PPOD_CLUSTER_SIZE 16U
135
136#define ULPMEM_DSGL_MAX_NPPODS 16
137#define ULPMEM_IDATA_MAX_NPPODS 3
138#define PCIE_MEMWIN_MAX_NPPODS 16
139
140#define PPOD_COLOR_SHIFT 0
141#define PPOD_COLOR(x) ((x) << PPOD_COLOR_SHIFT)
142
143#define PPOD_IDX_SHIFT 6
144#define PPOD_IDX_MAX_SIZE 24
145
146#define PPOD_TID_SHIFT 0
147#define PPOD_TID(x) ((x) << PPOD_TID_SHIFT)
148
149#define PPOD_TAG_SHIFT 6
150#define PPOD_TAG(x) ((x) << PPOD_TAG_SHIFT)
151
152#define PPOD_VALID_SHIFT 24
153#define PPOD_VALID(x) ((x) << PPOD_VALID_SHIFT)
154#define PPOD_VALID_FLAG PPOD_VALID(1U)
155
156#define PPOD_PI_EXTRACT_CTL_SHIFT 31
157#define PPOD_PI_EXTRACT_CTL(x) ((x) << PPOD_PI_EXTRACT_CTL_SHIFT)
158#define PPOD_PI_EXTRACT_CTL_FLAG V_PPOD_PI_EXTRACT_CTL(1U)
159
160#define PPOD_PI_TYPE_SHIFT 29
161#define PPOD_PI_TYPE_MASK 0x3
162#define PPOD_PI_TYPE(x) ((x) << PPOD_PI_TYPE_SHIFT)
163
164#define PPOD_PI_CHECK_CTL_SHIFT 27
165#define PPOD_PI_CHECK_CTL_MASK 0x3
166#define PPOD_PI_CHECK_CTL(x) ((x) << PPOD_PI_CHECK_CTL_SHIFT)
167
168#define PPOD_PI_REPORT_CTL_SHIFT 25
169#define PPOD_PI_REPORT_CTL_MASK 0x3
170#define PPOD_PI_REPORT_CTL(x) ((x) << PPOD_PI_REPORT_CTL_SHIFT)
171
172static inline int cxgbi_ppm_is_ddp_tag(struct cxgbi_ppm *ppm, u32 tag)
173{
174 return !(tag & ppm->tformat.no_ddp_mask);
175}
176
177static inline int cxgbi_ppm_sw_tag_is_usable(struct cxgbi_ppm *ppm,
178 u32 tag)
179{
180
181 return !(tag & 0x80000000U);
182}
183
184static inline int cxgbi_ppm_make_non_ddp_tag(struct cxgbi_ppm *ppm,
185 u32 sw_tag,
186 u32 *final_tag)
187{
188 struct cxgbi_tag_format *tformat = &ppm->tformat;
189
190 if (!cxgbi_ppm_sw_tag_is_usable(ppm, sw_tag)) {
191 pr_info("sw_tag 0x%x NOT usable.\n", sw_tag);
192 return -EINVAL;
193 }
194
195 if (!sw_tag) {
196 *final_tag = tformat->no_ddp_mask;
197 } else {
198 unsigned int shift = tformat->idx_bits + tformat->color_bits;
199 u32 lower = sw_tag & tformat->idx_clr_mask;
200 u32 upper = (sw_tag >> shift) << (shift + 1);
201
202 *final_tag = upper | tformat->no_ddp_mask | lower;
203 }
204 return 0;
205}
206
207static inline u32 cxgbi_ppm_decode_non_ddp_tag(struct cxgbi_ppm *ppm,
208 u32 tag)
209{
210 struct cxgbi_tag_format *tformat = &ppm->tformat;
211 unsigned int shift = tformat->idx_bits + tformat->color_bits;
212 u32 lower = tag & tformat->idx_clr_mask;
213 u32 upper = (tag >> tformat->rsvd_bits) << shift;
214
215 return upper | lower;
216}
217
218static inline u32 cxgbi_ppm_ddp_tag_get_idx(struct cxgbi_ppm *ppm,
219 u32 ddp_tag)
220{
221 u32 hw_idx = (ddp_tag >> PPOD_IDX_SHIFT) &
222 ppm->tformat.idx_mask;
223
224 return hw_idx - ppm->base_idx;
225}
226
227static inline u32 cxgbi_ppm_make_ddp_tag(unsigned int hw_idx,
228 unsigned char color)
229{
230 return (hw_idx << PPOD_IDX_SHIFT) | ((u32)color);
231}
232
233static inline unsigned long
234cxgbi_ppm_get_tag_caller_data(struct cxgbi_ppm *ppm,
235 u32 ddp_tag)
236{
237 u32 idx = cxgbi_ppm_ddp_tag_get_idx(ppm, ddp_tag);
238
239 return ppm->ppod_data[idx].caller_data;
240}
241
242
243static inline int cxgbi_ppm_ddp_tag_update_sw_bits(struct cxgbi_ppm *ppm,
244 u32 val, u32 orig_tag,
245 u32 *final_tag)
246{
247 struct cxgbi_tag_format *tformat = &ppm->tformat;
248 u32 v = val >> tformat->free_bits;
249
250 if (v) {
251 pr_info("sw_bits 0x%x too large, avail bits %u.\n",
252 val, tformat->free_bits);
253 return -EINVAL;
254 }
255 if (!cxgbi_ppm_is_ddp_tag(ppm, orig_tag))
256 return -EINVAL;
257
258 *final_tag = (val << tformat->rsvd_bits) |
259 (orig_tag & ppm->tformat.rsvd_mask);
260 return 0;
261}
262
263static inline void cxgbi_ppm_ppod_clear(struct cxgbi_pagepod *ppod)
264{
265 ppod->hdr.vld_tid = 0U;
266}
267
268static inline void cxgbi_tagmask_check(unsigned int tagmask,
269 struct cxgbi_tag_format *tformat)
270{
271 unsigned int bits = fls(tagmask);
272
273
274 tformat->free_bits = 32 - 2 - bits;
275 tformat->rsvd_bits = bits;
276 tformat->color_bits = PPOD_IDX_SHIFT;
277 tformat->idx_bits = bits - 1 - PPOD_IDX_SHIFT;
278 tformat->no_ddp_mask = 1 << (bits - 1);
279 tformat->idx_mask = (1 << tformat->idx_bits) - 1;
280 tformat->color_mask = (1 << PPOD_IDX_SHIFT) - 1;
281 tformat->idx_clr_mask = (1 << (bits - 1)) - 1;
282 tformat->rsvd_mask = (1 << bits) - 1;
283
284 pr_info("ippm: tagmask 0x%x, rsvd %u=%u+%u+1, mask 0x%x,0x%x, "
285 "pg %u,%u,%u,%u.\n",
286 tagmask, tformat->rsvd_bits, tformat->idx_bits,
287 tformat->color_bits, tformat->no_ddp_mask, tformat->rsvd_mask,
288 tformat->pgsz_order[0], tformat->pgsz_order[1],
289 tformat->pgsz_order[2], tformat->pgsz_order[3]);
290}
291
292int cxgbi_ppm_find_page_index(struct cxgbi_ppm *ppm, unsigned long pgsz);
293void cxgbi_ppm_make_ppod_hdr(struct cxgbi_ppm *ppm, u32 tag,
294 unsigned int tid, unsigned int offset,
295 unsigned int length,
296 struct cxgbi_pagepod_hdr *hdr);
297void cxgbi_ppm_ppod_release(struct cxgbi_ppm *, u32 idx);
298int cxgbi_ppm_ppods_reserve(struct cxgbi_ppm *, unsigned short nr_pages,
299 u32 per_tag_pg_idx, u32 *ppod_idx, u32 *ddp_tag,
300 unsigned long caller_data);
301int cxgbi_ppm_init(void **ppm_pp, struct net_device *, struct pci_dev *,
302 void *lldev, struct cxgbi_tag_format *,
303 unsigned int ppmax, unsigned int llimit,
304 unsigned int start,
305 unsigned int reserve_factor);
306int cxgbi_ppm_release(struct cxgbi_ppm *ppm);
307void cxgbi_tagmask_check(unsigned int tagmask, struct cxgbi_tag_format *);
308unsigned int cxgbi_tagmask_set(unsigned int ppmax);
309
310#endif
311