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
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
|
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _SYS_IB_ADAPTERS_HERMON_CMD_H
#define _SYS_IB_ADAPTERS_HERMON_CMD_H
/*
* hermon_cmd.h
* Contains all of the prototypes, #defines, and structures necessary
* for the Hermon Firmware Command routines.
* Specifically it contains the command types, command statuses and flags,
* structures used for managing Hermon mailboxes and outstanding commands,
* and prototypes for most of the functions consumed by other parts of
* the Hermon driver.
*/
#include <sys/types.h>
#include <sys/conf.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/ib/mgt/sm_attr.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Defines used hermon_write_hcr() to determine the duration and number of
* times (at maximum) to poll while waiting for a Hermon firmware command to
* release the HCR resource (i.e. waiting for the command to complete)
*/
#define HERMON_CMD_POLL_DELAY 1
#define HERMON_CMD_POLL_MAX 3000000
/*
* The following defines specify the default number of mailboxes (log 2) of
* each type and their size and alignment restrictions. By default the number
* of both "In" and "Out" mailboxes is set to 1024 (with each mailbox being
* 4KB in size), but both the number and sizes of each are controllable
* through the "hermon_log_num_inmbox", "hermon_log_num_outmbox",
* "hermon_log_inmbox_size" and "hermon_log_outmbox_size" configuration
* variables. Also, we have a define that is used to allocate interrupt
* mailboxes (1 in, 1 out).
*/
#define HERMON_NUM_MAILBOXES_SHIFT 0xA
#define HERMON_NUM_INTR_MAILBOXES_SHIFT 0
#define HERMON_MBOX_SIZE_SHIFT 0xC
#define HERMON_MBOX_SIZE (1 << HERMON_MBOX_SIZE_SHIFT)
#define HERMON_MBOX_ALIGN HERMON_MBOX_SIZE
/*
* These are the defines for the Hermon command type (opcodes). They are
* specified by the Hermon PRM
*/
/* Init Commands */
#define QUERY_DEV_LIM 0x3
#define QUERY_DEV_CAP 0x3
#define QUERY_FW 0x4
#define QUERY_ADAPTER 0x6
#define INIT_HCA 0x7
#define CLOSE_HCA 0x8
#define INIT_IB 0x9
#define INIT_PORT 0x9
#define CLOSE_IB 0xA
#define CLOSE_PORT 0xA
#define QUERY_HCA 0xB
#define SET_IB 0xC
#define SET_PORT 0xC
/* added late in tavor for SRQ support */
#define MOD_STAT_CFG 0x34
/* added late in Hermon (PRM 0.35) */
#define QUERY_PORT 0x43
/* TPT Commands */
#define SW2HW_MPT 0xD
#define QUERY_MPT 0xE
#define HW2SW_MPT 0xF
#define READ_MTT 0x10
#define WRITE_MTT 0x11
#define SYNC_TPT 0x2F
#define MODIFY_MPT 0x39
/* EQ Commands */
#define MAP_EQ 0x12
#define SW2HW_EQ 0x13
#define HW2SW_EQ 0x14
#define QUERY_EQ 0x15
/* CQ Commands */
#define SW2HW_CQ 0x16
#define HW2SW_CQ 0x17
#define QUERY_CQ 0x18
#define MODIFY_CQ 0x2C
/* Modify CQ Command - opcode modifiers */
#define RESIZE_CQ 0x0
#define MODIFY_MODERATION_CQ 0x1
#define MODIFY_EQN 0x2
/* QP Commands */
#define RST2INIT_QP 0x19
#define INIT2INIT_QP 0x2D
#define INIT2RTR_QP 0x1A
#define RTR2RTS_QP 0x1B
#define RTS2RTS_QP 0x1C
#define SQERR2RTS_QP 0x1D
#define TOERR_QP 0x1E
#define RTS2SQD_QP 0x1F
#define SQD2SQD_QP 0x38
#define SQD2RTS_QP 0x20
#define TORST_QP 0x21
#define QUERY_QP 0x22
#define SUSPEND_QP 0x32 /* new w/ hermon driver */
#define UNSUSPEND_QP 0x33 /* new w/ hermon driver */
/* SPECIAL QPs Commands */
#define CONF_SPECIAL_QP 0x23
#define MAD_IFC 0x24
/* added late in tavor for SRQ support */
/* SRQ Commands */
#define SW2HW_SRQ 0x35
#define HW2SW_SRQ 0x36
#define QUERY_SRQ 0x37
/* new in hermon, replaces part of modify MPT */
#define RESIZE_SRQ 0X44
/* new in hermon, set limit water mark */
#define ARM_RQ 0X40
/* new in hermon (PRM 0.36) configure interrupt moderation */
#define CONFIG_INT_MOD 0X45
#define HW_HEALTH_CHECK 0X50
/* Multicast Group Commands */
#define READ_MGM 0x25
#define READ_MCG 0x25
#define WRITE_MGM 0x26
#define WRITE_MCG 0x26
#define MGID_HASH 0x27
/* Debug/Diagnostic Commands */
#define QUERY_DEBUG_MSG 0x2A
#define SET_DEBUG_MSG 0x2B
#define DIAG_RPRT 0x30
#define CMD_NOP 0x31
#define SET_VLAN_FLTR 0x47
#define SET_MCAST_FLTR 0x48
#define CONFIG_FC 0x4A
#define QUERY_FC 0x4B
#define HEART_BEAT_RQ 0x4C
#define SENSE_PORT 0x4D
/* ICM and related commands - w/out LAM commands from Arbel */
#define RUN_FW 0xFF6
#define UNMAP_ICM 0xFF9
#define MAP_ICM 0xFFA
#define UNMAP_ICM_AUX 0xFFB
#define MAP_ICM_AUX 0xFFC
#define SET_ICM_SIZE 0xFFD
#define UNMAP_FA 0xFFE
#define MAP_FA 0xFFF
/*
* Commands mentioned but not defined in PRM v35
* REL_ICM_AUX
* INIT_VM
*/
/*
* These are the defines for the Hermon command completion statuses. They are
* also specified (in part) by the Hermon PRM. However,
* the HERMON_CMD_INSUFF_RSRC, HERMON_CMD_TIMEOUT and HERMON_CMD_INVALID_STATUS
* codes were added for this driver specifically to indicate the conditions
* when insufficient resources are available for a command, when a command has
* timed out (failure in the Hermon firmware) or when some other invalid result
* was received.
*/
#define HERMON_CMD_TIMEOUT_TOGGLE 0xFFFC /* -4 */
#define HERMON_CMD_INSUFF_RSRC 0xFFFD /* -3 */
#define HERMON_CMD_TIMEOUT_GOBIT 0xFFFE /* -2 */
#define HERMON_CMD_INVALID_STATUS 0xFFFF /* -1 */
#define HERMON_CMD_SUCCESS 0x00
#define HERMON_CMD_INTERNAL_ERR 0x01
#define HERMON_CMD_BAD_OP 0x02
#define HERMON_CMD_BAD_PARAM 0x03
#define HERMON_CMD_BAD_SYS_STATE 0x04
#define HERMON_CMD_BAD_RESOURCE 0x05
#define HERMON_CMD_RESOURCE_BUSY 0x06
#define HERMON_CMD_EXCEED_LIM 0x08
#define HERMON_CMD_BAD_RES_STATE 0x09
#define HERMON_CMD_BAD_INDEX 0x0A
#define HERMON_CMD_BAD_NVMEM 0x0B
#define HERMON_CMD_ICM_ERROR 0x0C
#define HERMON_CMD_BAD_QP_STATE 0x10
#define HERMON_CMD_BAD_SEG_PARAM 0x20
#define HERMON_CMD_REG_BOUND 0x21
#define HERMON_CMD_BAD_PKT 0x30
#define HERMON_CMD_BAD_SIZE 0x40
/*
* These defines are used in the "special QP" allocation to indicate the type
* of special QP (SMI, GSI, or one of the raw types). These values are
* specified by the Hermon PRM
*/
#define HERMON_CMD_QP_SMI 0
#define HERMON_CMD_QP_GSI 1
#define HERMON_CMD_QP_RAW_IPV6 2
#define HERMON_CMD_QP_RAW_ETH 3
#define HERMON_CMD_SPEC_QP_OPMOD(smi, gsi) \
((smi & 0x01) | ((gsi & 0x01) << 1))
/*
* For certain Hermon QP state transition commands some optional flags are
* allowed. These "opmask" flags are defined by the Hermon PRM
* as a bitmask.
*/
#define HERMON_CMD_OP_ALT_PATH (1 << 0)
#define HERMON_CMD_OP_RRE (1 << 1)
#define HERMON_CMD_OP_RAE (1 << 2)
#define HERMON_CMD_OP_RWE (1 << 3)
#define HERMON_CMD_OP_PKEYINDX (1 << 4) /* primary path */
#define HERMON_CMD_OP_QKEY (1 << 5)
#define HERMON_CMD_OP_MINRNRNAK (1 << 6)
#define HERMON_CMD_OP_PRIM_PATH (1 << 7)
#define HERMON_CMD_OP_SRA_SET (1 << 8)
#define HERMON_CMD_OP_RRA_SET (1 << 9)
#define HERMON_CMD_OP_PM_STATE (1 << 10) /* migration */
/* HERMON_CMD_OP_PRIM_PORT is obsolete, instead use HERMON_CMD_OP_SCHEDQUEUE */
#define HERMON_CMD_OP_PRIM_PORT (1 << 11)
#define HERMON_CMD_OP_RETRYCNT (1 << 12) /* Global */
#define HERMON_CMD_OP_ALT_RNRRETRY (1 << 13)
#define HERMON_CMD_OP_ACKTIMEOUT (1 << 14) /* primary path */
#define HERMON_CMD_OP_PRIM_RNRRETRY (1 << 15) /* reserved in HERMON */
#define HERMON_CMD_OP_SCHEDQUEUE (1 << 16)
#define HERMON_CMD_OP_RSSCONTEXT (1 << 17)
#define HERMON_CMD_OP_SRQN (1 << 18) /* for rss balancing */
#define HERMON_CMD_OP_CQN_RCV (1 << 19) /* for rss balancing */
/* Bits 20 - 31 RESERVED - per PRM 0.35c */
/*
* The Hermon RTS2SQD command can take the following flag as part of its
* input modifier to request the Send Queue Drained event
*/
#define HERMON_CMD_REQ_SQD_EVENT 0x80000000
/*
* The Hermon TORST command can take the following flag (as part of a bitmask)
* in its opcode modifier to request that the transition to reset should
* not go through the Error state (and, hence, should not generate "flushed-
* in-error" completions
*/
#define HERMON_CMD_DIRECT_TO_RESET (1 << 1)
/*
* Some Hermon commands write an OUT mailbox entry, depending on the value of
* the 'opmod' parameter. These defines provide the correct opmod value to
* write depending on whether to write an entry or not.
*/
#define HERMON_CMD_DO_OUTMBOX (0)
#define HERMON_CMD_NO_OUTMBOX (1 << 0)
/*
* The Hermon MAP_EQ command can take the following flags (and use the
* HERMON_CMD_UNMAP_EQ_MASK input modifier) to indicate whether the given
* event queue should mapped to or unmapped from the given event type.
*/
#define HERMON_CMD_MAP_EQ_EVT_MAP 0
#define HERMON_CMD_MAP_EQ_EVT_UNMAP 1
#define HERMON_CMD_UNMAP_EQ_MASK 0x80000000
/*
* The following defines are used by the MAD_IFC command and the helper
* routines that get PortInfo, NodeInfo, GUIDInfo, and PKeyTable entries.
*
* The first indicates whether of not MKey checking should be enforced.
* This is passed in the opcode modifier field for MAD_IFC commands.
*
* The next set are used to define certain hardcoded management datagram (MAD)
* sizes, offsets, and header formats for each of the helper operations.
*/
#define HERMON_CMD_MKEY_CHECK 0
#define HERMON_CMD_MKEY_DONTCHECK 1
#define HERMON_CMD_BKEY_DONTCHECK 2
#define HERMON_CMD_MAD_IFC_SIZE 0x100
#define HERMON_CMD_MADDATA_OFFSET 0x40
#define HERMON_CMD_MADHDR0 0x01010101
#define HERMON_CMD_MADHDR1 0x00000000
#define HERMON_CMD_MADHDR2 0x00000000
#define HERMON_CMD_MADHDR3 0x00000000
#define HERMON_CMD_PORTINFO 0x00150000
#define HERMON_CMD_NODEINFO 0x00110000
#define HERMON_CMD_NODEDESC 0x00100000
#define HERMON_CMD_GUIDINFO 0x00140000
#define HERMON_CMD_PKEYTBLE 0x00160000
#define HERMON_CMD_PERF_GET 0x01040101
#define HERMON_CMD_PERF_SET 0x01040102
#define HERMON_CMD_CLASSPORTINFO 0x00010000
#define HERMON_CMD_PERFCNTRS 0x00120000
#define HERMON_CMD_EXTPERFCNTRS 0x001D0000
#define HERMON_CMD_PERFATTR 0x00000000
#define HERMON_IS_EXT_WIDTH_SUPPORTED 0x0000020000000000
#define HERMON_IS_EXT_WIDTH_SUPPORTED_NOIETF 0x0000040000000000
/*
* The next few defines are used to indicate the size of the "reserved" area
* in the WRITE_MTT command, and the respective sizes of the SET_PORT and
* MGID_HASH commands
*/
#define HERMON_CMD_WRITEMTT_RSVD_SZ 0x10
#define HERMON_CMD_SETPORT_SZ 0x8
#define HERMON_CMD_MGIDHASH_SZ 0x10
/*
* This last define is used by hermon_cmn_ownership_cmd_post() to keep track
* of the direction (from hardware ownership to software, or vice versa) of
* the requested operation
*/
#define HERMON_CMD_RSRC_HW2SW 0
#define HERMON_CMD_RSRC_SW2HW 1
/*
* The following macros are used for handling any endianness related issues
* that might arise from the Hermon driver's internal use of MADs.
*
* HERMON_GETPORTINFO_SWAP - All the necessary swapping to handle the
* response to a GetPortInfo MAD
* HERMON_GETNODEINFO_SWAP - All the necessary swapping to handle the
* response to a GetNodeInfo MAD
* HERMON_GETGUIDINFO_SWAP - All the necessary swapping to handle the
* response to a GetGUIDInfo MAD
* HERMON_GETPKEYTABLE_SWAP - All the necessary swapping to handle the
* response to a GetPKeyTable MAD
*/
#ifdef _LITTLE_ENDIAN
#define HERMON_GETPORTINFO_SWAP(portinfo) \
{ \
(portinfo)->M_Key = ddi_swap64((portinfo)->M_Key); \
(portinfo)->GidPrefix = ddi_swap64((portinfo)->GidPrefix); \
(portinfo)->LID = ddi_swap16((portinfo)->LID); \
(portinfo)->MasterSMLID = ddi_swap16((portinfo)->MasterSMLID); \
(portinfo)->CapabilityMask = \
ddi_swap32((portinfo)->CapabilityMask); \
(portinfo)->DiagCode = ddi_swap16((portinfo)->DiagCode); \
(portinfo)->M_KeyLeasePeriod = \
ddi_swap16((portinfo)->M_KeyLeasePeriod); \
(portinfo)->M_KeyViolations = \
ddi_swap16((portinfo)->M_KeyViolations); \
(portinfo)->P_KeyViolations = \
ddi_swap16((portinfo)->P_KeyViolations); \
(portinfo)->Q_KeyViolations = \
ddi_swap16((portinfo)->Q_KeyViolations); \
}
#else
#define HERMON_GETPORTINFO_SWAP(portinfo)
#endif
#ifdef _LITTLE_ENDIAN
#define HERMON_GETNODEINFO_SWAP(nodeinfo) \
{ \
uint32_t tmp; \
\
tmp = ddi_swap32(((uint32_t *)nodeinfo)[9]); \
(nodeinfo)->VendorID = tmp & 0xFFFFFF; \
(nodeinfo)->LocalPortNum = tmp >> 24; \
(nodeinfo)->Revision = \
ddi_swap32(((uint32_t *)nodeinfo)[8]); \
tmp = ddi_swap32(((uint32_t *)nodeinfo)[7]); \
(nodeinfo)->PartitionCap = tmp >> 16; \
(nodeinfo)->DeviceID = tmp & 0xFFFF; \
(nodeinfo)->PortGUID = ddi_swap64((((uint64_t) \
(((uint32_t *)nodeinfo)[6]) << 32) | \
((uint32_t *)nodeinfo)[5])); \
(nodeinfo)->NodeGUID = ddi_swap64((((uint64_t) \
(((uint32_t *)nodeinfo)[4]) << 32) | \
((uint32_t *)nodeinfo)[3])); \
(nodeinfo)->SystemImageGUID = ddi_swap64((((uint64_t) \
(((uint32_t *)nodeinfo)[2]) << 32) | \
((uint32_t *)nodeinfo)[1])); \
}
#else
#define HERMON_GETNODEINFO_SWAP(nodeinfo) \
{ \
uint32_t tmp; \
\
tmp = ((uint32_t *)nodeinfo)[9]; \
(nodeinfo)->VendorID = tmp & 0xFFFFFF; \
(nodeinfo)->LocalPortNum = tmp >> 24; \
(nodeinfo)->Revision = ((uint32_t *)nodeinfo)[8]; \
tmp = ((uint32_t *)nodeinfo)[7]; \
(nodeinfo)->PartitionCap = tmp >> 16; \
(nodeinfo)->DeviceID = tmp & 0xFFFF; \
(nodeinfo)->PortGUID = (((uint64_t) \
(((uint32_t *)nodeinfo)[5]) << 32) | \
((uint32_t *)nodeinfo)[6]); \
(nodeinfo)->NodeGUID = (((uint64_t) \
(((uint32_t *)nodeinfo)[3]) << 32) | \
((uint32_t *)nodeinfo)[4]); \
(nodeinfo)->SystemImageGUID = (((uint64_t) \
(((uint32_t *)nodeinfo)[1]) << 32) | \
((uint32_t *)nodeinfo)[2]); \
}
#endif
#ifdef _LITTLE_ENDIAN
#define HERMON_GETGUIDINFO_SWAP(guidinfo) \
{ \
int i; \
\
for (i = 0; i < 8; i++) { \
(guidinfo)->GUIDBlocks[i] = \
ddi_swap64((guidinfo)->GUIDBlocks[i]); \
} \
}
#else
#define HERMON_GETGUIDINFO_SWAP(guidinfo)
#endif
#ifdef _LITTLE_ENDIAN
#define HERMON_GETPKEYTABLE_SWAP(pkeytable) \
{ \
int i; \
\
for (i = 0; i < 32; i++) { \
(pkeytable)->P_KeyTableBlocks[i] = \
ddi_swap16((pkeytable)->P_KeyTableBlocks[i]); \
} \
}
#else
#define HERMON_GETPKEYTABLE_SWAP(pkeytable)
#endif
/*
* The Hermon MODIFY_MPT command can take the following opcode modifier
* options to specify whether to modify for ResizeSRQ() or to swap the
* full MPT entry.
*/
#define HERMON_CMD_MODIFY_MPT_RESIZESRQ 3
#define HERMON_CMD_MODIFY_MPT_SWAPFULL 5
/*
* Hermon MOD_STAT_CFG Opcode Modifier
*/
#define HERMON_MOD_STAT_CFG_PTR 0x0
#define HERMON_MOD_STAT_CFG_INLINE 0x1
#define HERMON_MOD_STAT_CFG_DEFAULTS 0xF
/*
* The hermon_mbox_t structure is used internally by the Hermon driver to track
* all the information necessary to manage mailboxes for the Hermon command
* interface. Specifically, by containing a pointer to the buffer, the
* PCI mapped address, the access handle, and a back pointer to the
* hermon_rsrc_t structure used to track this resource, it provides enough
* information allocate, use, and free any type of mailbox.
*
* The mb_indx, mb_next, and mb_prev fields are used only by the mailbox
* alloc/free routines (see hermon_impl_mbox_alloc/free() for more details)
* and are not read or modified by any mailbox consumers. They are used
* to implement a fast allocation mechanism.
*/
typedef struct hermon_mbox_s {
void *mb_addr;
uint64_t mb_mapaddr;
ddi_acc_handle_t mb_acchdl;
hermon_rsrc_t *mb_rsrcptr;
uint_t mb_indx;
uint_t mb_next;
uint_t mb_prev;
} hermon_mbox_t;
/*
* The hermon_mboxlist_t structure is used to track all the information
* relevant to the pools of Hermon mailboxes. Specifically, it has a pointer
* to an array of hermon_mbox_t structures, a lock and cv used for blocking
* on alloc when mailboxes are not available, and a head, tail, and entries
* free counter to keep track of which (if any) mailboxes are currently free.
* This is used (along with the mb_indx, mb_next, and mb_prev fields in the
* hermon_mbox_t) to implement the fast allocation mechanism.
*/
typedef struct hermon_mboxlist_s {
kmutex_t mbl_lock;
kcondvar_t mbl_cv;
hermon_mbox_t *mbl_mbox;
uint_t mbl_list_sz;
uint_t mbl_num_alloc;
uint_t mbl_head_indx;
uint_t mbl_tail_indx;
uint_t mbl_entries_free;
uint_t mbl_waiters;
uint_t mbl_pollers;
uint_t mbl_signal;
} hermon_mboxlist_t;
_NOTE(MUTEX_PROTECTS_DATA(hermon_mboxlist_t::mbl_lock,
hermon_mboxlist_t::mbl_mbox
hermon_mboxlist_t::mbl_list_sz
hermon_mboxlist_t::mbl_num_alloc
hermon_mboxlist_t::mbl_cv
hermon_mboxlist_t::mbl_head_indx
hermon_mboxlist_t::mbl_tail_indx
hermon_mboxlist_t::mbl_entries_free
hermon_mboxlist_t::mbl_waiters
hermon_mboxlist_t::mbl_pollers
hermon_mboxlist_t::mbl_signal
hermon_mbox_t::mb_next
hermon_mbox_t::mb_prev))
/*
* The hermon_mbox_info_t structure is used by mailbox allocators to specify
* the type of mailbox(es) being requested. On a call to hermon_mbox_alloc()
* the mbi_alloc_flags may be set to HERMON_ALLOC_INMBOX, HERMON_ALLOC_OUTMBOX,
* or both. If it is able to allocate the request type(s) of mailboxes,
* hermon_mbox_alloc() will fill in the "mbi_in" and/or "mbi_out" pointers
* to point to valid hermon_mbox_t structures from the appropriate
* hermon_mboxlist_t (see above).
* This same structure is also passed to hermon_mbox_free(). It is the
* responsibility of the caller to hermon_mbox_alloc() to return this exact
* structure (unmodified) to hermon_mbox_free().
*
* Note: If both "In" and "Out" mailboxes are requested, it is assured that
* no deadlock can result (from holding one mailbox while attempting to get
* the other). This is assured by the fact that the "In" mailbox will always
* be allocated first before attempting to allocate the "Out"
*/
typedef struct hermon_mbox_info_s {
uint_t mbi_alloc_flags;
uint_t mbi_sleep_context;
hermon_mbox_t *mbi_in;
hermon_mbox_t *mbi_out;
} hermon_mbox_info_t;
#define HERMON_ALLOC_INMBOX (1 << 0)
#define HERMON_ALLOC_OUTMBOX (1 << 1)
/*
* The hermon_cmd_t structure is used internally by the Hermon driver to track
* all the information necessary to manage outstanding firmware commands on
* the Hermon command interface.
*
* Each hermon_cmd_t structure contains a cv and lock which are used by the
* posting thread to block for completion (with cmd_status being overloaded
* to indicate the condition variable). The cmd_outparam field is used to
* return additional status from those Hermon commands that specifically
* require it.
*
* The cmd_indx, cmd_next, and cmd_prev fields are used by the outstanding
* command alloc/free routines (see hermon_outstanding_cmd_alloc/free() for
* more details). They are used (in much the same way as the mb_indx,
* mb_next, and mb_prev fields in hermon_mbox_t above) to implement a fast
* allocation mechanism.
*/
typedef struct hermon_cmd_s {
kmutex_t cmd_comp_lock;
kcondvar_t cmd_comp_cv;
uint64_t cmd_outparm;
uint_t cmd_status;
uint_t cmd_indx;
uint_t cmd_next;
uint_t cmd_prev;
} hermon_cmd_t;
_NOTE(MUTEX_PROTECTS_DATA(hermon_cmd_t::cmd_comp_lock,
hermon_cmd_t::cmd_comp_cv
hermon_cmd_t::cmd_status))
/*
* The hermon_cmdlist_t structure is used in almost exactly the same way as
* the hermon_mboxlist_t above, but instead to track all the information
* relevant to the pool of outstanding Hermon commands. Specifically, it has
* a pointer to an array of hermon_cmd_t structures, a lock and cv used for
* blocking on alloc when outstanding command slots are not available, and a
* head, tail, and entries free counter to keep track of which (if any)
* command slots are currently free. This is used (along with the cmd_indx,
* cmd_next, and cmd_prev fields in the hermon_cmd_t) to implement the fast
* allocation mechanism.
*/
typedef struct hermon_cmdlist_s {
kmutex_t cml_lock;
kcondvar_t cml_cv;
hermon_cmd_t *cml_cmd;
uint_t cml_list_sz;
uint_t cml_num_alloc;
uint_t cml_head_indx;
uint_t cml_tail_indx;
uint_t cml_entries_free;
uint_t cml_waiters;
} hermon_cmdlist_t;
_NOTE(MUTEX_PROTECTS_DATA(hermon_cmdlist_t::cml_lock,
hermon_cmdlist_t::cml_cv
hermon_cmdlist_t::cml_cmd
hermon_cmdlist_t::cml_list_sz
hermon_cmdlist_t::cml_num_alloc
hermon_cmdlist_t::cml_head_indx
hermon_cmdlist_t::cml_tail_indx
hermon_cmdlist_t::cml_entries_free
hermon_cmdlist_t::cml_waiters
hermon_cmd_t::cmd_next
hermon_cmd_t::cmd_prev))
_NOTE(LOCK_ORDER(hermon_cmdlist_t::cml_lock
hermon_cmd_t::cmd_comp_lock))
/*
* The hermon_cmd_post_t structure is used by all the Hermon Firmware Command
* routines to post to Hermon firmware. The fields almost exactly mimic
* the fields in the Hermon HCR registers. The notable exception is the
* addition of the "cp_flags" field (which can be set to HERMON_CMD_SPIN or
* HERMON_CMD_NOSPIN). This flag really controls the value of the "e" bit
* in the HCR (i.e. the bit to indicate whether command should complete
* "in place" - in the HCR - or whether they should have their completions
* written to the command completion event queue. HERMON_CMD_SPIN means
* to allow commands to complete "in place" and to poll the "go" bit in
* the HCR to determine completion.
*
* We use HERMON_SLEEP and HERMON_NOSLEEP for our HERMON_CMD_ #defines. This is
* to maintain consistency with the rest of the SLEEP flags. Additionally,
* because HERMON_SLEEPFLAG_FOR_CONTEXT() in hermon_rsrc.h returns HERMON_SLEEP
* or NOSLEEP we must be compatible with this macro.
*/
typedef struct hermon_cmd_post_s {
uint64_t cp_inparm;
uint64_t cp_outparm;
uint32_t cp_inmod;
uint16_t cp_opcode;
uint16_t cp_opmod;
uint32_t cp_flags;
} hermon_cmd_post_t;
#define HERMON_CMD_SLEEP_NOSPIN HERMON_SLEEP
#define HERMON_CMD_NOSLEEP_SPIN HERMON_NOSLEEP
/*
* The following are the Hermon Firmware Command routines that accessible
* externally (i.e. throughout the rest of the Hermon driver software).
* These include the all the alloc/free routines, some initialization
* and cleanup routines, and the various specific Hermon firmware commands.
*/
int hermon_cmd_post(hermon_state_t *state, hermon_cmd_post_t *cmdpost);
int hermon_mbox_alloc(hermon_state_t *state, hermon_mbox_info_t *mbox_info,
uint_t mbox_wait);
void hermon_mbox_free(hermon_state_t *state, hermon_mbox_info_t *mbox_info);
int hermon_cmd_complete_handler(hermon_state_t *state, hermon_eqhdl_t eq,
hermon_hw_eqe_t *eqe);
int hermon_inmbox_list_init(hermon_state_t *state);
int hermon_intr_inmbox_list_init(hermon_state_t *state);
int hermon_outmbox_list_init(hermon_state_t *state);
int hermon_intr_outmbox_list_init(hermon_state_t *state);
void hermon_inmbox_list_fini(hermon_state_t *state);
void hermon_intr_inmbox_list_fini(hermon_state_t *state);
void hermon_outmbox_list_fini(hermon_state_t *state);
void hermon_intr_outmbox_list_fini(hermon_state_t *state);
int hermon_outstanding_cmdlist_init(hermon_state_t *state);
void hermon_outstanding_cmdlist_fini(hermon_state_t *state);
/* Added for MemFree */
int hermon_map_cmd_post(hermon_state_t *state, hermon_dma_info_t *dinfo,
uint16_t opcode, ddi_dma_cookie_t cookie, uint_t ccount);
int hermon_map_fa_cmd_post(hermon_state_t *state);
int hermon_run_fw_cmd_post(hermon_state_t *state);
int hermon_set_icm_size_cmd_post(hermon_state_t *state);
int hermon_map_icm_aux_cmd_post(hermon_state_t *state);
int hermon_map_icm_cmd_post(hermon_state_t *state);
int hermon_disable_lam_cmd_post(hermon_state_t *state);
int hermon_unmap_icm_cmd_post(hermon_state_t *state,
hermon_dma_info_t *dma_info);
int hermon_unmap_icm_aux_cmd_post(hermon_state_t *state);
int hermon_unmap_fa_cmd_post(hermon_state_t *state);
/*
* INIT_HCA and CLOSE_HCA - used for initialization and teardown of Hermon
* device configuration
*/
int hermon_init_hca_cmd_post(hermon_state_t *state,
hermon_hw_initqueryhca_t *inithca, uint_t sleepflag);
int hermon_close_hca_cmd_post(hermon_state_t *state, uint_t sleepflag);
/*
* INIT_PORT, CLOSE_PORT, and SET_PORT - used for bring Hermon ports up and
* down, and to set properties of each port (e.g. PortInfo capability mask)
* NOTE: New names for the commands in Hermon (previously init_ close_ and
* set_ib
*/
int hermon_set_port_cmd_post(hermon_state_t *state,
hermon_hw_set_port_t *initport, uint_t port, uint_t sleepflag);
int hermon_init_port_cmd_post(hermon_state_t *state, uint_t port,
uint_t sleepflag);
int hermon_close_port_cmd_post(hermon_state_t *state, uint_t port,
uint_t sleepflag);
/*
* This common function is used to post the following Hermon QP state
* transition firmware commands:
* RTS2SQD, TOERR, TORST, RST2INIT, INIT2INIT, INIT2RTR, RTR2RTS, RTS2RTS,
* SQD2SQD, SQD2RTS, and SQERR2RTS.
*/
int hermon_cmn_qp_cmd_post(hermon_state_t *state, uint_t opcode,
hermon_hw_qpc_t *qp, uint_t qpindx, uint32_t opmask, uint_t sleepflag);
/*
* This common function is used to post the following Hermon query firmware
* commands:
* QUERY_DEV_LIM/CAP, QUERY_FW, QUERY_ADAPTER, QUERY_HCA, QUERY_MPT,
* QUERY_EQ, QUERY_CQ, and QUERY_QP.
* New with FCoIB, QUERY_FC
*/
int hermon_cmn_query_cmd_post(hermon_state_t *state, uint_t opcode,
uint_t opmod, uint_t queryindx, void *query, uint_t size, uint_t sleepflag);
/*
* This common function is used to post the following Hermon resource ownership
* firmware commands:
* HW2SW_MPT, HW2SW_EQ, HW2SW_CQ, SW2HW_MPT, SW2HW_EQ, and SW2HW_CQ
*/
int hermon_cmn_ownership_cmd_post(hermon_state_t *state, uint_t opcode,
void *hwrsrc, uint_t size, uint_t hwrsrcindx, uint_t sleepflag);
/*
* MAD_IFC and helper functions - used for posting IB MADs to Hermon firmware.
* The helper functions are for the MADs most frequently used by the Hermon
* driver (internally).
*/
int hermon_mad_ifc_cmd_post(hermon_state_t *state, uint_t port,
uint_t sleepflag, uint32_t *mad, uint32_t *resp);
int hermon_getportinfo_cmd_post(hermon_state_t *state, uint_t port,
uint_t sleepflag, sm_portinfo_t *portinfo);
int hermon_getnodeinfo_cmd_post(hermon_state_t *state, uint_t sleepflag,
sm_nodeinfo_t *nodeinfo);
int hermon_getnodedesc_cmd_post(hermon_state_t *state, uint_t sleepflag,
sm_nodedesc_t *nodedesc);
int hermon_getguidinfo_cmd_post(hermon_state_t *state, uint_t port,
uint_t guidblock, uint_t sleepflag, sm_guidinfo_t *guidinfo);
int hermon_getpkeytable_cmd_post(hermon_state_t *state, uint_t port,
uint_t pkeyblock, uint_t sleepflag, sm_pkey_table_t *pkeytable);
int hermon_is_ext_port_counters_supported(hermon_state_t *state, uint_t port,
uint_t sleepflag, int *ext_width_supported);
int hermon_getextperfcntr_cmd_post(hermon_state_t *state, uint_t port,
uint_t sleepflag, hermon_hw_sm_extperfcntr_t *perfinfo);
int hermon_getperfcntr_cmd_post(hermon_state_t *state, uint_t port,
uint_t sleepflag, hermon_hw_sm_perfcntr_t *perfinfo, int reset);
/*
* WRITE_MTT - used for write MTT entries to the Hermon MTT table
*/
int hermon_write_mtt_cmd_post(hermon_state_t *state, hermon_rsrc_t *mtt,
uint64_t start_addr, uint_t nummtt, uint_t sleepflag);
/*
* SYNC_TPT - used to sync Hermon TPT caches
*/
int hermon_sync_tpt_cmd_post(hermon_state_t *state, uint_t sleepflag);
/*
* MAP_EQ - used for map classes of events to Hermon event queues (EQ)
*/
int hermon_map_eq_cmd_post(hermon_state_t *state, uint_t map,
uint_t eqcindx, uint64_t eqmapmask, uint_t sleepflag);
/*
* RESIZE_CQ - used for resize completion queue (CQ)
* opmod 0 is resize cq. opmod 1 is modify interrupt moderation.
*/
int hermon_resize_cq_cmd_post(hermon_state_t *state, hermon_hw_cqc_t *cqc,
uint_t cqcindx, uint32_t *prod_indx, uint_t sleepflag);
int hermon_modify_cq_cmd_post(hermon_state_t *state, hermon_hw_cqc_t *cqc,
uint_t cqcindx, uint_t opmod, uint_t sleepflag);
/*
* CONF_SPECIAL_QP - used to configure a pair of queue pairs for use as
* special QP. Necessary to enable full QP0 and/or QP1 operation.
*/
int hermon_conf_special_qp_cmd_post(hermon_state_t *state, uint_t qpindx,
uint_t qptype, uint_t sleepflag, uint_t opmod);
/*
* Get FEXCH HEART BEAT
*/
int hermon_get_heart_beat_rq_cmd_post(hermon_state_t *state, uint_t qpindx,
uint64_t *outparm);
/*
* MGID_HASH, READ_MGM, and WRITE_MGM - used for manipulation of the
* hardware resource tables for multicast groups.
* NOTE: for intial implementation these functions retain their original
* names, though the proper hermon terminology is READ_MCG and
* WRITE_MCG - MGID_HASH retains its original name
*/
int hermon_mgid_hash_cmd_post(hermon_state_t *state, uint64_t mgid_h,
uint64_t mgid_l, uint64_t *mgid_hash, uint_t sleepflag);
int hermon_read_mgm_cmd_post(hermon_state_t *state, hermon_hw_mcg_t *mcg,
uint_t mcgindx, uint_t sleepflag);
int hermon_write_mgm_cmd_post(hermon_state_t *state, hermon_hw_mcg_t *mcg,
uint_t mcgindx, uint_t sleepflag);
/*
* MOD_STAT_CFG - used to configure (override) settings set in NVRAM before
* a call to QUERY_DEV_LIM. This is primarily used for SRQ settings in
* the firmware.
*/
int hermon_mod_stat_cfg_cmd_post(hermon_state_t *state);
/*
* MODIFY_MPT - used to change MPT attributes of a memory region. This
* was (Tavor/Arbel) primarily used for Resizing SRQs -- now may be used
* to modify MPT paramters
*/
int hermon_modify_mpt_cmd_post(hermon_state_t *state, hermon_hw_dmpt_t *mpt,
uint_t mptindx, uint_t flags, uint_t sleepflag);
/*
* RESIZE_SRQ is new in hermon, replacing opcodes in modify_mpt. It is used
* to resize the SRQ, by passing the new information in the same format as
* the original srqc, which the HCA will update appropriately
*/
int hermon_resize_srq_cmd_post(hermon_state_t *state, hermon_hw_srqc_t *srq,
uint_t srqnum, uint_t sleepflag);
/*
* CMD_NOP - used to test the interrupt/Event Queue mechanism.
*/
int hermon_nop_post(hermon_state_t *state, uint_t interval, uint_t sleep);
int hermon_setdebug_post(hermon_state_t *state);
/*
* READ_MTT - used to read an mtt entry at address.
*/
int hermon_read_mtt_cmd_post(hermon_state_t *state, uint64_t mtt_addr,
hermon_hw_mtt_t *mtt);
/*
* SENSE_PORT - used to send protocol running on a port
*/
int hermon_sense_port_post(hermon_state_t *state, uint_t portnum,
uint32_t *protocol);
/*
* CONFIG_FC - used to do either a basic config passing in
* *hermon_hw_config_fc_basic_s, or config the N_Port table.
* passing in pointer to an array of 32-bit id's
* Note that either one needs to be cast to void *
*/
int hermon_config_fc_cmd_post(hermon_state_t *state, void *cfginfo, int enable,
int selector, int n_ports, int portnum, uint_t sleepflag);
/*
* CONFIG_INT_MOD - used to configure INTERRUPT moderation
*/
int hermon_config_int_mod(hermon_state_t *state, uint_t min_delay,
uint_t vector);
/*
* HW_HEALTH_CHECK - tests state of the HCA
* if command fails, *health is invalid/undefined
*/
int hermon_hw_health_check(hermon_state_t *state, int *health);
#ifdef __cplusplus
}
#endif
#endif /* _SYS_IB_ADAPTERS_HERMON_CMD_H */
|