xref: /illumos-gate/usr/src/uts/common/io/chxge/sge.h (revision 3d393ee6c37fa10ac512ed6d36109ad616dc7c1a)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * This file is part of the Chelsio T1 Ethernet driver.
29  *
30  * Copyright (C) 2003-2005 Chelsio Communications.  All rights reserved.
31  */
32 
33 #ifndef _CHELSIO_SGE_H
34 #define	_CHELSIO_SGE_H
35 
36 #pragma ident	"%Z%%M%	%I%	%E% SMI"
37 
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41 
42 #include <sys/types.h>
43 
44 #include "osdep.h"
45 
46 #define	MBLK_MAX 8
47 
48 #define	spin_lock mutex_enter
49 #define	spin_unlock mutex_exit
50 #define	atomic_sub(a, b) atomic_add_32(b, -(a))
51 #define	atomic_add(a, b) atomic_add_32(b, (a))
52 #define	atomic_read(a) (a)
53 #define	atomic_set(a, b) (*(a) = b)
54 #define	spinlock_t kmutex_t
55 #define	dma_addr_t uint64_t
56 #define	wmb() membar_producer()
57 #define	doorbell_pio(sge, cmd) sge_ring_doorbell(sge, cmd)
58 #define	skb_reserve(skb, offset) (skb->b_rptr += offset)
59 #define	__skb_pull(skb, len) (skb->b_rptr += len)
60 #define	skb_put(skb, len) ((skb)->b_wptr  = (skb)->b_rptr + (len))
61 #define	skb_pull(skb, len) (skb->b_rptr += len)
62 #define	unlikely(a) (a)
63 #define	likely(a) (a)
64 #define	SKB_DATA_ALIGN(X) (((X) + (sizeof (long)-1)) & ~(sizeof (long)-1))
65 #define	t1_is_T1B(adap) adapter_matches_type(adap, CHBT_TERM_T1, TERM_T1B)
66 #define	t1_is_T1C(adap) adapter_matches_type(adap, CHBT_TERM_T1, TERM_T1C)
67 
68 #define	SGE_SM_BUF_SZ(sa)	(sa->ch_sm_buf_sz)
69 #define	SGE_BG_BUF_SZ(sa)	(sa->ch_bg_buf_sz)
70 
71 #define	SGE_CMDQ_N		2
72 #define	SGE_FREELQ_N		2
73 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
74 #define	SGE_CMDQ0_E_N		4096
75 #define	SGE_CMDQ1_E_N		128
76 #define	SGE_FREELQ0_E_N		2048
77 #define	SGE_FREELQ1_E_N		1024
78 #define	SGE_RESPQ_E_N		7168    /* |CMDQ0| + |FREELQ0| + |FREELQ1| */
79 #else
80 #define	SGE_CMDQ0_E_N		2048
81 #define	SGE_CMDQ1_E_N		128
82 #define	SGE_FREELQ0_E_N		4096
83 #define	SGE_FREELQ1_E_N		1024
84 #define	SGE_RESPQ_E_N		7168    /* |CMDQ0| + |FREELQ0| + |FREELQ1| */
85 #endif  /* CONFIG_CHELSIO_T1_OFFLOAD */
86 #define	SGE_BATCH_THRESH	16
87 #define	SGE_INTR_BUCKETSIZE	100
88 #define	SGE_INTR_MAXBUCKETS	11
89 #define	SGE_INTRTIMER0		1
90 #define	SGE_INTRTIMER1		30
91 #define	SGE_INTRTIMER_NRES	10000
92 #define	SGE_RX_COPY_THRESHOLD	256
93 #define	SGE_RX_OFFSET		2
94 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
95 #define	SGE_RX_SM_BUF_SIZE(sa)	1536
96 #else
97 #define	SGE_RX_SM_BUF_SIZE(sa)	(sa->ch_sm_buf_sz)
98 #endif
99 
100 /*
101  * CPL5 Defines
102  */
103 #define	FLITSTOBYTES    8
104 
105 #define	CPL_FORMAT_0_SIZE 8
106 #define	CPL_FORMAT_1_SIZE 16
107 #define	CPL_FORMAT_2_SIZE 24
108 #define	CPL_FORMAT_3_SIZE 32
109 #define	CPL_FORMAT_4_SIZE 40
110 #define	CPL_FORMAT_5_SIZE 48
111 
112 #define	TID_MASK 0xffffff
113 
114 #define	SZ_CPL_RX_PKT CPL_FORMAT_0_SIZE
115 
116 #if BYTE_ORDER == BIG_ENDIAN
117 
118 typedef struct {
119 	u32 AddrLow;
120 	u32 GenerationBit: 1;
121 	u32 BufferLength: 31;
122 	u32 RespQueueSelector: 4;
123 	u32 ResponseTokens: 12;
124 	u32 CmdId: 8;
125 	u32 Reserved: 3;
126 	u32 TokenValid: 1;
127 	u32 Eop: 1;
128 	u32 Sop: 1;
129 	u32 DataValid: 1;
130 	u32 GenerationBit2: 1;
131 	u32 AddrHigh;
132 } CmdQueueEntry;
133 
134 
135 #elif BYTE_ORDER == LITTLE_ENDIAN
136 
137 
138 typedef struct {
139 	u32 BufferLength: 31;
140 	u32 GenerationBit: 1;
141 	u32 AddrLow;
142 	u32 AddrHigh;
143 	u32 GenerationBit2: 1;
144 	u32 DataValid: 1;
145 	u32 Sop: 1;
146 	u32 Eop: 1;
147 	u32 TokenValid: 1;
148 	u32 Reserved: 3;
149 	u32 CmdId: 8;
150 	u32 ResponseTokens: 12;
151 	u32 RespQueueSelector: 4;
152 } CmdQueueEntry;
153 
154 #endif
155 
156 
157 typedef CmdQueueEntry cmdQ_e;
158 
159 #if BYTE_ORDER == BIG_ENDIAN
160 
161 typedef struct {
162 	u32 Qsleeping: 4;
163 	u32 Cmdq1CreditReturn: 5;
164 	u32 Cmdq1DmaComplete: 5;
165 	u32 Cmdq0CreditReturn: 5;
166 	u32 Cmdq0DmaComplete: 5;
167 	u32 FreelistQid: 2;
168 	u32 CreditValid: 1;
169 	u32 DataValid: 1;
170 	u32 Offload: 1;
171 	u32 Eop: 1;
172 	u32 Sop: 1;
173 	u32 GenerationBit: 1;
174 	u32 BufferLength;
175 } ResponseQueueEntry;
176 
177 
178 #elif BYTE_ORDER == LITTLE_ENDIAN
179 
180 
181 typedef struct {
182 	u32 BufferLength;
183 	u32 GenerationBit: 1;
184 	u32 Sop: 1;
185 	u32 Eop: 1;
186 	u32 Offload: 1;
187 	u32 DataValid: 1;
188 	u32 CreditValid: 1;
189 	u32 FreelistQid: 2;
190 	u32 Cmdq0DmaComplete: 5;
191 	u32 Cmdq0CreditReturn: 5;
192 	u32 Cmdq1DmaComplete: 5;
193 	u32 Cmdq1CreditReturn: 5;
194 	u32 Qsleeping: 4;
195 } ResponseQueueEntry;
196 
197 #endif
198 
199 typedef ResponseQueueEntry respQ_e;
200 
201 #if BYTE_ORDER == BIG_ENDIAN
202 
203 
204 typedef struct {
205 	u32 AddrLow;
206 	u32 GenerationBit: 1;
207 	u32 BufferLength: 31;
208 	u32 Reserved: 31;
209 	u32 GenerationBit2: 1;
210 	u32 AddrHigh;
211 } FLQueueEntry;
212 
213 
214 #elif BYTE_ORDER == LITTLE_ENDIAN
215 
216 
217 typedef struct {
218 	u32 BufferLength: 31;
219 	u32 GenerationBit: 1;
220 	u32 AddrLow;
221 	u32 AddrHigh;
222 	u32 GenerationBit2: 1;
223 	u32 Reserved: 31;
224 } FLQueueEntry;
225 
226 
227 #endif
228 
229 typedef FLQueueEntry freelQ_e;
230 
231 /*
232  * Command QUEUE meta entry format.
233  */
234 typedef struct cmdQ_ce {
235 	void *ce_mp;		/* head mblk of pkt */
236 	free_dh_t *ce_dh;	/* ddi dma handle */
237 	uint_t ce_flg;		/* flag 0 - NIC descriptor; 1 - TOE */
238 	uint_t ce_len;		/* length of mblk component */
239 	uint64_t ce_pa;		/* physical address */
240 } cmdQ_ce_t;
241 
242 /*
243  * command queue control structure
244  */
245 typedef struct cmdQ {
246 	u32 cq_credits;		/* # available descriptors for Xmit */
247 	u32 cq_asleep;		/* HW DMA Fetch status */
248 	u32 cq_pio_pidx;	/* Variable updated on Doorbell */
249 	u32 cq_entries_n;	/* # entries for Xmit */
250 	u32 cq_pidx;		/* producer index (SW) */
251 	u32 cq_complete;		/* Shadow consumer index (HW) */
252 	u32 cq_cidx;		/* consumer index (HW) */
253 	u32 cq_genbit;		/* current generation (=valid) bit */
254 	cmdQ_e *cq_entries;
255 	cmdQ_ce_t *cq_centries;
256 	spinlock_t cq_qlock;
257 	uint64_t cq_pa;		/* may not be needed */
258 	ulong_t cq_dh;
259 	ulong_t cq_ah;		/* may not be needed */
260 } cmdQ_t;
261 
262 /*
263  * free list queue control structure
264  */
265 typedef struct freelQ {
266 	u32 fq_id;	/* 0 queue 0, 1 queue 1 */
267 	u32 fq_credits;	/* # available RX buffer descriptors */
268 	u32 fq_entries_n;	/* # RX buffer descriptors */
269 	u32 fq_pidx;	    /* producer index (SW) */
270 	u32 fq_cidx;	    /* consumer index (HW) */
271 	u32 fq_genbit;	  /* current generation (=valid) bit */
272 	u32 fq_rx_buffer_size;  /* size buffer on this freelist */
273 	freelQ_e *fq_entries;   /* HW freelist descriptor Q */
274 	struct freelQ_ce *fq_centries;  /* SW freelist conext descriptor Q */
275 	uint64_t fq_pa;	 /* may not be needed */
276 	ulong_t fq_dh;
277 	ulong_t fq_ah;
278 	u32 fq_pause_on_thresh;
279 	u32 fq_pause_off_thresh;
280 } freelQ_t;
281 
282 /*
283  * response queue control structure
284  */
285 typedef struct respQ {
286 	u32 rq_credits;	 /* # avail response Q entries */
287 	u32 rq_credits_pend;    /* # not yet returned entries */
288 	u32 rq_credits_thresh;  /* return threshold */
289 	u32 rq_entries_n;	/* # response Q descriptors */
290 	u32 rq_pidx;	    /* producer index (HW) */
291 	u32 rq_cidx;	    /* consumer index (SW) */
292 	u32 rq_genbit;	  /* current generation(=valid) bit */
293 	respQ_e *rq_entries;    /* HW response Q */
294 	uint64_t rq_pa;	 /* may not be needed */
295 	ulong_t rq_dh;
296 	ulong_t rq_ah;
297 } reapQ_t;
298 
299 struct sge_intr_counts {
300 	uint32_t respQ_empty;		/* # times respQ empty */
301 	uint32_t respQ_overflow;	/* # respQ overflow (fatal) */
302 	uint32_t freelistQ_empty;	/* # times freelist empty */
303 	uint32_t pkt_too_big;		/* packet too large (fatal) */
304 	uint32_t pkt_mismatch;
305 	uint32_t cmdQ_full[2];		/* not HW intr, host cmdQ[] full */
306 	uint32_t tx_reclaims[2];
307 	uint32_t tx_msg_pullups;	/* # of tx pkt coelescing events */
308 	uint32_t tx_hdr_pullups;	/* # of tx hdr coelescing events */
309 	uint32_t tx_tcp_ip_frag;	/* # of ip fragmentes for tcp data */
310 	uint32_t tx_udp_ip_frag;	/* # of ip fragmentes for udp data */
311 	uint32_t tx_soft_cksums;	/* # of Software checksums done. */
312 	uint32_t tx_need_cpl_space;	/* # of allocs for cpl header */
313 	uint32_t tx_multi_mblks;	/* # of Multi mblk packets */
314 	uint32_t tx_no_dvma1;		/* # of dvma mapping failures */
315 	uint32_t tx_no_dvma2;		/* # of dvma mapping failures */
316 	uint32_t tx_no_dma1;		/* # of dma mapping failures */
317 	uint32_t tx_no_dma2;		/* # of dma mapping failures */
318 	uint32_t rx_cmdq0;		/* # of Qsleeping CMDQ0's */
319 	uint32_t rx_cmdq1;		/* # of Qsleeping CMDQ1's */
320 	uint32_t rx_flq0;		/* # of Qsleeping FL0's */
321 	uint32_t rx_flq1;		/* # of Qsleeping FL1's */
322 	uint32_t rx_flq0_sz;		/* size of freelist-0 buffers */
323 	uint32_t rx_flq1_sz;		/* size of freelist-1 buffers */
324 	uint32_t rx_pkt_drops;		/* # intentionally dropped packets */
325 	uint32_t rx_pkt_copied;		/* # times packets copied by sge */
326 	uint32_t rx_pause_on;		/* # of system pause on's required. */
327 	uint32_t rx_pause_off;		/* # of system pauses off's required. */
328 	uint32_t rx_pause_ms;		/* micro seconds while paused */
329 	uint32_t rx_pause_spike;	/* maximum time paused */
330 	uint32_t rx_fl_credits;		/* Current free list credit usage. */
331 	uint32_t rx_flbuf_fails;	/* # of freelist buf alloc fails. */
332 	uint32_t rx_flbuf_allocs;	/* # of freelist buf allocs. */
333 	uint32_t rx_badEopSop;		/* # of times bad Eop/Sop received */
334 	uint32_t rx_flq0_cnt;	/* # of times free list Q 0 entry used */
335 	uint32_t rx_flq1_cnt;	/* # of times free list Q 1 entry used */
336 	uint32_t arp_sent;		/* # times arp packet sent */
337 #ifdef SUN_KSTATS
338 	uint32_t tx_doorbells;
339 	uint32_t intr_doorbells;
340 	uint32_t intr1_doorbells;
341 	uint32_t sleep_cnt;
342 	uint32_t pe_allocb_cnt;
343 	uint32_t tx_descs[MBLK_MAX];
344 #endif
345 };
346 
347 #ifdef SUN_KSTATS
348 typedef struct sge_intr_counts *p_ch_stats_t;
349 
350 /*
351  * Driver maintained kernel statistics.
352  */
353 typedef struct _ch_kstat_t {
354 	/*
355 	 * Link Input/Output stats
356 	 */
357 	kstat_named_t respQ_empty;	/* # times respQ empty */
358 	kstat_named_t respQ_overflow;	/* # respQ overflow (fatal) */
359 	kstat_named_t freelistQ_empty;	/* # times freelist empty */
360 	kstat_named_t pkt_too_big;	/* packet too large (fatal) */
361 	kstat_named_t pkt_mismatch;
362 	kstat_named_t cmdQ_full[2];	/* not HW intr, host cmdQ[] full */
363 	kstat_named_t tx_reclaims[2];	/* # of tx reclaims called */
364 	kstat_named_t tx_msg_pullups;	/* # of tx pkt coelescing events */
365 	kstat_named_t tx_hdr_pullups;	/* # of tx hdr coelescing events */
366 	kstat_named_t tx_tcp_ip_frag;	/* # of ip fragmentes for tcp data */
367 	kstat_named_t tx_udp_ip_frag;	/* # of ip fragmentes for udp data */
368 	kstat_named_t tx_soft_cksums;	/* # of Software checksums done. */
369 	kstat_named_t tx_need_cpl_space;	/* # of allocs for cpl header */
370 	kstat_named_t tx_multi_mblks;	/* # of multi fragment packets */
371 	kstat_named_t tx_no_dvma1;	/* # of dvma mapping failures */
372 	kstat_named_t tx_no_dvma2;	/* # of dvma mapping failures */
373 	kstat_named_t tx_no_dma1;	/* # of dma mapping failures */
374 	kstat_named_t tx_no_dma2;	/* # of dma mapping failures */
375 	kstat_named_t rx_cmdq0;		/* # times Qsleeping cmdq0 */
376 	kstat_named_t rx_cmdq1;		/* # times Qsleeping cmdq1 */
377 	kstat_named_t rx_flq0;		/* # times Qsleeping flq0 */
378 	kstat_named_t rx_flq0_sz;	/* size of freelist-0 buffers */
379 	kstat_named_t rx_flq1;		/* # times Qsleeping flq1 */
380 	kstat_named_t rx_flq1_sz;	/* size of freelist-1 buffers */
381 	kstat_named_t rx_pkt_drops;	/* # times packets dropped by sge */
382 	kstat_named_t rx_pkt_copied;	/* # intentionally copied packets */
383 	kstat_named_t rx_pause_on;	/* # of system pause on's required. */
384 	kstat_named_t rx_pause_off;	/* # of system pauses off's required. */
385 	kstat_named_t rx_pause_ms;	/* micro seconds while paused. */
386 	kstat_named_t rx_pause_spike;	/* maximum time paused. */
387 	kstat_named_t rx_fl_credits;	/* Current free list credit usage. */
388 	kstat_named_t rx_flbuf_fails;	/* # of freelist buf alloc fails. */
389 	kstat_named_t rx_flbuf_allocs;	/* # of freelist buf allocs. */
390 	kstat_named_t rx_badEopSop;	/* # of times bad Eop/Sop received */
391 	kstat_named_t rx_flq0_cnt; /* # of times free list Q 0 entry used */
392 	kstat_named_t rx_flq1_cnt; /* # of times free list Q 1 entry used */
393 	kstat_named_t arp_sent;		/* # times arp packet sent */
394 
395 	kstat_named_t tx_doorbells;
396 	kstat_named_t intr_doorbells;
397 	kstat_named_t intr1_doorbells;
398 	kstat_named_t sleep_cnt;
399 	kstat_named_t pe_allocb_cnt;
400 	kstat_named_t tx_descs[MBLK_MAX];
401 } ch_kstat_t;
402 typedef ch_kstat_t *p_ch_kstat_t;
403 #endif
404 
405 typedef struct _pesge {
406 	peobj *obj;			/* adapter backpointer */
407 	struct freelQ freelQ[2];	/* freelist Q(s) */
408 	struct respQ respQ;		/* response Q instatiation */
409 	uint32_t rx_pkt_pad;		/* RX padding for T2 packets (hw) */
410 	uint32_t rx_offset;		/* RX padding for T1 packets (sw) */
411 	uint32_t jumbo_fl;		/* jumbo freelist Q index */
412 	uint32_t intrtimer[SGE_INTR_MAXBUCKETS];	/* timer values */
413 	uint32_t currIndex;		/* current index into intrtimer[] */
414 	uint32_t intrtimer_nres;	/* no resource interrupt timer value */
415 	uint32_t sge_control;		/* shadow content of sge control reg */
416 	struct sge_intr_counts intr_cnt;
417 #ifdef SUN_KSTATS
418 	p_kstat_t ksp;
419 #endif
420 	ch_cyclic_t espi_wa_cyclic;
421 	uint32_t ptimeout;
422 	void *pskb;
423 	struct cmdQ cmdQ[2];	    /* command Q(s) */
424 	int do_udp_csum;
425 	int do_tcp_csum;
426 } _pesge;
427 
428 /*
429  * ce_flg flag values
430  */
431 #define	DH_DMA  1
432 #define	DH_DVMA 2
433 #define	DH_TOE  3
434 #define	DH_ARP  8
435 
436 typedef struct freelQ_ce {
437 	void *fe_mp;		/* head mblk of pkt */
438 	ulong_t fe_dh;		/* ddi dma handle */
439 	uint_t  fe_len;		/* length of mblk component */
440 	uint64_t fe_pa;		/* physical address */
441 } freelQ_ce_t;
442 
443 pesge *t1_sge_create(ch_t *, struct sge_params *);
444 
445 extern int  t1_sge_destroy(pesge* sge);
446 extern int  sge_data_out(pesge*, int,  mblk_t *, cmdQ_ce_t *, int, uint32_t);
447 extern int  sge_data_in(pesge *);
448 extern int  sge_start(pesge*);
449 extern int  sge_stop(pesge *);
450 extern int t1_sge_configure(pesge *sge, struct sge_params *p);
451 
452 extern int  t1_sge_intr_error_handler(pesge*);
453 extern int  t1_sge_intr_enable(pesge*);
454 extern int  t1_sge_intr_disable(pesge*);
455 extern int  t1_sge_intr_clear(pesge*);
456 extern u32  t1_sge_get_ptimeout(ch_t *);
457 extern void t1_sge_set_ptimeout(ch_t *, u32);
458 
459 extern struct sge_intr_counts *sge_get_stat(pesge *);
460 extern void sge_add_fake_arp(pesge *, void *);
461 
462 /*
463  * Default SGE settings
464  */
465 #define	SGE_CMDQ0_CNT	(512)
466 #define	SGE_FLQ0_CNT	(512)
467 #define	SGE_RESPQ_CNT	(1024)
468 
469 /*
470  * the structures below were taken from cpl5_cmd.h. It turns out that there
471  * is a number of   #includes    that causes build problems. For now, we're
472  * putting a private copy here. When the sge code is made common, then this
473  * problem will need to be resolved.
474  */
475 
476 typedef uint8_t  __u8;
477 typedef uint32_t __u32;
478 typedef uint16_t __u16;
479 
480 union opcode_tid {
481     __u32 opcode_tid;
482     __u8 opcode;
483 };
484 
485 /*
486  * We want this header's alignment to be no more stringent than 2-byte aligned.
487  * All fields are u8 or u16 except for the length.  However that field is not
488  * used so we break it into 2 16-bit parts to easily meet our alignment needs.
489  */
490 struct cpl_tx_pkt {
491     __u8 opcode;
492 #if BYTE_ORDER == BIG_ENDIAN
493     __u8 rsvd:1;
494     __u8 vlan_valid:1;
495     __u8 l4_csum_dis:1;
496     __u8 ip_csum_dis:1;
497     __u8 iff:4;
498 #else
499     __u8 iff:4;
500     __u8 ip_csum_dis:1;
501     __u8 l4_csum_dis:1;
502     __u8 vlan_valid:1;
503     __u8 rsvd:1;
504 #endif
505     __u16 vlan;
506     __u16 len_hi;
507     __u16 len_lo;
508 };
509 
510 #define	CPL_TX_PKT 0xb2
511 #define	SZ_CPL_TX_PKT CPL_FORMAT_0_SIZE
512 
513 struct cpl_rx_data {
514     union opcode_tid ot;
515     __u32 len;
516     __u32 seq;
517     __u16 urg;
518     __u8  rsvd;
519     __u8  status;
520 };
521 
522 struct cpl_rx_pkt {
523     __u8 opcode;
524 #if BYTE_ORDER == LITTLE_ENDIAN
525     __u8 iff:4;
526     __u8 csum_valid:1;
527     __u8 bad_pkt:1;
528     __u8 vlan_valid:1;
529     __u8 rsvd:1;
530 #else
531     __u8 rsvd:1;
532     __u8 vlan_valid:1;
533     __u8 bad_pkt:1;
534     __u8 csum_valid:1;
535     __u8 iff:4;
536 #endif
537     __u16 csum;
538     __u16 vlan;
539     __u16 len;
540 };
541 
542 #ifdef __cplusplus
543 }
544 #endif
545 
546 #endif /* _CHELSIO_SGE_H */
547