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
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
|
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright(c) 2023 Advanced Micro Devices, Inc */
#ifndef _PDS_CORE_ADMINQ_H_
#define _PDS_CORE_ADMINQ_H_
#define PDSC_ADMINQ_MAX_POLL_INTERVAL 256
enum pds_core_adminq_flags {
PDS_AQ_FLAG_FASTPOLL = BIT(1), /* completion poll at 1ms */
};
/*
* enum pds_core_adminq_opcode - AdminQ command opcodes
* These commands are only processed on AdminQ, not available in devcmd
*/
enum pds_core_adminq_opcode {
PDS_AQ_CMD_NOP = 0,
/* Client control */
PDS_AQ_CMD_CLIENT_REG = 6,
PDS_AQ_CMD_CLIENT_UNREG = 7,
PDS_AQ_CMD_CLIENT_CMD = 8,
/* LIF commands */
PDS_AQ_CMD_LIF_IDENTIFY = 20,
PDS_AQ_CMD_LIF_INIT = 21,
PDS_AQ_CMD_LIF_RESET = 22,
PDS_AQ_CMD_LIF_GETATTR = 23,
PDS_AQ_CMD_LIF_SETATTR = 24,
PDS_AQ_CMD_LIF_SETPHC = 25,
PDS_AQ_CMD_RX_MODE_SET = 30,
PDS_AQ_CMD_RX_FILTER_ADD = 31,
PDS_AQ_CMD_RX_FILTER_DEL = 32,
/* Queue commands */
PDS_AQ_CMD_Q_IDENTIFY = 39,
PDS_AQ_CMD_Q_INIT = 40,
PDS_AQ_CMD_Q_CONTROL = 41,
/* SR/IOV commands */
PDS_AQ_CMD_VF_GETATTR = 60,
PDS_AQ_CMD_VF_SETATTR = 61,
};
/*
* enum pds_core_notifyq_opcode - NotifyQ event codes
*/
enum pds_core_notifyq_opcode {
PDS_EVENT_LINK_CHANGE = 1,
PDS_EVENT_RESET = 2,
PDS_EVENT_XCVR = 5,
PDS_EVENT_CLIENT = 6,
};
#define PDS_COMP_COLOR_MASK 0x80
/**
* struct pds_core_notifyq_event - Generic event reporting structure
* @eid: event number
* @ecode: event code
*
* This is the generic event report struct from which the other
* actual events will be formed.
*/
struct pds_core_notifyq_event {
__le64 eid;
__le16 ecode;
};
/**
* struct pds_core_link_change_event - Link change event notification
* @eid: event number
* @ecode: event code = PDS_EVENT_LINK_CHANGE
* @link_status: link up/down, with error bits
* @link_speed: speed of the network link
*
* Sent when the network link state changes between UP and DOWN
*/
struct pds_core_link_change_event {
__le64 eid;
__le16 ecode;
__le16 link_status;
__le32 link_speed; /* units of 1Mbps: e.g. 10000 = 10Gbps */
};
/**
* struct pds_core_reset_event - Reset event notification
* @eid: event number
* @ecode: event code = PDS_EVENT_RESET
* @reset_code: reset type
* @state: 0=pending, 1=complete, 2=error
*
* Sent when the NIC or some subsystem is going to be or
* has been reset.
*/
struct pds_core_reset_event {
__le64 eid;
__le16 ecode;
u8 reset_code;
u8 state;
};
/**
* struct pds_core_client_event - Client event notification
* @eid: event number
* @ecode: event code = PDS_EVENT_CLIENT
* @client_id: client to sent event to
* @client_event: wrapped event struct for the client
*
* Sent when an event needs to be passed on to a client
*/
struct pds_core_client_event {
__le64 eid;
__le16 ecode;
__le16 client_id;
u8 client_event[54];
};
/**
* struct pds_core_notifyq_cmd - Placeholder for building qcq
* @data: anonymous field for building the qcq
*/
struct pds_core_notifyq_cmd {
__le32 data; /* Not used but needed for qcq structure */
};
/*
* union pds_core_notifyq_comp - Overlay of notifyq event structures
*/
union pds_core_notifyq_comp {
struct {
__le64 eid;
__le16 ecode;
};
struct pds_core_notifyq_event event;
struct pds_core_link_change_event link_change;
struct pds_core_reset_event reset;
u8 data[64];
};
#define PDS_DEVNAME_LEN 32
/**
* struct pds_core_client_reg_cmd - Register a new client with DSC
* @opcode: opcode PDS_AQ_CMD_CLIENT_REG
* @rsvd: word boundary padding
* @devname: text name of client device
* @vif_type: what type of device (enum pds_core_vif_types)
*
* Tell the DSC of the new client, and receive a client_id from DSC.
*/
struct pds_core_client_reg_cmd {
u8 opcode;
u8 rsvd[3];
char devname[PDS_DEVNAME_LEN];
u8 vif_type;
};
/**
* struct pds_core_client_reg_comp - Client registration completion
* @status: Status of the command (enum pdc_core_status_code)
* @rsvd: Word boundary padding
* @comp_index: Index in the descriptor ring for which this is the completion
* @client_id: New id assigned by DSC
* @rsvd1: Word boundary padding
* @color: Color bit
*/
struct pds_core_client_reg_comp {
u8 status;
u8 rsvd;
__le16 comp_index;
__le16 client_id;
u8 rsvd1[9];
u8 color;
};
/**
* struct pds_core_client_unreg_cmd - Unregister a client from DSC
* @opcode: opcode PDS_AQ_CMD_CLIENT_UNREG
* @rsvd: word boundary padding
* @client_id: id of client being removed
*
* Tell the DSC this client is going away and remove its context
* This uses the generic completion.
*/
struct pds_core_client_unreg_cmd {
u8 opcode;
u8 rsvd;
__le16 client_id;
};
/**
* struct pds_core_client_request_cmd - Pass along a wrapped client AdminQ cmd
* @opcode: opcode PDS_AQ_CMD_CLIENT_CMD
* @rsvd: word boundary padding
* @client_id: id of client being removed
* @client_cmd: the wrapped client command
*
* Proxy post an adminq command for the client.
* This uses the generic completion.
*/
struct pds_core_client_request_cmd {
u8 opcode;
u8 rsvd;
__le16 client_id;
u8 client_cmd[60];
};
#define PDS_CORE_MAX_FRAGS 16
#define PDS_CORE_QCQ_F_INITED BIT(0)
#define PDS_CORE_QCQ_F_SG BIT(1)
#define PDS_CORE_QCQ_F_INTR BIT(2)
#define PDS_CORE_QCQ_F_TX_STATS BIT(3)
#define PDS_CORE_QCQ_F_RX_STATS BIT(4)
#define PDS_CORE_QCQ_F_NOTIFYQ BIT(5)
#define PDS_CORE_QCQ_F_CMB_RINGS BIT(6)
#define PDS_CORE_QCQ_F_CORE BIT(7)
enum pds_core_lif_type {
PDS_CORE_LIF_TYPE_DEFAULT = 0,
};
/**
* union pds_core_lif_config - LIF configuration
* @state: LIF state (enum pds_core_lif_state)
* @rsvd: Word boundary padding
* @name: LIF name
* @rsvd2: Word boundary padding
* @features: LIF features active (enum pds_core_hw_features)
* @queue_count: Queue counts per queue-type
* @words: Full union buffer size
*/
union pds_core_lif_config {
struct {
u8 state;
u8 rsvd[3];
char name[PDS_CORE_IFNAMSIZ];
u8 rsvd2[12];
__le64 features;
__le32 queue_count[PDS_CORE_QTYPE_MAX];
} __packed;
__le32 words[64];
};
/**
* struct pds_core_lif_status - LIF status register
* @eid: most recent NotifyQ event id
* @rsvd: full struct size
*/
struct pds_core_lif_status {
__le64 eid;
u8 rsvd[56];
};
/**
* struct pds_core_lif_info - LIF info structure
* @config: LIF configuration structure
* @status: LIF status structure
*/
struct pds_core_lif_info {
union pds_core_lif_config config;
struct pds_core_lif_status status;
};
/**
* struct pds_core_lif_identity - LIF identity information (type-specific)
* @features: LIF features (see enum pds_core_hw_features)
* @version: Identify structure version
* @hw_index: LIF hardware index
* @rsvd: Word boundary padding
* @max_nb_sessions: Maximum number of sessions supported
* @rsvd2: buffer padding
* @config: LIF config struct with features, q counts
*/
struct pds_core_lif_identity {
__le64 features;
u8 version;
u8 hw_index;
u8 rsvd[2];
__le32 max_nb_sessions;
u8 rsvd2[120];
union pds_core_lif_config config;
};
/**
* struct pds_core_lif_identify_cmd - Get LIF identity info command
* @opcode: Opcode PDS_AQ_CMD_LIF_IDENTIFY
* @type: LIF type (enum pds_core_lif_type)
* @client_id: Client identifier
* @ver: Version of identify returned by device
* @rsvd: Word boundary padding
* @ident_pa: DMA address to receive identity info
*
* Firmware will copy LIF identity data (struct pds_core_lif_identity)
* into the buffer address given.
*/
struct pds_core_lif_identify_cmd {
u8 opcode;
u8 type;
__le16 client_id;
u8 ver;
u8 rsvd[3];
__le64 ident_pa;
};
/**
* struct pds_core_lif_identify_comp - LIF identify command completion
* @status: Status of the command (enum pds_core_status_code)
* @ver: Version of identify returned by device
* @bytes: Bytes copied into the buffer
* @rsvd: Word boundary padding
* @color: Color bit
*/
struct pds_core_lif_identify_comp {
u8 status;
u8 ver;
__le16 bytes;
u8 rsvd[11];
u8 color;
};
/**
* struct pds_core_lif_init_cmd - LIF init command
* @opcode: Opcode PDS_AQ_CMD_LIF_INIT
* @type: LIF type (enum pds_core_lif_type)
* @client_id: Client identifier
* @rsvd: Word boundary padding
* @info_pa: Destination address for LIF info (struct pds_core_lif_info)
*/
struct pds_core_lif_init_cmd {
u8 opcode;
u8 type;
__le16 client_id;
__le32 rsvd;
__le64 info_pa;
};
/**
* struct pds_core_lif_init_comp - LIF init command completion
* @status: Status of the command (enum pds_core_status_code)
* @rsvd: Word boundary padding
* @hw_index: Hardware index of the initialized LIF
* @rsvd1: Word boundary padding
* @color: Color bit
*/
struct pds_core_lif_init_comp {
u8 status;
u8 rsvd;
__le16 hw_index;
u8 rsvd1[11];
u8 color;
};
/**
* struct pds_core_lif_reset_cmd - LIF reset command
* Will reset only the specified LIF.
* @opcode: Opcode PDS_AQ_CMD_LIF_RESET
* @rsvd: Word boundary padding
* @client_id: Client identifier
*/
struct pds_core_lif_reset_cmd {
u8 opcode;
u8 rsvd;
__le16 client_id;
};
/**
* enum pds_core_lif_attr - List of LIF attributes
* @PDS_CORE_LIF_ATTR_STATE: LIF state attribute
* @PDS_CORE_LIF_ATTR_NAME: LIF name attribute
* @PDS_CORE_LIF_ATTR_FEATURES: LIF features attribute
* @PDS_CORE_LIF_ATTR_STATS_CTRL: LIF statistics control attribute
*/
enum pds_core_lif_attr {
PDS_CORE_LIF_ATTR_STATE = 0,
PDS_CORE_LIF_ATTR_NAME = 1,
PDS_CORE_LIF_ATTR_FEATURES = 4,
PDS_CORE_LIF_ATTR_STATS_CTRL = 6,
};
/**
* struct pds_core_lif_setattr_cmd - Set LIF attributes on the NIC
* @opcode: Opcode PDS_AQ_CMD_LIF_SETATTR
* @attr: Attribute type (enum pds_core_lif_attr)
* @client_id: Client identifier
* @state: LIF state (enum pds_core_lif_state)
* @name: The name string, 0 terminated
* @features: Features (enum pds_core_hw_features)
* @stats_ctl: Stats control commands (enum pds_core_stats_ctl_cmd)
* @rsvd: Command Buffer padding
*/
struct pds_core_lif_setattr_cmd {
u8 opcode;
u8 attr;
__le16 client_id;
union {
u8 state;
char name[PDS_CORE_IFNAMSIZ];
__le64 features;
u8 stats_ctl;
u8 rsvd[60];
} __packed;
};
/**
* struct pds_core_lif_setattr_comp - LIF set attr command completion
* @status: Status of the command (enum pds_core_status_code)
* @rsvd: Word boundary padding
* @comp_index: Index in the descriptor ring for which this is the completion
* @features: Features (enum pds_core_hw_features)
* @rsvd2: Word boundary padding
* @color: Color bit
*/
struct pds_core_lif_setattr_comp {
u8 status;
u8 rsvd;
__le16 comp_index;
union {
__le64 features;
u8 rsvd2[11];
} __packed;
u8 color;
};
/**
* struct pds_core_lif_getattr_cmd - Get LIF attributes from the NIC
* @opcode: Opcode PDS_AQ_CMD_LIF_GETATTR
* @attr: Attribute type (enum pds_core_lif_attr)
* @client_id: Client identifier
*/
struct pds_core_lif_getattr_cmd {
u8 opcode;
u8 attr;
__le16 client_id;
};
/**
* struct pds_core_lif_getattr_comp - LIF get attr command completion
* @status: Status of the command (enum pds_core_status_code)
* @rsvd: Word boundary padding
* @comp_index: Index in the descriptor ring for which this is the completion
* @state: LIF state (enum pds_core_lif_state)
* @name: LIF name string, 0 terminated
* @features: Features (enum pds_core_hw_features)
* @rsvd2: Word boundary padding
* @color: Color bit
*/
struct pds_core_lif_getattr_comp {
u8 status;
u8 rsvd;
__le16 comp_index;
union {
u8 state;
__le64 features;
u8 rsvd2[11];
} __packed;
u8 color;
};
/**
* union pds_core_q_identity - Queue identity information
* @version: Queue type version that can be used with FW
* @supported: Bitfield of queue versions, first bit = ver 0
* @rsvd: Word boundary padding
* @features: Queue features
* @desc_sz: Descriptor size
* @comp_sz: Completion descriptor size
* @rsvd2: Word boundary padding
*/
struct pds_core_q_identity {
u8 version;
u8 supported;
u8 rsvd[6];
#define PDS_CORE_QIDENT_F_CQ 0x01 /* queue has completion ring */
__le64 features;
__le16 desc_sz;
__le16 comp_sz;
u8 rsvd2[6];
};
/**
* struct pds_core_q_identify_cmd - queue identify command
* @opcode: Opcode PDS_AQ_CMD_Q_IDENTIFY
* @type: Logical queue type (enum pds_core_logical_qtype)
* @client_id: Client identifier
* @ver: Highest queue type version that the driver supports
* @rsvd: Word boundary padding
* @ident_pa: DMA address to receive the data (struct pds_core_q_identity)
*/
struct pds_core_q_identify_cmd {
u8 opcode;
u8 type;
__le16 client_id;
u8 ver;
u8 rsvd[3];
__le64 ident_pa;
};
/**
* struct pds_core_q_identify_comp - queue identify command completion
* @status: Status of the command (enum pds_core_status_code)
* @rsvd: Word boundary padding
* @comp_index: Index in the descriptor ring for which this is the completion
* @ver: Queue type version that can be used with FW
* @rsvd1: Word boundary padding
* @color: Color bit
*/
struct pds_core_q_identify_comp {
u8 status;
u8 rsvd;
__le16 comp_index;
u8 ver;
u8 rsvd1[10];
u8 color;
};
/**
* struct pds_core_q_init_cmd - Queue init command
* @opcode: Opcode PDS_AQ_CMD_Q_INIT
* @type: Logical queue type
* @client_id: Client identifier
* @ver: Queue type version
* @rsvd: Word boundary padding
* @index: (LIF, qtype) relative admin queue index
* @intr_index: Interrupt control register index, or Event queue index
* @pid: Process ID
* @flags:
* IRQ: Interrupt requested on completion
* ENA: Enable the queue. If ENA=0 the queue is initialized
* but remains disabled, to be later enabled with the
* Queue Enable command. If ENA=1, then queue is
* initialized and then enabled.
* @cos: Class of service for this queue
* @ring_size: Queue ring size, encoded as a log2(size), in
* number of descriptors. The actual ring size is
* (1 << ring_size). For example, to select a ring size
* of 64 descriptors write ring_size = 6. The minimum
* ring_size value is 2 for a ring of 4 descriptors.
* The maximum ring_size value is 12 for a ring of 4k
* descriptors. Values of ring_size <2 and >12 are
* reserved.
* @ring_base: Queue ring base address
* @cq_ring_base: Completion queue ring base address
*/
struct pds_core_q_init_cmd {
u8 opcode;
u8 type;
__le16 client_id;
u8 ver;
u8 rsvd[3];
__le32 index;
__le16 pid;
__le16 intr_index;
__le16 flags;
#define PDS_CORE_QINIT_F_IRQ 0x01 /* Request interrupt on completion */
#define PDS_CORE_QINIT_F_ENA 0x02 /* Enable the queue */
u8 cos;
#define PDS_CORE_QSIZE_MIN_LG2 2
#define PDS_CORE_QSIZE_MAX_LG2 12
u8 ring_size;
__le64 ring_base;
__le64 cq_ring_base;
} __packed;
/**
* struct pds_core_q_init_comp - Queue init command completion
* @status: Status of the command (enum pds_core_status_code)
* @rsvd: Word boundary padding
* @comp_index: Index in the descriptor ring for which this is the completion
* @hw_index: Hardware Queue ID
* @hw_type: Hardware Queue type
* @rsvd2: Word boundary padding
* @color: Color
*/
struct pds_core_q_init_comp {
u8 status;
u8 rsvd;
__le16 comp_index;
__le32 hw_index;
u8 hw_type;
u8 rsvd2[6];
u8 color;
};
union pds_core_adminq_cmd {
u8 opcode;
u8 bytes[64];
struct pds_core_client_reg_cmd client_reg;
struct pds_core_client_unreg_cmd client_unreg;
struct pds_core_client_request_cmd client_request;
struct pds_core_lif_identify_cmd lif_ident;
struct pds_core_lif_init_cmd lif_init;
struct pds_core_lif_reset_cmd lif_reset;
struct pds_core_lif_setattr_cmd lif_setattr;
struct pds_core_lif_getattr_cmd lif_getattr;
struct pds_core_q_identify_cmd q_ident;
struct pds_core_q_init_cmd q_init;
};
union pds_core_adminq_comp {
struct {
u8 status;
u8 rsvd;
__le16 comp_index;
u8 rsvd2[11];
u8 color;
};
u32 words[4];
struct pds_core_client_reg_comp client_reg;
struct pds_core_lif_identify_comp lif_ident;
struct pds_core_lif_init_comp lif_init;
struct pds_core_lif_setattr_comp lif_setattr;
struct pds_core_lif_getattr_comp lif_getattr;
struct pds_core_q_identify_comp q_ident;
struct pds_core_q_init_comp q_init;
};
#ifndef __CHECKER__
static_assert(sizeof(union pds_core_adminq_cmd) == 64);
static_assert(sizeof(union pds_core_adminq_comp) == 16);
static_assert(sizeof(union pds_core_notifyq_comp) == 64);
#endif /* __CHECKER__ */
/* The color bit is a 'done' bit for the completion descriptors
* where the meaning alternates between '1' and '0' for alternating
* passes through the completion descriptor ring.
*/
static inline bool pdsc_color_match(u8 color, bool done_color)
{
return (!!(color & PDS_COMP_COLOR_MASK)) == done_color;
}
struct pdsc;
int pdsc_adminq_post(struct pdsc *pdsc,
union pds_core_adminq_cmd *cmd,
union pds_core_adminq_comp *comp,
bool fast_poll);
#endif /* _PDS_CORE_ADMINQ_H_ */
|