| /* |
| * 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 2005 Sun Microsystems, Inc. All rights reserved. |
| * Use is subject to license terms. |
| */ |
| |
| /* |
| * This file is part of the Chelsio T1 Ethernet driver. |
| * |
| * Copyright (C) 2003-2005 Chelsio Communications. All rights reserved. |
| */ |
| |
| #ifndef _CHELSIO_SGE_H |
| #define _CHELSIO_SGE_H |
| |
| #pragma ident "%Z%%M% %I% %E% SMI" |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #include <sys/types.h> |
| |
| #include "osdep.h" |
| |
| #define MBLK_MAX 8 |
| |
| #define spin_lock mutex_enter |
| #define spin_unlock mutex_exit |
| #define atomic_sub(a, b) atomic_add_32(b, -(a)) |
| #define atomic_add(a, b) atomic_add_32(b, (a)) |
| #define atomic_read(a) (a) |
| #define atomic_set(a, b) (*(a) = b) |
| #define spinlock_t kmutex_t |
| #define dma_addr_t uint64_t |
| #define wmb() membar_producer() |
| #define doorbell_pio(sge, cmd) sge_ring_doorbell(sge, cmd) |
| #define skb_reserve(skb, offset) (skb->b_rptr += offset) |
| #define __skb_pull(skb, len) (skb->b_rptr += len) |
| #define skb_put(skb, len) ((skb)->b_wptr = (skb)->b_rptr + (len)) |
| #define skb_pull(skb, len) (skb->b_rptr += len) |
| #define unlikely(a) (a) |
| #define likely(a) (a) |
| #define SKB_DATA_ALIGN(X) (((X) + (sizeof (long)-1)) & ~(sizeof (long)-1)) |
| #define t1_is_T1B(adap) adapter_matches_type(adap, CHBT_TERM_T1, TERM_T1B) |
| #define t1_is_T1C(adap) adapter_matches_type(adap, CHBT_TERM_T1, TERM_T1C) |
| |
| #define SGE_SM_BUF_SZ(sa) (sa->ch_sm_buf_sz) |
| #define SGE_BG_BUF_SZ(sa) (sa->ch_bg_buf_sz) |
| |
| #define SGE_CMDQ_N 2 |
| #define SGE_FREELQ_N 2 |
| #ifdef CONFIG_CHELSIO_T1_OFFLOAD |
| #define SGE_CMDQ0_E_N 4096 |
| #define SGE_CMDQ1_E_N 128 |
| #define SGE_FREELQ0_E_N 2048 |
| #define SGE_FREELQ1_E_N 1024 |
| #define SGE_RESPQ_E_N 7168 /* |CMDQ0| + |FREELQ0| + |FREELQ1| */ |
| #else |
| #define SGE_CMDQ0_E_N 2048 |
| #define SGE_CMDQ1_E_N 128 |
| #define SGE_FREELQ0_E_N 4096 |
| #define SGE_FREELQ1_E_N 1024 |
| #define SGE_RESPQ_E_N 7168 /* |CMDQ0| + |FREELQ0| + |FREELQ1| */ |
| #endif /* CONFIG_CHELSIO_T1_OFFLOAD */ |
| #define SGE_BATCH_THRESH 16 |
| #define SGE_INTR_BUCKETSIZE 100 |
| #define SGE_INTR_MAXBUCKETS 11 |
| #define SGE_INTRTIMER0 1 |
| #define SGE_INTRTIMER1 30 |
| #define SGE_INTRTIMER_NRES 10000 |
| #define SGE_RX_COPY_THRESHOLD 256 |
| #define SGE_RX_OFFSET 2 |
| #ifdef CONFIG_CHELSIO_T1_OFFLOAD |
| #define SGE_RX_SM_BUF_SIZE(sa) 1536 |
| #else |
| #define SGE_RX_SM_BUF_SIZE(sa) (sa->ch_sm_buf_sz) |
| #endif |
| |
| /* |
| * CPL5 Defines |
| */ |
| #define FLITSTOBYTES 8 |
| |
| #define CPL_FORMAT_0_SIZE 8 |
| #define CPL_FORMAT_1_SIZE 16 |
| #define CPL_FORMAT_2_SIZE 24 |
| #define CPL_FORMAT_3_SIZE 32 |
| #define CPL_FORMAT_4_SIZE 40 |
| #define CPL_FORMAT_5_SIZE 48 |
| |
| #define TID_MASK 0xffffff |
| |
| #define SZ_CPL_RX_PKT CPL_FORMAT_0_SIZE |
| |
| #if BYTE_ORDER == BIG_ENDIAN |
| |
| typedef struct { |
| u32 AddrLow; |
| u32 GenerationBit: 1; |
| u32 BufferLength: 31; |
| u32 RespQueueSelector: 4; |
| u32 ResponseTokens: 12; |
| u32 CmdId: 8; |
| u32 Reserved: 3; |
| u32 TokenValid: 1; |
| u32 Eop: 1; |
| u32 Sop: 1; |
| u32 DataValid: 1; |
| u32 GenerationBit2: 1; |
| u32 AddrHigh; |
| } CmdQueueEntry; |
| |
| |
| #elif BYTE_ORDER == LITTLE_ENDIAN |
| |
| |
| typedef struct { |
| u32 BufferLength: 31; |
| u32 GenerationBit: 1; |
| u32 AddrLow; |
| u32 AddrHigh; |
| u32 GenerationBit2: 1; |
| u32 DataValid: 1; |
| u32 Sop: 1; |
| u32 Eop: 1; |
| u32 TokenValid: 1; |
| u32 Reserved: 3; |
| u32 CmdId: 8; |
| u32 ResponseTokens: 12; |
| u32 RespQueueSelector: 4; |
| } CmdQueueEntry; |
| |
| #endif |
| |
| |
| typedef CmdQueueEntry cmdQ_e; |
| |
| #if BYTE_ORDER == BIG_ENDIAN |
| |
| typedef struct { |
| u32 Qsleeping: 4; |
| u32 Cmdq1CreditReturn: 5; |
| u32 Cmdq1DmaComplete: 5; |
| u32 Cmdq0CreditReturn: 5; |
| u32 Cmdq0DmaComplete: 5; |
| u32 FreelistQid: 2; |
| u32 CreditValid: 1; |
| u32 DataValid: 1; |
| u32 Offload: 1; |
| u32 Eop: 1; |
| u32 Sop: 1; |
| u32 GenerationBit: 1; |
| u32 BufferLength; |
| } ResponseQueueEntry; |
| |
| |
| #elif BYTE_ORDER == LITTLE_ENDIAN |
| |
| |
| typedef struct { |
| u32 BufferLength; |
| u32 GenerationBit: 1; |
| u32 Sop: 1; |
| u32 Eop: 1; |
| u32 Offload: 1; |
| u32 DataValid: 1; |
| u32 CreditValid: 1; |
| u32 FreelistQid: 2; |
| u32 Cmdq0DmaComplete: 5; |
| u32 Cmdq0CreditReturn: 5; |
| u32 Cmdq1DmaComplete: 5; |
| u32 Cmdq1CreditReturn: 5; |
| u32 Qsleeping: 4; |
| } ResponseQueueEntry; |
| |
| #endif |
| |
| typedef ResponseQueueEntry respQ_e; |
| |
| #if BYTE_ORDER == BIG_ENDIAN |
| |
| |
| typedef struct { |
| u32 AddrLow; |
| u32 GenerationBit: 1; |
| u32 BufferLength: 31; |
| u32 Reserved: 31; |
| u32 GenerationBit2: 1; |
| u32 AddrHigh; |
| } FLQueueEntry; |
| |
| |
| #elif BYTE_ORDER == LITTLE_ENDIAN |
| |
| |
| typedef struct { |
| u32 BufferLength: 31; |
| u32 GenerationBit: 1; |
| u32 AddrLow; |
| u32 AddrHigh; |
| u32 GenerationBit2: 1; |
| u32 Reserved: 31; |
| } FLQueueEntry; |
| |
| |
| #endif |
| |
| typedef FLQueueEntry freelQ_e; |
| |
| /* |
| * Command QUEUE meta entry format. |
| */ |
| typedef struct cmdQ_ce { |
| void *ce_mp; /* head mblk of pkt */ |
| free_dh_t *ce_dh; /* ddi dma handle */ |
| uint_t ce_flg; /* flag 0 - NIC descriptor; 1 - TOE */ |
| uint_t ce_len; /* length of mblk component */ |
| uint64_t ce_pa; /* physical address */ |
| } cmdQ_ce_t; |
| |
| /* |
| * command queue control structure |
| */ |
| typedef struct cmdQ { |
| u32 cq_credits; /* # available descriptors for Xmit */ |
| u32 cq_asleep; /* HW DMA Fetch status */ |
| u32 cq_pio_pidx; /* Variable updated on Doorbell */ |
| u32 cq_entries_n; /* # entries for Xmit */ |
| u32 cq_pidx; /* producer index (SW) */ |
| u32 cq_complete; /* Shadow consumer index (HW) */ |
| u32 cq_cidx; /* consumer index (HW) */ |
| u32 cq_genbit; /* current generation (=valid) bit */ |
| cmdQ_e *cq_entries; |
| cmdQ_ce_t *cq_centries; |
| spinlock_t cq_qlock; |
| uint64_t cq_pa; /* may not be needed */ |
| ulong_t cq_dh; |
| ulong_t cq_ah; /* may not be needed */ |
| } cmdQ_t; |
| |
| /* |
| * free list queue control structure |
| */ |
| typedef struct freelQ { |
| u32 fq_id; /* 0 queue 0, 1 queue 1 */ |
| u32 fq_credits; /* # available RX buffer descriptors */ |
| u32 fq_entries_n; /* # RX buffer descriptors */ |
| u32 fq_pidx; /* producer index (SW) */ |
| u32 fq_cidx; /* consumer index (HW) */ |
| u32 fq_genbit; /* current generation (=valid) bit */ |
| u32 fq_rx_buffer_size; /* size buffer on this freelist */ |
| freelQ_e *fq_entries; /* HW freelist descriptor Q */ |
| struct freelQ_ce *fq_centries; /* SW freelist conext descriptor Q */ |
| uint64_t fq_pa; /* may not be needed */ |
| ulong_t fq_dh; |
| ulong_t fq_ah; |
| u32 fq_pause_on_thresh; |
| u32 fq_pause_off_thresh; |
| } freelQ_t; |
| |
| /* |
| * response queue control structure |
| */ |
| typedef struct respQ { |
| u32 rq_credits; /* # avail response Q entries */ |
| u32 rq_credits_pend; /* # not yet returned entries */ |
| u32 rq_credits_thresh; /* return threshold */ |
| u32 rq_entries_n; /* # response Q descriptors */ |
| u32 rq_pidx; /* producer index (HW) */ |
| u32 rq_cidx; /* consumer index (SW) */ |
| u32 rq_genbit; /* current generation(=valid) bit */ |
| respQ_e *rq_entries; /* HW response Q */ |
| uint64_t rq_pa; /* may not be needed */ |
| ulong_t rq_dh; |
| ulong_t rq_ah; |
| } reapQ_t; |
| |
| struct sge_intr_counts { |
| uint32_t respQ_empty; /* # times respQ empty */ |
| uint32_t respQ_overflow; /* # respQ overflow (fatal) */ |
| uint32_t freelistQ_empty; /* # times freelist empty */ |
| uint32_t pkt_too_big; /* packet too large (fatal) */ |
| uint32_t pkt_mismatch; |
| uint32_t cmdQ_full[2]; /* not HW intr, host cmdQ[] full */ |
| uint32_t tx_reclaims[2]; |
| uint32_t tx_msg_pullups; /* # of tx pkt coelescing events */ |
| uint32_t tx_hdr_pullups; /* # of tx hdr coelescing events */ |
| uint32_t tx_tcp_ip_frag; /* # of ip fragmentes for tcp data */ |
| uint32_t tx_udp_ip_frag; /* # of ip fragmentes for udp data */ |
| uint32_t tx_soft_cksums; /* # of Software checksums done. */ |
| uint32_t tx_need_cpl_space; /* # of allocs for cpl header */ |
| uint32_t tx_multi_mblks; /* # of Multi mblk packets */ |
| uint32_t tx_no_dvma1; /* # of dvma mapping failures */ |
| uint32_t tx_no_dvma2; /* # of dvma mapping failures */ |
| uint32_t tx_no_dma1; /* # of dma mapping failures */ |
| uint32_t tx_no_dma2; /* # of dma mapping failures */ |
| uint32_t rx_cmdq0; /* # of Qsleeping CMDQ0's */ |
| uint32_t rx_cmdq1; /* # of Qsleeping CMDQ1's */ |
| uint32_t rx_flq0; /* # of Qsleeping FL0's */ |
| uint32_t rx_flq1; /* # of Qsleeping FL1's */ |
| uint32_t rx_flq0_sz; /* size of freelist-0 buffers */ |
| uint32_t rx_flq1_sz; /* size of freelist-1 buffers */ |
| uint32_t rx_pkt_drops; /* # intentionally dropped packets */ |
| uint32_t rx_pkt_copied; /* # times packets copied by sge */ |
| uint32_t rx_pause_on; /* # of system pause on's required. */ |
| uint32_t rx_pause_off; /* # of system pauses off's required. */ |
| uint32_t rx_pause_ms; /* micro seconds while paused */ |
| uint32_t rx_pause_spike; /* maximum time paused */ |
| uint32_t rx_fl_credits; /* Current free list credit usage. */ |
| uint32_t rx_flbuf_fails; /* # of freelist buf alloc fails. */ |
| uint32_t rx_flbuf_allocs; /* # of freelist buf allocs. */ |
| uint32_t rx_badEopSop; /* # of times bad Eop/Sop received */ |
| uint32_t rx_flq0_cnt; /* # of times free list Q 0 entry used */ |
| uint32_t rx_flq1_cnt; /* # of times free list Q 1 entry used */ |
| uint32_t arp_sent; /* # times arp packet sent */ |
| #ifdef SUN_KSTATS |
| uint32_t tx_doorbells; |
| uint32_t intr_doorbells; |
| uint32_t intr1_doorbells; |
| uint32_t sleep_cnt; |
| uint32_t pe_allocb_cnt; |
| uint32_t tx_descs[MBLK_MAX]; |
| #endif |
| }; |
| |
| #ifdef SUN_KSTATS |
| typedef struct sge_intr_counts *p_ch_stats_t; |
| |
| /* |
| * Driver maintained kernel statistics. |
| */ |
| typedef struct _ch_kstat_t { |
| /* |
| * Link Input/Output stats |
| */ |
| kstat_named_t respQ_empty; /* # times respQ empty */ |
| kstat_named_t respQ_overflow; /* # respQ overflow (fatal) */ |
| kstat_named_t freelistQ_empty; /* # times freelist empty */ |
| kstat_named_t pkt_too_big; /* packet too large (fatal) */ |
| kstat_named_t pkt_mismatch; |
| kstat_named_t cmdQ_full[2]; /* not HW intr, host cmdQ[] full */ |
| kstat_named_t tx_reclaims[2]; /* # of tx reclaims called */ |
| kstat_named_t tx_msg_pullups; /* # of tx pkt coelescing events */ |
| kstat_named_t tx_hdr_pullups; /* # of tx hdr coelescing events */ |
| kstat_named_t tx_tcp_ip_frag; /* # of ip fragmentes for tcp data */ |
| kstat_named_t tx_udp_ip_frag; /* # of ip fragmentes for udp data */ |
| kstat_named_t tx_soft_cksums; /* # of Software checksums done. */ |
| kstat_named_t tx_need_cpl_space; /* # of allocs for cpl header */ |
| kstat_named_t tx_multi_mblks; /* # of multi fragment packets */ |
| kstat_named_t tx_no_dvma1; /* # of dvma mapping failures */ |
| kstat_named_t tx_no_dvma2; /* # of dvma mapping failures */ |
| kstat_named_t tx_no_dma1; /* # of dma mapping failures */ |
| kstat_named_t tx_no_dma2; /* # of dma mapping failures */ |
| kstat_named_t rx_cmdq0; /* # times Qsleeping cmdq0 */ |
| kstat_named_t rx_cmdq1; /* # times Qsleeping cmdq1 */ |
| kstat_named_t rx_flq0; /* # times Qsleeping flq0 */ |
| kstat_named_t rx_flq0_sz; /* size of freelist-0 buffers */ |
| kstat_named_t rx_flq1; /* # times Qsleeping flq1 */ |
| kstat_named_t rx_flq1_sz; /* size of freelist-1 buffers */ |
| kstat_named_t rx_pkt_drops; /* # times packets dropped by sge */ |
| kstat_named_t rx_pkt_copied; /* # intentionally copied packets */ |
| kstat_named_t rx_pause_on; /* # of system pause on's required. */ |
| kstat_named_t rx_pause_off; /* # of system pauses off's required. */ |
| kstat_named_t rx_pause_ms; /* micro seconds while paused. */ |
| kstat_named_t rx_pause_spike; /* maximum time paused. */ |
| kstat_named_t rx_fl_credits; /* Current free list credit usage. */ |
| kstat_named_t rx_flbuf_fails; /* # of freelist buf alloc fails. */ |
| kstat_named_t rx_flbuf_allocs; /* # of freelist buf allocs. */ |
| kstat_named_t rx_badEopSop; /* # of times bad Eop/Sop received */ |
| kstat_named_t rx_flq0_cnt; /* # of times free list Q 0 entry used */ |
| kstat_named_t rx_flq1_cnt; /* # of times free list Q 1 entry used */ |
| kstat_named_t arp_sent; /* # times arp packet sent */ |
| |
| kstat_named_t tx_doorbells; |
| kstat_named_t intr_doorbells; |
| kstat_named_t intr1_doorbells; |
| kstat_named_t sleep_cnt; |
| kstat_named_t pe_allocb_cnt; |
| kstat_named_t tx_descs[MBLK_MAX]; |
| } ch_kstat_t; |
| typedef ch_kstat_t *p_ch_kstat_t; |
| #endif |
| |
| typedef struct _pesge { |
| peobj *obj; /* adapter backpointer */ |
| struct freelQ freelQ[2]; /* freelist Q(s) */ |
| struct respQ respQ; /* response Q instatiation */ |
| uint32_t rx_pkt_pad; /* RX padding for T2 packets (hw) */ |
| uint32_t rx_offset; /* RX padding for T1 packets (sw) */ |
| uint32_t jumbo_fl; /* jumbo freelist Q index */ |
| uint32_t intrtimer[SGE_INTR_MAXBUCKETS]; /* timer values */ |
| uint32_t currIndex; /* current index into intrtimer[] */ |
| uint32_t intrtimer_nres; /* no resource interrupt timer value */ |
| uint32_t sge_control; /* shadow content of sge control reg */ |
| struct sge_intr_counts intr_cnt; |
| #ifdef SUN_KSTATS |
| p_kstat_t ksp; |
| #endif |
| ch_cyclic_t espi_wa_cyclic; |
| uint32_t ptimeout; |
| void *pskb; |
| struct cmdQ cmdQ[2]; /* command Q(s) */ |
| int do_udp_csum; |
| int do_tcp_csum; |
| } _pesge; |
| |
| /* |
| * ce_flg flag values |
| */ |
| #define DH_DMA 1 |
| #define DH_DVMA 2 |
| #define DH_TOE 3 |
| #define DH_ARP 8 |
| |
| typedef struct freelQ_ce { |
| void *fe_mp; /* head mblk of pkt */ |
| ulong_t fe_dh; /* ddi dma handle */ |
| uint_t fe_len; /* length of mblk component */ |
| uint64_t fe_pa; /* physical address */ |
| } freelQ_ce_t; |
| |
| pesge *t1_sge_create(ch_t *, struct sge_params *); |
| |
| extern int t1_sge_destroy(pesge* sge); |
| extern int sge_data_out(pesge*, int, mblk_t *, cmdQ_ce_t *, int, uint32_t); |
| extern int sge_data_in(pesge *); |
| extern int sge_start(pesge*); |
| extern int sge_stop(pesge *); |
| extern int t1_sge_configure(pesge *sge, struct sge_params *p); |
| |
| extern int t1_sge_intr_error_handler(pesge*); |
| extern int t1_sge_intr_enable(pesge*); |
| extern int t1_sge_intr_disable(pesge*); |
| extern int t1_sge_intr_clear(pesge*); |
| extern u32 t1_sge_get_ptimeout(ch_t *); |
| extern void t1_sge_set_ptimeout(ch_t *, u32); |
| |
| extern struct sge_intr_counts *sge_get_stat(pesge *); |
| extern void sge_add_fake_arp(pesge *, void *); |
| |
| /* |
| * Default SGE settings |
| */ |
| #define SGE_CMDQ0_CNT (512) |
| #define SGE_FLQ0_CNT (512) |
| #define SGE_RESPQ_CNT (1024) |
| |
| /* |
| * the structures below were taken from cpl5_cmd.h. It turns out that there |
| * is a number of #includes that causes build problems. For now, we're |
| * putting a private copy here. When the sge code is made common, then this |
| * problem will need to be resolved. |
| */ |
| |
| typedef uint8_t __u8; |
| typedef uint32_t __u32; |
| typedef uint16_t __u16; |
| |
| union opcode_tid { |
| __u32 opcode_tid; |
| __u8 opcode; |
| }; |
| |
| /* |
| * We want this header's alignment to be no more stringent than 2-byte aligned. |
| * All fields are u8 or u16 except for the length. However that field is not |
| * used so we break it into 2 16-bit parts to easily meet our alignment needs. |
| */ |
| struct cpl_tx_pkt { |
| __u8 opcode; |
| #if BYTE_ORDER == BIG_ENDIAN |
| __u8 rsvd:1; |
| __u8 vlan_valid:1; |
| __u8 l4_csum_dis:1; |
| __u8 ip_csum_dis:1; |
| __u8 iff:4; |
| #else |
| __u8 iff:4; |
| __u8 ip_csum_dis:1; |
| __u8 l4_csum_dis:1; |
| __u8 vlan_valid:1; |
| __u8 rsvd:1; |
| #endif |
| __u16 vlan; |
| __u16 len_hi; |
| __u16 len_lo; |
| }; |
| |
| #define CPL_TX_PKT 0xb2 |
| #define SZ_CPL_TX_PKT CPL_FORMAT_0_SIZE |
| |
| struct cpl_rx_data { |
| union opcode_tid ot; |
| __u32 len; |
| __u32 seq; |
| __u16 urg; |
| __u8 rsvd; |
| __u8 status; |
| }; |
| |
| struct cpl_rx_pkt { |
| __u8 opcode; |
| #if BYTE_ORDER == LITTLE_ENDIAN |
| __u8 iff:4; |
| __u8 csum_valid:1; |
| __u8 bad_pkt:1; |
| __u8 vlan_valid:1; |
| __u8 rsvd:1; |
| #else |
| __u8 rsvd:1; |
| __u8 vlan_valid:1; |
| __u8 bad_pkt:1; |
| __u8 csum_valid:1; |
| __u8 iff:4; |
| #endif |
| __u16 csum; |
| __u16 vlan; |
| __u16 len; |
| }; |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* _CHELSIO_SGE_H */ |