1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
|
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2018-2025, Advanced Micro Devices, Inc. */
#ifndef _IONIC_IBDEV_H_
#define _IONIC_IBDEV_H_
#include <rdma/ib_umem.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_pack.h>
#include <rdma/uverbs_ioctl.h>
#include <rdma/ionic-abi.h>
#include <ionic_api.h>
#include <ionic_regs.h>
#include "ionic_fw.h"
#include "ionic_queue.h"
#include "ionic_res.h"
#include "ionic_lif_cfg.h"
/* Config knobs */
#define IONIC_EQ_DEPTH 511
#define IONIC_EQ_COUNT 32
#define IONIC_AQ_DEPTH 63
#define IONIC_AQ_COUNT 4
#define IONIC_EQ_ISR_BUDGET 10
#define IONIC_EQ_WORK_BUDGET 1000
#define IONIC_MAX_RD_ATOM 16
#define IONIC_PKEY_TBL_LEN 1
#define IONIC_GID_TBL_LEN 256
#define IONIC_MAX_QPID 0xffffff
#define IONIC_SPEC_HIGH 8
#define IONIC_MAX_PD 1024
#define IONIC_SPEC_HIGH 8
#define IONIC_SQCMB_ORDER 5
#define IONIC_RQCMB_ORDER 0
#define IONIC_META_LAST ((void *)1ul)
#define IONIC_META_POSTED ((void *)2ul)
#define IONIC_CQ_GRACE 100
#define IONIC_ROCE_UDP_SPORT 28272
#define IONIC_DMA_LKEY 0
#define IONIC_DMA_RKEY IONIC_DMA_LKEY
#define IONIC_CMB_SUPPORTED \
(IONIC_CMB_ENABLE | IONIC_CMB_REQUIRE | IONIC_CMB_EXPDB | \
IONIC_CMB_WC | IONIC_CMB_UC)
/* resource is not reserved on the device, indicated in tbl_order */
#define IONIC_RES_INVALID -1
struct ionic_aq;
struct ionic_cq;
struct ionic_eq;
struct ionic_vcq;
enum ionic_admin_state {
IONIC_ADMIN_ACTIVE, /* submitting admin commands to queue */
IONIC_ADMIN_PAUSED, /* not submitting, but may complete normally */
IONIC_ADMIN_KILLED, /* not submitting, locally completed */
};
enum ionic_admin_flags {
IONIC_ADMIN_F_BUSYWAIT = BIT(0), /* Don't sleep */
IONIC_ADMIN_F_TEARDOWN = BIT(1), /* In destroy path */
IONIC_ADMIN_F_INTERRUPT = BIT(2), /* Interruptible w/timeout */
};
enum ionic_mmap_flag {
IONIC_MMAP_WC = BIT(0),
};
struct ionic_mmap_entry {
struct rdma_user_mmap_entry rdma_entry;
unsigned long size;
unsigned long pfn;
u8 mmap_flags;
};
struct ionic_ibdev {
struct ib_device ibdev;
struct ionic_lif_cfg lif_cfg;
struct xarray qp_tbl;
struct xarray cq_tbl;
struct ionic_resid_bits inuse_dbid;
struct ionic_resid_bits inuse_pdid;
struct ionic_resid_bits inuse_ahid;
struct ionic_resid_bits inuse_mrid;
struct ionic_resid_bits inuse_qpid;
struct ionic_resid_bits inuse_cqid;
u8 half_cqid_udma_shift;
u8 half_qpid_udma_shift;
u8 next_qpid_udma_idx;
u8 next_mrkey;
struct work_struct reset_work;
bool reset_posted;
u32 reset_cnt;
struct delayed_work admin_dwork;
struct ionic_aq **aq_vec;
atomic_t admin_state;
struct ionic_eq **eq_vec;
struct ionic_v1_stat *hw_stats;
void *hw_stats_buf;
struct rdma_stat_desc *hw_stats_hdrs;
struct ionic_counter_stats *counter_stats;
int hw_stats_count;
};
struct ionic_eq {
struct ionic_ibdev *dev;
u32 eqid;
u32 intr;
struct ionic_queue q;
int armed;
bool enable;
struct work_struct work;
int irq;
char name[32];
};
struct ionic_admin_wr {
struct completion work;
struct list_head aq_ent;
struct ionic_v1_admin_wqe wqe;
struct ionic_v1_cqe cqe;
struct ionic_aq *aq;
int status;
};
struct ionic_admin_wr_q {
struct ionic_admin_wr *wr;
int wqe_strides;
};
struct ionic_aq {
struct ionic_ibdev *dev;
struct ionic_vcq *vcq;
struct work_struct work;
atomic_t admin_state;
unsigned long stamp;
bool armed;
u32 aqid;
u32 cqid;
spinlock_t lock; /* for posting */
struct ionic_queue q;
struct ionic_admin_wr_q *q_wr;
struct list_head wr_prod;
struct list_head wr_post;
};
struct ionic_ctx {
struct ib_ucontext ibctx;
u32 dbid;
struct rdma_user_mmap_entry *mmap_dbell;
};
struct ionic_tbl_buf {
u32 tbl_limit;
u32 tbl_pages;
size_t tbl_size;
__le64 *tbl_buf;
dma_addr_t tbl_dma;
u8 page_size_log2;
};
struct ionic_pd {
struct ib_pd ibpd;
u32 pdid;
u32 flags;
};
struct ionic_cq {
struct ionic_vcq *vcq;
u32 cqid;
u32 eqid;
spinlock_t lock; /* for polling */
struct list_head poll_sq;
bool flush;
struct list_head flush_sq;
struct list_head flush_rq;
struct list_head ibkill_flush_ent;
struct ionic_queue q;
bool color;
int credit;
u16 arm_any_prod;
u16 arm_sol_prod;
struct kref cq_kref;
struct completion cq_rel_comp;
/* infrequently accessed, keep at end */
struct ib_umem *umem;
};
struct ionic_vcq {
struct ib_cq ibcq;
struct ionic_cq cq[2];
u8 udma_mask;
u8 poll_idx;
};
struct ionic_sq_meta {
u64 wrid;
u32 len;
u16 seq;
u8 ibop;
u8 ibsts;
u8 remote:1;
u8 signal:1;
u8 local_comp:1;
};
struct ionic_rq_meta {
struct ionic_rq_meta *next;
u64 wrid;
};
struct ionic_qp {
struct ib_qp ibqp;
enum ib_qp_state state;
u32 qpid;
u32 ahid;
u32 sq_cqid;
u32 rq_cqid;
u8 udma_idx;
u8 has_ah:1;
u8 has_sq:1;
u8 has_rq:1;
u8 sig_all:1;
struct list_head qp_list_counter;
struct list_head cq_poll_sq;
struct list_head cq_flush_sq;
struct list_head cq_flush_rq;
struct list_head ibkill_flush_ent;
spinlock_t sq_lock; /* for posting and polling */
struct ionic_queue sq;
struct ionic_sq_meta *sq_meta;
u16 *sq_msn_idx;
int sq_spec;
u16 sq_old_prod;
u16 sq_msn_prod;
u16 sq_msn_cons;
u8 sq_cmb;
bool sq_flush;
bool sq_flush_rcvd;
spinlock_t rq_lock; /* for posting and polling */
struct ionic_queue rq;
struct ionic_rq_meta *rq_meta;
struct ionic_rq_meta *rq_meta_head;
int rq_spec;
u16 rq_old_prod;
u8 rq_cmb;
bool rq_flush;
struct kref qp_kref;
struct completion qp_rel_comp;
/* infrequently accessed, keep at end */
int sgid_index;
int sq_cmb_order;
u32 sq_cmb_pgid;
phys_addr_t sq_cmb_addr;
struct rdma_user_mmap_entry *mmap_sq_cmb;
struct ib_umem *sq_umem;
int rq_cmb_order;
u32 rq_cmb_pgid;
phys_addr_t rq_cmb_addr;
struct rdma_user_mmap_entry *mmap_rq_cmb;
struct ib_umem *rq_umem;
int dcqcn_profile;
struct ib_ud_header *hdr;
};
struct ionic_ah {
struct ib_ah ibah;
u32 ahid;
int sgid_index;
struct ib_ud_header hdr;
};
struct ionic_mr {
union {
struct ib_mr ibmr;
struct ib_mw ibmw;
};
u32 mrid;
int flags;
struct ib_umem *umem;
struct ionic_tbl_buf buf;
bool created;
};
struct ionic_counter_stats {
int queue_stats_count;
struct ionic_v1_stat *hdr;
struct rdma_stat_desc *stats_hdrs;
struct xarray xa_counters;
};
struct ionic_counter {
void *vals;
struct list_head qp_list;
};
static inline struct ionic_ibdev *to_ionic_ibdev(struct ib_device *ibdev)
{
return container_of(ibdev, struct ionic_ibdev, ibdev);
}
static inline struct ionic_ctx *to_ionic_ctx(struct ib_ucontext *ibctx)
{
return container_of(ibctx, struct ionic_ctx, ibctx);
}
static inline struct ionic_ctx *to_ionic_ctx_uobj(struct ib_uobject *uobj)
{
if (!uobj)
return NULL;
if (!uobj->context)
return NULL;
return to_ionic_ctx(uobj->context);
}
static inline struct ionic_pd *to_ionic_pd(struct ib_pd *ibpd)
{
return container_of(ibpd, struct ionic_pd, ibpd);
}
static inline struct ionic_mr *to_ionic_mr(struct ib_mr *ibmr)
{
return container_of(ibmr, struct ionic_mr, ibmr);
}
static inline struct ionic_mr *to_ionic_mw(struct ib_mw *ibmw)
{
return container_of(ibmw, struct ionic_mr, ibmw);
}
static inline struct ionic_vcq *to_ionic_vcq(struct ib_cq *ibcq)
{
return container_of(ibcq, struct ionic_vcq, ibcq);
}
static inline struct ionic_cq *to_ionic_vcq_cq(struct ib_cq *ibcq,
uint8_t udma_idx)
{
return &to_ionic_vcq(ibcq)->cq[udma_idx];
}
static inline struct ionic_qp *to_ionic_qp(struct ib_qp *ibqp)
{
return container_of(ibqp, struct ionic_qp, ibqp);
}
static inline struct ionic_ah *to_ionic_ah(struct ib_ah *ibah)
{
return container_of(ibah, struct ionic_ah, ibah);
}
static inline u32 ionic_ctx_dbid(struct ionic_ibdev *dev,
struct ionic_ctx *ctx)
{
if (!ctx)
return dev->lif_cfg.dbid;
return ctx->dbid;
}
static inline u32 ionic_obj_dbid(struct ionic_ibdev *dev,
struct ib_uobject *uobj)
{
return ionic_ctx_dbid(dev, to_ionic_ctx_uobj(uobj));
}
static inline bool ionic_ibop_is_local(enum ib_wr_opcode op)
{
return op == IB_WR_LOCAL_INV || op == IB_WR_REG_MR;
}
static inline void ionic_qp_complete(struct kref *kref)
{
struct ionic_qp *qp = container_of(kref, struct ionic_qp, qp_kref);
complete(&qp->qp_rel_comp);
}
static inline void ionic_cq_complete(struct kref *kref)
{
struct ionic_cq *cq = container_of(kref, struct ionic_cq, cq_kref);
complete(&cq->cq_rel_comp);
}
/* ionic_admin.c */
extern struct workqueue_struct *ionic_evt_workq;
void ionic_admin_post(struct ionic_ibdev *dev, struct ionic_admin_wr *wr);
int ionic_admin_wait(struct ionic_ibdev *dev, struct ionic_admin_wr *wr,
enum ionic_admin_flags);
int ionic_rdma_reset_devcmd(struct ionic_ibdev *dev);
int ionic_create_rdma_admin(struct ionic_ibdev *dev);
void ionic_destroy_rdma_admin(struct ionic_ibdev *dev);
void ionic_kill_rdma_admin(struct ionic_ibdev *dev, bool fatal_path);
/* ionic_controlpath.c */
int ionic_create_cq_common(struct ionic_vcq *vcq,
struct ionic_tbl_buf *buf,
const struct ib_cq_init_attr *attr,
struct ionic_ctx *ctx,
struct ib_udata *udata,
struct ionic_qdesc *req_cq,
__u32 *resp_cqid,
int udma_idx);
void ionic_destroy_cq_common(struct ionic_ibdev *dev, struct ionic_cq *cq);
void ionic_flush_qp(struct ionic_ibdev *dev, struct ionic_qp *qp);
void ionic_notify_flush_cq(struct ionic_cq *cq);
int ionic_alloc_ucontext(struct ib_ucontext *ibctx, struct ib_udata *udata);
void ionic_dealloc_ucontext(struct ib_ucontext *ibctx);
int ionic_mmap(struct ib_ucontext *ibctx, struct vm_area_struct *vma);
void ionic_mmap_free(struct rdma_user_mmap_entry *rdma_entry);
int ionic_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata);
int ionic_dealloc_pd(struct ib_pd *ibpd, struct ib_udata *udata);
int ionic_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr,
struct ib_udata *udata);
int ionic_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr);
int ionic_destroy_ah(struct ib_ah *ibah, u32 flags);
struct ib_mr *ionic_get_dma_mr(struct ib_pd *ibpd, int access);
struct ib_mr *ionic_reg_user_mr(struct ib_pd *ibpd, u64 start, u64 length,
u64 addr, int access, struct ib_dmah *dmah,
struct ib_udata *udata);
struct ib_mr *ionic_reg_user_mr_dmabuf(struct ib_pd *ibpd, u64 offset,
u64 length, u64 addr, int fd, int access,
struct ib_dmah *dmah,
struct uverbs_attr_bundle *attrs);
int ionic_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata);
struct ib_mr *ionic_alloc_mr(struct ib_pd *ibpd, enum ib_mr_type type,
u32 max_sg);
int ionic_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents,
unsigned int *sg_offset);
int ionic_alloc_mw(struct ib_mw *ibmw, struct ib_udata *udata);
int ionic_dealloc_mw(struct ib_mw *ibmw);
int ionic_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
struct uverbs_attr_bundle *attrs);
int ionic_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata);
int ionic_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attr,
struct ib_udata *udata);
int ionic_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int mask,
struct ib_udata *udata);
int ionic_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int mask,
struct ib_qp_init_attr *init_attr);
int ionic_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata);
/* ionic_datapath.c */
int ionic_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr,
const struct ib_send_wr **bad);
int ionic_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *wr,
const struct ib_recv_wr **bad);
int ionic_poll_cq(struct ib_cq *ibcq, int nwc, struct ib_wc *wc);
int ionic_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags);
/* ionic_hw_stats.c */
void ionic_stats_init(struct ionic_ibdev *dev);
void ionic_stats_cleanup(struct ionic_ibdev *dev);
/* ionic_pgtbl.c */
__le64 ionic_pgtbl_dma(struct ionic_tbl_buf *buf, u64 va);
__be64 ionic_pgtbl_off(struct ionic_tbl_buf *buf, u64 va);
int ionic_pgtbl_page(struct ionic_tbl_buf *buf, u64 dma);
int ionic_pgtbl_init(struct ionic_ibdev *dev,
struct ionic_tbl_buf *buf,
struct ib_umem *umem,
dma_addr_t dma,
int limit,
u64 page_size);
void ionic_pgtbl_unbuf(struct ionic_ibdev *dev, struct ionic_tbl_buf *buf);
#endif /* _IONIC_IBDEV_H_ */
|