xref: /titanic_51/usr/src/uts/common/io/myri10ge/drv/myri10ge.c (revision 6d0043d8d3eb6aec4dcd2a08b6f9ec812da10113)
104b6cca3Slucy wang - Sun Microsystems - Beijing China /*
204b6cca3Slucy wang - Sun Microsystems - Beijing China  * CDDL HEADER START
304b6cca3Slucy wang - Sun Microsystems - Beijing China  *
404b6cca3Slucy wang - Sun Microsystems - Beijing China  * The contents of this file are subject to the terms of the
504b6cca3Slucy wang - Sun Microsystems - Beijing China  * Common Development and Distribution License (the "License").
604b6cca3Slucy wang - Sun Microsystems - Beijing China  * You may not use this file except in compliance with the License.
704b6cca3Slucy wang - Sun Microsystems - Beijing China  *
804b6cca3Slucy wang - Sun Microsystems - Beijing China  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
904b6cca3Slucy wang - Sun Microsystems - Beijing China  * or http://www.opensolaris.org/os/licensing.
1004b6cca3Slucy wang - Sun Microsystems - Beijing China  * See the License for the specific language governing permissions
1104b6cca3Slucy wang - Sun Microsystems - Beijing China  * and limitations under the License.
1204b6cca3Slucy wang - Sun Microsystems - Beijing China  *
1304b6cca3Slucy wang - Sun Microsystems - Beijing China  * When distributing Covered Code, include this CDDL HEADER in each
1404b6cca3Slucy wang - Sun Microsystems - Beijing China  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1504b6cca3Slucy wang - Sun Microsystems - Beijing China  * If applicable, add the following below this CDDL HEADER, with the
1604b6cca3Slucy wang - Sun Microsystems - Beijing China  * fields enclosed by brackets "[]" replaced with your own identifying
1704b6cca3Slucy wang - Sun Microsystems - Beijing China  * information: Portions Copyright [yyyy] [name of copyright owner]
1804b6cca3Slucy wang - Sun Microsystems - Beijing China  *
1904b6cca3Slucy wang - Sun Microsystems - Beijing China  * CDDL HEADER END
2004b6cca3Slucy wang - Sun Microsystems - Beijing China  */
2104b6cca3Slucy wang - Sun Microsystems - Beijing China 
2204b6cca3Slucy wang - Sun Microsystems - Beijing China /*
23a56d24eaSMark Johnson  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24a56d24eaSMark Johnson  * Use is subject to license terms.
25a56d24eaSMark Johnson  */
26a56d24eaSMark Johnson 
27a56d24eaSMark Johnson /*
2804b6cca3Slucy wang - Sun Microsystems - Beijing China  * Copyright 2007-2009 Myricom, Inc.  All rights reserved.
2904b6cca3Slucy wang - Sun Microsystems - Beijing China  * Use is subject to license terms.
3004b6cca3Slucy wang - Sun Microsystems - Beijing China  */
3104b6cca3Slucy wang - Sun Microsystems - Beijing China 
32*6d0043d8SRobert Mustacchi /*
33*6d0043d8SRobert Mustacchi  * Copyright (c) 2014, Joyent, Inc.
34*6d0043d8SRobert Mustacchi  */
35*6d0043d8SRobert Mustacchi 
3604b6cca3Slucy wang - Sun Microsystems - Beijing China #ifndef	lint
3704b6cca3Slucy wang - Sun Microsystems - Beijing China static const char __idstring[] =
3804b6cca3Slucy wang - Sun Microsystems - Beijing China 	"@(#)$Id: myri10ge.c,v 1.186 2009-06-29 13:47:22 gallatin Exp $";
3904b6cca3Slucy wang - Sun Microsystems - Beijing China #endif
4004b6cca3Slucy wang - Sun Microsystems - Beijing China 
4104b6cca3Slucy wang - Sun Microsystems - Beijing China #define	MXGEFW_NDIS
4204b6cca3Slucy wang - Sun Microsystems - Beijing China #include "myri10ge_var.h"
4304b6cca3Slucy wang - Sun Microsystems - Beijing China #include "rss_eth_z8e.h"
4404b6cca3Slucy wang - Sun Microsystems - Beijing China #include "rss_ethp_z8e.h"
4504b6cca3Slucy wang - Sun Microsystems - Beijing China #include "mcp_gen_header.h"
4604b6cca3Slucy wang - Sun Microsystems - Beijing China 
4704b6cca3Slucy wang - Sun Microsystems - Beijing China #define	MYRI10GE_MAX_ETHER_MTU 9014
48*6d0043d8SRobert Mustacchi #define	MYRI10GE_MAX_GLD_MTU	9000
49*6d0043d8SRobert Mustacchi #define	MYRI10GE_MIN_GLD_MTU	1500
5004b6cca3Slucy wang - Sun Microsystems - Beijing China 
5104b6cca3Slucy wang - Sun Microsystems - Beijing China #define	MYRI10GE_ETH_STOPPED 0
5204b6cca3Slucy wang - Sun Microsystems - Beijing China #define	MYRI10GE_ETH_STOPPING 1
5304b6cca3Slucy wang - Sun Microsystems - Beijing China #define	MYRI10GE_ETH_STARTING 2
5404b6cca3Slucy wang - Sun Microsystems - Beijing China #define	MYRI10GE_ETH_RUNNING 3
5504b6cca3Slucy wang - Sun Microsystems - Beijing China #define	MYRI10GE_ETH_OPEN_FAILED 4
5604b6cca3Slucy wang - Sun Microsystems - Beijing China #define	MYRI10GE_ETH_SUSPENDED_RUNNING 5
5704b6cca3Slucy wang - Sun Microsystems - Beijing China 
5804b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_small_bytes = 510;
5904b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_intr_coal_delay = 125;
6004b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_flow_control = 1;
615ee6ac27SRichard Lowe #if defined __i386 || defined i386 || defined __i386__ || defined __x86_64__
6204b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_nvidia_ecrc_enable = 1;
6304b6cca3Slucy wang - Sun Microsystems - Beijing China #endif
6404b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_mtu_override = 0;
6504b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_tx_copylen = 512;
6604b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_deassert_wait = 1;
6704b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_verbose = 0;
6804b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_watchdog_reset = 0;
6904b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_use_msix = 1;
7004b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_max_slices = -1;
7104b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_use_msi = 1;
7204b6cca3Slucy wang - Sun Microsystems - Beijing China int myri10ge_force_firmware = 0;
7304b6cca3Slucy wang - Sun Microsystems - Beijing China static boolean_t myri10ge_use_lso = B_TRUE;
7404b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_rss_hash = MXGEFW_RSS_HASH_TYPE_SRC_DST_PORT;
7504b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_tx_hash = 1;
7691e18787Slucy wang - Sun Microsystems - Beijing China static int myri10ge_lro = 0;
7704b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_lro_cnt = 8;
7804b6cca3Slucy wang - Sun Microsystems - Beijing China int myri10ge_lro_max_aggr = 2;
7904b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_lso_copy = 0;
8004b6cca3Slucy wang - Sun Microsystems - Beijing China static mblk_t *myri10ge_send_wrapper(void *arg, mblk_t *mp);
8104b6cca3Slucy wang - Sun Microsystems - Beijing China int myri10ge_tx_handles_initial = 128;
8204b6cca3Slucy wang - Sun Microsystems - Beijing China 
8304b6cca3Slucy wang - Sun Microsystems - Beijing China static 	kmutex_t myri10ge_param_lock;
8404b6cca3Slucy wang - Sun Microsystems - Beijing China static void* myri10ge_db_lastfree;
8504b6cca3Slucy wang - Sun Microsystems - Beijing China 
8604b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
8704b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
8804b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_quiesce(dev_info_t *dip);
8904b6cca3Slucy wang - Sun Microsystems - Beijing China 
9004b6cca3Slucy wang - Sun Microsystems - Beijing China DDI_DEFINE_STREAM_OPS(myri10ge_ops, nulldev, nulldev, myri10ge_attach,
9104b6cca3Slucy wang - Sun Microsystems - Beijing China     myri10ge_detach, nodev, NULL, D_MP, NULL, myri10ge_quiesce);
9204b6cca3Slucy wang - Sun Microsystems - Beijing China 
9304b6cca3Slucy wang - Sun Microsystems - Beijing China 
9404b6cca3Slucy wang - Sun Microsystems - Beijing China static struct modldrv modldrv = {
9504b6cca3Slucy wang - Sun Microsystems - Beijing China 	&mod_driverops,
9604b6cca3Slucy wang - Sun Microsystems - Beijing China 	"Myricom 10G driver (10GbE)",
9704b6cca3Slucy wang - Sun Microsystems - Beijing China 	&myri10ge_ops,
9804b6cca3Slucy wang - Sun Microsystems - Beijing China };
9904b6cca3Slucy wang - Sun Microsystems - Beijing China 
10004b6cca3Slucy wang - Sun Microsystems - Beijing China 
10104b6cca3Slucy wang - Sun Microsystems - Beijing China static struct modlinkage modlinkage = {
10204b6cca3Slucy wang - Sun Microsystems - Beijing China 	MODREV_1,
10304b6cca3Slucy wang - Sun Microsystems - Beijing China 	{&modldrv, NULL},
10404b6cca3Slucy wang - Sun Microsystems - Beijing China };
10504b6cca3Slucy wang - Sun Microsystems - Beijing China 
10604b6cca3Slucy wang - Sun Microsystems - Beijing China unsigned char myri10ge_broadcastaddr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
10704b6cca3Slucy wang - Sun Microsystems - Beijing China 
10804b6cca3Slucy wang - Sun Microsystems - Beijing China static ddi_dma_attr_t myri10ge_misc_dma_attr = {
10904b6cca3Slucy wang - Sun Microsystems - Beijing China 	DMA_ATTR_V0,			/* version number. */
11004b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint64_t)0, 			/* low address */
11104b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint64_t)0xffffffffffffffffULL, /* high address */
11204b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint64_t)0x7ffffff,		/* address counter max */
11304b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint64_t)4096,			/* alignment */
11404b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint_t)0x7f,			/* burstsizes for 32b and 64b xfers */
11504b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint32_t)0x1,			/* minimum transfer size */
11604b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint64_t)0x7fffffff,		/* maximum transfer size */
11704b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint64_t)0x7fffffff,		/* maximum segment size */
11804b6cca3Slucy wang - Sun Microsystems - Beijing China 	1,				/* scatter/gather list length */
11904b6cca3Slucy wang - Sun Microsystems - Beijing China 	1,				/* granularity */
12004b6cca3Slucy wang - Sun Microsystems - Beijing China 	0				/* attribute flags */
12104b6cca3Slucy wang - Sun Microsystems - Beijing China };
12204b6cca3Slucy wang - Sun Microsystems - Beijing China 
12304b6cca3Slucy wang - Sun Microsystems - Beijing China /*
12404b6cca3Slucy wang - Sun Microsystems - Beijing China  * The Myri10GE NIC has the following constraints on receive buffers:
12504b6cca3Slucy wang - Sun Microsystems - Beijing China  * 1) Buffers which cross a 4KB boundary must be aligned to 4KB
12604b6cca3Slucy wang - Sun Microsystems - Beijing China  * 2) Buffers which are not aligned to 4KB must not cross a 4KB boundary
12704b6cca3Slucy wang - Sun Microsystems - Beijing China  */
12804b6cca3Slucy wang - Sun Microsystems - Beijing China 
12904b6cca3Slucy wang - Sun Microsystems - Beijing China static ddi_dma_attr_t myri10ge_rx_jumbo_dma_attr = {
13004b6cca3Slucy wang - Sun Microsystems - Beijing China 	DMA_ATTR_V0,			/* version number. */
13104b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint64_t)0, 			/* low address */
13204b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint64_t)0xffffffffffffffffULL, /* high address */
13304b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint64_t)0x7ffffff,		/* address counter max */
13404b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint64_t)4096,			/* alignment */
13504b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint_t)0x7f,			/* burstsizes for 32b and 64b xfers */
13604b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint32_t)0x1,			/* minimum transfer size */
13704b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint64_t)0x7fffffff,		/* maximum transfer size */
13804b6cca3Slucy wang - Sun Microsystems - Beijing China 	UINT64_MAX,			/* maximum segment size */
13904b6cca3Slucy wang - Sun Microsystems - Beijing China 	1,				/* scatter/gather list length */
14004b6cca3Slucy wang - Sun Microsystems - Beijing China 	1,				/* granularity */
14104b6cca3Slucy wang - Sun Microsystems - Beijing China 	0				/* attribute flags */
14204b6cca3Slucy wang - Sun Microsystems - Beijing China };
14304b6cca3Slucy wang - Sun Microsystems - Beijing China 
14404b6cca3Slucy wang - Sun Microsystems - Beijing China static ddi_dma_attr_t myri10ge_rx_std_dma_attr = {
14504b6cca3Slucy wang - Sun Microsystems - Beijing China 	DMA_ATTR_V0,			/* version number. */
14604b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint64_t)0, 			/* low address */
14704b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint64_t)0xffffffffffffffffULL, /* high address */
14804b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint64_t)0x7ffffff,		/* address counter max */
14904b6cca3Slucy wang - Sun Microsystems - Beijing China #if defined sparc64 || defined __sparcv9
15004b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint64_t)4096,			/* alignment */
15104b6cca3Slucy wang - Sun Microsystems - Beijing China #else
15204b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint64_t)0x80,			/* alignment */
15304b6cca3Slucy wang - Sun Microsystems - Beijing China #endif
15404b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint_t)0x7f,			/* burstsizes for 32b and 64b xfers */
15504b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint32_t)0x1,			/* minimum transfer size */
15604b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint64_t)0x7fffffff,		/* maximum transfer size */
15704b6cca3Slucy wang - Sun Microsystems - Beijing China #if defined sparc64 || defined __sparcv9
15804b6cca3Slucy wang - Sun Microsystems - Beijing China 	UINT64_MAX,			/* maximum segment size */
15904b6cca3Slucy wang - Sun Microsystems - Beijing China #else
16004b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint64_t)0xfff,		/* maximum segment size */
16104b6cca3Slucy wang - Sun Microsystems - Beijing China #endif
16204b6cca3Slucy wang - Sun Microsystems - Beijing China 	1,				/* scatter/gather list length */
16304b6cca3Slucy wang - Sun Microsystems - Beijing China 	1,				/* granularity */
16404b6cca3Slucy wang - Sun Microsystems - Beijing China 	0				/* attribute flags */
16504b6cca3Slucy wang - Sun Microsystems - Beijing China };
16604b6cca3Slucy wang - Sun Microsystems - Beijing China 
16704b6cca3Slucy wang - Sun Microsystems - Beijing China static ddi_dma_attr_t myri10ge_tx_dma_attr = {
16804b6cca3Slucy wang - Sun Microsystems - Beijing China 	DMA_ATTR_V0,			/* version number. */
16904b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint64_t)0, 			/* low address */
17004b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint64_t)0xffffffffffffffffULL, /* high address */
17104b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint64_t)0x7ffffff,		/* address counter max */
17204b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint64_t)1,			/* alignment */
17304b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint_t)0x7f,			/* burstsizes for 32b and 64b xfers */
17404b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint32_t)0x1,			/* minimum transfer size */
17504b6cca3Slucy wang - Sun Microsystems - Beijing China 	(uint64_t)0x7fffffff,		/* maximum transfer size */
17604b6cca3Slucy wang - Sun Microsystems - Beijing China 	UINT64_MAX,			/* maximum segment size */
17704b6cca3Slucy wang - Sun Microsystems - Beijing China 	INT32_MAX,			/* scatter/gather list length */
17804b6cca3Slucy wang - Sun Microsystems - Beijing China 	1,				/* granularity */
17904b6cca3Slucy wang - Sun Microsystems - Beijing China 	0			/* attribute flags */
18004b6cca3Slucy wang - Sun Microsystems - Beijing China };
18104b6cca3Slucy wang - Sun Microsystems - Beijing China 
18204b6cca3Slucy wang - Sun Microsystems - Beijing China #if defined sparc64 || defined __sparcv9
18304b6cca3Slucy wang - Sun Microsystems - Beijing China #define	WC 0
18404b6cca3Slucy wang - Sun Microsystems - Beijing China #else
18504b6cca3Slucy wang - Sun Microsystems - Beijing China #define	WC 1
18604b6cca3Slucy wang - Sun Microsystems - Beijing China #endif
18704b6cca3Slucy wang - Sun Microsystems - Beijing China 
18804b6cca3Slucy wang - Sun Microsystems - Beijing China struct ddi_device_acc_attr myri10ge_dev_access_attr = {
18904b6cca3Slucy wang - Sun Microsystems - Beijing China 	DDI_DEVICE_ATTR_V0,		/* version */
19004b6cca3Slucy wang - Sun Microsystems - Beijing China 	DDI_NEVERSWAP_ACC,		/* endian flash */
19104b6cca3Slucy wang - Sun Microsystems - Beijing China #if WC
19204b6cca3Slucy wang - Sun Microsystems - Beijing China 	DDI_MERGING_OK_ACC		/* data order */
19304b6cca3Slucy wang - Sun Microsystems - Beijing China #else
19404b6cca3Slucy wang - Sun Microsystems - Beijing China 	DDI_STRICTORDER_ACC
19504b6cca3Slucy wang - Sun Microsystems - Beijing China #endif
19604b6cca3Slucy wang - Sun Microsystems - Beijing China };
19704b6cca3Slucy wang - Sun Microsystems - Beijing China 
19804b6cca3Slucy wang - Sun Microsystems - Beijing China static void myri10ge_watchdog(void *arg);
19904b6cca3Slucy wang - Sun Microsystems - Beijing China 
20004b6cca3Slucy wang - Sun Microsystems - Beijing China #ifdef MYRICOM_PRIV
20104b6cca3Slucy wang - Sun Microsystems - Beijing China int myri10ge_mtu = MYRI10GE_MAX_ETHER_MTU + MXGEFW_PAD + VLAN_TAGSZ;
202*6d0043d8SRobert Mustacchi #define	MYRI10GE_DEFAULT_GLD_MTU	MYRI10GE_MAX_GLD_MTU
20304b6cca3Slucy wang - Sun Microsystems - Beijing China #else
20404b6cca3Slucy wang - Sun Microsystems - Beijing China int myri10ge_mtu = ETHERMAX + MXGEFW_PAD + VLAN_TAGSZ;
205*6d0043d8SRobert Mustacchi #define	MYRI10GE_DEFAULT_GLD_MTU	MYRI10GE_MIN_GLD_MTU
20604b6cca3Slucy wang - Sun Microsystems - Beijing China #endif
20704b6cca3Slucy wang - Sun Microsystems - Beijing China int myri10ge_bigbufs_initial = 1024;
20804b6cca3Slucy wang - Sun Microsystems - Beijing China int myri10ge_bigbufs_max = 4096;
20904b6cca3Slucy wang - Sun Microsystems - Beijing China 
21004b6cca3Slucy wang - Sun Microsystems - Beijing China 
21104b6cca3Slucy wang - Sun Microsystems - Beijing China caddr_t
21204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_dma_alloc(dev_info_t *dip, size_t len,
21304b6cca3Slucy wang - Sun Microsystems - Beijing China     ddi_dma_attr_t *attr, ddi_device_acc_attr_t  *accattr,
21404b6cca3Slucy wang - Sun Microsystems - Beijing China     uint_t alloc_flags, int bind_flags, struct myri10ge_dma_stuff *dma,
21504b6cca3Slucy wang - Sun Microsystems - Beijing China     int warn, int (*wait)(caddr_t))
21604b6cca3Slucy wang - Sun Microsystems - Beijing China {
21704b6cca3Slucy wang - Sun Microsystems - Beijing China 	caddr_t  kaddr;
21804b6cca3Slucy wang - Sun Microsystems - Beijing China 	size_t real_length;
21904b6cca3Slucy wang - Sun Microsystems - Beijing China 	ddi_dma_cookie_t cookie;
22004b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint_t count;
22104b6cca3Slucy wang - Sun Microsystems - Beijing China 	int err;
22204b6cca3Slucy wang - Sun Microsystems - Beijing China 
22304b6cca3Slucy wang - Sun Microsystems - Beijing China 	err = ddi_dma_alloc_handle(dip, attr, wait,
22404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    NULL, &dma->handle);
22504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
22604b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (warn)
22704b6cca3Slucy wang - Sun Microsystems - Beijing China 			cmn_err(CE_WARN,
22804b6cca3Slucy wang - Sun Microsystems - Beijing China 			    "myri10ge: ddi_dma_alloc_handle failed\n");
22904b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_nothing;
23004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
23104b6cca3Slucy wang - Sun Microsystems - Beijing China 
23204b6cca3Slucy wang - Sun Microsystems - Beijing China 	err = ddi_dma_mem_alloc(dma->handle, len, accattr, alloc_flags,
23304b6cca3Slucy wang - Sun Microsystems - Beijing China 	    wait, NULL, &kaddr, &real_length,
23404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    &dma->acc_handle);
23504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
23604b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (warn)
23704b6cca3Slucy wang - Sun Microsystems - Beijing China 			cmn_err(CE_WARN,
23804b6cca3Slucy wang - Sun Microsystems - Beijing China 			    "myri10ge: ddi_dma_mem_alloc failed\n");
23904b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_handle;
24004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
24104b6cca3Slucy wang - Sun Microsystems - Beijing China 
24204b6cca3Slucy wang - Sun Microsystems - Beijing China 	err = ddi_dma_addr_bind_handle(dma->handle, NULL, kaddr, len,
24304b6cca3Slucy wang - Sun Microsystems - Beijing China 	    bind_flags, wait, NULL, &cookie, &count);
24404b6cca3Slucy wang - Sun Microsystems - Beijing China 
24504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
24604b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (warn)
24704b6cca3Slucy wang - Sun Microsystems - Beijing China 			cmn_err(CE_WARN,
24804b6cca3Slucy wang - Sun Microsystems - Beijing China 			    "myri10ge: ddi_dma_addr_bind_handle failed\n");
24904b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_mem;
25004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
25104b6cca3Slucy wang - Sun Microsystems - Beijing China 
25204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (count != 1) {
25304b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (warn)
25404b6cca3Slucy wang - Sun Microsystems - Beijing China 			cmn_err(CE_WARN,
25504b6cca3Slucy wang - Sun Microsystems - Beijing China 			    "myri10ge: got too many dma segments ");
25604b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_bind;
25704b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
25804b6cca3Slucy wang - Sun Microsystems - Beijing China 	dma->low = htonl(MYRI10GE_LOWPART_TO_U32(cookie.dmac_laddress));
25904b6cca3Slucy wang - Sun Microsystems - Beijing China 	dma->high = htonl(MYRI10GE_HIGHPART_TO_U32(cookie.dmac_laddress));
26004b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (kaddr);
26104b6cca3Slucy wang - Sun Microsystems - Beijing China 
26204b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_bind:
26304b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) ddi_dma_unbind_handle(dma->handle);
26404b6cca3Slucy wang - Sun Microsystems - Beijing China 
26504b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_mem:
26604b6cca3Slucy wang - Sun Microsystems - Beijing China 	ddi_dma_mem_free(&dma->acc_handle);
26704b6cca3Slucy wang - Sun Microsystems - Beijing China 
26804b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_handle:
26904b6cca3Slucy wang - Sun Microsystems - Beijing China 	ddi_dma_free_handle(&dma->handle);
27004b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_nothing:
27104b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (warn) {
27204b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "myri10ge: myri10ge_dma_alloc failed.\n  ");
27304b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "args: dip=%p len=0x%lx ddi_dma_attr=%p\n",
27404b6cca3Slucy wang - Sun Microsystems - Beijing China 		    (void*) dip, len, (void*) attr);
27504b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN,
27604b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "args: ddi_device_acc_attr=%p  alloc_flags=0x%x\n",
27704b6cca3Slucy wang - Sun Microsystems - Beijing China 		    (void*) accattr, alloc_flags);
27804b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "args: bind_flags=0x%x  dmastuff=%p",
27904b6cca3Slucy wang - Sun Microsystems - Beijing China 		    bind_flags, (void*) dma);
28004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
28104b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (NULL);
28204b6cca3Slucy wang - Sun Microsystems - Beijing China 
28304b6cca3Slucy wang - Sun Microsystems - Beijing China }
28404b6cca3Slucy wang - Sun Microsystems - Beijing China 
28504b6cca3Slucy wang - Sun Microsystems - Beijing China void
28604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_dma_free(struct myri10ge_dma_stuff *dma)
28704b6cca3Slucy wang - Sun Microsystems - Beijing China {
28804b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) ddi_dma_unbind_handle(dma->handle);
28904b6cca3Slucy wang - Sun Microsystems - Beijing China 	ddi_dma_mem_free(&dma->acc_handle);
29004b6cca3Slucy wang - Sun Microsystems - Beijing China 	ddi_dma_free_handle(&dma->handle);
29104b6cca3Slucy wang - Sun Microsystems - Beijing China }
29204b6cca3Slucy wang - Sun Microsystems - Beijing China 
29304b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void
29404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_pio_copy32(void *to, uint32_t *from32, size_t size)
29504b6cca3Slucy wang - Sun Microsystems - Beijing China {
29604b6cca3Slucy wang - Sun Microsystems - Beijing China 	register volatile uint32_t *to32;
29704b6cca3Slucy wang - Sun Microsystems - Beijing China 	size_t i;
29804b6cca3Slucy wang - Sun Microsystems - Beijing China 
29904b6cca3Slucy wang - Sun Microsystems - Beijing China 	to32 = (volatile uint32_t *) to;
30004b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (i = (size / 4); i; i--) {
30104b6cca3Slucy wang - Sun Microsystems - Beijing China 		*to32 = *from32;
30204b6cca3Slucy wang - Sun Microsystems - Beijing China 		to32++;
30304b6cca3Slucy wang - Sun Microsystems - Beijing China 		from32++;
30404b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
30504b6cca3Slucy wang - Sun Microsystems - Beijing China }
30604b6cca3Slucy wang - Sun Microsystems - Beijing China 
30704b6cca3Slucy wang - Sun Microsystems - Beijing China #if defined(_LP64)
30804b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void
30904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_pio_copy64(void *to, uint64_t *from64, size_t size)
31004b6cca3Slucy wang - Sun Microsystems - Beijing China {
31104b6cca3Slucy wang - Sun Microsystems - Beijing China 	register volatile uint64_t *to64;
31204b6cca3Slucy wang - Sun Microsystems - Beijing China 	size_t i;
31304b6cca3Slucy wang - Sun Microsystems - Beijing China 
31404b6cca3Slucy wang - Sun Microsystems - Beijing China 	to64 = (volatile uint64_t *) to;
31504b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (i = (size / 8); i; i--) {
31604b6cca3Slucy wang - Sun Microsystems - Beijing China 		*to64 = *from64;
31704b6cca3Slucy wang - Sun Microsystems - Beijing China 		to64++;
31804b6cca3Slucy wang - Sun Microsystems - Beijing China 		from64++;
31904b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
32004b6cca3Slucy wang - Sun Microsystems - Beijing China }
32104b6cca3Slucy wang - Sun Microsystems - Beijing China #endif
32204b6cca3Slucy wang - Sun Microsystems - Beijing China 
32304b6cca3Slucy wang - Sun Microsystems - Beijing China /*
32404b6cca3Slucy wang - Sun Microsystems - Beijing China  * This routine copies memory from the host to the NIC.
32504b6cca3Slucy wang - Sun Microsystems - Beijing China  * The "size" argument must always be a multiple of
32604b6cca3Slucy wang - Sun Microsystems - Beijing China  * the size of long (4 or 8 bytes), and to/from must also
32704b6cca3Slucy wang - Sun Microsystems - Beijing China  * be naturally aligned.
32804b6cca3Slucy wang - Sun Microsystems - Beijing China  */
32904b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void
33004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_pio_copy(void *to, void *from, size_t size)
33104b6cca3Slucy wang - Sun Microsystems - Beijing China {
33204b6cca3Slucy wang - Sun Microsystems - Beijing China #if !defined(_LP64)
33304b6cca3Slucy wang - Sun Microsystems - Beijing China 	ASSERT((size % 4) == 0);
33404b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_pio_copy32(to, (uint32_t *)from, size);
33504b6cca3Slucy wang - Sun Microsystems - Beijing China #else
33604b6cca3Slucy wang - Sun Microsystems - Beijing China 	ASSERT((size % 8) == 0);
33704b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_pio_copy64(to, (uint64_t *)from, size);
33804b6cca3Slucy wang - Sun Microsystems - Beijing China #endif
33904b6cca3Slucy wang - Sun Microsystems - Beijing China }
34004b6cca3Slucy wang - Sun Microsystems - Beijing China 
34104b6cca3Slucy wang - Sun Microsystems - Beijing China 
34204b6cca3Slucy wang - Sun Microsystems - Beijing China /*
34304b6cca3Slucy wang - Sun Microsystems - Beijing China  * Due to various bugs in Solaris (especially bug 6186772 where the
34404b6cca3Slucy wang - Sun Microsystems - Beijing China  * TCP/UDP checksum is calculated incorrectly on mblk chains with more
34504b6cca3Slucy wang - Sun Microsystems - Beijing China  * than two elements), and the design bug where hardware checksums are
34604b6cca3Slucy wang - Sun Microsystems - Beijing China  * ignored on mblk chains with more than 2 elements, we need to
34704b6cca3Slucy wang - Sun Microsystems - Beijing China  * allocate private pool of physically contiguous receive buffers.
34804b6cca3Slucy wang - Sun Microsystems - Beijing China  */
34904b6cca3Slucy wang - Sun Microsystems - Beijing China 
35004b6cca3Slucy wang - Sun Microsystems - Beijing China static void
35104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_jpool_init(struct myri10ge_slice_state *ss)
35204b6cca3Slucy wang - Sun Microsystems - Beijing China {
35304b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_jpool_stuff *jpool = &ss->jpool;
35404b6cca3Slucy wang - Sun Microsystems - Beijing China 
35504b6cca3Slucy wang - Sun Microsystems - Beijing China 	bzero(jpool, sizeof (*jpool));
35604b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_init(&jpool->mtx, NULL, MUTEX_DRIVER,
35704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    ss->mgp->icookie);
35804b6cca3Slucy wang - Sun Microsystems - Beijing China 	jpool->head = NULL;
35904b6cca3Slucy wang - Sun Microsystems - Beijing China }
36004b6cca3Slucy wang - Sun Microsystems - Beijing China 
36104b6cca3Slucy wang - Sun Microsystems - Beijing China static void
36204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_jpool_fini(struct myri10ge_slice_state *ss)
36304b6cca3Slucy wang - Sun Microsystems - Beijing China {
36404b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_jpool_stuff *jpool = &ss->jpool;
36504b6cca3Slucy wang - Sun Microsystems - Beijing China 
36604b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (jpool->head != NULL) {
36704b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN,
36804b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "%s: BUG! myri10ge_jpool_fini called on non-empty pool\n",
36904b6cca3Slucy wang - Sun Microsystems - Beijing China 		    ss->mgp->name);
37004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
37104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_destroy(&jpool->mtx);
37204b6cca3Slucy wang - Sun Microsystems - Beijing China }
37304b6cca3Slucy wang - Sun Microsystems - Beijing China 
37404b6cca3Slucy wang - Sun Microsystems - Beijing China 
37504b6cca3Slucy wang - Sun Microsystems - Beijing China /*
37604b6cca3Slucy wang - Sun Microsystems - Beijing China  * copy an array of mcp_kreq_ether_recv_t's to the mcp.  Copy
37704b6cca3Slucy wang - Sun Microsystems - Beijing China  * at most 32 bytes at a time, so as to avoid involving the software
37804b6cca3Slucy wang - Sun Microsystems - Beijing China  * pio handler in the nic.   We re-write the first segment's low
37904b6cca3Slucy wang - Sun Microsystems - Beijing China  * DMA address to mark it valid only after we write the entire chunk
38004b6cca3Slucy wang - Sun Microsystems - Beijing China  * in a burst
38104b6cca3Slucy wang - Sun Microsystems - Beijing China  */
38204b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void
38304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_submit_8rx(mcp_kreq_ether_recv_t *dst, mcp_kreq_ether_recv_t *src)
38404b6cca3Slucy wang - Sun Microsystems - Beijing China {
38504b6cca3Slucy wang - Sun Microsystems - Beijing China 	src->addr_low |= BE_32(1);
38604b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_pio_copy(dst, src, 4 * sizeof (*src));
38704b6cca3Slucy wang - Sun Microsystems - Beijing China 	mb();
38804b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_pio_copy(dst + 4, src + 4, 4 * sizeof (*src));
38904b6cca3Slucy wang - Sun Microsystems - Beijing China 	mb();
39004b6cca3Slucy wang - Sun Microsystems - Beijing China 	src->addr_low &= ~(BE_32(1));
39104b6cca3Slucy wang - Sun Microsystems - Beijing China 	dst->addr_low = src->addr_low;
39204b6cca3Slucy wang - Sun Microsystems - Beijing China 	mb();
39304b6cca3Slucy wang - Sun Microsystems - Beijing China }
39404b6cca3Slucy wang - Sun Microsystems - Beijing China 
39504b6cca3Slucy wang - Sun Microsystems - Beijing China static void
39604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_pull_jpool(struct myri10ge_slice_state *ss)
39704b6cca3Slucy wang - Sun Microsystems - Beijing China {
39804b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_jpool_stuff *jpool = &ss->jpool;
39904b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_jpool_entry *jtail, *j, *jfree;
40004b6cca3Slucy wang - Sun Microsystems - Beijing China 	volatile uintptr_t *putp;
40104b6cca3Slucy wang - Sun Microsystems - Beijing China 	uintptr_t put;
40204b6cca3Slucy wang - Sun Microsystems - Beijing China 	int i;
40304b6cca3Slucy wang - Sun Microsystems - Beijing China 
40404b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* find tail */
40504b6cca3Slucy wang - Sun Microsystems - Beijing China 	jtail = NULL;
40604b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (jpool->head != NULL) {
40704b6cca3Slucy wang - Sun Microsystems - Beijing China 		j = jpool->head;
40804b6cca3Slucy wang - Sun Microsystems - Beijing China 		while (j->next != NULL)
40904b6cca3Slucy wang - Sun Microsystems - Beijing China 			j = j->next;
41004b6cca3Slucy wang - Sun Microsystems - Beijing China 		jtail = j;
41104b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
41204b6cca3Slucy wang - Sun Microsystems - Beijing China 
41304b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
41404b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * iterate over all per-CPU caches, and add contents into
41504b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * jpool
41604b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
41704b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (i = 0; i < MYRI10GE_MAX_CPUS; i++) {
41804b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* take per-CPU free list */
41904b6cca3Slucy wang - Sun Microsystems - Beijing China 		putp = (void *)&jpool->cpu[i & MYRI10GE_MAX_CPU_MASK].head;
42004b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (*putp == NULL)
42104b6cca3Slucy wang - Sun Microsystems - Beijing China 			continue;
42204b6cca3Slucy wang - Sun Microsystems - Beijing China 		put = atomic_swap_ulong(putp, 0);
42304b6cca3Slucy wang - Sun Microsystems - Beijing China 		jfree = (struct myri10ge_jpool_entry *)put;
42404b6cca3Slucy wang - Sun Microsystems - Beijing China 
42504b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* append to pool */
42604b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (jtail == NULL) {
42704b6cca3Slucy wang - Sun Microsystems - Beijing China 			jpool->head = jfree;
42804b6cca3Slucy wang - Sun Microsystems - Beijing China 		} else {
42904b6cca3Slucy wang - Sun Microsystems - Beijing China 			jtail->next = jfree;
43004b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
43104b6cca3Slucy wang - Sun Microsystems - Beijing China 		j = jfree;
43204b6cca3Slucy wang - Sun Microsystems - Beijing China 		while (j->next != NULL)
43304b6cca3Slucy wang - Sun Microsystems - Beijing China 			j = j->next;
43404b6cca3Slucy wang - Sun Microsystems - Beijing China 		jtail = j;
43504b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
43604b6cca3Slucy wang - Sun Microsystems - Beijing China }
43704b6cca3Slucy wang - Sun Microsystems - Beijing China 
43804b6cca3Slucy wang - Sun Microsystems - Beijing China /*
43904b6cca3Slucy wang - Sun Microsystems - Beijing China  * Transfers buffers from the free pool to the nic
44004b6cca3Slucy wang - Sun Microsystems - Beijing China  * Must be called holding the jpool mutex.
44104b6cca3Slucy wang - Sun Microsystems - Beijing China  */
44204b6cca3Slucy wang - Sun Microsystems - Beijing China 
44304b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void
44404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_restock_jumbos(struct myri10ge_slice_state *ss)
44504b6cca3Slucy wang - Sun Microsystems - Beijing China {
44604b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_jpool_stuff *jpool = &ss->jpool;
44704b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_jpool_entry *j;
44804b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_rx_ring_t *rx;
44904b6cca3Slucy wang - Sun Microsystems - Beijing China 	int i, idx, limit;
45004b6cca3Slucy wang - Sun Microsystems - Beijing China 
45104b6cca3Slucy wang - Sun Microsystems - Beijing China 	rx = &ss->rx_big;
45204b6cca3Slucy wang - Sun Microsystems - Beijing China 	limit = ss->j_rx_cnt + (rx->mask + 1);
45304b6cca3Slucy wang - Sun Microsystems - Beijing China 
45404b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (i = rx->cnt; i != limit; i++) {
45504b6cca3Slucy wang - Sun Microsystems - Beijing China 		idx = i & (rx->mask);
45604b6cca3Slucy wang - Sun Microsystems - Beijing China 		j = jpool->head;
45704b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (j == NULL) {
45804b6cca3Slucy wang - Sun Microsystems - Beijing China 			myri10ge_pull_jpool(ss);
45904b6cca3Slucy wang - Sun Microsystems - Beijing China 			j = jpool->head;
46004b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (j == NULL) {
46104b6cca3Slucy wang - Sun Microsystems - Beijing China 				break;
46204b6cca3Slucy wang - Sun Microsystems - Beijing China 			}
46304b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
46404b6cca3Slucy wang - Sun Microsystems - Beijing China 		jpool->head = j->next;
46504b6cca3Slucy wang - Sun Microsystems - Beijing China 		rx->info[idx].j = j;
46604b6cca3Slucy wang - Sun Microsystems - Beijing China 		rx->shadow[idx].addr_low = j->dma.low;
46704b6cca3Slucy wang - Sun Microsystems - Beijing China 		rx->shadow[idx].addr_high = j->dma.high;
46804b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* copy 4 descriptors (32-bytes) to the mcp at a time */
46904b6cca3Slucy wang - Sun Microsystems - Beijing China 		if ((idx & 7) == 7) {
47004b6cca3Slucy wang - Sun Microsystems - Beijing China 			myri10ge_submit_8rx(&rx->lanai[idx - 7],
47104b6cca3Slucy wang - Sun Microsystems - Beijing China 			    &rx->shadow[idx - 7]);
47204b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
47304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
47404b6cca3Slucy wang - Sun Microsystems - Beijing China 	rx->cnt = i;
47504b6cca3Slucy wang - Sun Microsystems - Beijing China }
47604b6cca3Slucy wang - Sun Microsystems - Beijing China 
47704b6cca3Slucy wang - Sun Microsystems - Beijing China /*
47804b6cca3Slucy wang - Sun Microsystems - Beijing China  * Transfer buffers from the nic to the free pool.
47904b6cca3Slucy wang - Sun Microsystems - Beijing China  * Should be called holding the jpool mutex
48004b6cca3Slucy wang - Sun Microsystems - Beijing China  */
48104b6cca3Slucy wang - Sun Microsystems - Beijing China 
48204b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void
48304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_unstock_jumbos(struct myri10ge_slice_state *ss)
48404b6cca3Slucy wang - Sun Microsystems - Beijing China {
48504b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_jpool_stuff *jpool = &ss->jpool;
48604b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_jpool_entry *j;
48704b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_rx_ring_t *rx;
48804b6cca3Slucy wang - Sun Microsystems - Beijing China 	int i;
48904b6cca3Slucy wang - Sun Microsystems - Beijing China 
49004b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&jpool->mtx);
49104b6cca3Slucy wang - Sun Microsystems - Beijing China 	rx = &ss->rx_big;
49204b6cca3Slucy wang - Sun Microsystems - Beijing China 
49304b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (i = 0; i < rx->mask + 1; i++) {
49404b6cca3Slucy wang - Sun Microsystems - Beijing China 		j = rx->info[i].j;
49504b6cca3Slucy wang - Sun Microsystems - Beijing China 		rx->info[i].j = NULL;
49604b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (j == NULL)
49704b6cca3Slucy wang - Sun Microsystems - Beijing China 			continue;
49804b6cca3Slucy wang - Sun Microsystems - Beijing China 		j->next = jpool->head;
49904b6cca3Slucy wang - Sun Microsystems - Beijing China 		jpool->head = j;
50004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
50104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&jpool->mtx);
50204b6cca3Slucy wang - Sun Microsystems - Beijing China 
50304b6cca3Slucy wang - Sun Microsystems - Beijing China }
50404b6cca3Slucy wang - Sun Microsystems - Beijing China 
50504b6cca3Slucy wang - Sun Microsystems - Beijing China 
50604b6cca3Slucy wang - Sun Microsystems - Beijing China /*
50704b6cca3Slucy wang - Sun Microsystems - Beijing China  * Free routine which is called when the mblk allocated via
50804b6cca3Slucy wang - Sun Microsystems - Beijing China  * esballoc() is freed.   Here we return the jumbo buffer
50904b6cca3Slucy wang - Sun Microsystems - Beijing China  * to the free pool, and possibly pass some jumbo buffers
51004b6cca3Slucy wang - Sun Microsystems - Beijing China  * to the nic
51104b6cca3Slucy wang - Sun Microsystems - Beijing China  */
51204b6cca3Slucy wang - Sun Microsystems - Beijing China 
51304b6cca3Slucy wang - Sun Microsystems - Beijing China static void
51404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_jfree_rtn(void *arg)
51504b6cca3Slucy wang - Sun Microsystems - Beijing China {
51604b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_jpool_entry *j = (struct myri10ge_jpool_entry *)arg;
51704b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_jpool_stuff *jpool;
51804b6cca3Slucy wang - Sun Microsystems - Beijing China 	volatile uintptr_t *putp;
51904b6cca3Slucy wang - Sun Microsystems - Beijing China 	uintptr_t old, new;
52004b6cca3Slucy wang - Sun Microsystems - Beijing China 
52104b6cca3Slucy wang - Sun Microsystems - Beijing China 	jpool = &j->ss->jpool;
52204b6cca3Slucy wang - Sun Microsystems - Beijing China 
52304b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* prepend buffer locklessly to per-CPU freelist */
52404b6cca3Slucy wang - Sun Microsystems - Beijing China 	putp = (void *)&jpool->cpu[CPU->cpu_seqid & MYRI10GE_MAX_CPU_MASK].head;
52504b6cca3Slucy wang - Sun Microsystems - Beijing China 	new = (uintptr_t)j;
52604b6cca3Slucy wang - Sun Microsystems - Beijing China 	do {
52704b6cca3Slucy wang - Sun Microsystems - Beijing China 		old = *putp;
52804b6cca3Slucy wang - Sun Microsystems - Beijing China 		j->next = (void *)old;
52904b6cca3Slucy wang - Sun Microsystems - Beijing China 	} while (atomic_cas_ulong(putp, old, new) != old);
53004b6cca3Slucy wang - Sun Microsystems - Beijing China }
53104b6cca3Slucy wang - Sun Microsystems - Beijing China 
53204b6cca3Slucy wang - Sun Microsystems - Beijing China static void
53304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_remove_jbuf(struct myri10ge_jpool_entry *j)
53404b6cca3Slucy wang - Sun Microsystems - Beijing China {
53504b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) ddi_dma_unbind_handle(j->dma_handle);
53604b6cca3Slucy wang - Sun Microsystems - Beijing China 	ddi_dma_mem_free(&j->acc_handle);
53704b6cca3Slucy wang - Sun Microsystems - Beijing China 	ddi_dma_free_handle(&j->dma_handle);
53804b6cca3Slucy wang - Sun Microsystems - Beijing China 	kmem_free(j, sizeof (*j));
53904b6cca3Slucy wang - Sun Microsystems - Beijing China }
54004b6cca3Slucy wang - Sun Microsystems - Beijing China 
54104b6cca3Slucy wang - Sun Microsystems - Beijing China 
54204b6cca3Slucy wang - Sun Microsystems - Beijing China /*
54304b6cca3Slucy wang - Sun Microsystems - Beijing China  * Allocates one physically contiguous descriptor
54404b6cca3Slucy wang - Sun Microsystems - Beijing China  * and add it to the jumbo buffer pool.
54504b6cca3Slucy wang - Sun Microsystems - Beijing China  */
54604b6cca3Slucy wang - Sun Microsystems - Beijing China 
54704b6cca3Slucy wang - Sun Microsystems - Beijing China static int
54804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_add_jbuf(struct myri10ge_slice_state *ss)
54904b6cca3Slucy wang - Sun Microsystems - Beijing China {
55004b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_jpool_entry *j;
55104b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_jpool_stuff *jpool = &ss->jpool;
55204b6cca3Slucy wang - Sun Microsystems - Beijing China 	ddi_dma_attr_t *rx_dma_attr;
55304b6cca3Slucy wang - Sun Microsystems - Beijing China 	size_t real_length;
55404b6cca3Slucy wang - Sun Microsystems - Beijing China 	ddi_dma_cookie_t cookie;
55504b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint_t count;
55604b6cca3Slucy wang - Sun Microsystems - Beijing China 	int err;
55704b6cca3Slucy wang - Sun Microsystems - Beijing China 
55804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (myri10ge_mtu < 2048)
55904b6cca3Slucy wang - Sun Microsystems - Beijing China 		rx_dma_attr = &myri10ge_rx_std_dma_attr;
56004b6cca3Slucy wang - Sun Microsystems - Beijing China 	else
56104b6cca3Slucy wang - Sun Microsystems - Beijing China 		rx_dma_attr = &myri10ge_rx_jumbo_dma_attr;
56204b6cca3Slucy wang - Sun Microsystems - Beijing China 
56304b6cca3Slucy wang - Sun Microsystems - Beijing China again:
56404b6cca3Slucy wang - Sun Microsystems - Beijing China 	j = (struct myri10ge_jpool_entry *)
56504b6cca3Slucy wang - Sun Microsystems - Beijing China 	    kmem_alloc(sizeof (*j), KM_SLEEP);
56604b6cca3Slucy wang - Sun Microsystems - Beijing China 	err = ddi_dma_alloc_handle(ss->mgp->dip, rx_dma_attr,
56704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    DDI_DMA_DONTWAIT, NULL, &j->dma_handle);
56804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS)
56904b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_j;
57004b6cca3Slucy wang - Sun Microsystems - Beijing China 
57104b6cca3Slucy wang - Sun Microsystems - Beijing China 	err = ddi_dma_mem_alloc(j->dma_handle, myri10ge_mtu,
57204b6cca3Slucy wang - Sun Microsystems - Beijing China 	    &myri10ge_dev_access_attr,  DDI_DMA_STREAMING, DDI_DMA_DONTWAIT,
57304b6cca3Slucy wang - Sun Microsystems - Beijing China 	    NULL, &j->buf, &real_length, &j->acc_handle);
57404b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS)
57504b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_handle;
57604b6cca3Slucy wang - Sun Microsystems - Beijing China 
57704b6cca3Slucy wang - Sun Microsystems - Beijing China 	err = ddi_dma_addr_bind_handle(j->dma_handle, NULL, j->buf,
57804b6cca3Slucy wang - Sun Microsystems - Beijing China 	    real_length, DDI_DMA_READ|DDI_DMA_STREAMING, DDI_DMA_DONTWAIT,
57904b6cca3Slucy wang - Sun Microsystems - Beijing China 	    NULL, &cookie, &count);
58004b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS)
58104b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_mem;
58204b6cca3Slucy wang - Sun Microsystems - Beijing China 
58304b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
58404b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * Make certain std MTU buffers do not cross a 4KB boundary:
58504b6cca3Slucy wang - Sun Microsystems - Beijing China 	 *
58604b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * Setting dma_attr_align=4096 will do this, but the system
58704b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * will only allocate 1 RX buffer per 4KB page, rather than 2.
58804b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * Setting dma_attr_granular=4096 *seems* to work around this,
58904b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * but I'm paranoid about future systems no longer honoring
59004b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * this, so fall back to the safe, but memory wasting way if a
59104b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * buffer crosses a 4KB boundary.
59204b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
59304b6cca3Slucy wang - Sun Microsystems - Beijing China 
59404b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (rx_dma_attr == &myri10ge_rx_std_dma_attr &&
59504b6cca3Slucy wang - Sun Microsystems - Beijing China 	    rx_dma_attr->dma_attr_align != 4096) {
59604b6cca3Slucy wang - Sun Microsystems - Beijing China 		uint32_t start, end;
59704b6cca3Slucy wang - Sun Microsystems - Beijing China 
59804b6cca3Slucy wang - Sun Microsystems - Beijing China 		start = MYRI10GE_LOWPART_TO_U32(cookie.dmac_laddress);
59904b6cca3Slucy wang - Sun Microsystems - Beijing China 		end = start + myri10ge_mtu;
60004b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (((end >> 12) != (start >> 12)) && (start & 4095U)) {
60104b6cca3Slucy wang - Sun Microsystems - Beijing China 			printf("std buffer crossed a 4KB boundary!\n");
60204b6cca3Slucy wang - Sun Microsystems - Beijing China 			myri10ge_remove_jbuf(j);
60304b6cca3Slucy wang - Sun Microsystems - Beijing China 			rx_dma_attr->dma_attr_align = 4096;
60404b6cca3Slucy wang - Sun Microsystems - Beijing China 			rx_dma_attr->dma_attr_seg = UINT64_MAX;
60504b6cca3Slucy wang - Sun Microsystems - Beijing China 			goto again;
60604b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
60704b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
60804b6cca3Slucy wang - Sun Microsystems - Beijing China 
60904b6cca3Slucy wang - Sun Microsystems - Beijing China 	j->dma.low =
61004b6cca3Slucy wang - Sun Microsystems - Beijing China 	    htonl(MYRI10GE_LOWPART_TO_U32(cookie.dmac_laddress));
61104b6cca3Slucy wang - Sun Microsystems - Beijing China 	j->dma.high =
61204b6cca3Slucy wang - Sun Microsystems - Beijing China 	    htonl(MYRI10GE_HIGHPART_TO_U32(cookie.dmac_laddress));
61304b6cca3Slucy wang - Sun Microsystems - Beijing China 	j->ss = ss;
61404b6cca3Slucy wang - Sun Microsystems - Beijing China 
61504b6cca3Slucy wang - Sun Microsystems - Beijing China 
61604b6cca3Slucy wang - Sun Microsystems - Beijing China 	j->free_func.free_func = myri10ge_jfree_rtn;
61704b6cca3Slucy wang - Sun Microsystems - Beijing China 	j->free_func.free_arg = (char *)j;
61804b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&jpool->mtx);
61904b6cca3Slucy wang - Sun Microsystems - Beijing China 	j->next = jpool->head;
62004b6cca3Slucy wang - Sun Microsystems - Beijing China 	jpool->head = j;
62104b6cca3Slucy wang - Sun Microsystems - Beijing China 	jpool->num_alloc++;
62204b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&jpool->mtx);
62304b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
62404b6cca3Slucy wang - Sun Microsystems - Beijing China 
62504b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_mem:
62604b6cca3Slucy wang - Sun Microsystems - Beijing China 	ddi_dma_mem_free(&j->acc_handle);
62704b6cca3Slucy wang - Sun Microsystems - Beijing China 
62804b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_handle:
62904b6cca3Slucy wang - Sun Microsystems - Beijing China 	ddi_dma_free_handle(&j->dma_handle);
63004b6cca3Slucy wang - Sun Microsystems - Beijing China 
63104b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_j:
63204b6cca3Slucy wang - Sun Microsystems - Beijing China 	kmem_free(j, sizeof (*j));
63304b6cca3Slucy wang - Sun Microsystems - Beijing China 
63404b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
63504b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * If an allocation failed, perhaps it failed because it could
63604b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * not satisfy granularity requirement.  Disable that, and
63704b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * try agin.
63804b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
63904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (rx_dma_attr == &myri10ge_rx_std_dma_attr &&
64004b6cca3Slucy wang - Sun Microsystems - Beijing China 	    rx_dma_attr->dma_attr_align != 4096) {
64104b6cca3Slucy wang - Sun Microsystems - Beijing China 			cmn_err(CE_NOTE,
64204b6cca3Slucy wang - Sun Microsystems - Beijing China 			    "!alloc failed, reverting to gran=1\n");
64304b6cca3Slucy wang - Sun Microsystems - Beijing China 			rx_dma_attr->dma_attr_align = 4096;
64404b6cca3Slucy wang - Sun Microsystems - Beijing China 			rx_dma_attr->dma_attr_seg = UINT64_MAX;
64504b6cca3Slucy wang - Sun Microsystems - Beijing China 			goto again;
64604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
64704b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (err);
64804b6cca3Slucy wang - Sun Microsystems - Beijing China }
64904b6cca3Slucy wang - Sun Microsystems - Beijing China 
65004b6cca3Slucy wang - Sun Microsystems - Beijing China static int
65104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_jfree_cnt(struct myri10ge_jpool_stuff *jpool)
65204b6cca3Slucy wang - Sun Microsystems - Beijing China {
65304b6cca3Slucy wang - Sun Microsystems - Beijing China 	int i;
65404b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_jpool_entry *j;
65504b6cca3Slucy wang - Sun Microsystems - Beijing China 
65604b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&jpool->mtx);
65704b6cca3Slucy wang - Sun Microsystems - Beijing China 	j = jpool->head;
65804b6cca3Slucy wang - Sun Microsystems - Beijing China 	i = 0;
65904b6cca3Slucy wang - Sun Microsystems - Beijing China 	while (j != NULL) {
66004b6cca3Slucy wang - Sun Microsystems - Beijing China 		i++;
66104b6cca3Slucy wang - Sun Microsystems - Beijing China 		j = j->next;
66204b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
66304b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&jpool->mtx);
66404b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (i);
66504b6cca3Slucy wang - Sun Microsystems - Beijing China }
66604b6cca3Slucy wang - Sun Microsystems - Beijing China 
66704b6cca3Slucy wang - Sun Microsystems - Beijing China static int
66804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_add_jbufs(struct myri10ge_slice_state *ss, int num, int total)
66904b6cca3Slucy wang - Sun Microsystems - Beijing China {
67004b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_jpool_stuff *jpool = &ss->jpool;
67104b6cca3Slucy wang - Sun Microsystems - Beijing China 	int allocated = 0;
67204b6cca3Slucy wang - Sun Microsystems - Beijing China 	int err;
67304b6cca3Slucy wang - Sun Microsystems - Beijing China 	int needed;
67404b6cca3Slucy wang - Sun Microsystems - Beijing China 
67504b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
67604b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * if total is set, user wants "num" jbufs in the pool,
67704b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * otherwise the user wants to "num" additional jbufs
67804b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * added to the pool
67904b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
68004b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (total && jpool->num_alloc) {
68104b6cca3Slucy wang - Sun Microsystems - Beijing China 		allocated = myri10ge_jfree_cnt(jpool);
68204b6cca3Slucy wang - Sun Microsystems - Beijing China 		needed = num - allocated;
68304b6cca3Slucy wang - Sun Microsystems - Beijing China 	} else {
68404b6cca3Slucy wang - Sun Microsystems - Beijing China 		needed = num;
68504b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
68604b6cca3Slucy wang - Sun Microsystems - Beijing China 
68704b6cca3Slucy wang - Sun Microsystems - Beijing China 	while (needed > 0) {
68804b6cca3Slucy wang - Sun Microsystems - Beijing China 		needed--;
68904b6cca3Slucy wang - Sun Microsystems - Beijing China 		err = myri10ge_add_jbuf(ss);
69004b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (err == 0) {
69104b6cca3Slucy wang - Sun Microsystems - Beijing China 			allocated++;
69204b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
69304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
69404b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (allocated);
69504b6cca3Slucy wang - Sun Microsystems - Beijing China }
69604b6cca3Slucy wang - Sun Microsystems - Beijing China 
69704b6cca3Slucy wang - Sun Microsystems - Beijing China static void
69804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_remove_jbufs(struct myri10ge_slice_state *ss)
69904b6cca3Slucy wang - Sun Microsystems - Beijing China {
70004b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_jpool_stuff *jpool = &ss->jpool;
70104b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_jpool_entry *j;
70204b6cca3Slucy wang - Sun Microsystems - Beijing China 
70304b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&jpool->mtx);
70404b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_pull_jpool(ss);
70504b6cca3Slucy wang - Sun Microsystems - Beijing China 	while (jpool->head != NULL) {
70604b6cca3Slucy wang - Sun Microsystems - Beijing China 		jpool->num_alloc--;
70704b6cca3Slucy wang - Sun Microsystems - Beijing China 		j = jpool->head;
70804b6cca3Slucy wang - Sun Microsystems - Beijing China 		jpool->head = j->next;
70904b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_remove_jbuf(j);
71004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
71104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&jpool->mtx);
71204b6cca3Slucy wang - Sun Microsystems - Beijing China }
71304b6cca3Slucy wang - Sun Microsystems - Beijing China 
71404b6cca3Slucy wang - Sun Microsystems - Beijing China static void
71504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_carve_up_jbufs_into_small_ring(struct myri10ge_slice_state *ss)
71604b6cca3Slucy wang - Sun Microsystems - Beijing China {
71704b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_jpool_stuff *jpool = &ss->jpool;
71804b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_jpool_entry *j = NULL;
71904b6cca3Slucy wang - Sun Microsystems - Beijing China 	caddr_t ptr;
72004b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint32_t dma_low, dma_high;
72104b6cca3Slucy wang - Sun Microsystems - Beijing China 	int idx, len;
72204b6cca3Slucy wang - Sun Microsystems - Beijing China 	unsigned int alloc_size;
72304b6cca3Slucy wang - Sun Microsystems - Beijing China 
72404b6cca3Slucy wang - Sun Microsystems - Beijing China 	dma_low = dma_high = len = 0;
72504b6cca3Slucy wang - Sun Microsystems - Beijing China 	alloc_size = myri10ge_small_bytes + MXGEFW_PAD;
72604b6cca3Slucy wang - Sun Microsystems - Beijing China 	ptr = NULL;
72704b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (idx = 0; idx < ss->rx_small.mask + 1; idx++) {
72804b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* Allocate a jumbo frame and carve it into small frames */
72904b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (len < alloc_size) {
73004b6cca3Slucy wang - Sun Microsystems - Beijing China 			mutex_enter(&jpool->mtx);
73104b6cca3Slucy wang - Sun Microsystems - Beijing China 			/* remove jumbo from freelist */
73204b6cca3Slucy wang - Sun Microsystems - Beijing China 			j = jpool->head;
73304b6cca3Slucy wang - Sun Microsystems - Beijing China 			jpool->head = j->next;
73404b6cca3Slucy wang - Sun Microsystems - Beijing China 			/* place it onto small list */
73504b6cca3Slucy wang - Sun Microsystems - Beijing China 			j->next = ss->small_jpool;
73604b6cca3Slucy wang - Sun Microsystems - Beijing China 			ss->small_jpool = j;
73704b6cca3Slucy wang - Sun Microsystems - Beijing China 			mutex_exit(&jpool->mtx);
73804b6cca3Slucy wang - Sun Microsystems - Beijing China 			len = myri10ge_mtu;
73904b6cca3Slucy wang - Sun Microsystems - Beijing China 			dma_low = ntohl(j->dma.low);
74004b6cca3Slucy wang - Sun Microsystems - Beijing China 			dma_high = ntohl(j->dma.high);
74104b6cca3Slucy wang - Sun Microsystems - Beijing China 			ptr = j->buf;
74204b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
74304b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->rx_small.info[idx].ptr = ptr;
74404b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->rx_small.shadow[idx].addr_low = htonl(dma_low);
74504b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->rx_small.shadow[idx].addr_high = htonl(dma_high);
74604b6cca3Slucy wang - Sun Microsystems - Beijing China 		len -= alloc_size;
74704b6cca3Slucy wang - Sun Microsystems - Beijing China 		ptr += alloc_size;
74804b6cca3Slucy wang - Sun Microsystems - Beijing China 		dma_low += alloc_size;
74904b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
75004b6cca3Slucy wang - Sun Microsystems - Beijing China }
75104b6cca3Slucy wang - Sun Microsystems - Beijing China 
75204b6cca3Slucy wang - Sun Microsystems - Beijing China /*
75304b6cca3Slucy wang - Sun Microsystems - Beijing China  * Return the jumbo bufs we carved up for small to the jumbo pool
75404b6cca3Slucy wang - Sun Microsystems - Beijing China  */
75504b6cca3Slucy wang - Sun Microsystems - Beijing China 
75604b6cca3Slucy wang - Sun Microsystems - Beijing China static void
75704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_release_small_jbufs(struct myri10ge_slice_state *ss)
75804b6cca3Slucy wang - Sun Microsystems - Beijing China {
75904b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_jpool_stuff *jpool = &ss->jpool;
76004b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_jpool_entry *j = NULL;
76104b6cca3Slucy wang - Sun Microsystems - Beijing China 
76204b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&jpool->mtx);
76304b6cca3Slucy wang - Sun Microsystems - Beijing China 	while (ss->small_jpool != NULL) {
76404b6cca3Slucy wang - Sun Microsystems - Beijing China 		j = ss->small_jpool;
76504b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->small_jpool = j->next;
76604b6cca3Slucy wang - Sun Microsystems - Beijing China 		j->next = jpool->head;
76704b6cca3Slucy wang - Sun Microsystems - Beijing China 		jpool->head = j;
76804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
76904b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&jpool->mtx);
77004b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->jbufs_for_smalls = 0;
77104b6cca3Slucy wang - Sun Microsystems - Beijing China }
77204b6cca3Slucy wang - Sun Microsystems - Beijing China 
77304b6cca3Slucy wang - Sun Microsystems - Beijing China static int
77404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_add_tx_handle(struct myri10ge_slice_state *ss)
77504b6cca3Slucy wang - Sun Microsystems - Beijing China {
77604b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_tx_ring_t *tx = &ss->tx;
77704b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp = ss->mgp;
77804b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_tx_dma_handle *handle;
77904b6cca3Slucy wang - Sun Microsystems - Beijing China 	int err;
78004b6cca3Slucy wang - Sun Microsystems - Beijing China 
78104b6cca3Slucy wang - Sun Microsystems - Beijing China 	handle = kmem_zalloc(sizeof (*handle), KM_SLEEP);
78204b6cca3Slucy wang - Sun Microsystems - Beijing China 	err = ddi_dma_alloc_handle(mgp->dip,
78304b6cca3Slucy wang - Sun Microsystems - Beijing China 	    &myri10ge_tx_dma_attr,
78404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    DDI_DMA_SLEEP, NULL,
78504b6cca3Slucy wang - Sun Microsystems - Beijing China 	    &handle->h);
78604b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (err) {
78704b6cca3Slucy wang - Sun Microsystems - Beijing China 		static int limit = 0;
78804b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (limit == 0)
78904b6cca3Slucy wang - Sun Microsystems - Beijing China 			cmn_err(CE_WARN, "%s: Falled to alloc tx dma handle\n",
79004b6cca3Slucy wang - Sun Microsystems - Beijing China 			    mgp->name);
79104b6cca3Slucy wang - Sun Microsystems - Beijing China 		limit++;
79204b6cca3Slucy wang - Sun Microsystems - Beijing China 		kmem_free(handle, sizeof (*handle));
79304b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (err);
79404b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
79504b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&tx->handle_lock);
79604b6cca3Slucy wang - Sun Microsystems - Beijing China 	MYRI10GE_SLICE_STAT_INC(tx_handles_alloced);
79704b6cca3Slucy wang - Sun Microsystems - Beijing China 	handle->next = tx->free_tx_handles;
79804b6cca3Slucy wang - Sun Microsystems - Beijing China 	tx->free_tx_handles = handle;
79904b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&tx->handle_lock);
80004b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
80104b6cca3Slucy wang - Sun Microsystems - Beijing China }
80204b6cca3Slucy wang - Sun Microsystems - Beijing China 
80304b6cca3Slucy wang - Sun Microsystems - Beijing China static void
80404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_remove_tx_handles(struct myri10ge_slice_state *ss)
80504b6cca3Slucy wang - Sun Microsystems - Beijing China {
80604b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_tx_ring_t *tx = &ss->tx;
80704b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_tx_dma_handle *handle;
80804b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&tx->handle_lock);
80904b6cca3Slucy wang - Sun Microsystems - Beijing China 
81004b6cca3Slucy wang - Sun Microsystems - Beijing China 	handle = tx->free_tx_handles;
81104b6cca3Slucy wang - Sun Microsystems - Beijing China 	while (handle != NULL) {
81204b6cca3Slucy wang - Sun Microsystems - Beijing China 		tx->free_tx_handles = handle->next;
81304b6cca3Slucy wang - Sun Microsystems - Beijing China 		ddi_dma_free_handle(&handle->h);
81404b6cca3Slucy wang - Sun Microsystems - Beijing China 		kmem_free(handle, sizeof (*handle));
81504b6cca3Slucy wang - Sun Microsystems - Beijing China 		handle = tx->free_tx_handles;
81604b6cca3Slucy wang - Sun Microsystems - Beijing China 		MYRI10GE_SLICE_STAT_DEC(tx_handles_alloced);
81704b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
81804b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&tx->handle_lock);
81904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (MYRI10GE_SLICE_STAT(tx_handles_alloced) != 0) {
82004b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: %d tx dma handles allocated at close\n",
82104b6cca3Slucy wang - Sun Microsystems - Beijing China 		    ss->mgp->name,
82204b6cca3Slucy wang - Sun Microsystems - Beijing China 		    (int)MYRI10GE_SLICE_STAT(tx_handles_alloced));
82304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
82404b6cca3Slucy wang - Sun Microsystems - Beijing China }
82504b6cca3Slucy wang - Sun Microsystems - Beijing China 
82604b6cca3Slucy wang - Sun Microsystems - Beijing China static void
82704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_free_tx_handles(myri10ge_tx_ring_t *tx,
82804b6cca3Slucy wang - Sun Microsystems - Beijing China     struct myri10ge_tx_dma_handle_head *list)
82904b6cca3Slucy wang - Sun Microsystems - Beijing China {
83004b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&tx->handle_lock);
83104b6cca3Slucy wang - Sun Microsystems - Beijing China 	list->tail->next = tx->free_tx_handles;
83204b6cca3Slucy wang - Sun Microsystems - Beijing China 	tx->free_tx_handles = list->head;
83304b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&tx->handle_lock);
83404b6cca3Slucy wang - Sun Microsystems - Beijing China }
83504b6cca3Slucy wang - Sun Microsystems - Beijing China 
83604b6cca3Slucy wang - Sun Microsystems - Beijing China static void
83704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_free_tx_handle_slist(myri10ge_tx_ring_t *tx,
83804b6cca3Slucy wang - Sun Microsystems - Beijing China     struct myri10ge_tx_dma_handle *handle)
83904b6cca3Slucy wang - Sun Microsystems - Beijing China {
84004b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_tx_dma_handle_head list;
84104b6cca3Slucy wang - Sun Microsystems - Beijing China 
84204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (handle == NULL)
84304b6cca3Slucy wang - Sun Microsystems - Beijing China 		return;
84404b6cca3Slucy wang - Sun Microsystems - Beijing China 	list.head = handle;
84504b6cca3Slucy wang - Sun Microsystems - Beijing China 	list.tail = handle;
84604b6cca3Slucy wang - Sun Microsystems - Beijing China 	while (handle != NULL) {
84704b6cca3Slucy wang - Sun Microsystems - Beijing China 		list.tail = handle;
84804b6cca3Slucy wang - Sun Microsystems - Beijing China 		handle = handle->next;
84904b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
85004b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_free_tx_handles(tx, &list);
85104b6cca3Slucy wang - Sun Microsystems - Beijing China }
85204b6cca3Slucy wang - Sun Microsystems - Beijing China 
85304b6cca3Slucy wang - Sun Microsystems - Beijing China static int
85404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_alloc_tx_handles(struct myri10ge_slice_state *ss, int count,
85504b6cca3Slucy wang - Sun Microsystems - Beijing China     struct myri10ge_tx_dma_handle **ret)
85604b6cca3Slucy wang - Sun Microsystems - Beijing China {
85704b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_tx_ring_t *tx = &ss->tx;
85804b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_tx_dma_handle *handle;
85904b6cca3Slucy wang - Sun Microsystems - Beijing China 	int err, i;
86004b6cca3Slucy wang - Sun Microsystems - Beijing China 
86104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&tx->handle_lock);
86204b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (i = 0; i < count; i++) {
86304b6cca3Slucy wang - Sun Microsystems - Beijing China 		handle = tx->free_tx_handles;
86404b6cca3Slucy wang - Sun Microsystems - Beijing China 		while (handle == NULL) {
86504b6cca3Slucy wang - Sun Microsystems - Beijing China 			mutex_exit(&tx->handle_lock);
86604b6cca3Slucy wang - Sun Microsystems - Beijing China 			err = myri10ge_add_tx_handle(ss);
86704b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (err != DDI_SUCCESS) {
86804b6cca3Slucy wang - Sun Microsystems - Beijing China 				goto abort_with_handles;
86904b6cca3Slucy wang - Sun Microsystems - Beijing China 			}
87004b6cca3Slucy wang - Sun Microsystems - Beijing China 			mutex_enter(&tx->handle_lock);
87104b6cca3Slucy wang - Sun Microsystems - Beijing China 			handle = tx->free_tx_handles;
87204b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
87304b6cca3Slucy wang - Sun Microsystems - Beijing China 		tx->free_tx_handles = handle->next;
87404b6cca3Slucy wang - Sun Microsystems - Beijing China 		handle->next = *ret;
87504b6cca3Slucy wang - Sun Microsystems - Beijing China 		*ret = handle;
87604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
87704b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&tx->handle_lock);
87804b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
87904b6cca3Slucy wang - Sun Microsystems - Beijing China 
88004b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_handles:
88104b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_free_tx_handle_slist(tx, *ret);
88204b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (err);
88304b6cca3Slucy wang - Sun Microsystems - Beijing China }
88404b6cca3Slucy wang - Sun Microsystems - Beijing China 
88504b6cca3Slucy wang - Sun Microsystems - Beijing China 
88604b6cca3Slucy wang - Sun Microsystems - Beijing China /*
88704b6cca3Slucy wang - Sun Microsystems - Beijing China  * Frees DMA resources associated with the send ring
88804b6cca3Slucy wang - Sun Microsystems - Beijing China  */
88904b6cca3Slucy wang - Sun Microsystems - Beijing China static void
89004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_unprepare_tx_ring(struct myri10ge_slice_state *ss)
89104b6cca3Slucy wang - Sun Microsystems - Beijing China {
89204b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_tx_ring_t *tx;
89304b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_tx_dma_handle_head handles;
89404b6cca3Slucy wang - Sun Microsystems - Beijing China 	size_t bytes;
89504b6cca3Slucy wang - Sun Microsystems - Beijing China 	int idx;
89604b6cca3Slucy wang - Sun Microsystems - Beijing China 
89704b6cca3Slucy wang - Sun Microsystems - Beijing China 	tx = &ss->tx;
89804b6cca3Slucy wang - Sun Microsystems - Beijing China 	handles.head = NULL;
89904b6cca3Slucy wang - Sun Microsystems - Beijing China 	handles.tail = NULL;
90004b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (idx = 0; idx < ss->tx.mask + 1; idx++) {
90104b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (tx->info[idx].m) {
90204b6cca3Slucy wang - Sun Microsystems - Beijing China 			(void) ddi_dma_unbind_handle(tx->info[idx].handle->h);
90304b6cca3Slucy wang - Sun Microsystems - Beijing China 			handles.head = tx->info[idx].handle;
90404b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (handles.tail == NULL)
90504b6cca3Slucy wang - Sun Microsystems - Beijing China 				handles.tail = tx->info[idx].handle;
90604b6cca3Slucy wang - Sun Microsystems - Beijing China 			freeb(tx->info[idx].m);
90704b6cca3Slucy wang - Sun Microsystems - Beijing China 			tx->info[idx].m = 0;
90804b6cca3Slucy wang - Sun Microsystems - Beijing China 			tx->info[idx].handle = 0;
90904b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
91004b6cca3Slucy wang - Sun Microsystems - Beijing China 		tx->cp[idx].va = NULL;
91104b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_dma_free(&tx->cp[idx].dma);
91204b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
91304b6cca3Slucy wang - Sun Microsystems - Beijing China 	bytes = sizeof (*tx->cp) * (tx->mask + 1);
91404b6cca3Slucy wang - Sun Microsystems - Beijing China 	kmem_free(tx->cp, bytes);
91504b6cca3Slucy wang - Sun Microsystems - Beijing China 	tx->cp = NULL;
91604b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (handles.head != NULL)
91704b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_free_tx_handles(tx, &handles);
91804b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_remove_tx_handles(ss);
91904b6cca3Slucy wang - Sun Microsystems - Beijing China }
92004b6cca3Slucy wang - Sun Microsystems - Beijing China 
92104b6cca3Slucy wang - Sun Microsystems - Beijing China /*
92204b6cca3Slucy wang - Sun Microsystems - Beijing China  * Allocates DMA handles associated with the send ring
92304b6cca3Slucy wang - Sun Microsystems - Beijing China  */
92404b6cca3Slucy wang - Sun Microsystems - Beijing China static inline int
92504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_prepare_tx_ring(struct myri10ge_slice_state *ss)
92604b6cca3Slucy wang - Sun Microsystems - Beijing China {
92704b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_tx_dma_handle *handles;
92804b6cca3Slucy wang - Sun Microsystems - Beijing China 	int h;
92904b6cca3Slucy wang - Sun Microsystems - Beijing China 	size_t bytes;
93004b6cca3Slucy wang - Sun Microsystems - Beijing China 
93104b6cca3Slucy wang - Sun Microsystems - Beijing China 	bytes = sizeof (*ss->tx.cp) * (ss->tx.mask + 1);
93204b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->tx.cp = kmem_zalloc(bytes, KM_SLEEP);
93304b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (ss->tx.cp == NULL) {
93404b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN,
93504b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "%s: Failed to allocate tx copyblock storage\n",
93604b6cca3Slucy wang - Sun Microsystems - Beijing China 		    ss->mgp->name);
93704b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
93804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
93904b6cca3Slucy wang - Sun Microsystems - Beijing China 
94004b6cca3Slucy wang - Sun Microsystems - Beijing China 
94104b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* allocate the TX copyblocks */
94204b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (h = 0; h < ss->tx.mask + 1; h++) {
94304b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->tx.cp[h].va = myri10ge_dma_alloc(ss->mgp->dip,
94404b6cca3Slucy wang - Sun Microsystems - Beijing China 		    4096, &myri10ge_rx_jumbo_dma_attr,
94504b6cca3Slucy wang - Sun Microsystems - Beijing China 		    &myri10ge_dev_access_attr, DDI_DMA_STREAMING,
94604b6cca3Slucy wang - Sun Microsystems - Beijing China 		    DDI_DMA_WRITE|DDI_DMA_STREAMING, &ss->tx.cp[h].dma, 1,
94704b6cca3Slucy wang - Sun Microsystems - Beijing China 		    DDI_DMA_DONTWAIT);
94804b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (ss->tx.cp[h].va == NULL) {
94904b6cca3Slucy wang - Sun Microsystems - Beijing China 			cmn_err(CE_WARN, "%s: Failed to allocate tx "
95004b6cca3Slucy wang - Sun Microsystems - Beijing China 			    "copyblock %d\n", ss->mgp->name, h);
95104b6cca3Slucy wang - Sun Microsystems - Beijing China 			goto abort_with_copyblocks;
95204b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
95304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
95404b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* pre-allocate transmit handles */
95504b6cca3Slucy wang - Sun Microsystems - Beijing China 	handles = NULL;
95604b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) myri10ge_alloc_tx_handles(ss, myri10ge_tx_handles_initial,
95704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    &handles);
95804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (handles != NULL)
95904b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_free_tx_handle_slist(&ss->tx, handles);
96004b6cca3Slucy wang - Sun Microsystems - Beijing China 
96104b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
96204b6cca3Slucy wang - Sun Microsystems - Beijing China 
96304b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_copyblocks:
96404b6cca3Slucy wang - Sun Microsystems - Beijing China 	while (h > 0)  {
96504b6cca3Slucy wang - Sun Microsystems - Beijing China 		h--;
96604b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_dma_free(&ss->tx.cp[h].dma);
96704b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
96804b6cca3Slucy wang - Sun Microsystems - Beijing China 
96904b6cca3Slucy wang - Sun Microsystems - Beijing China 	bytes = sizeof (*ss->tx.cp) * (ss->tx.mask + 1);
97004b6cca3Slucy wang - Sun Microsystems - Beijing China 	kmem_free(ss->tx.cp, bytes);
97104b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->tx.cp = NULL;
97204b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (DDI_FAILURE);
97304b6cca3Slucy wang - Sun Microsystems - Beijing China }
97404b6cca3Slucy wang - Sun Microsystems - Beijing China 
97504b6cca3Slucy wang - Sun Microsystems - Beijing China /*
97604b6cca3Slucy wang - Sun Microsystems - Beijing China  * The eeprom strings on the lanaiX have the format
97704b6cca3Slucy wang - Sun Microsystems - Beijing China  * SN=x\0
97804b6cca3Slucy wang - Sun Microsystems - Beijing China  * MAC=x:x:x:x:x:x\0
97904b6cca3Slucy wang - Sun Microsystems - Beijing China  * PT:ddd mmm xx xx:xx:xx xx\0
98004b6cca3Slucy wang - Sun Microsystems - Beijing China  * PV:ddd mmm xx xx:xx:xx xx\0
98104b6cca3Slucy wang - Sun Microsystems - Beijing China  */
98204b6cca3Slucy wang - Sun Microsystems - Beijing China static int
98304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_read_mac_addr(struct myri10ge_priv *mgp)
98404b6cca3Slucy wang - Sun Microsystems - Beijing China {
98504b6cca3Slucy wang - Sun Microsystems - Beijing China #define	MYRI10GE_NEXT_STRING(p) while (ptr < limit && *ptr++)
98604b6cca3Slucy wang - Sun Microsystems - Beijing China #define	myri10ge_digit(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') :	\
98704b6cca3Slucy wang - Sun Microsystems - Beijing China 		(((c) >= 'A' && (c) <= 'F') ? (10 + (c) - 'A') :	\
98804b6cca3Slucy wang - Sun Microsystems - Beijing China 		(((c) >= 'a' && (c) <= 'f') ? (10 + (c) - 'a') : -1)))
98904b6cca3Slucy wang - Sun Microsystems - Beijing China 
99004b6cca3Slucy wang - Sun Microsystems - Beijing China 	char *ptr, *limit;
99104b6cca3Slucy wang - Sun Microsystems - Beijing China 	int i, hv, lv;
99204b6cca3Slucy wang - Sun Microsystems - Beijing China 
99304b6cca3Slucy wang - Sun Microsystems - Beijing China 	ptr = mgp->eeprom_strings;
99404b6cca3Slucy wang - Sun Microsystems - Beijing China 	limit = mgp->eeprom_strings + MYRI10GE_EEPROM_STRINGS_SIZE;
99504b6cca3Slucy wang - Sun Microsystems - Beijing China 
99604b6cca3Slucy wang - Sun Microsystems - Beijing China 	while (*ptr != '\0' && ptr < limit) {
99704b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (memcmp(ptr, "MAC=", 4) == 0) {
99804b6cca3Slucy wang - Sun Microsystems - Beijing China 			ptr += 4;
99904b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (myri10ge_verbose)
100004b6cca3Slucy wang - Sun Microsystems - Beijing China 				printf("%s: mac address = %s\n", mgp->name,
100104b6cca3Slucy wang - Sun Microsystems - Beijing China 				    ptr);
100204b6cca3Slucy wang - Sun Microsystems - Beijing China 			mgp->mac_addr_string = ptr;
100304b6cca3Slucy wang - Sun Microsystems - Beijing China 			for (i = 0; i < 6; i++) {
100404b6cca3Slucy wang - Sun Microsystems - Beijing China 				if ((ptr + 2) > limit)
100504b6cca3Slucy wang - Sun Microsystems - Beijing China 					goto abort;
100604b6cca3Slucy wang - Sun Microsystems - Beijing China 
100704b6cca3Slucy wang - Sun Microsystems - Beijing China 				if (*(ptr+1) == ':') {
100804b6cca3Slucy wang - Sun Microsystems - Beijing China 					hv = 0;
100904b6cca3Slucy wang - Sun Microsystems - Beijing China 					lv = myri10ge_digit(*ptr); ptr++;
101004b6cca3Slucy wang - Sun Microsystems - Beijing China 				} else {
101104b6cca3Slucy wang - Sun Microsystems - Beijing China 					hv = myri10ge_digit(*ptr); ptr++;
101204b6cca3Slucy wang - Sun Microsystems - Beijing China 					lv = myri10ge_digit(*ptr); ptr++;
101304b6cca3Slucy wang - Sun Microsystems - Beijing China 				}
101404b6cca3Slucy wang - Sun Microsystems - Beijing China 				mgp->mac_addr[i] = (hv << 4) | lv;
101504b6cca3Slucy wang - Sun Microsystems - Beijing China 				ptr++;
101604b6cca3Slucy wang - Sun Microsystems - Beijing China 			}
101704b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
101804b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (memcmp((const void *)ptr, "SN=", 3) == 0) {
101904b6cca3Slucy wang - Sun Microsystems - Beijing China 			ptr += 3;
102004b6cca3Slucy wang - Sun Microsystems - Beijing China 			mgp->sn_str = (char *)ptr;
102104b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
102204b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (memcmp((const void *)ptr, "PC=", 3) == 0) {
102304b6cca3Slucy wang - Sun Microsystems - Beijing China 			ptr += 3;
102404b6cca3Slucy wang - Sun Microsystems - Beijing China 			mgp->pc_str = (char *)ptr;
102504b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
102604b6cca3Slucy wang - Sun Microsystems - Beijing China 		MYRI10GE_NEXT_STRING(ptr);
102704b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
102804b6cca3Slucy wang - Sun Microsystems - Beijing China 
102904b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
103004b6cca3Slucy wang - Sun Microsystems - Beijing China 
103104b6cca3Slucy wang - Sun Microsystems - Beijing China abort:
103204b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmn_err(CE_WARN, "%s: failed to parse eeprom_strings", mgp->name);
103304b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (ENXIO);
103404b6cca3Slucy wang - Sun Microsystems - Beijing China }
103504b6cca3Slucy wang - Sun Microsystems - Beijing China 
103604b6cca3Slucy wang - Sun Microsystems - Beijing China 
103704b6cca3Slucy wang - Sun Microsystems - Beijing China /*
103804b6cca3Slucy wang - Sun Microsystems - Beijing China  * Determine the register set containing the PCI resource we
103904b6cca3Slucy wang - Sun Microsystems - Beijing China  * want to map: the memory-mappable part of the interface. We do
104004b6cca3Slucy wang - Sun Microsystems - Beijing China  * this by scanning the DDI "reg" property of the interface,
104104b6cca3Slucy wang - Sun Microsystems - Beijing China  * which is an array of mx_ddi_reg_set structures.
104204b6cca3Slucy wang - Sun Microsystems - Beijing China  */
104304b6cca3Slucy wang - Sun Microsystems - Beijing China static int
104404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_reg_set(dev_info_t *dip, int *reg_set, int *span,
104504b6cca3Slucy wang - Sun Microsystems - Beijing China     unsigned long *busno, unsigned long *devno,
104604b6cca3Slucy wang - Sun Microsystems - Beijing China     unsigned long *funcno)
104704b6cca3Slucy wang - Sun Microsystems - Beijing China {
104804b6cca3Slucy wang - Sun Microsystems - Beijing China 
104904b6cca3Slucy wang - Sun Microsystems - Beijing China #define	REGISTER_NUMBER(ip)	(ip[0] >>  0 & 0xff)
105004b6cca3Slucy wang - Sun Microsystems - Beijing China #define	FUNCTION_NUMBER(ip)	(ip[0] >>  8 & 0x07)
105104b6cca3Slucy wang - Sun Microsystems - Beijing China #define	DEVICE_NUMBER(ip)	(ip[0] >> 11 & 0x1f)
105204b6cca3Slucy wang - Sun Microsystems - Beijing China #define	BUS_NUMBER(ip)		(ip[0] >> 16 & 0xff)
105304b6cca3Slucy wang - Sun Microsystems - Beijing China #define	ADDRESS_SPACE(ip)	(ip[0] >> 24 & 0x03)
105404b6cca3Slucy wang - Sun Microsystems - Beijing China #define	PCI_ADDR_HIGH(ip)	(ip[1])
105504b6cca3Slucy wang - Sun Microsystems - Beijing China #define	PCI_ADDR_LOW(ip) 	(ip[2])
105604b6cca3Slucy wang - Sun Microsystems - Beijing China #define	PCI_SPAN_HIGH(ip)	(ip[3])
105704b6cca3Slucy wang - Sun Microsystems - Beijing China #define	PCI_SPAN_LOW(ip)	(ip[4])
105804b6cca3Slucy wang - Sun Microsystems - Beijing China 
105904b6cca3Slucy wang - Sun Microsystems - Beijing China #define	MX_DDI_REG_SET_32_BIT_MEMORY_SPACE 2
106004b6cca3Slucy wang - Sun Microsystems - Beijing China #define	MX_DDI_REG_SET_64_BIT_MEMORY_SPACE 3
106104b6cca3Slucy wang - Sun Microsystems - Beijing China 
106204b6cca3Slucy wang - Sun Microsystems - Beijing China 	int *data, i, *rs;
106304b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint32_t nelementsp;
106404b6cca3Slucy wang - Sun Microsystems - Beijing China 
106504b6cca3Slucy wang - Sun Microsystems - Beijing China #ifdef MYRI10GE_REGSET_VERBOSE
106604b6cca3Slucy wang - Sun Microsystems - Beijing China 	char *address_space_name[] = { "Configuration Space",
106704b6cca3Slucy wang - Sun Microsystems - Beijing China 					"I/O Space",
106804b6cca3Slucy wang - Sun Microsystems - Beijing China 					"32-bit Memory Space",
106904b6cca3Slucy wang - Sun Microsystems - Beijing China 					"64-bit Memory Space"
107004b6cca3Slucy wang - Sun Microsystems - Beijing China 	};
107104b6cca3Slucy wang - Sun Microsystems - Beijing China #endif
107204b6cca3Slucy wang - Sun Microsystems - Beijing China 
107304b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
107404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "reg", &data, &nelementsp) != DDI_SUCCESS) {
107504b6cca3Slucy wang - Sun Microsystems - Beijing China 		printf("Could not determine register set.\n");
107604b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (ENXIO);
107704b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
107804b6cca3Slucy wang - Sun Microsystems - Beijing China 
107904b6cca3Slucy wang - Sun Microsystems - Beijing China #ifdef MYRI10GE_REGSET_VERBOSE
108004b6cca3Slucy wang - Sun Microsystems - Beijing China 	printf("There are %d register sets.\n", nelementsp / 5);
108104b6cca3Slucy wang - Sun Microsystems - Beijing China #endif
108204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (!nelementsp) {
108304b6cca3Slucy wang - Sun Microsystems - Beijing China 		printf("Didn't find any \"reg\" properties.\n");
108404b6cca3Slucy wang - Sun Microsystems - Beijing China 		ddi_prop_free(data);
108504b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (ENODEV);
108604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
108704b6cca3Slucy wang - Sun Microsystems - Beijing China 
108804b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* Scan for the register number. */
108904b6cca3Slucy wang - Sun Microsystems - Beijing China 	rs = &data[0];
109004b6cca3Slucy wang - Sun Microsystems - Beijing China 	*busno = BUS_NUMBER(rs);
109104b6cca3Slucy wang - Sun Microsystems - Beijing China 	*devno = DEVICE_NUMBER(rs);
109204b6cca3Slucy wang - Sun Microsystems - Beijing China 	*funcno = FUNCTION_NUMBER(rs);
109304b6cca3Slucy wang - Sun Microsystems - Beijing China 
109404b6cca3Slucy wang - Sun Microsystems - Beijing China #ifdef MYRI10GE_REGSET_VERBOSE
109504b6cca3Slucy wang - Sun Microsystems - Beijing China 	printf("*** Scanning for register number.\n");
109604b6cca3Slucy wang - Sun Microsystems - Beijing China #endif
109704b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (i = 0; i < nelementsp / 5; i++) {
109804b6cca3Slucy wang - Sun Microsystems - Beijing China 		rs = &data[5 * i];
109904b6cca3Slucy wang - Sun Microsystems - Beijing China #ifdef MYRI10GE_REGSET_VERBOSE
110004b6cca3Slucy wang - Sun Microsystems - Beijing China 		printf("Examining register set %d:\n", i);
110104b6cca3Slucy wang - Sun Microsystems - Beijing China 		printf("  Register number = %d.\n", REGISTER_NUMBER(rs));
110204b6cca3Slucy wang - Sun Microsystems - Beijing China 		printf("  Function number = %d.\n", FUNCTION_NUMBER(rs));
110304b6cca3Slucy wang - Sun Microsystems - Beijing China 		printf("  Device number   = %d.\n", DEVICE_NUMBER(rs));
110404b6cca3Slucy wang - Sun Microsystems - Beijing China 		printf("  Bus number      = %d.\n", BUS_NUMBER(rs));
110504b6cca3Slucy wang - Sun Microsystems - Beijing China 		printf("  Address space   = %d (%s ).\n", ADDRESS_SPACE(rs),
110604b6cca3Slucy wang - Sun Microsystems - Beijing China 		    address_space_name[ADDRESS_SPACE(rs)]);
110704b6cca3Slucy wang - Sun Microsystems - Beijing China 		printf("  pci address 0x%08x %08x\n", PCI_ADDR_HIGH(rs),
110804b6cca3Slucy wang - Sun Microsystems - Beijing China 		    PCI_ADDR_LOW(rs));
110904b6cca3Slucy wang - Sun Microsystems - Beijing China 		printf("  pci span 0x%08x %08x\n", PCI_SPAN_HIGH(rs),
111004b6cca3Slucy wang - Sun Microsystems - Beijing China 		    PCI_SPAN_LOW(rs));
111104b6cca3Slucy wang - Sun Microsystems - Beijing China #endif
111204b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* We are looking for a memory property. */
111304b6cca3Slucy wang - Sun Microsystems - Beijing China 
111404b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (ADDRESS_SPACE(rs) == MX_DDI_REG_SET_64_BIT_MEMORY_SPACE ||
111504b6cca3Slucy wang - Sun Microsystems - Beijing China 		    ADDRESS_SPACE(rs) == MX_DDI_REG_SET_32_BIT_MEMORY_SPACE) {
111604b6cca3Slucy wang - Sun Microsystems - Beijing China 			*reg_set = i;
111704b6cca3Slucy wang - Sun Microsystems - Beijing China 
111804b6cca3Slucy wang - Sun Microsystems - Beijing China #ifdef MYRI10GE_REGSET_VERBOSE
111904b6cca3Slucy wang - Sun Microsystems - Beijing China 			printf("%s uses register set %d.\n",
112004b6cca3Slucy wang - Sun Microsystems - Beijing China 			    address_space_name[ADDRESS_SPACE(rs)], *reg_set);
112104b6cca3Slucy wang - Sun Microsystems - Beijing China #endif
112204b6cca3Slucy wang - Sun Microsystems - Beijing China 
112304b6cca3Slucy wang - Sun Microsystems - Beijing China 			*span = (PCI_SPAN_LOW(rs));
112404b6cca3Slucy wang - Sun Microsystems - Beijing China #ifdef MYRI10GE_REGSET_VERBOSE
112504b6cca3Slucy wang - Sun Microsystems - Beijing China 			printf("Board span is 0x%x\n", *span);
112604b6cca3Slucy wang - Sun Microsystems - Beijing China #endif
112704b6cca3Slucy wang - Sun Microsystems - Beijing China 			break;
112804b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
112904b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
113004b6cca3Slucy wang - Sun Microsystems - Beijing China 
113104b6cca3Slucy wang - Sun Microsystems - Beijing China 	ddi_prop_free(data);
113204b6cca3Slucy wang - Sun Microsystems - Beijing China 
113304b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* If no match, fail. */
113404b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (i >= nelementsp / 5) {
113504b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (EIO);
113604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
113704b6cca3Slucy wang - Sun Microsystems - Beijing China 
113804b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
113904b6cca3Slucy wang - Sun Microsystems - Beijing China }
114004b6cca3Slucy wang - Sun Microsystems - Beijing China 
114104b6cca3Slucy wang - Sun Microsystems - Beijing China 
114204b6cca3Slucy wang - Sun Microsystems - Beijing China static int
114304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_load_firmware_from_zlib(struct myri10ge_priv *mgp, uint32_t *limit)
114404b6cca3Slucy wang - Sun Microsystems - Beijing China {
114504b6cca3Slucy wang - Sun Microsystems - Beijing China 	void *inflate_buffer;
114604b6cca3Slucy wang - Sun Microsystems - Beijing China 	int rv, status;
114704b6cca3Slucy wang - Sun Microsystems - Beijing China 	size_t sram_size = mgp->sram_size - MYRI10GE_EEPROM_STRINGS_SIZE;
114804b6cca3Slucy wang - Sun Microsystems - Beijing China 	size_t destlen;
114904b6cca3Slucy wang - Sun Microsystems - Beijing China 	mcp_gen_header_t *hdr;
115004b6cca3Slucy wang - Sun Microsystems - Beijing China 	unsigned hdr_offset, i;
115104b6cca3Slucy wang - Sun Microsystems - Beijing China 
115204b6cca3Slucy wang - Sun Microsystems - Beijing China 
115304b6cca3Slucy wang - Sun Microsystems - Beijing China 	*limit = 0; /* -Wuninitialized */
115404b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = 0;
115504b6cca3Slucy wang - Sun Microsystems - Beijing China 
115604b6cca3Slucy wang - Sun Microsystems - Beijing China 	inflate_buffer = kmem_zalloc(sram_size, KM_NOSLEEP);
115704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (!inflate_buffer) {
115804b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN,
115904b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "%s: Could not allocate buffer to inflate mcp\n",
116004b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->name);
116104b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (ENOMEM);
116204b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
116304b6cca3Slucy wang - Sun Microsystems - Beijing China 
116404b6cca3Slucy wang - Sun Microsystems - Beijing China 	destlen = sram_size;
116504b6cca3Slucy wang - Sun Microsystems - Beijing China 	rv = z_uncompress(inflate_buffer, &destlen, mgp->eth_z8e,
116604b6cca3Slucy wang - Sun Microsystems - Beijing China 	    mgp->eth_z8e_length);
116704b6cca3Slucy wang - Sun Microsystems - Beijing China 
116804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (rv != Z_OK) {
116904b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: Could not inflate mcp: %s\n",
117004b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->name, z_strerror(rv));
117104b6cca3Slucy wang - Sun Microsystems - Beijing China 		status = ENXIO;
117204b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort;
117304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
117404b6cca3Slucy wang - Sun Microsystems - Beijing China 
117504b6cca3Slucy wang - Sun Microsystems - Beijing China 	*limit = (uint32_t)destlen;
117604b6cca3Slucy wang - Sun Microsystems - Beijing China 
117704b6cca3Slucy wang - Sun Microsystems - Beijing China 	hdr_offset = htonl(*(uint32_t *)(void *)((char *)inflate_buffer +
117804b6cca3Slucy wang - Sun Microsystems - Beijing China 	    MCP_HEADER_PTR_OFFSET));
117904b6cca3Slucy wang - Sun Microsystems - Beijing China 	hdr = (void *)((char *)inflate_buffer + hdr_offset);
118004b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (ntohl(hdr->mcp_type) != MCP_TYPE_ETH) {
118104b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: Bad firmware type: 0x%x\n", mgp->name,
118204b6cca3Slucy wang - Sun Microsystems - Beijing China 		    ntohl(hdr->mcp_type));
118304b6cca3Slucy wang - Sun Microsystems - Beijing China 		status = EIO;
118404b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort;
118504b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
118604b6cca3Slucy wang - Sun Microsystems - Beijing China 
118704b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* save firmware version for kstat */
118804b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) strncpy(mgp->fw_version, hdr->version, sizeof (mgp->fw_version));
118904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (myri10ge_verbose)
119004b6cca3Slucy wang - Sun Microsystems - Beijing China 		printf("%s: firmware id: %s\n", mgp->name, hdr->version);
119104b6cca3Slucy wang - Sun Microsystems - Beijing China 
119204b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* Copy the inflated firmware to NIC SRAM. */
119304b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (i = 0; i < *limit; i += 256) {
119404b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_pio_copy((char *)mgp->sram + MYRI10GE_FW_OFFSET + i,
119504b6cca3Slucy wang - Sun Microsystems - Beijing China 		    (char *)inflate_buffer + i,
119604b6cca3Slucy wang - Sun Microsystems - Beijing China 		    min(256U, (unsigned)(*limit - i)));
119704b6cca3Slucy wang - Sun Microsystems - Beijing China 		mb();
119804b6cca3Slucy wang - Sun Microsystems - Beijing China 		(void) *(int *)(void *)mgp->sram;
119904b6cca3Slucy wang - Sun Microsystems - Beijing China 		mb();
120004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
120104b6cca3Slucy wang - Sun Microsystems - Beijing China 
120204b6cca3Slucy wang - Sun Microsystems - Beijing China abort:
120304b6cca3Slucy wang - Sun Microsystems - Beijing China 	kmem_free(inflate_buffer, sram_size);
120404b6cca3Slucy wang - Sun Microsystems - Beijing China 
120504b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (status);
120604b6cca3Slucy wang - Sun Microsystems - Beijing China 
120704b6cca3Slucy wang - Sun Microsystems - Beijing China }
120804b6cca3Slucy wang - Sun Microsystems - Beijing China 
120904b6cca3Slucy wang - Sun Microsystems - Beijing China 
121004b6cca3Slucy wang - Sun Microsystems - Beijing China int
121104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_send_cmd(struct myri10ge_priv *mgp, uint32_t cmd,
121204b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_cmd_t *data)
121304b6cca3Slucy wang - Sun Microsystems - Beijing China {
121404b6cca3Slucy wang - Sun Microsystems - Beijing China 	mcp_cmd_t *buf;
121504b6cca3Slucy wang - Sun Microsystems - Beijing China 	char buf_bytes[sizeof (*buf) + 8];
121604b6cca3Slucy wang - Sun Microsystems - Beijing China 	volatile mcp_cmd_response_t *response = mgp->cmd;
121704b6cca3Slucy wang - Sun Microsystems - Beijing China 	volatile char *cmd_addr =
121804b6cca3Slucy wang - Sun Microsystems - Beijing China 	    (volatile char *)mgp->sram + MXGEFW_ETH_CMD;
121904b6cca3Slucy wang - Sun Microsystems - Beijing China 	int sleep_total = 0;
122004b6cca3Slucy wang - Sun Microsystems - Beijing China 
122104b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* ensure buf is aligned to 8 bytes */
122204b6cca3Slucy wang - Sun Microsystems - Beijing China 	buf = (mcp_cmd_t *)((unsigned long)(buf_bytes + 7) & ~7UL);
122304b6cca3Slucy wang - Sun Microsystems - Beijing China 
122404b6cca3Slucy wang - Sun Microsystems - Beijing China 	buf->data0 = htonl(data->data0);
122504b6cca3Slucy wang - Sun Microsystems - Beijing China 	buf->data1 = htonl(data->data1);
122604b6cca3Slucy wang - Sun Microsystems - Beijing China 	buf->data2 = htonl(data->data2);
122704b6cca3Slucy wang - Sun Microsystems - Beijing China 	buf->cmd = htonl(cmd);
122804b6cca3Slucy wang - Sun Microsystems - Beijing China 	buf->response_addr.low = mgp->cmd_dma.low;
122904b6cca3Slucy wang - Sun Microsystems - Beijing China 	buf->response_addr.high = mgp->cmd_dma.high;
123004b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&mgp->cmd_lock);
123104b6cca3Slucy wang - Sun Microsystems - Beijing China 	response->result = 0xffffffff;
123204b6cca3Slucy wang - Sun Microsystems - Beijing China 	mb();
123304b6cca3Slucy wang - Sun Microsystems - Beijing China 
123404b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_pio_copy((void *)cmd_addr, buf, sizeof (*buf));
123504b6cca3Slucy wang - Sun Microsystems - Beijing China 
123604b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* wait up to 20ms */
123704b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (sleep_total = 0; sleep_total < 20; sleep_total++) {
123804b6cca3Slucy wang - Sun Microsystems - Beijing China 		mb();
123904b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (response->result != 0xffffffff) {
124004b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (response->result == 0) {
124104b6cca3Slucy wang - Sun Microsystems - Beijing China 				data->data0 = ntohl(response->data);
124204b6cca3Slucy wang - Sun Microsystems - Beijing China 				mutex_exit(&mgp->cmd_lock);
124304b6cca3Slucy wang - Sun Microsystems - Beijing China 				return (0);
124404b6cca3Slucy wang - Sun Microsystems - Beijing China 			} else if (ntohl(response->result)
124504b6cca3Slucy wang - Sun Microsystems - Beijing China 			    == MXGEFW_CMD_UNKNOWN) {
124604b6cca3Slucy wang - Sun Microsystems - Beijing China 				mutex_exit(&mgp->cmd_lock);
124704b6cca3Slucy wang - Sun Microsystems - Beijing China 				return (ENOSYS);
124804b6cca3Slucy wang - Sun Microsystems - Beijing China 			} else if (ntohl(response->result)
124904b6cca3Slucy wang - Sun Microsystems - Beijing China 			    == MXGEFW_CMD_ERROR_UNALIGNED) {
125004b6cca3Slucy wang - Sun Microsystems - Beijing China 				mutex_exit(&mgp->cmd_lock);
125104b6cca3Slucy wang - Sun Microsystems - Beijing China 				return (E2BIG);
125204b6cca3Slucy wang - Sun Microsystems - Beijing China 			} else {
125304b6cca3Slucy wang - Sun Microsystems - Beijing China 				cmn_err(CE_WARN,
125404b6cca3Slucy wang - Sun Microsystems - Beijing China 				    "%s: command %d failed, result = %d\n",
125504b6cca3Slucy wang - Sun Microsystems - Beijing China 				    mgp->name, cmd, ntohl(response->result));
125604b6cca3Slucy wang - Sun Microsystems - Beijing China 				mutex_exit(&mgp->cmd_lock);
125704b6cca3Slucy wang - Sun Microsystems - Beijing China 				return (ENXIO);
125804b6cca3Slucy wang - Sun Microsystems - Beijing China 			}
125904b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
126004b6cca3Slucy wang - Sun Microsystems - Beijing China 		drv_usecwait(1000);
126104b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
126204b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&mgp->cmd_lock);
126304b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmn_err(CE_WARN, "%s: command %d timed out, result = %d\n",
126404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    mgp->name, cmd, ntohl(response->result));
126504b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (EAGAIN);
126604b6cca3Slucy wang - Sun Microsystems - Beijing China }
126704b6cca3Slucy wang - Sun Microsystems - Beijing China 
126804b6cca3Slucy wang - Sun Microsystems - Beijing China /*
126904b6cca3Slucy wang - Sun Microsystems - Beijing China  * Enable or disable periodic RDMAs from the host to make certain
127004b6cca3Slucy wang - Sun Microsystems - Beijing China  * chipsets resend dropped PCIe messages
127104b6cca3Slucy wang - Sun Microsystems - Beijing China  */
127204b6cca3Slucy wang - Sun Microsystems - Beijing China 
127304b6cca3Slucy wang - Sun Microsystems - Beijing China static void
127404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_dummy_rdma(struct myri10ge_priv *mgp, int enable)
127504b6cca3Slucy wang - Sun Microsystems - Beijing China {
127604b6cca3Slucy wang - Sun Microsystems - Beijing China 	char buf_bytes[72];
127704b6cca3Slucy wang - Sun Microsystems - Beijing China 	volatile uint32_t *confirm;
127804b6cca3Slucy wang - Sun Microsystems - Beijing China 	volatile char *submit;
127904b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint32_t *buf;
128004b6cca3Slucy wang - Sun Microsystems - Beijing China 	int i;
128104b6cca3Slucy wang - Sun Microsystems - Beijing China 
128204b6cca3Slucy wang - Sun Microsystems - Beijing China 	buf = (uint32_t *)((unsigned long)(buf_bytes + 7) & ~7UL);
128304b6cca3Slucy wang - Sun Microsystems - Beijing China 
128404b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* clear confirmation addr */
128504b6cca3Slucy wang - Sun Microsystems - Beijing China 	confirm = (volatile uint32_t *)mgp->cmd;
128604b6cca3Slucy wang - Sun Microsystems - Beijing China 	*confirm = 0;
128704b6cca3Slucy wang - Sun Microsystems - Beijing China 	mb();
128804b6cca3Slucy wang - Sun Microsystems - Beijing China 
128904b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
129004b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * send an rdma command to the PCIe engine, and wait for the
129104b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * response in the confirmation address.  The firmware should
129204b6cca3Slucy wang - Sun Microsystems - Beijing China 	 *  write a -1 there to indicate it is alive and well
129304b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
129404b6cca3Slucy wang - Sun Microsystems - Beijing China 
129504b6cca3Slucy wang - Sun Microsystems - Beijing China 	buf[0] = mgp->cmd_dma.high;		/* confirm addr MSW */
129604b6cca3Slucy wang - Sun Microsystems - Beijing China 	buf[1] = mgp->cmd_dma.low;		/* confirm addr LSW */
129704b6cca3Slucy wang - Sun Microsystems - Beijing China 	buf[2] = htonl(0xffffffff);		/* confirm data */
129804b6cca3Slucy wang - Sun Microsystems - Beijing China 	buf[3] = htonl(mgp->cmd_dma.high); 	/* dummy addr MSW */
129904b6cca3Slucy wang - Sun Microsystems - Beijing China 	buf[4] = htonl(mgp->cmd_dma.low); 	/* dummy addr LSW */
130004b6cca3Slucy wang - Sun Microsystems - Beijing China 	buf[5] = htonl(enable);			/* enable? */
130104b6cca3Slucy wang - Sun Microsystems - Beijing China 
130204b6cca3Slucy wang - Sun Microsystems - Beijing China 
130304b6cca3Slucy wang - Sun Microsystems - Beijing China 	submit = (volatile char *)(mgp->sram + MXGEFW_BOOT_DUMMY_RDMA);
130404b6cca3Slucy wang - Sun Microsystems - Beijing China 
130504b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_pio_copy((char *)submit, buf, 64);
130604b6cca3Slucy wang - Sun Microsystems - Beijing China 	mb();
130704b6cca3Slucy wang - Sun Microsystems - Beijing China 	drv_usecwait(1000);
130804b6cca3Slucy wang - Sun Microsystems - Beijing China 	mb();
130904b6cca3Slucy wang - Sun Microsystems - Beijing China 	i = 0;
131004b6cca3Slucy wang - Sun Microsystems - Beijing China 	while (*confirm != 0xffffffff && i < 20) {
131104b6cca3Slucy wang - Sun Microsystems - Beijing China 		drv_usecwait(1000);
131204b6cca3Slucy wang - Sun Microsystems - Beijing China 		i++;
131304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
131404b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (*confirm != 0xffffffff) {
131504b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: dummy rdma %s failed (%p = 0x%x)",
131604b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->name,
131704b6cca3Slucy wang - Sun Microsystems - Beijing China 		    (enable ? "enable" : "disable"), (void*) confirm, *confirm);
131804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
131904b6cca3Slucy wang - Sun Microsystems - Beijing China }
132004b6cca3Slucy wang - Sun Microsystems - Beijing China 
132104b6cca3Slucy wang - Sun Microsystems - Beijing China static int
132204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_load_firmware(struct myri10ge_priv *mgp)
132304b6cca3Slucy wang - Sun Microsystems - Beijing China {
132404b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_cmd_t cmd;
132504b6cca3Slucy wang - Sun Microsystems - Beijing China 	volatile uint32_t *confirm;
132604b6cca3Slucy wang - Sun Microsystems - Beijing China 	volatile char *submit;
132704b6cca3Slucy wang - Sun Microsystems - Beijing China 	char buf_bytes[72];
132804b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint32_t *buf, size;
132904b6cca3Slucy wang - Sun Microsystems - Beijing China 	int status, i;
133004b6cca3Slucy wang - Sun Microsystems - Beijing China 
133104b6cca3Slucy wang - Sun Microsystems - Beijing China 	buf = (uint32_t *)((unsigned long)(buf_bytes + 7) & ~7UL);
133204b6cca3Slucy wang - Sun Microsystems - Beijing China 
133304b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_load_firmware_from_zlib(mgp, &size);
133404b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status) {
133504b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: firmware loading failed\n", mgp->name);
133604b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (status);
133704b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
133804b6cca3Slucy wang - Sun Microsystems - Beijing China 
133904b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* clear confirmation addr */
134004b6cca3Slucy wang - Sun Microsystems - Beijing China 	confirm = (volatile uint32_t *)mgp->cmd;
134104b6cca3Slucy wang - Sun Microsystems - Beijing China 	*confirm = 0;
134204b6cca3Slucy wang - Sun Microsystems - Beijing China 	mb();
134304b6cca3Slucy wang - Sun Microsystems - Beijing China 
134404b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
134504b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * send a reload command to the bootstrap MCP, and wait for the
134604b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * response in the confirmation address.  The firmware should
134704b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * write a -1 there to indicate it is alive and well
134804b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
134904b6cca3Slucy wang - Sun Microsystems - Beijing China 
135004b6cca3Slucy wang - Sun Microsystems - Beijing China 	buf[0] = mgp->cmd_dma.high;	/* confirm addr MSW */
135104b6cca3Slucy wang - Sun Microsystems - Beijing China 	buf[1] = mgp->cmd_dma.low;	/* confirm addr LSW */
135204b6cca3Slucy wang - Sun Microsystems - Beijing China 	buf[2] = htonl(0xffffffff);	/* confirm data */
135304b6cca3Slucy wang - Sun Microsystems - Beijing China 
135404b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
135504b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * FIX: All newest firmware should un-protect the bottom of
135604b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * the sram before handoff. However, the very first interfaces
135704b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * do not. Therefore the handoff copy must skip the first 8 bytes
135804b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
135904b6cca3Slucy wang - Sun Microsystems - Beijing China 	buf[3] = htonl(MYRI10GE_FW_OFFSET + 8); /* where the code starts */
136004b6cca3Slucy wang - Sun Microsystems - Beijing China 	buf[4] = htonl(size - 8); 	/* length of code */
136104b6cca3Slucy wang - Sun Microsystems - Beijing China 	buf[5] = htonl(8);		/* where to copy to */
136204b6cca3Slucy wang - Sun Microsystems - Beijing China 	buf[6] = htonl(0);		/* where to jump to */
136304b6cca3Slucy wang - Sun Microsystems - Beijing China 
136404b6cca3Slucy wang - Sun Microsystems - Beijing China 	submit = (volatile char *)(mgp->sram + MXGEFW_BOOT_HANDOFF);
136504b6cca3Slucy wang - Sun Microsystems - Beijing China 
136604b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_pio_copy((char *)submit, buf, 64);
136704b6cca3Slucy wang - Sun Microsystems - Beijing China 	mb();
136804b6cca3Slucy wang - Sun Microsystems - Beijing China 	drv_usecwait(1000);
136904b6cca3Slucy wang - Sun Microsystems - Beijing China 	mb();
137004b6cca3Slucy wang - Sun Microsystems - Beijing China 	i = 0;
137104b6cca3Slucy wang - Sun Microsystems - Beijing China 	while (*confirm != 0xffffffff && i < 1000) {
137204b6cca3Slucy wang - Sun Microsystems - Beijing China 		drv_usecwait(1000);
137304b6cca3Slucy wang - Sun Microsystems - Beijing China 		i++;
137404b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
137504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (*confirm != 0xffffffff) {
137604b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: handoff failed (%p = 0x%x)",
137704b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->name, (void *) confirm, *confirm);
137804b6cca3Slucy wang - Sun Microsystems - Beijing China 
137904b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (ENXIO);
138004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
138104b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_RX_RING_SIZE, &cmd);
138204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != 0) {
138304b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: failed MXGEFW_CMD_GET_RX_RING_SIZE\n",
138404b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->name);
138504b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (ENXIO);
138604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
138704b6cca3Slucy wang - Sun Microsystems - Beijing China 
138804b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->max_intr_slots = 2 * (cmd.data0 / sizeof (mcp_dma_addr_t));
138904b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_dummy_rdma(mgp, 1);
139004b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
139104b6cca3Slucy wang - Sun Microsystems - Beijing China }
139204b6cca3Slucy wang - Sun Microsystems - Beijing China 
139304b6cca3Slucy wang - Sun Microsystems - Beijing China static int
139404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_m_unicst(void *arg, const uint8_t *addr)
139504b6cca3Slucy wang - Sun Microsystems - Beijing China {
139604b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp = arg;
139704b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_cmd_t cmd;
139804b6cca3Slucy wang - Sun Microsystems - Beijing China 	int status;
139904b6cca3Slucy wang - Sun Microsystems - Beijing China 
140004b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data0 = ((addr[0] << 24) | (addr[1] << 16)
140104b6cca3Slucy wang - Sun Microsystems - Beijing China 	    | (addr[2] << 8) | addr[3]);
140204b6cca3Slucy wang - Sun Microsystems - Beijing China 
140304b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data1 = ((addr[4] << 8) | (addr[5]));
140404b6cca3Slucy wang - Sun Microsystems - Beijing China 
140504b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_send_cmd(mgp, MXGEFW_SET_MAC_ADDRESS, &cmd);
140604b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status == 0 && (addr != mgp->mac_addr))
140704b6cca3Slucy wang - Sun Microsystems - Beijing China 		(void) memcpy(mgp->mac_addr, addr, sizeof (mgp->mac_addr));
140804b6cca3Slucy wang - Sun Microsystems - Beijing China 
140904b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (status);
141004b6cca3Slucy wang - Sun Microsystems - Beijing China }
141104b6cca3Slucy wang - Sun Microsystems - Beijing China 
141204b6cca3Slucy wang - Sun Microsystems - Beijing China static int
141304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_change_pause(struct myri10ge_priv *mgp, int pause)
141404b6cca3Slucy wang - Sun Microsystems - Beijing China {
141504b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_cmd_t cmd;
141604b6cca3Slucy wang - Sun Microsystems - Beijing China 	int status;
141704b6cca3Slucy wang - Sun Microsystems - Beijing China 
141804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (pause)
141904b6cca3Slucy wang - Sun Microsystems - Beijing China 		status = myri10ge_send_cmd(mgp, MXGEFW_ENABLE_FLOW_CONTROL,
142004b6cca3Slucy wang - Sun Microsystems - Beijing China 		    &cmd);
142104b6cca3Slucy wang - Sun Microsystems - Beijing China 	else
142204b6cca3Slucy wang - Sun Microsystems - Beijing China 		status = myri10ge_send_cmd(mgp, MXGEFW_DISABLE_FLOW_CONTROL,
142304b6cca3Slucy wang - Sun Microsystems - Beijing China 		    &cmd);
142404b6cca3Slucy wang - Sun Microsystems - Beijing China 
142504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status) {
142604b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: Failed to set flow control mode\n",
142704b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->name);
142804b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (ENXIO);
142904b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
143004b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->pause = pause;
143104b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
143204b6cca3Slucy wang - Sun Microsystems - Beijing China }
143304b6cca3Slucy wang - Sun Microsystems - Beijing China 
143404b6cca3Slucy wang - Sun Microsystems - Beijing China static void
143504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_change_promisc(struct myri10ge_priv *mgp, int promisc)
143604b6cca3Slucy wang - Sun Microsystems - Beijing China {
143704b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_cmd_t cmd;
143804b6cca3Slucy wang - Sun Microsystems - Beijing China 	int status;
143904b6cca3Slucy wang - Sun Microsystems - Beijing China 
144004b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (promisc)
144104b6cca3Slucy wang - Sun Microsystems - Beijing China 		status = myri10ge_send_cmd(mgp, MXGEFW_ENABLE_PROMISC, &cmd);
144204b6cca3Slucy wang - Sun Microsystems - Beijing China 	else
144304b6cca3Slucy wang - Sun Microsystems - Beijing China 		status = myri10ge_send_cmd(mgp, MXGEFW_DISABLE_PROMISC, &cmd);
144404b6cca3Slucy wang - Sun Microsystems - Beijing China 
144504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status) {
144604b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: Failed to set promisc mode\n",
144704b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->name);
144804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
144904b6cca3Slucy wang - Sun Microsystems - Beijing China }
145004b6cca3Slucy wang - Sun Microsystems - Beijing China 
145104b6cca3Slucy wang - Sun Microsystems - Beijing China static int
145204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_dma_test(struct myri10ge_priv *mgp, int test_type)
145304b6cca3Slucy wang - Sun Microsystems - Beijing China {
145404b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_cmd_t cmd;
145504b6cca3Slucy wang - Sun Microsystems - Beijing China 	int status;
145604b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint32_t len;
145704b6cca3Slucy wang - Sun Microsystems - Beijing China 	void *dmabench;
145804b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_dma_stuff dmabench_dma;
145904b6cca3Slucy wang - Sun Microsystems - Beijing China 	char *test = " ";
146004b6cca3Slucy wang - Sun Microsystems - Beijing China 
146104b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
146204b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * Run a small DMA test.
146304b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * The magic multipliers to the length tell the firmware
146404b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * tp do DMA read, write, or read+write tests.  The
146504b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * results are returned in cmd.data0.  The upper 16
146604b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * bits or the return is the number of transfers completed.
146704b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * The lower 16 bits is the time in 0.5us ticks that the
146804b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * transfers took to complete
146904b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
147004b6cca3Slucy wang - Sun Microsystems - Beijing China 
147104b6cca3Slucy wang - Sun Microsystems - Beijing China 	len = mgp->tx_boundary;
147204b6cca3Slucy wang - Sun Microsystems - Beijing China 
147304b6cca3Slucy wang - Sun Microsystems - Beijing China 	dmabench = myri10ge_dma_alloc(mgp->dip, len,
147404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    &myri10ge_rx_jumbo_dma_attr, &myri10ge_dev_access_attr,
147504b6cca3Slucy wang - Sun Microsystems - Beijing China 	    DDI_DMA_STREAMING,  DDI_DMA_RDWR|DDI_DMA_STREAMING,
147604b6cca3Slucy wang - Sun Microsystems - Beijing China 	    &dmabench_dma, 1, DDI_DMA_DONTWAIT);
147704b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->read_dma = mgp->write_dma = mgp->read_write_dma = 0;
147804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (dmabench == NULL) {
147904b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s dma benchmark aborted\n", mgp->name);
148004b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (ENOMEM);
148104b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
148204b6cca3Slucy wang - Sun Microsystems - Beijing China 
148304b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data0 = ntohl(dmabench_dma.low);
148404b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data1 = ntohl(dmabench_dma.high);
148504b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data2 = len * 0x10000;
148604b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_send_cmd(mgp, test_type, &cmd);
148704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != 0) {
148804b6cca3Slucy wang - Sun Microsystems - Beijing China 		test = "read";
148904b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort;
149004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
149104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->read_dma = ((cmd.data0>>16) * len * 2) / (cmd.data0 & 0xffff);
149204b6cca3Slucy wang - Sun Microsystems - Beijing China 
149304b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data0 = ntohl(dmabench_dma.low);
149404b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data1 = ntohl(dmabench_dma.high);
149504b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data2 = len * 0x1;
149604b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_send_cmd(mgp, test_type, &cmd);
149704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != 0) {
149804b6cca3Slucy wang - Sun Microsystems - Beijing China 		test = "write";
149904b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort;
150004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
150104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->write_dma = ((cmd.data0>>16) * len * 2) / (cmd.data0 & 0xffff);
150204b6cca3Slucy wang - Sun Microsystems - Beijing China 
150304b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data0 = ntohl(dmabench_dma.low);
150404b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data1 = ntohl(dmabench_dma.high);
150504b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data2 = len * 0x10001;
150604b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_send_cmd(mgp, test_type, &cmd);
150704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != 0) {
150804b6cca3Slucy wang - Sun Microsystems - Beijing China 		test = "read/write";
150904b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort;
151004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
151104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->read_write_dma = ((cmd.data0>>16) * len * 2 * 2) /
151204b6cca3Slucy wang - Sun Microsystems - Beijing China 	    (cmd.data0 & 0xffff);
151304b6cca3Slucy wang - Sun Microsystems - Beijing China 
151404b6cca3Slucy wang - Sun Microsystems - Beijing China 
151504b6cca3Slucy wang - Sun Microsystems - Beijing China abort:
151604b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_dma_free(&dmabench_dma);
151704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != 0 && test_type != MXGEFW_CMD_UNALIGNED_TEST)
151804b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s %s dma benchmark failed\n", mgp->name,
151904b6cca3Slucy wang - Sun Microsystems - Beijing China 		    test);
152004b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (status);
152104b6cca3Slucy wang - Sun Microsystems - Beijing China }
152204b6cca3Slucy wang - Sun Microsystems - Beijing China 
152304b6cca3Slucy wang - Sun Microsystems - Beijing China static int
152404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_reset(struct myri10ge_priv *mgp)
152504b6cca3Slucy wang - Sun Microsystems - Beijing China {
152604b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_cmd_t cmd;
152704b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_nic_stat *ethstat;
152804b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_slice_state *ss;
152904b6cca3Slucy wang - Sun Microsystems - Beijing China 	int i, status;
153004b6cca3Slucy wang - Sun Microsystems - Beijing China 	size_t bytes;
153104b6cca3Slucy wang - Sun Microsystems - Beijing China 
153204b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* send a reset command to the card to see if it is alive */
153304b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) memset(&cmd, 0, sizeof (cmd));
153404b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_RESET, &cmd);
153504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != 0) {
153604b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: failed reset\n", mgp->name);
153704b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (ENXIO);
153804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
153904b6cca3Slucy wang - Sun Microsystems - Beijing China 
154004b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* Now exchange information about interrupts  */
154104b6cca3Slucy wang - Sun Microsystems - Beijing China 
154204b6cca3Slucy wang - Sun Microsystems - Beijing China 	bytes = mgp->max_intr_slots * sizeof (*mgp->ss[0].rx_done.entry);
154304b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data0 = (uint32_t)bytes;
154404b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_SIZE, &cmd);
154504b6cca3Slucy wang - Sun Microsystems - Beijing China 
154604b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
154704b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * Even though we already know how many slices are supported
154804b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * via myri10ge_probe_slices() MXGEFW_CMD_GET_MAX_RSS_QUEUES
154904b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * has magic side effects, and must be called after a reset.
155004b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * It must be called prior to calling any RSS related cmds,
155104b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * including assigning an interrupt queue for anything but
155204b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * slice 0.  It must also be called *after*
155304b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * MXGEFW_CMD_SET_INTRQ_SIZE, since the intrq size is used by
155404b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * the firmware to compute offsets.
155504b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
155604b6cca3Slucy wang - Sun Microsystems - Beijing China 
155704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->num_slices > 1) {
155804b6cca3Slucy wang - Sun Microsystems - Beijing China 
155904b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* ask the maximum number of slices it supports */
156004b6cca3Slucy wang - Sun Microsystems - Beijing China 		status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_MAX_RSS_QUEUES,
156104b6cca3Slucy wang - Sun Microsystems - Beijing China 		    &cmd);
156204b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (status != 0) {
156304b6cca3Slucy wang - Sun Microsystems - Beijing China 			cmn_err(CE_WARN,
156404b6cca3Slucy wang - Sun Microsystems - Beijing China 			    "%s: failed to get number of slices\n",
156504b6cca3Slucy wang - Sun Microsystems - Beijing China 			    mgp->name);
156604b6cca3Slucy wang - Sun Microsystems - Beijing China 			return (status);
156704b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
156804b6cca3Slucy wang - Sun Microsystems - Beijing China 
156904b6cca3Slucy wang - Sun Microsystems - Beijing China 		/*
157004b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * MXGEFW_CMD_ENABLE_RSS_QUEUES must be called prior
157104b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * to setting up the interrupt queue DMA
157204b6cca3Slucy wang - Sun Microsystems - Beijing China 		 */
157304b6cca3Slucy wang - Sun Microsystems - Beijing China 
157404b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmd.data0 = mgp->num_slices;
157504b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmd.data1 = MXGEFW_SLICE_INTR_MODE_ONE_PER_SLICE |
157604b6cca3Slucy wang - Sun Microsystems - Beijing China 		    MXGEFW_SLICE_ENABLE_MULTIPLE_TX_QUEUES;
157704b6cca3Slucy wang - Sun Microsystems - Beijing China 		status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ENABLE_RSS_QUEUES,
157804b6cca3Slucy wang - Sun Microsystems - Beijing China 		    &cmd);
157904b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (status != 0) {
158004b6cca3Slucy wang - Sun Microsystems - Beijing China 			cmn_err(CE_WARN,
158104b6cca3Slucy wang - Sun Microsystems - Beijing China 			    "%s: failed to set number of slices\n",
158204b6cca3Slucy wang - Sun Microsystems - Beijing China 			    mgp->name);
158304b6cca3Slucy wang - Sun Microsystems - Beijing China 			return (status);
158404b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
158504b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
158604b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (i = 0; i < mgp->num_slices; i++) {
158704b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss = &mgp->ss[i];
158804b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmd.data0 = ntohl(ss->rx_done.dma.low);
158904b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmd.data1 = ntohl(ss->rx_done.dma.high);
159004b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmd.data2 = i;
159104b6cca3Slucy wang - Sun Microsystems - Beijing China 		status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_DMA,
159204b6cca3Slucy wang - Sun Microsystems - Beijing China 		    &cmd);
159304b6cca3Slucy wang - Sun Microsystems - Beijing China 	};
159404b6cca3Slucy wang - Sun Microsystems - Beijing China 
159504b6cca3Slucy wang - Sun Microsystems - Beijing China 	status |= myri10ge_send_cmd(mgp,  MXGEFW_CMD_GET_IRQ_ACK_OFFSET, &cmd);
159604b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (i = 0; i < mgp->num_slices; i++) {
159704b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss = &mgp->ss[i];
159804b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->irq_claim = (volatile unsigned int *)
159904b6cca3Slucy wang - Sun Microsystems - Beijing China 		    (void *)(mgp->sram + cmd.data0 + 8 * i);
160004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
160104b6cca3Slucy wang - Sun Microsystems - Beijing China 
160204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->ddi_intr_type == DDI_INTR_TYPE_FIXED) {
160304b6cca3Slucy wang - Sun Microsystems - Beijing China 		status |= myri10ge_send_cmd(mgp,
160404b6cca3Slucy wang - Sun Microsystems - Beijing China 		    MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET, &cmd);
160504b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->irq_deassert = (uint32_t *)(void *)(mgp->sram + cmd.data0);
160604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
160704b6cca3Slucy wang - Sun Microsystems - Beijing China 
160804b6cca3Slucy wang - Sun Microsystems - Beijing China 	status |= myri10ge_send_cmd(mgp,
160904b6cca3Slucy wang - Sun Microsystems - Beijing China 	    MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET, &cmd);
161004b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->intr_coal_delay_ptr = (uint32_t *)(void *)(mgp->sram + cmd.data0);
161104b6cca3Slucy wang - Sun Microsystems - Beijing China 
161204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != 0) {
161304b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: failed set interrupt parameters\n",
161404b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->name);
161504b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (status);
161604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
161704b6cca3Slucy wang - Sun Microsystems - Beijing China 
161804b6cca3Slucy wang - Sun Microsystems - Beijing China 	*mgp->intr_coal_delay_ptr = htonl(mgp->intr_coal_delay);
161904b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) myri10ge_dma_test(mgp, MXGEFW_DMA_TEST);
162004b6cca3Slucy wang - Sun Microsystems - Beijing China 
162104b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* reset mcp/driver shared state back to 0 */
162204b6cca3Slucy wang - Sun Microsystems - Beijing China 
162304b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (i = 0; i < mgp->num_slices; i++) {
162404b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss = &mgp->ss[i];
162504b6cca3Slucy wang - Sun Microsystems - Beijing China 		bytes = mgp->max_intr_slots *
162604b6cca3Slucy wang - Sun Microsystems - Beijing China 		    sizeof (*mgp->ss[0].rx_done.entry);
162704b6cca3Slucy wang - Sun Microsystems - Beijing China 		(void) memset(ss->rx_done.entry, 0, bytes);
162804b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->tx.req = 0;
162904b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->tx.done = 0;
163004b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->tx.pkt_done = 0;
163104b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->rx_big.cnt = 0;
163204b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->rx_small.cnt = 0;
163304b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->rx_done.idx = 0;
163404b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->rx_done.cnt = 0;
163504b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->rx_token = 0;
163604b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->tx.watchdog_done = 0;
163704b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->tx.watchdog_req = 0;
163804b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->tx.active = 0;
163904b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->tx.activate = 0;
164004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
164104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->watchdog_rx_pause = 0;
164204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->ksp_stat != NULL) {
164304b6cca3Slucy wang - Sun Microsystems - Beijing China 		ethstat = (struct myri10ge_nic_stat *)mgp->ksp_stat->ks_data;
164404b6cca3Slucy wang - Sun Microsystems - Beijing China 		ethstat->link_changes.value.ul = 0;
164504b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
164604b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_m_unicst(mgp, mgp->mac_addr);
164704b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_change_promisc(mgp, 0);
164804b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) myri10ge_change_pause(mgp, mgp->pause);
164904b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (status);
165004b6cca3Slucy wang - Sun Microsystems - Beijing China }
165104b6cca3Slucy wang - Sun Microsystems - Beijing China 
165204b6cca3Slucy wang - Sun Microsystems - Beijing China static int
165304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_init_toeplitz(struct myri10ge_priv *mgp)
165404b6cca3Slucy wang - Sun Microsystems - Beijing China {
165504b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_cmd_t cmd;
165604b6cca3Slucy wang - Sun Microsystems - Beijing China 	int i, b, s, t, j;
165704b6cca3Slucy wang - Sun Microsystems - Beijing China 	int status;
165804b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint32_t k[8];
165904b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint32_t tmp;
166004b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint8_t *key;
166104b6cca3Slucy wang - Sun Microsystems - Beijing China 
166204b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_RSS_KEY_OFFSET,
166304b6cca3Slucy wang - Sun Microsystems - Beijing China 	    &cmd);
166404b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != 0) {
166504b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: failed to get rss key\n",
166604b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->name);
166704b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (EIO);
166804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
166904b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_pio_copy32(mgp->rss_key,
167004b6cca3Slucy wang - Sun Microsystems - Beijing China 	    (uint32_t *)(void*)((char *)mgp->sram + cmd.data0),
167104b6cca3Slucy wang - Sun Microsystems - Beijing China 	    sizeof (mgp->rss_key));
167204b6cca3Slucy wang - Sun Microsystems - Beijing China 
167304b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->toeplitz_hash_table = kmem_alloc(sizeof (uint32_t) * 12 * 256,
167404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KM_SLEEP);
167504b6cca3Slucy wang - Sun Microsystems - Beijing China 	key = (uint8_t *)mgp->rss_key;
167604b6cca3Slucy wang - Sun Microsystems - Beijing China 	t = 0;
167704b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (b = 0; b < 12; b++) {
167804b6cca3Slucy wang - Sun Microsystems - Beijing China 		for (s = 0; s < 8; s++) {
167904b6cca3Slucy wang - Sun Microsystems - Beijing China 			/* Bits: b*8+s, ..., b*8+s+31 */
168004b6cca3Slucy wang - Sun Microsystems - Beijing China 			k[s] = 0;
168104b6cca3Slucy wang - Sun Microsystems - Beijing China 			for (j = 0; j < 32; j++) {
168204b6cca3Slucy wang - Sun Microsystems - Beijing China 				int bit = b*8+s+j;
168304b6cca3Slucy wang - Sun Microsystems - Beijing China 				bit = 0x1 & (key[bit / 8] >> (7 -(bit & 0x7)));
168404b6cca3Slucy wang - Sun Microsystems - Beijing China 				k[s] |= bit << (31 - j);
168504b6cca3Slucy wang - Sun Microsystems - Beijing China 			}
168604b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
168704b6cca3Slucy wang - Sun Microsystems - Beijing China 
168804b6cca3Slucy wang - Sun Microsystems - Beijing China 		for (i = 0; i <= 0xff; i++) {
168904b6cca3Slucy wang - Sun Microsystems - Beijing China 			tmp = 0;
169004b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (i & (1 << 7)) { tmp ^= k[0]; }
169104b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (i & (1 << 6)) { tmp ^= k[1]; }
169204b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (i & (1 << 5)) { tmp ^= k[2]; }
169304b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (i & (1 << 4)) { tmp ^= k[3]; }
169404b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (i & (1 << 3)) { tmp ^= k[4]; }
169504b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (i & (1 << 2)) { tmp ^= k[5]; }
169604b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (i & (1 << 1)) { tmp ^= k[6]; }
169704b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (i & (1 << 0)) { tmp ^= k[7]; }
169804b6cca3Slucy wang - Sun Microsystems - Beijing China 			mgp->toeplitz_hash_table[t++] = tmp;
169904b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
170004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
170104b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
170204b6cca3Slucy wang - Sun Microsystems - Beijing China }
170304b6cca3Slucy wang - Sun Microsystems - Beijing China 
170404b6cca3Slucy wang - Sun Microsystems - Beijing China static inline struct myri10ge_slice_state *
170504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_toeplitz_send_hash(struct myri10ge_priv *mgp, struct ip *ip)
170604b6cca3Slucy wang - Sun Microsystems - Beijing China {
170704b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct tcphdr *hdr;
170804b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint32_t saddr, daddr;
170904b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint32_t hash, slice;
171004b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint32_t *table = mgp->toeplitz_hash_table;
171104b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint16_t src, dst;
171204b6cca3Slucy wang - Sun Microsystems - Beijing China 
171304b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
171404b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * Note hashing order is reversed from how it is done
171504b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * in the NIC, so as to generate the same hash value
171604b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * for the connection to try to keep connections CPU local
171704b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
171804b6cca3Slucy wang - Sun Microsystems - Beijing China 
171904b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* hash on IPv4 src/dst address */
172004b6cca3Slucy wang - Sun Microsystems - Beijing China 	saddr = ntohl(ip->ip_src.s_addr);
172104b6cca3Slucy wang - Sun Microsystems - Beijing China 	daddr = ntohl(ip->ip_dst.s_addr);
172204b6cca3Slucy wang - Sun Microsystems - Beijing China 	hash = table[(256 * 0) + ((daddr >> 24) & 0xff)];
172304b6cca3Slucy wang - Sun Microsystems - Beijing China 	hash ^= table[(256 * 1) + ((daddr >> 16) & 0xff)];
172404b6cca3Slucy wang - Sun Microsystems - Beijing China 	hash ^= table[(256 * 2) + ((daddr >> 8) & 0xff)];
172504b6cca3Slucy wang - Sun Microsystems - Beijing China 	hash ^= table[(256 * 3) + ((daddr) & 0xff)];
172604b6cca3Slucy wang - Sun Microsystems - Beijing China 	hash ^= table[(256 * 4) + ((saddr >> 24) & 0xff)];
172704b6cca3Slucy wang - Sun Microsystems - Beijing China 	hash ^= table[(256 * 5) + ((saddr >> 16) & 0xff)];
172804b6cca3Slucy wang - Sun Microsystems - Beijing China 	hash ^= table[(256 * 6) + ((saddr >> 8) & 0xff)];
172904b6cca3Slucy wang - Sun Microsystems - Beijing China 	hash ^= table[(256 * 7) + ((saddr) & 0xff)];
173004b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* hash on TCP port, if required */
173104b6cca3Slucy wang - Sun Microsystems - Beijing China 	if ((myri10ge_rss_hash & MXGEFW_RSS_HASH_TYPE_TCP_IPV4) &&
173204b6cca3Slucy wang - Sun Microsystems - Beijing China 	    ip->ip_p == IPPROTO_TCP) {
173304b6cca3Slucy wang - Sun Microsystems - Beijing China 		hdr = (struct tcphdr *)(void *)
173404b6cca3Slucy wang - Sun Microsystems - Beijing China 		    (((uint8_t *)ip) +  (ip->ip_hl << 2));
173504b6cca3Slucy wang - Sun Microsystems - Beijing China 		src = ntohs(hdr->th_sport);
173604b6cca3Slucy wang - Sun Microsystems - Beijing China 		dst = ntohs(hdr->th_dport);
173704b6cca3Slucy wang - Sun Microsystems - Beijing China 
173804b6cca3Slucy wang - Sun Microsystems - Beijing China 		hash ^= table[(256 * 8) + ((dst >> 8) & 0xff)];
173904b6cca3Slucy wang - Sun Microsystems - Beijing China 		hash ^= table[(256 * 9) + ((dst) & 0xff)];
174004b6cca3Slucy wang - Sun Microsystems - Beijing China 		hash ^= table[(256 * 10) + ((src >> 8) & 0xff)];
174104b6cca3Slucy wang - Sun Microsystems - Beijing China 		hash ^= table[(256 * 11) + ((src) & 0xff)];
174204b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
174304b6cca3Slucy wang - Sun Microsystems - Beijing China 	slice = (mgp->num_slices - 1) & hash;
174404b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (&mgp->ss[slice]);
174504b6cca3Slucy wang - Sun Microsystems - Beijing China 
174604b6cca3Slucy wang - Sun Microsystems - Beijing China }
174704b6cca3Slucy wang - Sun Microsystems - Beijing China 
174804b6cca3Slucy wang - Sun Microsystems - Beijing China static inline struct myri10ge_slice_state *
174904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_simple_send_hash(struct myri10ge_priv *mgp, struct ip *ip)
175004b6cca3Slucy wang - Sun Microsystems - Beijing China {
175104b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct tcphdr *hdr;
175204b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint32_t slice, hash_val;
175304b6cca3Slucy wang - Sun Microsystems - Beijing China 
175404b6cca3Slucy wang - Sun Microsystems - Beijing China 
175504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (ip->ip_p != IPPROTO_TCP && ip->ip_p != IPPROTO_UDP) {
175604b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (&mgp->ss[0]);
175704b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
175804b6cca3Slucy wang - Sun Microsystems - Beijing China 	hdr = (struct tcphdr *)(void *)(((uint8_t *)ip) +  (ip->ip_hl << 2));
175904b6cca3Slucy wang - Sun Microsystems - Beijing China 
176004b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
176104b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * Use the second byte of the *destination* address for
176204b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * MXGEFW_RSS_HASH_TYPE_SRC_PORT, so as to match NIC's hashing
176304b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
176404b6cca3Slucy wang - Sun Microsystems - Beijing China 	hash_val = ntohs(hdr->th_dport) & 0xff;
176504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (myri10ge_rss_hash == MXGEFW_RSS_HASH_TYPE_SRC_DST_PORT)
176604b6cca3Slucy wang - Sun Microsystems - Beijing China 		hash_val += ntohs(hdr->th_sport) & 0xff;
176704b6cca3Slucy wang - Sun Microsystems - Beijing China 
176804b6cca3Slucy wang - Sun Microsystems - Beijing China 	slice = (mgp->num_slices - 1) & hash_val;
176904b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (&mgp->ss[slice]);
177004b6cca3Slucy wang - Sun Microsystems - Beijing China }
177104b6cca3Slucy wang - Sun Microsystems - Beijing China 
177204b6cca3Slucy wang - Sun Microsystems - Beijing China static inline struct myri10ge_slice_state *
177304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_send_hash(struct myri10ge_priv *mgp, mblk_t *mp)
177404b6cca3Slucy wang - Sun Microsystems - Beijing China {
177504b6cca3Slucy wang - Sun Microsystems - Beijing China 	unsigned int slice = 0;
177604b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct ether_header *eh;
177704b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct ether_vlan_header *vh;
177804b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct ip *ip;
177904b6cca3Slucy wang - Sun Microsystems - Beijing China 	int ehl, ihl;
178004b6cca3Slucy wang - Sun Microsystems - Beijing China 
178104b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->num_slices == 1)
178204b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (&mgp->ss[0]);
178304b6cca3Slucy wang - Sun Microsystems - Beijing China 
178404b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (myri10ge_tx_hash == 0) {
178504b6cca3Slucy wang - Sun Microsystems - Beijing China 		slice = CPU->cpu_id & (mgp->num_slices - 1);
178604b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (&mgp->ss[slice]);
178704b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
178804b6cca3Slucy wang - Sun Microsystems - Beijing China 
178904b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
179004b6cca3Slucy wang - Sun Microsystems - Beijing China 	 *  ensure it is a TCP or UDP over IPv4 packet, and that the
179104b6cca3Slucy wang - Sun Microsystems - Beijing China 	 *  headers are in the 1st mblk.  Otherwise, punt
179204b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
179304b6cca3Slucy wang - Sun Microsystems - Beijing China 	ehl = sizeof (*eh);
179404b6cca3Slucy wang - Sun Microsystems - Beijing China 	ihl = sizeof (*ip);
179504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if ((MBLKL(mp)) <  (ehl + ihl + 8))
179604b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (&mgp->ss[0]);
179704b6cca3Slucy wang - Sun Microsystems - Beijing China 	eh = (struct ether_header *)(void *)mp->b_rptr;
179804b6cca3Slucy wang - Sun Microsystems - Beijing China 	ip = (struct ip *)(void *)(eh + 1);
179904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (eh->ether_type != BE_16(ETHERTYPE_IP)) {
180004b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (eh->ether_type != BE_16(ETHERTYPE_VLAN))
180104b6cca3Slucy wang - Sun Microsystems - Beijing China 			return (&mgp->ss[0]);
180204b6cca3Slucy wang - Sun Microsystems - Beijing China 		vh = (struct ether_vlan_header *)(void *)mp->b_rptr;
180304b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (vh->ether_type != BE_16(ETHERTYPE_IP))
180404b6cca3Slucy wang - Sun Microsystems - Beijing China 			return (&mgp->ss[0]);
180504b6cca3Slucy wang - Sun Microsystems - Beijing China 		ehl += 4;
180604b6cca3Slucy wang - Sun Microsystems - Beijing China 		ip = (struct ip *)(void *)(vh + 1);
180704b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
180804b6cca3Slucy wang - Sun Microsystems - Beijing China 	ihl = ip->ip_hl << 2;
180904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (MBLKL(mp) <  (ehl + ihl + 8))
181004b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (&mgp->ss[0]);
181104b6cca3Slucy wang - Sun Microsystems - Beijing China 	switch (myri10ge_rss_hash) {
181204b6cca3Slucy wang - Sun Microsystems - Beijing China 	case MXGEFW_RSS_HASH_TYPE_IPV4:
181304b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* fallthru */
181404b6cca3Slucy wang - Sun Microsystems - Beijing China 	case MXGEFW_RSS_HASH_TYPE_TCP_IPV4:
181504b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* fallthru */
181604b6cca3Slucy wang - Sun Microsystems - Beijing China 	case (MXGEFW_RSS_HASH_TYPE_IPV4|MXGEFW_RSS_HASH_TYPE_TCP_IPV4):
181704b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (myri10ge_toeplitz_send_hash(mgp, ip));
181804b6cca3Slucy wang - Sun Microsystems - Beijing China 	case MXGEFW_RSS_HASH_TYPE_SRC_PORT:
181904b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* fallthru */
182004b6cca3Slucy wang - Sun Microsystems - Beijing China 	case MXGEFW_RSS_HASH_TYPE_SRC_DST_PORT:
182104b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (myri10ge_simple_send_hash(mgp, ip));
182204b6cca3Slucy wang - Sun Microsystems - Beijing China 	default:
182304b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
182404b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
182504b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (&mgp->ss[0]);
182604b6cca3Slucy wang - Sun Microsystems - Beijing China }
182704b6cca3Slucy wang - Sun Microsystems - Beijing China 
182804b6cca3Slucy wang - Sun Microsystems - Beijing China static int
182904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_setup_slice(struct myri10ge_slice_state *ss)
183004b6cca3Slucy wang - Sun Microsystems - Beijing China {
183104b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp = ss->mgp;
183204b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_cmd_t cmd;
183304b6cca3Slucy wang - Sun Microsystems - Beijing China 	int tx_ring_size, rx_ring_size;
183404b6cca3Slucy wang - Sun Microsystems - Beijing China 	int tx_ring_entries, rx_ring_entries;
183504b6cca3Slucy wang - Sun Microsystems - Beijing China 	int slice, status;
183604b6cca3Slucy wang - Sun Microsystems - Beijing China 	int allocated, idx;
183704b6cca3Slucy wang - Sun Microsystems - Beijing China 	size_t bytes;
183804b6cca3Slucy wang - Sun Microsystems - Beijing China 
183904b6cca3Slucy wang - Sun Microsystems - Beijing China 	slice = ss - mgp->ss;
184004b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data0 = slice;
184104b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_RING_SIZE, &cmd);
184204b6cca3Slucy wang - Sun Microsystems - Beijing China 	tx_ring_size = cmd.data0;
184304b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data0 = slice;
184404b6cca3Slucy wang - Sun Microsystems - Beijing China 	status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_RX_RING_SIZE, &cmd);
184504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != 0)
184604b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (status);
184704b6cca3Slucy wang - Sun Microsystems - Beijing China 	rx_ring_size = cmd.data0;
184804b6cca3Slucy wang - Sun Microsystems - Beijing China 
184904b6cca3Slucy wang - Sun Microsystems - Beijing China 	tx_ring_entries = tx_ring_size / sizeof (struct mcp_kreq_ether_send);
185004b6cca3Slucy wang - Sun Microsystems - Beijing China 	rx_ring_entries = rx_ring_size / sizeof (struct mcp_dma_addr);
185104b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->tx.mask = tx_ring_entries - 1;
185204b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->rx_small.mask = ss->rx_big.mask = rx_ring_entries - 1;
185304b6cca3Slucy wang - Sun Microsystems - Beijing China 
185404b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* get the lanai pointers to the send and receive rings */
185504b6cca3Slucy wang - Sun Microsystems - Beijing China 
185604b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data0 = slice;
185704b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET, &cmd);
185804b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->tx.lanai = (mcp_kreq_ether_send_t *)(void *)(mgp->sram + cmd.data0);
185904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->num_slices > 1) {
186004b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->tx.go = (char *)mgp->sram + MXGEFW_ETH_SEND_GO + 64 * slice;
186104b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->tx.stop = (char *)mgp->sram + MXGEFW_ETH_SEND_STOP +
186204b6cca3Slucy wang - Sun Microsystems - Beijing China 		    64 * slice;
186304b6cca3Slucy wang - Sun Microsystems - Beijing China 	} else {
186404b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->tx.go = NULL;
186504b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->tx.stop = NULL;
186604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
186704b6cca3Slucy wang - Sun Microsystems - Beijing China 
186804b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data0 = slice;
186904b6cca3Slucy wang - Sun Microsystems - Beijing China 	status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SMALL_RX_OFFSET, &cmd);
187004b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->rx_small.lanai = (mcp_kreq_ether_recv_t *)
187104b6cca3Slucy wang - Sun Microsystems - Beijing China 	    (void *)(mgp->sram + cmd.data0);
187204b6cca3Slucy wang - Sun Microsystems - Beijing China 
187304b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data0 = slice;
187404b6cca3Slucy wang - Sun Microsystems - Beijing China 	status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_BIG_RX_OFFSET, &cmd);
187504b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->rx_big.lanai = (mcp_kreq_ether_recv_t *)(void *)
187604b6cca3Slucy wang - Sun Microsystems - Beijing China 	    (mgp->sram + cmd.data0);
187704b6cca3Slucy wang - Sun Microsystems - Beijing China 
187804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != 0) {
187904b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN,
188004b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "%s: failed to get ring sizes or locations\n", mgp->name);
188104b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (status);
188204b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
188304b6cca3Slucy wang - Sun Microsystems - Beijing China 
188404b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = ENOMEM;
188504b6cca3Slucy wang - Sun Microsystems - Beijing China 	bytes = rx_ring_entries * sizeof (*ss->rx_small.shadow);
188604b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->rx_small.shadow = kmem_zalloc(bytes, KM_SLEEP);
188704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (ss->rx_small.shadow == NULL)
188804b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort;
188904b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) memset(ss->rx_small.shadow, 0, bytes);
189004b6cca3Slucy wang - Sun Microsystems - Beijing China 
189104b6cca3Slucy wang - Sun Microsystems - Beijing China 	bytes = rx_ring_entries * sizeof (*ss->rx_big.shadow);
189204b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->rx_big.shadow = kmem_zalloc(bytes, KM_SLEEP);
189304b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (ss->rx_big.shadow == NULL)
189404b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_rx_small_shadow;
189504b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) memset(ss->rx_big.shadow, 0, bytes);
189604b6cca3Slucy wang - Sun Microsystems - Beijing China 
189704b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* allocate the host info rings */
189804b6cca3Slucy wang - Sun Microsystems - Beijing China 
189904b6cca3Slucy wang - Sun Microsystems - Beijing China 	bytes = tx_ring_entries * sizeof (*ss->tx.info);
190004b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->tx.info = kmem_zalloc(bytes, KM_SLEEP);
190104b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (ss->tx.info == NULL)
190204b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_rx_big_shadow;
190304b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) memset(ss->tx.info, 0, bytes);
190404b6cca3Slucy wang - Sun Microsystems - Beijing China 
190504b6cca3Slucy wang - Sun Microsystems - Beijing China 	bytes = rx_ring_entries * sizeof (*ss->rx_small.info);
190604b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->rx_small.info = kmem_zalloc(bytes, KM_SLEEP);
190704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (ss->rx_small.info == NULL)
190804b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_tx_info;
190904b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) memset(ss->rx_small.info, 0, bytes);
191004b6cca3Slucy wang - Sun Microsystems - Beijing China 
191104b6cca3Slucy wang - Sun Microsystems - Beijing China 	bytes = rx_ring_entries * sizeof (*ss->rx_big.info);
191204b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->rx_big.info = kmem_zalloc(bytes, KM_SLEEP);
191304b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (ss->rx_big.info == NULL)
191404b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_rx_small_info;
191504b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) memset(ss->rx_big.info, 0, bytes);
191604b6cca3Slucy wang - Sun Microsystems - Beijing China 
191704b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->tx.stall = ss->tx.sched = 0;
191804b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->tx.stall_early = ss->tx.stall_late = 0;
191904b6cca3Slucy wang - Sun Microsystems - Beijing China 
192004b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->jbufs_for_smalls = 1 + (1 + ss->rx_small.mask) /
192104b6cca3Slucy wang - Sun Microsystems - Beijing China 	    (myri10ge_mtu / (myri10ge_small_bytes + MXGEFW_PAD));
192204b6cca3Slucy wang - Sun Microsystems - Beijing China 
192304b6cca3Slucy wang - Sun Microsystems - Beijing China 	allocated = myri10ge_add_jbufs(ss,
192404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    myri10ge_bigbufs_initial + ss->jbufs_for_smalls, 1);
192504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (allocated < ss->jbufs_for_smalls + myri10ge_bigbufs_initial) {
192604b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN,
192704b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "%s: Could not allocate enough receive buffers (%d/%d)\n",
192804b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->name, allocated,
192904b6cca3Slucy wang - Sun Microsystems - Beijing China 		    myri10ge_bigbufs_initial + ss->jbufs_for_smalls);
193004b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_jumbos;
193104b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
193204b6cca3Slucy wang - Sun Microsystems - Beijing China 
193304b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_carve_up_jbufs_into_small_ring(ss);
193404b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->j_rx_cnt = 0;
193504b6cca3Slucy wang - Sun Microsystems - Beijing China 
193604b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&ss->jpool.mtx);
193704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (allocated < rx_ring_entries)
193804b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->jpool.low_water = allocated / 4;
193904b6cca3Slucy wang - Sun Microsystems - Beijing China 	else
194004b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->jpool.low_water = rx_ring_entries / 2;
194104b6cca3Slucy wang - Sun Microsystems - Beijing China 
194204b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
194304b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * invalidate the big receive ring in case we do not
194404b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * allocate sufficient jumbos to fill it
194504b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
194604b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) memset(ss->rx_big.shadow, 1,
194704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    (ss->rx_big.mask + 1) * sizeof (ss->rx_big.shadow[0]));
194804b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (idx = 7; idx <= ss->rx_big.mask; idx += 8) {
194904b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_submit_8rx(&ss->rx_big.lanai[idx - 7],
195004b6cca3Slucy wang - Sun Microsystems - Beijing China 		    &ss->rx_big.shadow[idx - 7]);
195104b6cca3Slucy wang - Sun Microsystems - Beijing China 		mb();
195204b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
195304b6cca3Slucy wang - Sun Microsystems - Beijing China 
195404b6cca3Slucy wang - Sun Microsystems - Beijing China 
195504b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_restock_jumbos(ss);
195604b6cca3Slucy wang - Sun Microsystems - Beijing China 
195704b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (idx = 7; idx <= ss->rx_small.mask; idx += 8) {
195804b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_submit_8rx(&ss->rx_small.lanai[idx - 7],
195904b6cca3Slucy wang - Sun Microsystems - Beijing China 		    &ss->rx_small.shadow[idx - 7]);
196004b6cca3Slucy wang - Sun Microsystems - Beijing China 		mb();
196104b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
196204b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->rx_small.cnt = ss->rx_small.mask + 1;
196304b6cca3Slucy wang - Sun Microsystems - Beijing China 
196404b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&ss->jpool.mtx);
196504b6cca3Slucy wang - Sun Microsystems - Beijing China 
196604b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_prepare_tx_ring(ss);
196704b6cca3Slucy wang - Sun Microsystems - Beijing China 
196804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != 0)
196904b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_small_jbufs;
197004b6cca3Slucy wang - Sun Microsystems - Beijing China 
197104b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data0 = ntohl(ss->fw_stats_dma.low);
197204b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data1 = ntohl(ss->fw_stats_dma.high);
197304b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data2 = sizeof (mcp_irq_data_t);
197404b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data2 |= (slice << 16);
197504b6cca3Slucy wang - Sun Microsystems - Beijing China 	bzero(ss->fw_stats, sizeof (*ss->fw_stats));
197604b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_STATS_DMA_V2, &cmd);
197704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status == ENOSYS) {
197804b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmd.data0 = ntohl(ss->fw_stats_dma.low) +
197904b6cca3Slucy wang - Sun Microsystems - Beijing China 		    offsetof(mcp_irq_data_t, send_done_count);
198004b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmd.data1 = ntohl(ss->fw_stats_dma.high);
198104b6cca3Slucy wang - Sun Microsystems - Beijing China 		status = myri10ge_send_cmd(mgp,
198204b6cca3Slucy wang - Sun Microsystems - Beijing China 		    MXGEFW_CMD_SET_STATS_DMA_OBSOLETE, &cmd);
198304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
198404b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status) {
198504b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: Couldn't set stats DMA\n", mgp->name);
198604b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_tx;
198704b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
198804b6cca3Slucy wang - Sun Microsystems - Beijing China 
198904b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
199004b6cca3Slucy wang - Sun Microsystems - Beijing China 
199104b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_tx:
199204b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_unprepare_tx_ring(ss);
199304b6cca3Slucy wang - Sun Microsystems - Beijing China 
199404b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_small_jbufs:
199504b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_release_small_jbufs(ss);
199604b6cca3Slucy wang - Sun Microsystems - Beijing China 
199704b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_jumbos:
199804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (allocated != 0) {
199904b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_enter(&ss->jpool.mtx);
200004b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->jpool.low_water = 0;
200104b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_exit(&ss->jpool.mtx);
200204b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_unstock_jumbos(ss);
200304b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_remove_jbufs(ss);
200404b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
200504b6cca3Slucy wang - Sun Microsystems - Beijing China 
200604b6cca3Slucy wang - Sun Microsystems - Beijing China 	bytes = rx_ring_entries * sizeof (*ss->rx_big.info);
200704b6cca3Slucy wang - Sun Microsystems - Beijing China 	kmem_free(ss->rx_big.info, bytes);
200804b6cca3Slucy wang - Sun Microsystems - Beijing China 
200904b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_rx_small_info:
201004b6cca3Slucy wang - Sun Microsystems - Beijing China 	bytes = rx_ring_entries * sizeof (*ss->rx_small.info);
201104b6cca3Slucy wang - Sun Microsystems - Beijing China 	kmem_free(ss->rx_small.info, bytes);
201204b6cca3Slucy wang - Sun Microsystems - Beijing China 
201304b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_tx_info:
201404b6cca3Slucy wang - Sun Microsystems - Beijing China 	bytes = tx_ring_entries * sizeof (*ss->tx.info);
201504b6cca3Slucy wang - Sun Microsystems - Beijing China 	kmem_free(ss->tx.info, bytes);
201604b6cca3Slucy wang - Sun Microsystems - Beijing China 
201704b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_rx_big_shadow:
201804b6cca3Slucy wang - Sun Microsystems - Beijing China 	bytes = rx_ring_entries * sizeof (*ss->rx_big.shadow);
201904b6cca3Slucy wang - Sun Microsystems - Beijing China 	kmem_free(ss->rx_big.shadow, bytes);
202004b6cca3Slucy wang - Sun Microsystems - Beijing China 
202104b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_rx_small_shadow:
202204b6cca3Slucy wang - Sun Microsystems - Beijing China 	bytes = rx_ring_entries * sizeof (*ss->rx_small.shadow);
202304b6cca3Slucy wang - Sun Microsystems - Beijing China 	kmem_free(ss->rx_small.shadow, bytes);
202404b6cca3Slucy wang - Sun Microsystems - Beijing China abort:
202504b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (status);
202604b6cca3Slucy wang - Sun Microsystems - Beijing China 
202704b6cca3Slucy wang - Sun Microsystems - Beijing China }
202804b6cca3Slucy wang - Sun Microsystems - Beijing China 
202904b6cca3Slucy wang - Sun Microsystems - Beijing China static void
203004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_teardown_slice(struct myri10ge_slice_state *ss)
203104b6cca3Slucy wang - Sun Microsystems - Beijing China {
203204b6cca3Slucy wang - Sun Microsystems - Beijing China 	int tx_ring_entries, rx_ring_entries;
203304b6cca3Slucy wang - Sun Microsystems - Beijing China 	size_t bytes;
203404b6cca3Slucy wang - Sun Microsystems - Beijing China 
203504b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* ignore slices that have not been fully setup */
203604b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (ss->tx.cp == NULL)
203704b6cca3Slucy wang - Sun Microsystems - Beijing China 		return;
203804b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* Free the TX copy buffers */
203904b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_unprepare_tx_ring(ss);
204004b6cca3Slucy wang - Sun Microsystems - Beijing China 
204104b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* stop passing returned buffers to firmware */
204204b6cca3Slucy wang - Sun Microsystems - Beijing China 
204304b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&ss->jpool.mtx);
204404b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->jpool.low_water = 0;
204504b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&ss->jpool.mtx);
204604b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_release_small_jbufs(ss);
204704b6cca3Slucy wang - Sun Microsystems - Beijing China 
204804b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* Release the free jumbo frame pool */
204904b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_unstock_jumbos(ss);
205004b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_remove_jbufs(ss);
205104b6cca3Slucy wang - Sun Microsystems - Beijing China 
205204b6cca3Slucy wang - Sun Microsystems - Beijing China 	rx_ring_entries = ss->rx_big.mask + 1;
205304b6cca3Slucy wang - Sun Microsystems - Beijing China 	tx_ring_entries = ss->tx.mask + 1;
205404b6cca3Slucy wang - Sun Microsystems - Beijing China 
205504b6cca3Slucy wang - Sun Microsystems - Beijing China 	bytes = rx_ring_entries * sizeof (*ss->rx_big.info);
205604b6cca3Slucy wang - Sun Microsystems - Beijing China 	kmem_free(ss->rx_big.info, bytes);
205704b6cca3Slucy wang - Sun Microsystems - Beijing China 
205804b6cca3Slucy wang - Sun Microsystems - Beijing China 	bytes = rx_ring_entries * sizeof (*ss->rx_small.info);
205904b6cca3Slucy wang - Sun Microsystems - Beijing China 	kmem_free(ss->rx_small.info, bytes);
206004b6cca3Slucy wang - Sun Microsystems - Beijing China 
206104b6cca3Slucy wang - Sun Microsystems - Beijing China 	bytes = tx_ring_entries * sizeof (*ss->tx.info);
206204b6cca3Slucy wang - Sun Microsystems - Beijing China 	kmem_free(ss->tx.info, bytes);
206304b6cca3Slucy wang - Sun Microsystems - Beijing China 
206404b6cca3Slucy wang - Sun Microsystems - Beijing China 	bytes = rx_ring_entries * sizeof (*ss->rx_big.shadow);
206504b6cca3Slucy wang - Sun Microsystems - Beijing China 	kmem_free(ss->rx_big.shadow, bytes);
206604b6cca3Slucy wang - Sun Microsystems - Beijing China 
206704b6cca3Slucy wang - Sun Microsystems - Beijing China 	bytes = rx_ring_entries * sizeof (*ss->rx_small.shadow);
206804b6cca3Slucy wang - Sun Microsystems - Beijing China 	kmem_free(ss->rx_small.shadow, bytes);
206904b6cca3Slucy wang - Sun Microsystems - Beijing China 
207004b6cca3Slucy wang - Sun Microsystems - Beijing China }
207104b6cca3Slucy wang - Sun Microsystems - Beijing China static int
207204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_start_locked(struct myri10ge_priv *mgp)
207304b6cca3Slucy wang - Sun Microsystems - Beijing China {
207404b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_cmd_t cmd;
207504b6cca3Slucy wang - Sun Microsystems - Beijing China 	int status, big_pow2, i;
207604b6cca3Slucy wang - Sun Microsystems - Beijing China 	volatile uint8_t *itable;
207704b6cca3Slucy wang - Sun Microsystems - Beijing China 
207804b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = DDI_SUCCESS;
207904b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* Allocate DMA resources and receive buffers */
208004b6cca3Slucy wang - Sun Microsystems - Beijing China 
208104b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_reset(mgp);
208204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != 0) {
208304b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: failed reset\n", mgp->name);
208404b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
208504b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
208604b6cca3Slucy wang - Sun Microsystems - Beijing China 
208704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->num_slices > 1) {
208804b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmd.data0 = mgp->num_slices;
208904b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmd.data1 = 1; /* use MSI-X */
209004b6cca3Slucy wang - Sun Microsystems - Beijing China 		status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ENABLE_RSS_QUEUES,
209104b6cca3Slucy wang - Sun Microsystems - Beijing China 		    &cmd);
209204b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (status != 0) {
209304b6cca3Slucy wang - Sun Microsystems - Beijing China 			cmn_err(CE_WARN,
209404b6cca3Slucy wang - Sun Microsystems - Beijing China 			    "%s: failed to set number of slices\n",
209504b6cca3Slucy wang - Sun Microsystems - Beijing China 			    mgp->name);
209604b6cca3Slucy wang - Sun Microsystems - Beijing China 			goto abort_with_nothing;
209704b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
209804b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* setup the indirection table */
209904b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmd.data0 = mgp->num_slices;
210004b6cca3Slucy wang - Sun Microsystems - Beijing China 		status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_RSS_TABLE_SIZE,
210104b6cca3Slucy wang - Sun Microsystems - Beijing China 		    &cmd);
210204b6cca3Slucy wang - Sun Microsystems - Beijing China 
210304b6cca3Slucy wang - Sun Microsystems - Beijing China 		status |= myri10ge_send_cmd(mgp,
210404b6cca3Slucy wang - Sun Microsystems - Beijing China 		    MXGEFW_CMD_GET_RSS_TABLE_OFFSET, &cmd);
210504b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (status != 0) {
210604b6cca3Slucy wang - Sun Microsystems - Beijing China 			cmn_err(CE_WARN,
210704b6cca3Slucy wang - Sun Microsystems - Beijing China 			    "%s: failed to setup rss tables\n", mgp->name);
210804b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
210904b6cca3Slucy wang - Sun Microsystems - Beijing China 
211004b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* just enable an identity mapping */
211104b6cca3Slucy wang - Sun Microsystems - Beijing China 		itable = mgp->sram + cmd.data0;
211204b6cca3Slucy wang - Sun Microsystems - Beijing China 		for (i = 0; i < mgp->num_slices; i++)
211304b6cca3Slucy wang - Sun Microsystems - Beijing China 			itable[i] = (uint8_t)i;
211404b6cca3Slucy wang - Sun Microsystems - Beijing China 
211504b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (myri10ge_rss_hash & MYRI10GE_TOEPLITZ_HASH) {
211604b6cca3Slucy wang - Sun Microsystems - Beijing China 			status = myri10ge_init_toeplitz(mgp);
211704b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (status != 0) {
211804b6cca3Slucy wang - Sun Microsystems - Beijing China 				cmn_err(CE_WARN, "%s: failed to setup "
211904b6cca3Slucy wang - Sun Microsystems - Beijing China 				    "toeplitz tx hash table", mgp->name);
212004b6cca3Slucy wang - Sun Microsystems - Beijing China 				goto abort_with_nothing;
212104b6cca3Slucy wang - Sun Microsystems - Beijing China 			}
212204b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
212304b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmd.data0 = 1;
212404b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmd.data1 = myri10ge_rss_hash;
212504b6cca3Slucy wang - Sun Microsystems - Beijing China 		status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_RSS_ENABLE,
212604b6cca3Slucy wang - Sun Microsystems - Beijing China 		    &cmd);
212704b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (status != 0) {
212804b6cca3Slucy wang - Sun Microsystems - Beijing China 			cmn_err(CE_WARN,
212904b6cca3Slucy wang - Sun Microsystems - Beijing China 			    "%s: failed to enable slices\n", mgp->name);
213004b6cca3Slucy wang - Sun Microsystems - Beijing China 			goto abort_with_toeplitz;
213104b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
213204b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
213304b6cca3Slucy wang - Sun Microsystems - Beijing China 
213404b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (i = 0; i < mgp->num_slices; i++) {
213504b6cca3Slucy wang - Sun Microsystems - Beijing China 		status = myri10ge_setup_slice(&mgp->ss[i]);
213604b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (status != 0)
213704b6cca3Slucy wang - Sun Microsystems - Beijing China 			goto abort_with_slices;
213804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
213904b6cca3Slucy wang - Sun Microsystems - Beijing China 
214004b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
214104b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * Tell the MCP how many buffers he has, and to
214204b6cca3Slucy wang - Sun Microsystems - Beijing China 	 *  bring the ethernet interface up
214304b6cca3Slucy wang - Sun Microsystems - Beijing China 	 *
214404b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * Firmware needs the big buff size as a power of 2.  Lie and
214504b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * tell him the buffer is larger, because we only use 1
214604b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * buffer/pkt, and the mtu will prevent overruns
214704b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
214804b6cca3Slucy wang - Sun Microsystems - Beijing China 	big_pow2 = myri10ge_mtu + MXGEFW_PAD;
2149de710d24SJosef 'Jeff' Sipek 	while (!ISP2(big_pow2))
215004b6cca3Slucy wang - Sun Microsystems - Beijing China 		big_pow2++;
215104b6cca3Slucy wang - Sun Microsystems - Beijing China 
215204b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* now give firmware buffers sizes, and MTU */
215304b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data0 = myri10ge_mtu;
215404b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_MTU, &cmd);
215504b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data0 = myri10ge_small_bytes;
215604b6cca3Slucy wang - Sun Microsystems - Beijing China 	status |=
215704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_SMALL_BUFFER_SIZE, &cmd);
215804b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data0 = big_pow2;
215904b6cca3Slucy wang - Sun Microsystems - Beijing China 	status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_BIG_BUFFER_SIZE, &cmd);
216004b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status) {
216104b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: Couldn't set buffer sizes\n", mgp->name);
216204b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_slices;
216304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
216404b6cca3Slucy wang - Sun Microsystems - Beijing China 
216504b6cca3Slucy wang - Sun Microsystems - Beijing China 
216604b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data0 = 1;
216704b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_TSO_MODE, &cmd);
216804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status) {
216904b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: unable to setup TSO (%d)\n",
217004b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->name, status);
217104b6cca3Slucy wang - Sun Microsystems - Beijing China 	} else {
217204b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->features |= MYRI10GE_TSO;
217304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
217404b6cca3Slucy wang - Sun Microsystems - Beijing China 
217504b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->link_state = -1;
217604b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->rdma_tags_available = 15;
217704b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_UP, &cmd);
217804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status) {
217904b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: unable to start ethernet\n", mgp->name);
218004b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_slices;
218104b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
218204b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->running = MYRI10GE_ETH_RUNNING;
218304b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
218404b6cca3Slucy wang - Sun Microsystems - Beijing China 
218504b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_slices:
218604b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (i = 0; i < mgp->num_slices; i++)
218704b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_teardown_slice(&mgp->ss[i]);
218804b6cca3Slucy wang - Sun Microsystems - Beijing China 
218904b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->running = MYRI10GE_ETH_STOPPED;
219004b6cca3Slucy wang - Sun Microsystems - Beijing China 
219104b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_toeplitz:
219204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->toeplitz_hash_table != NULL) {
219304b6cca3Slucy wang - Sun Microsystems - Beijing China 		kmem_free(mgp->toeplitz_hash_table,
219404b6cca3Slucy wang - Sun Microsystems - Beijing China 		    sizeof (uint32_t) * 12 * 256);
219504b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->toeplitz_hash_table = NULL;
219604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
219704b6cca3Slucy wang - Sun Microsystems - Beijing China 
219804b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_nothing:
219904b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (DDI_FAILURE);
220004b6cca3Slucy wang - Sun Microsystems - Beijing China }
220104b6cca3Slucy wang - Sun Microsystems - Beijing China 
220204b6cca3Slucy wang - Sun Microsystems - Beijing China static void
220304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_stop_locked(struct myri10ge_priv *mgp)
220404b6cca3Slucy wang - Sun Microsystems - Beijing China {
220504b6cca3Slucy wang - Sun Microsystems - Beijing China 	int status, old_down_cnt;
220604b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_cmd_t cmd;
220704b6cca3Slucy wang - Sun Microsystems - Beijing China 	int wait_time = 10;
220804b6cca3Slucy wang - Sun Microsystems - Beijing China 	int i, polling;
220904b6cca3Slucy wang - Sun Microsystems - Beijing China 
221004b6cca3Slucy wang - Sun Microsystems - Beijing China 	old_down_cnt = mgp->down_cnt;
221104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mb();
221204b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_DOWN, &cmd);
221304b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status) {
221404b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: Couldn't bring down link\n", mgp->name);
221504b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
221604b6cca3Slucy wang - Sun Microsystems - Beijing China 
221704b6cca3Slucy wang - Sun Microsystems - Beijing China 	while (old_down_cnt == *((volatile int *)&mgp->down_cnt)) {
221804b6cca3Slucy wang - Sun Microsystems - Beijing China 		delay(1 * drv_usectohz(1000000));
221904b6cca3Slucy wang - Sun Microsystems - Beijing China 		wait_time--;
222004b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (wait_time == 0)
222104b6cca3Slucy wang - Sun Microsystems - Beijing China 			break;
222204b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
222304b6cca3Slucy wang - Sun Microsystems - Beijing China again:
222404b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (old_down_cnt == *((volatile int *)&mgp->down_cnt)) {
222504b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: didn't get down irq\n", mgp->name);
222604b6cca3Slucy wang - Sun Microsystems - Beijing China 		for (i = 0; i < mgp->num_slices; i++) {
222704b6cca3Slucy wang - Sun Microsystems - Beijing China 			/*
222804b6cca3Slucy wang - Sun Microsystems - Beijing China 			 * take and release the rx lock to ensure
222904b6cca3Slucy wang - Sun Microsystems - Beijing China 			 * that no interrupt thread is blocked
223004b6cca3Slucy wang - Sun Microsystems - Beijing China 			 * elsewhere in the stack, preventing
223104b6cca3Slucy wang - Sun Microsystems - Beijing China 			 * completion
223204b6cca3Slucy wang - Sun Microsystems - Beijing China 			 */
223304b6cca3Slucy wang - Sun Microsystems - Beijing China 
223404b6cca3Slucy wang - Sun Microsystems - Beijing China 			mutex_enter(&mgp->ss[i].rx_lock);
223504b6cca3Slucy wang - Sun Microsystems - Beijing China 			printf("%s: slice %d rx irq idle\n",
223604b6cca3Slucy wang - Sun Microsystems - Beijing China 			    mgp->name, i);
223704b6cca3Slucy wang - Sun Microsystems - Beijing China 			mutex_exit(&mgp->ss[i].rx_lock);
223804b6cca3Slucy wang - Sun Microsystems - Beijing China 
223904b6cca3Slucy wang - Sun Microsystems - Beijing China 			/* verify that the poll handler is inactive */
224004b6cca3Slucy wang - Sun Microsystems - Beijing China 			mutex_enter(&mgp->ss->poll_lock);
224104b6cca3Slucy wang - Sun Microsystems - Beijing China 			polling = mgp->ss->rx_polling;
224204b6cca3Slucy wang - Sun Microsystems - Beijing China 			mutex_exit(&mgp->ss->poll_lock);
224304b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (polling) {
224404b6cca3Slucy wang - Sun Microsystems - Beijing China 				printf("%s: slice %d is polling\n",
224504b6cca3Slucy wang - Sun Microsystems - Beijing China 				    mgp->name, i);
224604b6cca3Slucy wang - Sun Microsystems - Beijing China 				delay(1 * drv_usectohz(1000000));
224704b6cca3Slucy wang - Sun Microsystems - Beijing China 				goto again;
224804b6cca3Slucy wang - Sun Microsystems - Beijing China 			}
224904b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
225004b6cca3Slucy wang - Sun Microsystems - Beijing China 		delay(1 * drv_usectohz(1000000));
225104b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (old_down_cnt == *((volatile int *)&mgp->down_cnt)) {
225204b6cca3Slucy wang - Sun Microsystems - Beijing China 			cmn_err(CE_WARN, "%s: Never got down irq\n", mgp->name);
225304b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
225404b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
225504b6cca3Slucy wang - Sun Microsystems - Beijing China 
225604b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (i = 0; i < mgp->num_slices; i++)
225704b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_teardown_slice(&mgp->ss[i]);
225804b6cca3Slucy wang - Sun Microsystems - Beijing China 
225904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->toeplitz_hash_table != NULL) {
226004b6cca3Slucy wang - Sun Microsystems - Beijing China 		kmem_free(mgp->toeplitz_hash_table,
226104b6cca3Slucy wang - Sun Microsystems - Beijing China 		    sizeof (uint32_t) * 12 * 256);
226204b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->toeplitz_hash_table = NULL;
226304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
226404b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->running = MYRI10GE_ETH_STOPPED;
226504b6cca3Slucy wang - Sun Microsystems - Beijing China }
226604b6cca3Slucy wang - Sun Microsystems - Beijing China 
226704b6cca3Slucy wang - Sun Microsystems - Beijing China static int
226804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_m_start(void *arg)
226904b6cca3Slucy wang - Sun Microsystems - Beijing China {
227004b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp = arg;
227104b6cca3Slucy wang - Sun Microsystems - Beijing China 	int status;
227204b6cca3Slucy wang - Sun Microsystems - Beijing China 
227304b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&mgp->intrlock);
227404b6cca3Slucy wang - Sun Microsystems - Beijing China 
227504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->running != MYRI10GE_ETH_STOPPED) {
227604b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_exit(&mgp->intrlock);
227704b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
227804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
227904b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_start_locked(mgp);
228004b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&mgp->intrlock);
228104b6cca3Slucy wang - Sun Microsystems - Beijing China 
228204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != DDI_SUCCESS)
228304b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (status);
228404b6cca3Slucy wang - Sun Microsystems - Beijing China 
228504b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* start the watchdog timer */
228604b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->timer_id = timeout(myri10ge_watchdog, mgp,
228704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    mgp->timer_ticks);
228804b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
228904b6cca3Slucy wang - Sun Microsystems - Beijing China 
229004b6cca3Slucy wang - Sun Microsystems - Beijing China }
229104b6cca3Slucy wang - Sun Microsystems - Beijing China 
229204b6cca3Slucy wang - Sun Microsystems - Beijing China static void
229304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_m_stop(void *arg)
229404b6cca3Slucy wang - Sun Microsystems - Beijing China {
229504b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp = arg;
229604b6cca3Slucy wang - Sun Microsystems - Beijing China 
229704b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&mgp->intrlock);
229804b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* if the device not running give up */
229904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->running != MYRI10GE_ETH_RUNNING) {
230004b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_exit(&mgp->intrlock);
230104b6cca3Slucy wang - Sun Microsystems - Beijing China 		return;
230204b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
230304b6cca3Slucy wang - Sun Microsystems - Beijing China 
230404b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->running = MYRI10GE_ETH_STOPPING;
230504b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&mgp->intrlock);
230604b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) untimeout(mgp->timer_id);
230704b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&mgp->intrlock);
230804b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_stop_locked(mgp);
230904b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&mgp->intrlock);
231004b6cca3Slucy wang - Sun Microsystems - Beijing China 
231104b6cca3Slucy wang - Sun Microsystems - Beijing China }
231204b6cca3Slucy wang - Sun Microsystems - Beijing China 
231304b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void
231404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rx_csum(mblk_t *mp, struct myri10ge_rx_ring_stats *s, uint32_t csum)
231504b6cca3Slucy wang - Sun Microsystems - Beijing China {
231604b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct ether_header *eh;
231704b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct ip *ip;
231804b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct ip6_hdr *ip6;
231904b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint32_t start, stuff, end, partial, hdrlen;
232004b6cca3Slucy wang - Sun Microsystems - Beijing China 
232104b6cca3Slucy wang - Sun Microsystems - Beijing China 
232204b6cca3Slucy wang - Sun Microsystems - Beijing China 	csum = ntohs((uint16_t)csum);
232304b6cca3Slucy wang - Sun Microsystems - Beijing China 	eh = (struct ether_header *)(void *)mp->b_rptr;
232404b6cca3Slucy wang - Sun Microsystems - Beijing China 	hdrlen = sizeof (*eh);
232504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (eh->ether_dhost.ether_addr_octet[0] & 1) {
232604b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (0 == (bcmp(eh->ether_dhost.ether_addr_octet,
232704b6cca3Slucy wang - Sun Microsystems - Beijing China 		    myri10ge_broadcastaddr, sizeof (eh->ether_dhost))))
232804b6cca3Slucy wang - Sun Microsystems - Beijing China 			s->brdcstrcv++;
232904b6cca3Slucy wang - Sun Microsystems - Beijing China 		else
233004b6cca3Slucy wang - Sun Microsystems - Beijing China 			s->multircv++;
233104b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
233204b6cca3Slucy wang - Sun Microsystems - Beijing China 
233304b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (eh->ether_type == BE_16(ETHERTYPE_VLAN)) {
233404b6cca3Slucy wang - Sun Microsystems - Beijing China 		/*
233504b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * fix checksum by subtracting 4 bytes after what the
233604b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * firmware thought was the end of the ether hdr
233704b6cca3Slucy wang - Sun Microsystems - Beijing China 		 */
233804b6cca3Slucy wang - Sun Microsystems - Beijing China 		partial = *(uint32_t *)
233904b6cca3Slucy wang - Sun Microsystems - Beijing China 		    (void *)(mp->b_rptr + ETHERNET_HEADER_SIZE);
234004b6cca3Slucy wang - Sun Microsystems - Beijing China 		csum += ~partial;
234104b6cca3Slucy wang - Sun Microsystems - Beijing China 		csum +=  (csum < ~partial);
234204b6cca3Slucy wang - Sun Microsystems - Beijing China 		csum = (csum >> 16) + (csum & 0xFFFF);
234304b6cca3Slucy wang - Sun Microsystems - Beijing China 		csum = (csum >> 16) + (csum & 0xFFFF);
234404b6cca3Slucy wang - Sun Microsystems - Beijing China 		hdrlen += VLAN_TAGSZ;
234504b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
234604b6cca3Slucy wang - Sun Microsystems - Beijing China 
234704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (eh->ether_type ==  BE_16(ETHERTYPE_IP)) {
234804b6cca3Slucy wang - Sun Microsystems - Beijing China 		ip = (struct ip *)(void *)(mp->b_rptr + hdrlen);
234904b6cca3Slucy wang - Sun Microsystems - Beijing China 		start = ip->ip_hl << 2;
235004b6cca3Slucy wang - Sun Microsystems - Beijing China 
235104b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (ip->ip_p == IPPROTO_TCP)
235204b6cca3Slucy wang - Sun Microsystems - Beijing China 			stuff = start + offsetof(struct tcphdr, th_sum);
235304b6cca3Slucy wang - Sun Microsystems - Beijing China 		else if (ip->ip_p == IPPROTO_UDP)
235404b6cca3Slucy wang - Sun Microsystems - Beijing China 			stuff = start + offsetof(struct udphdr, uh_sum);
235504b6cca3Slucy wang - Sun Microsystems - Beijing China 		else
235604b6cca3Slucy wang - Sun Microsystems - Beijing China 			return;
235704b6cca3Slucy wang - Sun Microsystems - Beijing China 		end = ntohs(ip->ip_len);
235804b6cca3Slucy wang - Sun Microsystems - Beijing China 	} else if (eh->ether_type ==  BE_16(ETHERTYPE_IPV6)) {
235904b6cca3Slucy wang - Sun Microsystems - Beijing China 		ip6 = (struct ip6_hdr *)(void *)(mp->b_rptr + hdrlen);
236004b6cca3Slucy wang - Sun Microsystems - Beijing China 		start = sizeof (*ip6);
236104b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (ip6->ip6_nxt == IPPROTO_TCP) {
236204b6cca3Slucy wang - Sun Microsystems - Beijing China 			stuff = start + offsetof(struct tcphdr, th_sum);
236304b6cca3Slucy wang - Sun Microsystems - Beijing China 		} else if (ip6->ip6_nxt == IPPROTO_UDP)
236404b6cca3Slucy wang - Sun Microsystems - Beijing China 			stuff = start + offsetof(struct udphdr, uh_sum);
236504b6cca3Slucy wang - Sun Microsystems - Beijing China 		else
236604b6cca3Slucy wang - Sun Microsystems - Beijing China 			return;
236704b6cca3Slucy wang - Sun Microsystems - Beijing China 		end = start + ntohs(ip6->ip6_plen);
236804b6cca3Slucy wang - Sun Microsystems - Beijing China 		/*
236904b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * IPv6 headers do not contain a checksum, and hence
237004b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * do not checksum to zero, so they don't "fall out"
237104b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * of the partial checksum calculation like IPv4
237204b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * headers do.  We need to fix the partial checksum by
237304b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * subtracting the checksum of the IPv6 header.
237404b6cca3Slucy wang - Sun Microsystems - Beijing China 		 */
237504b6cca3Slucy wang - Sun Microsystems - Beijing China 
237604b6cca3Slucy wang - Sun Microsystems - Beijing China 		partial = myri10ge_csum_generic((uint16_t *)ip6, sizeof (*ip6));
237704b6cca3Slucy wang - Sun Microsystems - Beijing China 		csum += ~partial;
237804b6cca3Slucy wang - Sun Microsystems - Beijing China 		csum +=  (csum < ~partial);
237904b6cca3Slucy wang - Sun Microsystems - Beijing China 		csum = (csum >> 16) + (csum & 0xFFFF);
238004b6cca3Slucy wang - Sun Microsystems - Beijing China 		csum = (csum >> 16) + (csum & 0xFFFF);
238104b6cca3Slucy wang - Sun Microsystems - Beijing China 	} else {
238204b6cca3Slucy wang - Sun Microsystems - Beijing China 		return;
238304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
238404b6cca3Slucy wang - Sun Microsystems - Beijing China 
238504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (MBLKL(mp) > hdrlen + end) {
238604b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* padded frame, so hw csum may be invalid */
238704b6cca3Slucy wang - Sun Microsystems - Beijing China 		return;
238804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
238904b6cca3Slucy wang - Sun Microsystems - Beijing China 
23900dc2366fSVenugopal Iyer 	mac_hcksum_set(mp, start, stuff, end, csum, HCK_PARTIALCKSUM);
239104b6cca3Slucy wang - Sun Microsystems - Beijing China }
239204b6cca3Slucy wang - Sun Microsystems - Beijing China 
239304b6cca3Slucy wang - Sun Microsystems - Beijing China static mblk_t *
239404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rx_done_small(struct myri10ge_slice_state *ss, uint32_t len,
239504b6cca3Slucy wang - Sun Microsystems - Beijing China     uint32_t csum)
239604b6cca3Slucy wang - Sun Microsystems - Beijing China {
239704b6cca3Slucy wang - Sun Microsystems - Beijing China 	mblk_t *mp;
239804b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_rx_ring_t *rx;
239904b6cca3Slucy wang - Sun Microsystems - Beijing China 	int idx;
240004b6cca3Slucy wang - Sun Microsystems - Beijing China 
240104b6cca3Slucy wang - Sun Microsystems - Beijing China 	rx = &ss->rx_small;
240204b6cca3Slucy wang - Sun Microsystems - Beijing China 	idx = rx->cnt & rx->mask;
240304b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->rx_small.cnt++;
240404b6cca3Slucy wang - Sun Microsystems - Beijing China 
240504b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* allocate a new buffer to pass up the stack */
240604b6cca3Slucy wang - Sun Microsystems - Beijing China 	mp = allocb(len + MXGEFW_PAD, 0);
240704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mp == NULL) {
240804b6cca3Slucy wang - Sun Microsystems - Beijing China 		MYRI10GE_ATOMIC_SLICE_STAT_INC(rx_small_nobuf);
240904b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort;
241004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
241104b6cca3Slucy wang - Sun Microsystems - Beijing China 	bcopy(ss->rx_small.info[idx].ptr,
241204b6cca3Slucy wang - Sun Microsystems - Beijing China 	    (caddr_t)mp->b_wptr, len + MXGEFW_PAD);
241304b6cca3Slucy wang - Sun Microsystems - Beijing China 	mp->b_wptr += len + MXGEFW_PAD;
241404b6cca3Slucy wang - Sun Microsystems - Beijing China 	mp->b_rptr += MXGEFW_PAD;
241504b6cca3Slucy wang - Sun Microsystems - Beijing China 
241604b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->rx_stats.ibytes += len;
241704b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->rx_stats.ipackets += 1;
241804b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_rx_csum(mp, &ss->rx_stats, csum);
241904b6cca3Slucy wang - Sun Microsystems - Beijing China 
242004b6cca3Slucy wang - Sun Microsystems - Beijing China abort:
242104b6cca3Slucy wang - Sun Microsystems - Beijing China 	if ((idx & 7) == 7) {
242204b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_submit_8rx(&rx->lanai[idx - 7],
242304b6cca3Slucy wang - Sun Microsystems - Beijing China 		    &rx->shadow[idx - 7]);
242404b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
242504b6cca3Slucy wang - Sun Microsystems - Beijing China 
242604b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (mp);
242704b6cca3Slucy wang - Sun Microsystems - Beijing China }
242804b6cca3Slucy wang - Sun Microsystems - Beijing China 
242904b6cca3Slucy wang - Sun Microsystems - Beijing China 
243004b6cca3Slucy wang - Sun Microsystems - Beijing China static mblk_t *
243104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rx_done_big(struct myri10ge_slice_state *ss, uint32_t len,
243204b6cca3Slucy wang - Sun Microsystems - Beijing China     uint32_t csum)
243304b6cca3Slucy wang - Sun Microsystems - Beijing China {
243404b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_jpool_stuff *jpool;
243504b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_jpool_entry *j;
243604b6cca3Slucy wang - Sun Microsystems - Beijing China 	mblk_t *mp;
243704b6cca3Slucy wang - Sun Microsystems - Beijing China 	int idx, num_owned_by_mcp;
243804b6cca3Slucy wang - Sun Microsystems - Beijing China 
243904b6cca3Slucy wang - Sun Microsystems - Beijing China 	jpool = &ss->jpool;
244004b6cca3Slucy wang - Sun Microsystems - Beijing China 	idx = ss->j_rx_cnt & ss->rx_big.mask;
244104b6cca3Slucy wang - Sun Microsystems - Beijing China 	j = ss->rx_big.info[idx].j;
244204b6cca3Slucy wang - Sun Microsystems - Beijing China 
244304b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (j == NULL) {
244404b6cca3Slucy wang - Sun Microsystems - Beijing China 		printf("%s: null j at idx=%d, rx_big.cnt = %d, j_rx_cnt=%d\n",
244504b6cca3Slucy wang - Sun Microsystems - Beijing China 		    ss->mgp->name, idx, ss->rx_big.cnt, ss->j_rx_cnt);
244604b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (NULL);
244704b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
244804b6cca3Slucy wang - Sun Microsystems - Beijing China 
244904b6cca3Slucy wang - Sun Microsystems - Beijing China 
245004b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->rx_big.info[idx].j = NULL;
245104b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->j_rx_cnt++;
245204b6cca3Slucy wang - Sun Microsystems - Beijing China 
245304b6cca3Slucy wang - Sun Microsystems - Beijing China 
245404b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
245504b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * Check to see if we are low on rx buffers.
245604b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * Note that we must leave at least 8 free so there are
245704b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * enough to free in a single 64-byte write.
245804b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
245904b6cca3Slucy wang - Sun Microsystems - Beijing China 	num_owned_by_mcp = ss->rx_big.cnt - ss->j_rx_cnt;
246004b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (num_owned_by_mcp < jpool->low_water) {
246104b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_enter(&jpool->mtx);
246204b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_restock_jumbos(ss);
246304b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_exit(&jpool->mtx);
246404b6cca3Slucy wang - Sun Microsystems - Beijing China 		num_owned_by_mcp = ss->rx_big.cnt - ss->j_rx_cnt;
246504b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* if we are still low, then we have to copy */
246604b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (num_owned_by_mcp < 16) {
246704b6cca3Slucy wang - Sun Microsystems - Beijing China 			MYRI10GE_ATOMIC_SLICE_STAT_INC(rx_copy);
246804b6cca3Slucy wang - Sun Microsystems - Beijing China 			/* allocate a new buffer to pass up the stack */
246904b6cca3Slucy wang - Sun Microsystems - Beijing China 			mp = allocb(len + MXGEFW_PAD, 0);
247004b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (mp == NULL) {
247104b6cca3Slucy wang - Sun Microsystems - Beijing China 				goto abort;
247204b6cca3Slucy wang - Sun Microsystems - Beijing China 			}
247304b6cca3Slucy wang - Sun Microsystems - Beijing China 			bcopy(j->buf,
247404b6cca3Slucy wang - Sun Microsystems - Beijing China 			    (caddr_t)mp->b_wptr, len + MXGEFW_PAD);
247504b6cca3Slucy wang - Sun Microsystems - Beijing China 			myri10ge_jfree_rtn(j);
247604b6cca3Slucy wang - Sun Microsystems - Beijing China 			/* push buffer back to NIC */
247704b6cca3Slucy wang - Sun Microsystems - Beijing China 			mutex_enter(&jpool->mtx);
247804b6cca3Slucy wang - Sun Microsystems - Beijing China 			myri10ge_restock_jumbos(ss);
247904b6cca3Slucy wang - Sun Microsystems - Beijing China 			mutex_exit(&jpool->mtx);
248004b6cca3Slucy wang - Sun Microsystems - Beijing China 			goto set_len;
248104b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
248204b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
248304b6cca3Slucy wang - Sun Microsystems - Beijing China 
248404b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* loan our buffer to the stack */
248504b6cca3Slucy wang - Sun Microsystems - Beijing China 	mp = desballoc((unsigned char *)j->buf, myri10ge_mtu, 0, &j->free_func);
248604b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mp == NULL) {
248704b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort;
248804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
248904b6cca3Slucy wang - Sun Microsystems - Beijing China 
249004b6cca3Slucy wang - Sun Microsystems - Beijing China set_len:
249104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mp->b_rptr += MXGEFW_PAD;
249204b6cca3Slucy wang - Sun Microsystems - Beijing China 	mp->b_wptr = ((unsigned char *) mp->b_rptr + len);
249304b6cca3Slucy wang - Sun Microsystems - Beijing China 
249404b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->rx_stats.ibytes += len;
249504b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->rx_stats.ipackets += 1;
249604b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_rx_csum(mp, &ss->rx_stats, csum);
249704b6cca3Slucy wang - Sun Microsystems - Beijing China 
249804b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (mp);
249904b6cca3Slucy wang - Sun Microsystems - Beijing China 
250004b6cca3Slucy wang - Sun Microsystems - Beijing China abort:
250104b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_jfree_rtn(j);
250204b6cca3Slucy wang - Sun Microsystems - Beijing China 	MYRI10GE_ATOMIC_SLICE_STAT_INC(rx_big_nobuf);
250304b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (NULL);
250404b6cca3Slucy wang - Sun Microsystems - Beijing China }
250504b6cca3Slucy wang - Sun Microsystems - Beijing China 
250604b6cca3Slucy wang - Sun Microsystems - Beijing China /*
250704b6cca3Slucy wang - Sun Microsystems - Beijing China  * Free all transmit buffers up until the specified index
250804b6cca3Slucy wang - Sun Microsystems - Beijing China  */
250904b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void
251004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_done(struct myri10ge_slice_state *ss, uint32_t mcp_index)
251104b6cca3Slucy wang - Sun Microsystems - Beijing China {
251204b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_tx_ring_t *tx;
251304b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_tx_dma_handle_head handles;
251404b6cca3Slucy wang - Sun Microsystems - Beijing China 	int idx;
251504b6cca3Slucy wang - Sun Microsystems - Beijing China 	int limit = 0;
251604b6cca3Slucy wang - Sun Microsystems - Beijing China 
251704b6cca3Slucy wang - Sun Microsystems - Beijing China 	tx = &ss->tx;
251804b6cca3Slucy wang - Sun Microsystems - Beijing China 	handles.head = NULL;
251904b6cca3Slucy wang - Sun Microsystems - Beijing China 	handles.tail = NULL;
252004b6cca3Slucy wang - Sun Microsystems - Beijing China 	while (tx->pkt_done != (int)mcp_index) {
252104b6cca3Slucy wang - Sun Microsystems - Beijing China 		idx = tx->done & tx->mask;
252204b6cca3Slucy wang - Sun Microsystems - Beijing China 
252304b6cca3Slucy wang - Sun Microsystems - Beijing China 		/*
252404b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * mblk & DMA handle attached only to first slot
252504b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * per buffer in the packet
252604b6cca3Slucy wang - Sun Microsystems - Beijing China 		 */
252704b6cca3Slucy wang - Sun Microsystems - Beijing China 
252804b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (tx->info[idx].m) {
252904b6cca3Slucy wang - Sun Microsystems - Beijing China 			(void) ddi_dma_unbind_handle(tx->info[idx].handle->h);
253004b6cca3Slucy wang - Sun Microsystems - Beijing China 			tx->info[idx].handle->next = handles.head;
253104b6cca3Slucy wang - Sun Microsystems - Beijing China 			handles.head = tx->info[idx].handle;
253204b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (handles.tail == NULL)
253304b6cca3Slucy wang - Sun Microsystems - Beijing China 				handles.tail = tx->info[idx].handle;
253404b6cca3Slucy wang - Sun Microsystems - Beijing China 			freeb(tx->info[idx].m);
253504b6cca3Slucy wang - Sun Microsystems - Beijing China 			tx->info[idx].m = 0;
253604b6cca3Slucy wang - Sun Microsystems - Beijing China 			tx->info[idx].handle = 0;
253704b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
253804b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (tx->info[idx].ostat.opackets != 0) {
253904b6cca3Slucy wang - Sun Microsystems - Beijing China 			tx->stats.multixmt += tx->info[idx].ostat.multixmt;
254004b6cca3Slucy wang - Sun Microsystems - Beijing China 			tx->stats.brdcstxmt += tx->info[idx].ostat.brdcstxmt;
254104b6cca3Slucy wang - Sun Microsystems - Beijing China 			tx->stats.obytes += tx->info[idx].ostat.obytes;
254204b6cca3Slucy wang - Sun Microsystems - Beijing China 			tx->stats.opackets += tx->info[idx].ostat.opackets;
254304b6cca3Slucy wang - Sun Microsystems - Beijing China 			tx->info[idx].stat.un.all = 0;
254404b6cca3Slucy wang - Sun Microsystems - Beijing China 			tx->pkt_done++;
254504b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
254604b6cca3Slucy wang - Sun Microsystems - Beijing China 
254704b6cca3Slucy wang - Sun Microsystems - Beijing China 		tx->done++;
254804b6cca3Slucy wang - Sun Microsystems - Beijing China 		/*
254904b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * if we stalled the queue, wake it.  But Wait until
255004b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * we have at least 1/2 our slots free.
255104b6cca3Slucy wang - Sun Microsystems - Beijing China 		 */
255204b6cca3Slucy wang - Sun Microsystems - Beijing China 		if ((tx->req - tx->done) < (tx->mask >> 1) &&
255304b6cca3Slucy wang - Sun Microsystems - Beijing China 		    tx->stall != tx->sched) {
255404b6cca3Slucy wang - Sun Microsystems - Beijing China 			mutex_enter(&ss->tx.lock);
255504b6cca3Slucy wang - Sun Microsystems - Beijing China 			tx->sched = tx->stall;
255604b6cca3Slucy wang - Sun Microsystems - Beijing China 			mutex_exit(&ss->tx.lock);
255704b6cca3Slucy wang - Sun Microsystems - Beijing China 			mac_tx_ring_update(ss->mgp->mh, tx->rh);
255804b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
255904b6cca3Slucy wang - Sun Microsystems - Beijing China 
256004b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* limit potential for livelock */
256104b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (unlikely(++limit >  2 * tx->mask))
256204b6cca3Slucy wang - Sun Microsystems - Beijing China 			break;
256304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
256404b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (tx->req == tx->done && tx->stop != NULL) {
256504b6cca3Slucy wang - Sun Microsystems - Beijing China 		/*
256604b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * Nic has sent all pending requests, allow him
256704b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * to stop polling this queue
256804b6cca3Slucy wang - Sun Microsystems - Beijing China 		 */
256904b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_enter(&tx->lock);
257004b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (tx->req == tx->done && tx->active) {
257104b6cca3Slucy wang - Sun Microsystems - Beijing China 			*(int *)(void *)tx->stop = 1;
257204b6cca3Slucy wang - Sun Microsystems - Beijing China 			tx->active = 0;
257304b6cca3Slucy wang - Sun Microsystems - Beijing China 			mb();
257404b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
257504b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_exit(&tx->lock);
257604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
257704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (handles.head != NULL)
257804b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_free_tx_handles(tx, &handles);
257904b6cca3Slucy wang - Sun Microsystems - Beijing China }
258004b6cca3Slucy wang - Sun Microsystems - Beijing China 
258104b6cca3Slucy wang - Sun Microsystems - Beijing China static void
258204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_mbl_init(struct myri10ge_mblk_list *mbl)
258304b6cca3Slucy wang - Sun Microsystems - Beijing China {
258404b6cca3Slucy wang - Sun Microsystems - Beijing China 	mbl->head = NULL;
258504b6cca3Slucy wang - Sun Microsystems - Beijing China 	mbl->tail = &mbl->head;
258604b6cca3Slucy wang - Sun Microsystems - Beijing China 	mbl->cnt = 0;
258704b6cca3Slucy wang - Sun Microsystems - Beijing China }
258804b6cca3Slucy wang - Sun Microsystems - Beijing China 
258904b6cca3Slucy wang - Sun Microsystems - Beijing China /*ARGSUSED*/
259004b6cca3Slucy wang - Sun Microsystems - Beijing China void
259104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_mbl_append(struct myri10ge_slice_state *ss,
259204b6cca3Slucy wang - Sun Microsystems - Beijing China     struct myri10ge_mblk_list *mbl, mblk_t *mp)
259304b6cca3Slucy wang - Sun Microsystems - Beijing China {
259404b6cca3Slucy wang - Sun Microsystems - Beijing China 	*(mbl->tail) = mp;
259504b6cca3Slucy wang - Sun Microsystems - Beijing China 	mbl->tail = &mp->b_next;
259604b6cca3Slucy wang - Sun Microsystems - Beijing China 	mp->b_next = NULL;
259704b6cca3Slucy wang - Sun Microsystems - Beijing China 	mbl->cnt++;
259804b6cca3Slucy wang - Sun Microsystems - Beijing China }
259904b6cca3Slucy wang - Sun Microsystems - Beijing China 
260004b6cca3Slucy wang - Sun Microsystems - Beijing China 
260104b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void
260204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_clean_rx_done(struct myri10ge_slice_state *ss,
260304b6cca3Slucy wang - Sun Microsystems - Beijing China     struct myri10ge_mblk_list *mbl, int limit, boolean_t *stop)
260404b6cca3Slucy wang - Sun Microsystems - Beijing China {
260504b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_rx_done_t *rx_done = &ss->rx_done;
260604b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp = ss->mgp;
260704b6cca3Slucy wang - Sun Microsystems - Beijing China 	mblk_t *mp;
260804b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct lro_entry *lro;
260904b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint16_t length;
261004b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint16_t checksum;
261104b6cca3Slucy wang - Sun Microsystems - Beijing China 
261204b6cca3Slucy wang - Sun Microsystems - Beijing China 
261304b6cca3Slucy wang - Sun Microsystems - Beijing China 	while (rx_done->entry[rx_done->idx].length != 0) {
261404b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (unlikely (*stop)) {
261504b6cca3Slucy wang - Sun Microsystems - Beijing China 			break;
261604b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
261704b6cca3Slucy wang - Sun Microsystems - Beijing China 		length = ntohs(rx_done->entry[rx_done->idx].length);
261804b6cca3Slucy wang - Sun Microsystems - Beijing China 		length &= (~MXGEFW_RSS_HASH_MASK);
261904b6cca3Slucy wang - Sun Microsystems - Beijing China 
262004b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* limit potential for livelock */
262104b6cca3Slucy wang - Sun Microsystems - Beijing China 		limit -= length;
262204b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (unlikely(limit < 0))
262304b6cca3Slucy wang - Sun Microsystems - Beijing China 			break;
262404b6cca3Slucy wang - Sun Microsystems - Beijing China 
262504b6cca3Slucy wang - Sun Microsystems - Beijing China 		rx_done->entry[rx_done->idx].length = 0;
262604b6cca3Slucy wang - Sun Microsystems - Beijing China 		checksum = ntohs(rx_done->entry[rx_done->idx].checksum);
262704b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (length <= myri10ge_small_bytes)
262804b6cca3Slucy wang - Sun Microsystems - Beijing China 			mp = myri10ge_rx_done_small(ss, length, checksum);
262904b6cca3Slucy wang - Sun Microsystems - Beijing China 		else
263004b6cca3Slucy wang - Sun Microsystems - Beijing China 			mp = myri10ge_rx_done_big(ss, length, checksum);
263104b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (mp != NULL) {
263204b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (!myri10ge_lro ||
263304b6cca3Slucy wang - Sun Microsystems - Beijing China 			    0 != myri10ge_lro_rx(ss, mp, checksum, mbl))
263404b6cca3Slucy wang - Sun Microsystems - Beijing China 				myri10ge_mbl_append(ss, mbl, mp);
263504b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
263604b6cca3Slucy wang - Sun Microsystems - Beijing China 		rx_done->cnt++;
263704b6cca3Slucy wang - Sun Microsystems - Beijing China 		rx_done->idx = rx_done->cnt & (mgp->max_intr_slots - 1);
263804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
263904b6cca3Slucy wang - Sun Microsystems - Beijing China 	while (ss->lro_active != NULL) {
264004b6cca3Slucy wang - Sun Microsystems - Beijing China 		lro = ss->lro_active;
264104b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->lro_active = lro->next;
264204b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_lro_flush(ss, lro, mbl);
264304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
264404b6cca3Slucy wang - Sun Microsystems - Beijing China }
264504b6cca3Slucy wang - Sun Microsystems - Beijing China 
264604b6cca3Slucy wang - Sun Microsystems - Beijing China static void
264704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_intr_rx(struct myri10ge_slice_state *ss)
264804b6cca3Slucy wang - Sun Microsystems - Beijing China {
264904b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint64_t gen;
265004b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_mblk_list mbl;
265104b6cca3Slucy wang - Sun Microsystems - Beijing China 
265204b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_mbl_init(&mbl);
265304b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mutex_tryenter(&ss->rx_lock) == 0)
265404b6cca3Slucy wang - Sun Microsystems - Beijing China 		return;
265504b6cca3Slucy wang - Sun Microsystems - Beijing China 	gen = ss->rx_gen_num;
265604b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_clean_rx_done(ss, &mbl, MYRI10GE_POLL_NULL,
265704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    &ss->rx_polling);
265804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mbl.head != NULL)
265904b6cca3Slucy wang - Sun Microsystems - Beijing China 		mac_rx_ring(ss->mgp->mh, ss->rx_rh, mbl.head, gen);
266004b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&ss->rx_lock);
266104b6cca3Slucy wang - Sun Microsystems - Beijing China 
266204b6cca3Slucy wang - Sun Microsystems - Beijing China }
266304b6cca3Slucy wang - Sun Microsystems - Beijing China 
266404b6cca3Slucy wang - Sun Microsystems - Beijing China static mblk_t *
266504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_poll_rx(void *arg, int bytes)
266604b6cca3Slucy wang - Sun Microsystems - Beijing China {
266704b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_slice_state *ss = arg;
266804b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_mblk_list mbl;
266904b6cca3Slucy wang - Sun Microsystems - Beijing China 	boolean_t dummy = B_FALSE;
267004b6cca3Slucy wang - Sun Microsystems - Beijing China 
267104b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (bytes == 0)
267204b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (NULL);
267304b6cca3Slucy wang - Sun Microsystems - Beijing China 
267404b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_mbl_init(&mbl);
267504b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&ss->rx_lock);
267604b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (ss->rx_polling)
267704b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_clean_rx_done(ss, &mbl, bytes, &dummy);
267804b6cca3Slucy wang - Sun Microsystems - Beijing China 	else
267904b6cca3Slucy wang - Sun Microsystems - Beijing China 		printf("%d: poll_rx: token=%d, polling=%d\n", (int)(ss -
268004b6cca3Slucy wang - Sun Microsystems - Beijing China 		    ss->mgp->ss), ss->rx_token, ss->rx_polling);
268104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&ss->rx_lock);
268204b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (mbl.head);
268304b6cca3Slucy wang - Sun Microsystems - Beijing China }
268404b6cca3Slucy wang - Sun Microsystems - Beijing China 
268504b6cca3Slucy wang - Sun Microsystems - Beijing China /*ARGSUSED*/
268604b6cca3Slucy wang - Sun Microsystems - Beijing China static uint_t
268704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_intr(caddr_t arg0, caddr_t arg1)
268804b6cca3Slucy wang - Sun Microsystems - Beijing China {
268904b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_slice_state *ss =
269004b6cca3Slucy wang - Sun Microsystems - Beijing China 	    (struct myri10ge_slice_state *)(void *)arg0;
269104b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp = ss->mgp;
269204b6cca3Slucy wang - Sun Microsystems - Beijing China 	mcp_irq_data_t *stats = ss->fw_stats;
269304b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_tx_ring_t *tx = &ss->tx;
269404b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint32_t send_done_count;
269504b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint8_t valid;
269604b6cca3Slucy wang - Sun Microsystems - Beijing China 
269704b6cca3Slucy wang - Sun Microsystems - Beijing China 
269804b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* make sure the DMA has finished */
269904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (!stats->valid) {
270004b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_INTR_UNCLAIMED);
270104b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
270204b6cca3Slucy wang - Sun Microsystems - Beijing China 	valid = stats->valid;
270304b6cca3Slucy wang - Sun Microsystems - Beijing China 
270404b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* low bit indicates receives are present */
270504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (valid & 1)
270604b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_intr_rx(ss);
270704b6cca3Slucy wang - Sun Microsystems - Beijing China 
270804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->ddi_intr_type == DDI_INTR_TYPE_FIXED) {
270904b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* lower legacy IRQ  */
271004b6cca3Slucy wang - Sun Microsystems - Beijing China 		*mgp->irq_deassert = 0;
271104b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (!myri10ge_deassert_wait)
271204b6cca3Slucy wang - Sun Microsystems - Beijing China 			/* don't wait for conf. that irq is low */
271304b6cca3Slucy wang - Sun Microsystems - Beijing China 			stats->valid = 0;
271404b6cca3Slucy wang - Sun Microsystems - Beijing China 		mb();
271504b6cca3Slucy wang - Sun Microsystems - Beijing China 	} else {
271604b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* no need to wait for conf. that irq is low */
271704b6cca3Slucy wang - Sun Microsystems - Beijing China 		stats->valid = 0;
271804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
271904b6cca3Slucy wang - Sun Microsystems - Beijing China 
272004b6cca3Slucy wang - Sun Microsystems - Beijing China 	do {
272104b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* check for transmit completes and receives */
272204b6cca3Slucy wang - Sun Microsystems - Beijing China 		send_done_count = ntohl(stats->send_done_count);
272304b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (send_done_count != tx->pkt_done)
272404b6cca3Slucy wang - Sun Microsystems - Beijing China 			myri10ge_tx_done(ss, (int)send_done_count);
272504b6cca3Slucy wang - Sun Microsystems - Beijing China 	} while (*((volatile uint8_t *) &stats->valid));
272604b6cca3Slucy wang - Sun Microsystems - Beijing China 
272704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (stats->stats_updated) {
272804b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (mgp->link_state != stats->link_up || stats->link_down) {
272904b6cca3Slucy wang - Sun Microsystems - Beijing China 			mgp->link_state = stats->link_up;
273004b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (stats->link_down) {
273104b6cca3Slucy wang - Sun Microsystems - Beijing China 				mgp->down_cnt += stats->link_down;
273204b6cca3Slucy wang - Sun Microsystems - Beijing China 				mgp->link_state = 0;
273304b6cca3Slucy wang - Sun Microsystems - Beijing China 			}
273404b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (mgp->link_state) {
273504b6cca3Slucy wang - Sun Microsystems - Beijing China 				if (myri10ge_verbose)
273604b6cca3Slucy wang - Sun Microsystems - Beijing China 					printf("%s: link up\n", mgp->name);
273704b6cca3Slucy wang - Sun Microsystems - Beijing China 				mac_link_update(mgp->mh, LINK_STATE_UP);
273804b6cca3Slucy wang - Sun Microsystems - Beijing China 			} else {
273904b6cca3Slucy wang - Sun Microsystems - Beijing China 				if (myri10ge_verbose)
274004b6cca3Slucy wang - Sun Microsystems - Beijing China 					printf("%s: link down\n", mgp->name);
274104b6cca3Slucy wang - Sun Microsystems - Beijing China 				mac_link_update(mgp->mh, LINK_STATE_DOWN);
274204b6cca3Slucy wang - Sun Microsystems - Beijing China 			}
274304b6cca3Slucy wang - Sun Microsystems - Beijing China 			MYRI10GE_NIC_STAT_INC(link_changes);
274404b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
274504b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (mgp->rdma_tags_available !=
274604b6cca3Slucy wang - Sun Microsystems - Beijing China 		    ntohl(ss->fw_stats->rdma_tags_available)) {
274704b6cca3Slucy wang - Sun Microsystems - Beijing China 			mgp->rdma_tags_available =
274804b6cca3Slucy wang - Sun Microsystems - Beijing China 			    ntohl(ss->fw_stats->rdma_tags_available);
274904b6cca3Slucy wang - Sun Microsystems - Beijing China 			cmn_err(CE_NOTE, "%s: RDMA timed out! "
275004b6cca3Slucy wang - Sun Microsystems - Beijing China 			    "%d tags left\n", mgp->name,
275104b6cca3Slucy wang - Sun Microsystems - Beijing China 			    mgp->rdma_tags_available);
275204b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
275304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
275404b6cca3Slucy wang - Sun Microsystems - Beijing China 
275504b6cca3Slucy wang - Sun Microsystems - Beijing China 	mb();
275604b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* check to see if we have rx token to pass back */
275704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (valid & 0x1) {
275804b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_enter(&ss->poll_lock);
275904b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (ss->rx_polling) {
276004b6cca3Slucy wang - Sun Microsystems - Beijing China 			ss->rx_token = 1;
276104b6cca3Slucy wang - Sun Microsystems - Beijing China 		} else {
276204b6cca3Slucy wang - Sun Microsystems - Beijing China 			*ss->irq_claim = BE_32(3);
276304b6cca3Slucy wang - Sun Microsystems - Beijing China 			ss->rx_token = 0;
276404b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
276504b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_exit(&ss->poll_lock);
276604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
276704b6cca3Slucy wang - Sun Microsystems - Beijing China 	*(ss->irq_claim + 1) = BE_32(3);
276804b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (DDI_INTR_CLAIMED);
276904b6cca3Slucy wang - Sun Microsystems - Beijing China }
277004b6cca3Slucy wang - Sun Microsystems - Beijing China 
277104b6cca3Slucy wang - Sun Microsystems - Beijing China /*
277204b6cca3Slucy wang - Sun Microsystems - Beijing China  * Add or remove a multicast address.  This is called with our
277304b6cca3Slucy wang - Sun Microsystems - Beijing China  * macinfo's lock held by GLD, so we do not need to worry about
277404b6cca3Slucy wang - Sun Microsystems - Beijing China  * our own locking here.
277504b6cca3Slucy wang - Sun Microsystems - Beijing China  */
277604b6cca3Slucy wang - Sun Microsystems - Beijing China static int
277704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_m_multicst(void *arg, boolean_t add, const uint8_t *multicastaddr)
277804b6cca3Slucy wang - Sun Microsystems - Beijing China {
277904b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_cmd_t cmd;
278004b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp = arg;
278104b6cca3Slucy wang - Sun Microsystems - Beijing China 	int status, join_leave;
278204b6cca3Slucy wang - Sun Microsystems - Beijing China 
278304b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (add)
278404b6cca3Slucy wang - Sun Microsystems - Beijing China 		join_leave = MXGEFW_JOIN_MULTICAST_GROUP;
278504b6cca3Slucy wang - Sun Microsystems - Beijing China 	else
278604b6cca3Slucy wang - Sun Microsystems - Beijing China 		join_leave = MXGEFW_LEAVE_MULTICAST_GROUP;
278704b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) memcpy(&cmd.data0, multicastaddr, 4);
278804b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) memcpy(&cmd.data1, multicastaddr + 4, 2);
278904b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data0 = htonl(cmd.data0);
279004b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data1 = htonl(cmd.data1);
279104b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_send_cmd(mgp, join_leave, &cmd);
279204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status == 0)
279304b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (0);
279404b6cca3Slucy wang - Sun Microsystems - Beijing China 
279504b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmn_err(CE_WARN, "%s: failed to set multicast address\n",
279604b6cca3Slucy wang - Sun Microsystems - Beijing China 	    mgp->name);
279704b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (status);
279804b6cca3Slucy wang - Sun Microsystems - Beijing China }
279904b6cca3Slucy wang - Sun Microsystems - Beijing China 
280004b6cca3Slucy wang - Sun Microsystems - Beijing China 
280104b6cca3Slucy wang - Sun Microsystems - Beijing China static int
280204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_m_promisc(void *arg, boolean_t on)
280304b6cca3Slucy wang - Sun Microsystems - Beijing China {
280404b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp = arg;
280504b6cca3Slucy wang - Sun Microsystems - Beijing China 
280604b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_change_promisc(mgp, on);
280704b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
280804b6cca3Slucy wang - Sun Microsystems - Beijing China }
280904b6cca3Slucy wang - Sun Microsystems - Beijing China 
281004b6cca3Slucy wang - Sun Microsystems - Beijing China /*
281104b6cca3Slucy wang - Sun Microsystems - Beijing China  * copy an array of mcp_kreq_ether_send_t's to the mcp.  Copy
281204b6cca3Slucy wang - Sun Microsystems - Beijing China  *  backwards one at a time and handle ring wraps
281304b6cca3Slucy wang - Sun Microsystems - Beijing China  */
281404b6cca3Slucy wang - Sun Microsystems - Beijing China 
281504b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void
281604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_submit_req_backwards(myri10ge_tx_ring_t *tx,
281704b6cca3Slucy wang - Sun Microsystems - Beijing China     mcp_kreq_ether_send_t *src, int cnt)
281804b6cca3Slucy wang - Sun Microsystems - Beijing China {
281904b6cca3Slucy wang - Sun Microsystems - Beijing China 	int idx, starting_slot;
282004b6cca3Slucy wang - Sun Microsystems - Beijing China 	starting_slot = tx->req;
282104b6cca3Slucy wang - Sun Microsystems - Beijing China 	while (cnt > 1) {
282204b6cca3Slucy wang - Sun Microsystems - Beijing China 		cnt--;
282304b6cca3Slucy wang - Sun Microsystems - Beijing China 		idx = (starting_slot + cnt) & tx->mask;
282404b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_pio_copy(&tx->lanai[idx],
282504b6cca3Slucy wang - Sun Microsystems - Beijing China 		    &src[cnt], sizeof (*src));
282604b6cca3Slucy wang - Sun Microsystems - Beijing China 		mb();
282704b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
282804b6cca3Slucy wang - Sun Microsystems - Beijing China }
282904b6cca3Slucy wang - Sun Microsystems - Beijing China 
283004b6cca3Slucy wang - Sun Microsystems - Beijing China /*
283104b6cca3Slucy wang - Sun Microsystems - Beijing China  * copy an array of mcp_kreq_ether_send_t's to the mcp.  Copy
283204b6cca3Slucy wang - Sun Microsystems - Beijing China  * at most 32 bytes at a time, so as to avoid involving the software
283304b6cca3Slucy wang - Sun Microsystems - Beijing China  * pio handler in the nic.   We re-write the first segment's flags
283404b6cca3Slucy wang - Sun Microsystems - Beijing China  * to mark them valid only after writing the entire chain
283504b6cca3Slucy wang - Sun Microsystems - Beijing China  */
283604b6cca3Slucy wang - Sun Microsystems - Beijing China 
283704b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void
283804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_submit_req(myri10ge_tx_ring_t *tx, mcp_kreq_ether_send_t *src,
283904b6cca3Slucy wang - Sun Microsystems - Beijing China     int cnt)
284004b6cca3Slucy wang - Sun Microsystems - Beijing China {
284104b6cca3Slucy wang - Sun Microsystems - Beijing China 	int idx, i;
284204b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint32_t *src_ints, *dst_ints;
284304b6cca3Slucy wang - Sun Microsystems - Beijing China 	mcp_kreq_ether_send_t *srcp, *dstp, *dst;
284404b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint8_t last_flags;
284504b6cca3Slucy wang - Sun Microsystems - Beijing China 
284604b6cca3Slucy wang - Sun Microsystems - Beijing China 	idx = tx->req & tx->mask;
284704b6cca3Slucy wang - Sun Microsystems - Beijing China 
284804b6cca3Slucy wang - Sun Microsystems - Beijing China 	last_flags = src->flags;
284904b6cca3Slucy wang - Sun Microsystems - Beijing China 	src->flags = 0;
285004b6cca3Slucy wang - Sun Microsystems - Beijing China 	mb();
285104b6cca3Slucy wang - Sun Microsystems - Beijing China 	dst = dstp = &tx->lanai[idx];
285204b6cca3Slucy wang - Sun Microsystems - Beijing China 	srcp = src;
285304b6cca3Slucy wang - Sun Microsystems - Beijing China 
285404b6cca3Slucy wang - Sun Microsystems - Beijing China 	if ((idx + cnt) < tx->mask) {
285504b6cca3Slucy wang - Sun Microsystems - Beijing China 		for (i = 0; i < (cnt - 1); i += 2) {
285604b6cca3Slucy wang - Sun Microsystems - Beijing China 			myri10ge_pio_copy(dstp, srcp, 2 * sizeof (*src));
285704b6cca3Slucy wang - Sun Microsystems - Beijing China 			mb(); /* force write every 32 bytes */
285804b6cca3Slucy wang - Sun Microsystems - Beijing China 			srcp += 2;
285904b6cca3Slucy wang - Sun Microsystems - Beijing China 			dstp += 2;
286004b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
286104b6cca3Slucy wang - Sun Microsystems - Beijing China 	} else {
286204b6cca3Slucy wang - Sun Microsystems - Beijing China 		/*
286304b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * submit all but the first request, and ensure
286404b6cca3Slucy wang - Sun Microsystems - Beijing China 		 *  that it is submitted below
286504b6cca3Slucy wang - Sun Microsystems - Beijing China 		 */
286604b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_submit_req_backwards(tx, src, cnt);
286704b6cca3Slucy wang - Sun Microsystems - Beijing China 		i = 0;
286804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
286904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (i < cnt) {
287004b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* submit the first request */
287104b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_pio_copy(dstp, srcp, sizeof (*src));
287204b6cca3Slucy wang - Sun Microsystems - Beijing China 		mb(); /* barrier before setting valid flag */
287304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
287404b6cca3Slucy wang - Sun Microsystems - Beijing China 
287504b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* re-write the last 32-bits with the valid flags */
287604b6cca3Slucy wang - Sun Microsystems - Beijing China 	src->flags |= last_flags;
287704b6cca3Slucy wang - Sun Microsystems - Beijing China 	src_ints = (uint32_t *)src;
287804b6cca3Slucy wang - Sun Microsystems - Beijing China 	src_ints += 3;
287904b6cca3Slucy wang - Sun Microsystems - Beijing China 	dst_ints = (uint32_t *)dst;
288004b6cca3Slucy wang - Sun Microsystems - Beijing China 	dst_ints += 3;
288104b6cca3Slucy wang - Sun Microsystems - Beijing China 	*dst_ints =  *src_ints;
288204b6cca3Slucy wang - Sun Microsystems - Beijing China 	tx->req += cnt;
288304b6cca3Slucy wang - Sun Microsystems - Beijing China 	mb();
288404b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* notify NIC to poll this tx ring */
288504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (!tx->active && tx->go != NULL) {
288604b6cca3Slucy wang - Sun Microsystems - Beijing China 		*(int *)(void *)tx->go = 1;
288704b6cca3Slucy wang - Sun Microsystems - Beijing China 		tx->active = 1;
288804b6cca3Slucy wang - Sun Microsystems - Beijing China 		tx->activate++;
288904b6cca3Slucy wang - Sun Microsystems - Beijing China 		mb();
289004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
289104b6cca3Slucy wang - Sun Microsystems - Beijing China }
289204b6cca3Slucy wang - Sun Microsystems - Beijing China 
289304b6cca3Slucy wang - Sun Microsystems - Beijing China /* ARGSUSED */
289404b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void
289504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_lso_info_get(mblk_t *mp, uint32_t *mss, uint32_t *flags)
289604b6cca3Slucy wang - Sun Microsystems - Beijing China {
289704b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint32_t lso_flag;
28980dc2366fSVenugopal Iyer 	mac_lso_get(mp, mss, &lso_flag);
289904b6cca3Slucy wang - Sun Microsystems - Beijing China 	(*flags) |= lso_flag;
290004b6cca3Slucy wang - Sun Microsystems - Beijing China }
290104b6cca3Slucy wang - Sun Microsystems - Beijing China 
290204b6cca3Slucy wang - Sun Microsystems - Beijing China 
290304b6cca3Slucy wang - Sun Microsystems - Beijing China /* like pullupmsg, except preserve hcksum/LSO attributes */
290404b6cca3Slucy wang - Sun Microsystems - Beijing China static int
290504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_pullup(struct myri10ge_slice_state *ss, mblk_t *mp)
290604b6cca3Slucy wang - Sun Microsystems - Beijing China {
290704b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint32_t start, stuff, tx_offload_flags, mss;
290804b6cca3Slucy wang - Sun Microsystems - Beijing China 	int ok;
290904b6cca3Slucy wang - Sun Microsystems - Beijing China 
291004b6cca3Slucy wang - Sun Microsystems - Beijing China 	mss = 0;
29110dc2366fSVenugopal Iyer 	mac_hcksum_get(mp, &start, &stuff, NULL, NULL, &tx_offload_flags);
291204b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_lso_info_get(mp, &mss, &tx_offload_flags);
291304b6cca3Slucy wang - Sun Microsystems - Beijing China 
291404b6cca3Slucy wang - Sun Microsystems - Beijing China 	ok = pullupmsg(mp, -1);
291504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (!ok) {
291604b6cca3Slucy wang - Sun Microsystems - Beijing China 		printf("pullupmsg failed");
291704b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
291804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
291904b6cca3Slucy wang - Sun Microsystems - Beijing China 	MYRI10GE_ATOMIC_SLICE_STAT_INC(xmit_pullup);
29200dc2366fSVenugopal Iyer 	mac_hcksum_set(mp, start, stuff, NULL, NULL, tx_offload_flags);
292104b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (tx_offload_flags & HW_LSO)
292204b6cca3Slucy wang - Sun Microsystems - Beijing China 		DB_LSOMSS(mp) = (uint16_t)mss;
292304b6cca3Slucy wang - Sun Microsystems - Beijing China 	lso_info_set(mp, mss, tx_offload_flags);
292404b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
292504b6cca3Slucy wang - Sun Microsystems - Beijing China }
292604b6cca3Slucy wang - Sun Microsystems - Beijing China 
292704b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void
292804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_stat(struct myri10ge_tx_pkt_stats *s, struct ether_header *eh,
292904b6cca3Slucy wang - Sun Microsystems - Beijing China     int opackets, int obytes)
293004b6cca3Slucy wang - Sun Microsystems - Beijing China {
293104b6cca3Slucy wang - Sun Microsystems - Beijing China 	s->un.all = 0;
293204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (eh->ether_dhost.ether_addr_octet[0] & 1) {
293304b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (0 == (bcmp(eh->ether_dhost.ether_addr_octet,
293404b6cca3Slucy wang - Sun Microsystems - Beijing China 		    myri10ge_broadcastaddr, sizeof (eh->ether_dhost))))
293504b6cca3Slucy wang - Sun Microsystems - Beijing China 			s->un.s.brdcstxmt = 1;
293604b6cca3Slucy wang - Sun Microsystems - Beijing China 		else
293704b6cca3Slucy wang - Sun Microsystems - Beijing China 			s->un.s.multixmt = 1;
293804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
293904b6cca3Slucy wang - Sun Microsystems - Beijing China 	s->un.s.opackets = (uint16_t)opackets;
294004b6cca3Slucy wang - Sun Microsystems - Beijing China 	s->un.s.obytes = obytes;
294104b6cca3Slucy wang - Sun Microsystems - Beijing China }
294204b6cca3Slucy wang - Sun Microsystems - Beijing China 
294304b6cca3Slucy wang - Sun Microsystems - Beijing China static int
294404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_copy(struct myri10ge_slice_state *ss, mblk_t *mp,
294504b6cca3Slucy wang - Sun Microsystems - Beijing China     mcp_kreq_ether_send_t *req)
294604b6cca3Slucy wang - Sun Microsystems - Beijing China {
294704b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_tx_ring_t *tx = &ss->tx;
294804b6cca3Slucy wang - Sun Microsystems - Beijing China 	caddr_t ptr;
294904b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_tx_copybuf *cp;
295004b6cca3Slucy wang - Sun Microsystems - Beijing China 	mblk_t *bp;
295104b6cca3Slucy wang - Sun Microsystems - Beijing China 	int idx, mblen, avail;
295204b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint16_t len;
295304b6cca3Slucy wang - Sun Microsystems - Beijing China 
295404b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&tx->lock);
295504b6cca3Slucy wang - Sun Microsystems - Beijing China 	avail = tx->mask - (tx->req - tx->done);
295604b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (avail <= 1) {
295704b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_exit(&tx->lock);
295804b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (EBUSY);
295904b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
296004b6cca3Slucy wang - Sun Microsystems - Beijing China 	idx = tx->req & tx->mask;
296104b6cca3Slucy wang - Sun Microsystems - Beijing China 	cp = &tx->cp[idx];
296204b6cca3Slucy wang - Sun Microsystems - Beijing China 	ptr = cp->va;
296304b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (len = 0, bp = mp; bp != NULL; bp = bp->b_cont) {
296404b6cca3Slucy wang - Sun Microsystems - Beijing China 		mblen = MBLKL(bp);
296504b6cca3Slucy wang - Sun Microsystems - Beijing China 		bcopy(bp->b_rptr, ptr, mblen);
296604b6cca3Slucy wang - Sun Microsystems - Beijing China 		ptr += mblen;
296704b6cca3Slucy wang - Sun Microsystems - Beijing China 		len += mblen;
296804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
296904b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* ensure runts are padded to 60 bytes */
297004b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (len < 60) {
297104b6cca3Slucy wang - Sun Microsystems - Beijing China 		bzero(ptr, 64 - len);
297204b6cca3Slucy wang - Sun Microsystems - Beijing China 		len = 60;
297304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
297404b6cca3Slucy wang - Sun Microsystems - Beijing China 	req->addr_low = cp->dma.low;
297504b6cca3Slucy wang - Sun Microsystems - Beijing China 	req->addr_high = cp->dma.high;
297604b6cca3Slucy wang - Sun Microsystems - Beijing China 	req->length = htons(len);
297704b6cca3Slucy wang - Sun Microsystems - Beijing China 	req->pad = 0;
297804b6cca3Slucy wang - Sun Microsystems - Beijing China 	req->rdma_count = 1;
297904b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_tx_stat(&tx->info[idx].stat,
298004b6cca3Slucy wang - Sun Microsystems - Beijing China 	    (struct ether_header *)(void *)cp->va, 1, len);
298104b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) ddi_dma_sync(cp->dma.handle, 0, len, DDI_DMA_SYNC_FORDEV);
298204b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_submit_req(&ss->tx, req, 1);
298304b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&tx->lock);
298404b6cca3Slucy wang - Sun Microsystems - Beijing China 	freemsg(mp);
298504b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
298604b6cca3Slucy wang - Sun Microsystems - Beijing China }
298704b6cca3Slucy wang - Sun Microsystems - Beijing China 
298804b6cca3Slucy wang - Sun Microsystems - Beijing China 
298904b6cca3Slucy wang - Sun Microsystems - Beijing China static void
299004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_send_locked(myri10ge_tx_ring_t *tx, mcp_kreq_ether_send_t *req_list,
299104b6cca3Slucy wang - Sun Microsystems - Beijing China     struct myri10ge_tx_buffer_state *tx_info,
299204b6cca3Slucy wang - Sun Microsystems - Beijing China     int count)
299304b6cca3Slucy wang - Sun Microsystems - Beijing China {
299404b6cca3Slucy wang - Sun Microsystems - Beijing China 	int i, idx;
299504b6cca3Slucy wang - Sun Microsystems - Beijing China 
299604b6cca3Slucy wang - Sun Microsystems - Beijing China 	idx = 0; /* gcc -Wuninitialized */
299704b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* store unmapping and bp info for tx irq handler */
299804b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (i = 0; i < count; i++) {
299904b6cca3Slucy wang - Sun Microsystems - Beijing China 		idx = (tx->req + i) & tx->mask;
300004b6cca3Slucy wang - Sun Microsystems - Beijing China 		tx->info[idx].m = tx_info[i].m;
300104b6cca3Slucy wang - Sun Microsystems - Beijing China 		tx->info[idx].handle = tx_info[i].handle;
300204b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
300304b6cca3Slucy wang - Sun Microsystems - Beijing China 	tx->info[idx].stat.un.all = tx_info[0].stat.un.all;
300404b6cca3Slucy wang - Sun Microsystems - Beijing China 
300504b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* submit the frame to the nic */
300604b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_submit_req(tx, req_list, count);
300704b6cca3Slucy wang - Sun Microsystems - Beijing China 
300804b6cca3Slucy wang - Sun Microsystems - Beijing China 
300904b6cca3Slucy wang - Sun Microsystems - Beijing China }
301004b6cca3Slucy wang - Sun Microsystems - Beijing China 
301104b6cca3Slucy wang - Sun Microsystems - Beijing China 
301204b6cca3Slucy wang - Sun Microsystems - Beijing China 
301304b6cca3Slucy wang - Sun Microsystems - Beijing China static void
301404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_copydata(mblk_t *mp, int off, int len, caddr_t buf)
301504b6cca3Slucy wang - Sun Microsystems - Beijing China {
301604b6cca3Slucy wang - Sun Microsystems - Beijing China 	mblk_t *bp;
301704b6cca3Slucy wang - Sun Microsystems - Beijing China 	int seglen;
301804b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint_t count;
301904b6cca3Slucy wang - Sun Microsystems - Beijing China 
302004b6cca3Slucy wang - Sun Microsystems - Beijing China 	bp = mp;
302104b6cca3Slucy wang - Sun Microsystems - Beijing China 
302204b6cca3Slucy wang - Sun Microsystems - Beijing China 	while (off > 0) {
302304b6cca3Slucy wang - Sun Microsystems - Beijing China 		seglen = MBLKL(bp);
302404b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (off < seglen)
302504b6cca3Slucy wang - Sun Microsystems - Beijing China 			break;
302604b6cca3Slucy wang - Sun Microsystems - Beijing China 		off -= seglen;
302704b6cca3Slucy wang - Sun Microsystems - Beijing China 		bp = bp->b_cont;
302804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
302904b6cca3Slucy wang - Sun Microsystems - Beijing China 	while (len > 0) {
303004b6cca3Slucy wang - Sun Microsystems - Beijing China 		seglen = MBLKL(bp);
303104b6cca3Slucy wang - Sun Microsystems - Beijing China 		count = min(seglen - off, len);
303204b6cca3Slucy wang - Sun Microsystems - Beijing China 		bcopy(bp->b_rptr + off, buf, count);
303304b6cca3Slucy wang - Sun Microsystems - Beijing China 		len -= count;
303404b6cca3Slucy wang - Sun Microsystems - Beijing China 		buf += count;
303504b6cca3Slucy wang - Sun Microsystems - Beijing China 		off = 0;
303604b6cca3Slucy wang - Sun Microsystems - Beijing China 		bp = bp->b_cont;
303704b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
303804b6cca3Slucy wang - Sun Microsystems - Beijing China }
303904b6cca3Slucy wang - Sun Microsystems - Beijing China 
304004b6cca3Slucy wang - Sun Microsystems - Beijing China static int
304104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_ether_parse_header(mblk_t *mp)
304204b6cca3Slucy wang - Sun Microsystems - Beijing China {
304304b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct ether_header eh_copy;
304404b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct ether_header *eh;
304504b6cca3Slucy wang - Sun Microsystems - Beijing China 	int eth_hdr_len, seglen;
304604b6cca3Slucy wang - Sun Microsystems - Beijing China 
304704b6cca3Slucy wang - Sun Microsystems - Beijing China 	seglen = MBLKL(mp);
304804b6cca3Slucy wang - Sun Microsystems - Beijing China 	eth_hdr_len = sizeof (*eh);
304904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (seglen < eth_hdr_len) {
305004b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_copydata(mp, 0, eth_hdr_len, (caddr_t)&eh_copy);
305104b6cca3Slucy wang - Sun Microsystems - Beijing China 		eh = &eh_copy;
305204b6cca3Slucy wang - Sun Microsystems - Beijing China 	} else {
305304b6cca3Slucy wang - Sun Microsystems - Beijing China 		eh = (struct ether_header *)(void *)mp->b_rptr;
305404b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
305504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (eh->ether_type == BE_16(ETHERTYPE_VLAN)) {
305604b6cca3Slucy wang - Sun Microsystems - Beijing China 		eth_hdr_len += 4;
305704b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
305804b6cca3Slucy wang - Sun Microsystems - Beijing China 
305904b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (eth_hdr_len);
306004b6cca3Slucy wang - Sun Microsystems - Beijing China }
306104b6cca3Slucy wang - Sun Microsystems - Beijing China 
306204b6cca3Slucy wang - Sun Microsystems - Beijing China static int
306304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_lso_parse_header(mblk_t *mp, int off)
306404b6cca3Slucy wang - Sun Microsystems - Beijing China {
306504b6cca3Slucy wang - Sun Microsystems - Beijing China 	char buf[128];
306691e18787Slucy wang - Sun Microsystems - Beijing China 	int seglen, sum_off;
306704b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct ip *ip;
306804b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct tcphdr *tcp;
306904b6cca3Slucy wang - Sun Microsystems - Beijing China 
307004b6cca3Slucy wang - Sun Microsystems - Beijing China 	seglen = MBLKL(mp);
307104b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (seglen < off + sizeof (*ip)) {
307204b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_copydata(mp, off, sizeof (*ip), buf);
307304b6cca3Slucy wang - Sun Microsystems - Beijing China 		ip = (struct ip *)(void *)buf;
307404b6cca3Slucy wang - Sun Microsystems - Beijing China 	} else {
307504b6cca3Slucy wang - Sun Microsystems - Beijing China 		ip = (struct ip *)(void *)(mp->b_rptr + off);
307604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
307704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (seglen < off + (ip->ip_hl << 2) + sizeof (*tcp)) {
307804b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_copydata(mp, off,
307904b6cca3Slucy wang - Sun Microsystems - Beijing China 		    (ip->ip_hl << 2) + sizeof (*tcp), buf);
308004b6cca3Slucy wang - Sun Microsystems - Beijing China 		ip = (struct ip *)(void *)buf;
308104b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
308204b6cca3Slucy wang - Sun Microsystems - Beijing China 	tcp = (struct tcphdr *)(void *)((char *)ip + (ip->ip_hl << 2));
308391e18787Slucy wang - Sun Microsystems - Beijing China 
308491e18787Slucy wang - Sun Microsystems - Beijing China 	/*
308591e18787Slucy wang - Sun Microsystems - Beijing China 	 * NIC expects ip_sum to be zero.  Recent changes to
308691e18787Slucy wang - Sun Microsystems - Beijing China 	 * OpenSolaris leave the correct ip checksum there, rather
308791e18787Slucy wang - Sun Microsystems - Beijing China 	 * than the required zero, so we need to zero it.  Otherwise,
308891e18787Slucy wang - Sun Microsystems - Beijing China 	 * the NIC will produce bad checksums when sending LSO packets.
308991e18787Slucy wang - Sun Microsystems - Beijing China 	 */
309091e18787Slucy wang - Sun Microsystems - Beijing China 	if (ip->ip_sum != 0) {
309191e18787Slucy wang - Sun Microsystems - Beijing China 		if (((char *)ip) != buf) {
309291e18787Slucy wang - Sun Microsystems - Beijing China 			/* ip points into mblk, so just zero it */
309391e18787Slucy wang - Sun Microsystems - Beijing China 			ip->ip_sum = 0;
309491e18787Slucy wang - Sun Microsystems - Beijing China 		} else {
309591e18787Slucy wang - Sun Microsystems - Beijing China 			/*
309691e18787Slucy wang - Sun Microsystems - Beijing China 			 * ip points into a copy, so walk the chain
309791e18787Slucy wang - Sun Microsystems - Beijing China 			 * to find the ip_csum, then zero it
309891e18787Slucy wang - Sun Microsystems - Beijing China 			 */
309991e18787Slucy wang - Sun Microsystems - Beijing China 			sum_off = off + _PTRDIFF(&ip->ip_sum, buf);
310091e18787Slucy wang - Sun Microsystems - Beijing China 			while (sum_off > (int)(MBLKL(mp) - 1)) {
310191e18787Slucy wang - Sun Microsystems - Beijing China 				sum_off -= MBLKL(mp);
310291e18787Slucy wang - Sun Microsystems - Beijing China 				mp = mp->b_cont;
310391e18787Slucy wang - Sun Microsystems - Beijing China 			}
310491e18787Slucy wang - Sun Microsystems - Beijing China 			mp->b_rptr[sum_off] = 0;
310591e18787Slucy wang - Sun Microsystems - Beijing China 			sum_off++;
310691e18787Slucy wang - Sun Microsystems - Beijing China 			while (sum_off > MBLKL(mp) - 1) {
310791e18787Slucy wang - Sun Microsystems - Beijing China 				sum_off -= MBLKL(mp);
310891e18787Slucy wang - Sun Microsystems - Beijing China 				mp = mp->b_cont;
310991e18787Slucy wang - Sun Microsystems - Beijing China 			}
311091e18787Slucy wang - Sun Microsystems - Beijing China 			mp->b_rptr[sum_off] = 0;
311191e18787Slucy wang - Sun Microsystems - Beijing China 		}
311291e18787Slucy wang - Sun Microsystems - Beijing China 	}
311304b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (off + ((ip->ip_hl + tcp->th_off) << 2));
311404b6cca3Slucy wang - Sun Microsystems - Beijing China }
311504b6cca3Slucy wang - Sun Microsystems - Beijing China 
311604b6cca3Slucy wang - Sun Microsystems - Beijing China static int
311704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_tso_copy(struct myri10ge_slice_state *ss, mblk_t *mp,
311804b6cca3Slucy wang - Sun Microsystems - Beijing China     mcp_kreq_ether_send_t *req_list, int hdr_size, int pkt_size,
311904b6cca3Slucy wang - Sun Microsystems - Beijing China     uint16_t mss, uint8_t cksum_offset)
312004b6cca3Slucy wang - Sun Microsystems - Beijing China {
312104b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_tx_ring_t *tx = &ss->tx;
312204b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp = ss->mgp;
312304b6cca3Slucy wang - Sun Microsystems - Beijing China 	mblk_t *bp;
312404b6cca3Slucy wang - Sun Microsystems - Beijing China 	mcp_kreq_ether_send_t *req;
312504b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_tx_copybuf *cp;
312604b6cca3Slucy wang - Sun Microsystems - Beijing China 	caddr_t rptr, ptr;
312704b6cca3Slucy wang - Sun Microsystems - Beijing China 	int mblen, count, cum_len, mss_resid, tx_req, pkt_size_tmp;
312804b6cca3Slucy wang - Sun Microsystems - Beijing China 	int resid, avail, idx, hdr_size_tmp, tx_boundary;
312904b6cca3Slucy wang - Sun Microsystems - Beijing China 	int rdma_count;
313004b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint32_t seglen, len, boundary, low, high_swapped;
313104b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint16_t pseudo_hdr_offset = htons(mss);
313204b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint8_t flags;
313304b6cca3Slucy wang - Sun Microsystems - Beijing China 
313404b6cca3Slucy wang - Sun Microsystems - Beijing China 	tx_boundary = mgp->tx_boundary;
313504b6cca3Slucy wang - Sun Microsystems - Beijing China 	hdr_size_tmp = hdr_size;
313604b6cca3Slucy wang - Sun Microsystems - Beijing China 	resid = tx_boundary;
313704b6cca3Slucy wang - Sun Microsystems - Beijing China 	count = 1;
313804b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&tx->lock);
313904b6cca3Slucy wang - Sun Microsystems - Beijing China 
314004b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* check to see if the slots are really there */
314104b6cca3Slucy wang - Sun Microsystems - Beijing China 	avail = tx->mask - (tx->req - tx->done);
314204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (unlikely(avail <=  MYRI10GE_MAX_SEND_DESC_TSO)) {
31431a5e258fSJosef 'Jeff' Sipek 		atomic_inc_32(&tx->stall);
314404b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_exit(&tx->lock);
314504b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (EBUSY);
314604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
314704b6cca3Slucy wang - Sun Microsystems - Beijing China 
314804b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* copy */
314904b6cca3Slucy wang - Sun Microsystems - Beijing China 	cum_len = -hdr_size;
315004b6cca3Slucy wang - Sun Microsystems - Beijing China 	count = 0;
315104b6cca3Slucy wang - Sun Microsystems - Beijing China 	req = req_list;
315204b6cca3Slucy wang - Sun Microsystems - Beijing China 	idx = tx->mask & tx->req;
315304b6cca3Slucy wang - Sun Microsystems - Beijing China 	cp = &tx->cp[idx];
315404b6cca3Slucy wang - Sun Microsystems - Beijing China 	low = ntohl(cp->dma.low);
315504b6cca3Slucy wang - Sun Microsystems - Beijing China 	ptr = cp->va;
315604b6cca3Slucy wang - Sun Microsystems - Beijing China 	cp->len = 0;
315704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mss) {
315804b6cca3Slucy wang - Sun Microsystems - Beijing China 		int payload = pkt_size - hdr_size;
315904b6cca3Slucy wang - Sun Microsystems - Beijing China 		uint16_t opackets = (payload / mss) + ((payload % mss) != 0);
316004b6cca3Slucy wang - Sun Microsystems - Beijing China 		tx->info[idx].ostat.opackets = opackets;
316104b6cca3Slucy wang - Sun Microsystems - Beijing China 		tx->info[idx].ostat.obytes = (opackets - 1) * hdr_size
316204b6cca3Slucy wang - Sun Microsystems - Beijing China 		    + pkt_size;
316304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
316404b6cca3Slucy wang - Sun Microsystems - Beijing China 	hdr_size_tmp = hdr_size;
316504b6cca3Slucy wang - Sun Microsystems - Beijing China 	mss_resid = mss;
316604b6cca3Slucy wang - Sun Microsystems - Beijing China 	flags = (MXGEFW_FLAGS_TSO_HDR | MXGEFW_FLAGS_FIRST);
316704b6cca3Slucy wang - Sun Microsystems - Beijing China 	tx_req = tx->req;
316804b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (bp = mp; bp != NULL; bp = bp->b_cont) {
316904b6cca3Slucy wang - Sun Microsystems - Beijing China 		mblen = MBLKL(bp);
317004b6cca3Slucy wang - Sun Microsystems - Beijing China 		rptr = (caddr_t)bp->b_rptr;
317104b6cca3Slucy wang - Sun Microsystems - Beijing China 		len = min(hdr_size_tmp, mblen);
317204b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (len) {
317304b6cca3Slucy wang - Sun Microsystems - Beijing China 			bcopy(rptr, ptr, len);
317404b6cca3Slucy wang - Sun Microsystems - Beijing China 			rptr += len;
317504b6cca3Slucy wang - Sun Microsystems - Beijing China 			ptr += len;
317604b6cca3Slucy wang - Sun Microsystems - Beijing China 			resid -= len;
317704b6cca3Slucy wang - Sun Microsystems - Beijing China 			mblen -= len;
317804b6cca3Slucy wang - Sun Microsystems - Beijing China 			hdr_size_tmp -= len;
317904b6cca3Slucy wang - Sun Microsystems - Beijing China 			cp->len += len;
318004b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (hdr_size_tmp)
318104b6cca3Slucy wang - Sun Microsystems - Beijing China 				continue;
318204b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (resid < mss) {
318304b6cca3Slucy wang - Sun Microsystems - Beijing China 				tx_req++;
318404b6cca3Slucy wang - Sun Microsystems - Beijing China 				idx = tx->mask & tx_req;
318504b6cca3Slucy wang - Sun Microsystems - Beijing China 				cp = &tx->cp[idx];
318604b6cca3Slucy wang - Sun Microsystems - Beijing China 				low = ntohl(cp->dma.low);
318704b6cca3Slucy wang - Sun Microsystems - Beijing China 				ptr = cp->va;
318804b6cca3Slucy wang - Sun Microsystems - Beijing China 				resid = tx_boundary;
318904b6cca3Slucy wang - Sun Microsystems - Beijing China 			}
319004b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
319104b6cca3Slucy wang - Sun Microsystems - Beijing China 		while (mblen) {
319204b6cca3Slucy wang - Sun Microsystems - Beijing China 			len = min(mss_resid, mblen);
319304b6cca3Slucy wang - Sun Microsystems - Beijing China 			bcopy(rptr, ptr, len);
319404b6cca3Slucy wang - Sun Microsystems - Beijing China 			mss_resid -= len;
319504b6cca3Slucy wang - Sun Microsystems - Beijing China 			resid -= len;
319604b6cca3Slucy wang - Sun Microsystems - Beijing China 			mblen -= len;
319704b6cca3Slucy wang - Sun Microsystems - Beijing China 			rptr += len;
319804b6cca3Slucy wang - Sun Microsystems - Beijing China 			ptr += len;
319904b6cca3Slucy wang - Sun Microsystems - Beijing China 			cp->len += len;
320004b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (mss_resid == 0) {
320104b6cca3Slucy wang - Sun Microsystems - Beijing China 				mss_resid = mss;
320204b6cca3Slucy wang - Sun Microsystems - Beijing China 				if (resid < mss) {
320304b6cca3Slucy wang - Sun Microsystems - Beijing China 					tx_req++;
320404b6cca3Slucy wang - Sun Microsystems - Beijing China 					idx = tx->mask & tx_req;
320504b6cca3Slucy wang - Sun Microsystems - Beijing China 					cp = &tx->cp[idx];
320604b6cca3Slucy wang - Sun Microsystems - Beijing China 					cp->len = 0;
320704b6cca3Slucy wang - Sun Microsystems - Beijing China 					low = ntohl(cp->dma.low);
320804b6cca3Slucy wang - Sun Microsystems - Beijing China 					ptr = cp->va;
320904b6cca3Slucy wang - Sun Microsystems - Beijing China 					resid = tx_boundary;
321004b6cca3Slucy wang - Sun Microsystems - Beijing China 				}
321104b6cca3Slucy wang - Sun Microsystems - Beijing China 			}
321204b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
321304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
321404b6cca3Slucy wang - Sun Microsystems - Beijing China 
321504b6cca3Slucy wang - Sun Microsystems - Beijing China 	req = req_list;
321604b6cca3Slucy wang - Sun Microsystems - Beijing China 	pkt_size_tmp = pkt_size;
321704b6cca3Slucy wang - Sun Microsystems - Beijing China 	count = 0;
321804b6cca3Slucy wang - Sun Microsystems - Beijing China 	rdma_count = 0;
321904b6cca3Slucy wang - Sun Microsystems - Beijing China 	tx_req = tx->req;
322004b6cca3Slucy wang - Sun Microsystems - Beijing China 	while (pkt_size_tmp) {
322104b6cca3Slucy wang - Sun Microsystems - Beijing China 		idx = tx->mask & tx_req;
322204b6cca3Slucy wang - Sun Microsystems - Beijing China 		cp = &tx->cp[idx];
322304b6cca3Slucy wang - Sun Microsystems - Beijing China 		high_swapped = cp->dma.high;
322404b6cca3Slucy wang - Sun Microsystems - Beijing China 		low = ntohl(cp->dma.low);
322504b6cca3Slucy wang - Sun Microsystems - Beijing China 		len = cp->len;
322604b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (len == 0) {
322704b6cca3Slucy wang - Sun Microsystems - Beijing China 			printf("len=0! pkt_size_tmp=%d, pkt_size=%d\n",
322804b6cca3Slucy wang - Sun Microsystems - Beijing China 			    pkt_size_tmp, pkt_size);
322904b6cca3Slucy wang - Sun Microsystems - Beijing China 			for (bp = mp; bp != NULL; bp = bp->b_cont) {
323004b6cca3Slucy wang - Sun Microsystems - Beijing China 				mblen = MBLKL(bp);
323104b6cca3Slucy wang - Sun Microsystems - Beijing China 				printf("mblen:%d\n", mblen);
323204b6cca3Slucy wang - Sun Microsystems - Beijing China 			}
323304b6cca3Slucy wang - Sun Microsystems - Beijing China 			pkt_size_tmp = pkt_size;
323404b6cca3Slucy wang - Sun Microsystems - Beijing China 			tx_req = tx->req;
323504b6cca3Slucy wang - Sun Microsystems - Beijing China 			while (pkt_size_tmp > 0) {
323604b6cca3Slucy wang - Sun Microsystems - Beijing China 				idx = tx->mask & tx_req;
323704b6cca3Slucy wang - Sun Microsystems - Beijing China 				cp = &tx->cp[idx];
323804b6cca3Slucy wang - Sun Microsystems - Beijing China 				printf("cp->len = %d\n", cp->len);
323904b6cca3Slucy wang - Sun Microsystems - Beijing China 				pkt_size_tmp -= cp->len;
324004b6cca3Slucy wang - Sun Microsystems - Beijing China 				tx_req++;
324104b6cca3Slucy wang - Sun Microsystems - Beijing China 			}
324204b6cca3Slucy wang - Sun Microsystems - Beijing China 			printf("dropped\n");
324304b6cca3Slucy wang - Sun Microsystems - Beijing China 			MYRI10GE_ATOMIC_SLICE_STAT_INC(xmit_err);
324404b6cca3Slucy wang - Sun Microsystems - Beijing China 			goto done;
324504b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
324604b6cca3Slucy wang - Sun Microsystems - Beijing China 		pkt_size_tmp -= len;
324704b6cca3Slucy wang - Sun Microsystems - Beijing China 		while (len) {
324804b6cca3Slucy wang - Sun Microsystems - Beijing China 			while (len) {
324904b6cca3Slucy wang - Sun Microsystems - Beijing China 				uint8_t flags_next;
325004b6cca3Slucy wang - Sun Microsystems - Beijing China 				int cum_len_next;
325104b6cca3Slucy wang - Sun Microsystems - Beijing China 
325204b6cca3Slucy wang - Sun Microsystems - Beijing China 				boundary = (low + mgp->tx_boundary) &
325304b6cca3Slucy wang - Sun Microsystems - Beijing China 				    ~(mgp->tx_boundary - 1);
325404b6cca3Slucy wang - Sun Microsystems - Beijing China 				seglen = boundary - low;
325504b6cca3Slucy wang - Sun Microsystems - Beijing China 				if (seglen > len)
325604b6cca3Slucy wang - Sun Microsystems - Beijing China 					seglen = len;
325704b6cca3Slucy wang - Sun Microsystems - Beijing China 
325804b6cca3Slucy wang - Sun Microsystems - Beijing China 				flags_next = flags & ~MXGEFW_FLAGS_FIRST;
325904b6cca3Slucy wang - Sun Microsystems - Beijing China 				cum_len_next = cum_len + seglen;
326004b6cca3Slucy wang - Sun Microsystems - Beijing China 				(req-rdma_count)->rdma_count = rdma_count + 1;
326104b6cca3Slucy wang - Sun Microsystems - Beijing China 				if (likely(cum_len >= 0)) {
326204b6cca3Slucy wang - Sun Microsystems - Beijing China 					/* payload */
326304b6cca3Slucy wang - Sun Microsystems - Beijing China 					int next_is_first, chop;
326404b6cca3Slucy wang - Sun Microsystems - Beijing China 
326504b6cca3Slucy wang - Sun Microsystems - Beijing China 					chop = (cum_len_next > mss);
326604b6cca3Slucy wang - Sun Microsystems - Beijing China 					cum_len_next = cum_len_next % mss;
326704b6cca3Slucy wang - Sun Microsystems - Beijing China 					next_is_first = (cum_len_next == 0);
326804b6cca3Slucy wang - Sun Microsystems - Beijing China 					flags |= chop *
326904b6cca3Slucy wang - Sun Microsystems - Beijing China 					    MXGEFW_FLAGS_TSO_CHOP;
327004b6cca3Slucy wang - Sun Microsystems - Beijing China 					flags_next |= next_is_first *
327104b6cca3Slucy wang - Sun Microsystems - Beijing China 					    MXGEFW_FLAGS_FIRST;
327204b6cca3Slucy wang - Sun Microsystems - Beijing China 					rdma_count |= -(chop | next_is_first);
327304b6cca3Slucy wang - Sun Microsystems - Beijing China 					rdma_count += chop & !next_is_first;
327404b6cca3Slucy wang - Sun Microsystems - Beijing China 				} else if (likely(cum_len_next >= 0)) {
327504b6cca3Slucy wang - Sun Microsystems - Beijing China 					/* header ends */
327604b6cca3Slucy wang - Sun Microsystems - Beijing China 					int small;
327704b6cca3Slucy wang - Sun Microsystems - Beijing China 
327804b6cca3Slucy wang - Sun Microsystems - Beijing China 					rdma_count = -1;
327904b6cca3Slucy wang - Sun Microsystems - Beijing China 					cum_len_next = 0;
328004b6cca3Slucy wang - Sun Microsystems - Beijing China 					seglen = -cum_len;
328104b6cca3Slucy wang - Sun Microsystems - Beijing China 					small = (mss <= MXGEFW_SEND_SMALL_SIZE);
328204b6cca3Slucy wang - Sun Microsystems - Beijing China 					flags_next = MXGEFW_FLAGS_TSO_PLD |
328304b6cca3Slucy wang - Sun Microsystems - Beijing China 					    MXGEFW_FLAGS_FIRST |
328404b6cca3Slucy wang - Sun Microsystems - Beijing China 					    (small * MXGEFW_FLAGS_SMALL);
328504b6cca3Slucy wang - Sun Microsystems - Beijing China 				}
328604b6cca3Slucy wang - Sun Microsystems - Beijing China 				req->addr_high = high_swapped;
328704b6cca3Slucy wang - Sun Microsystems - Beijing China 				req->addr_low = htonl(low);
328804b6cca3Slucy wang - Sun Microsystems - Beijing China 				req->pseudo_hdr_offset = pseudo_hdr_offset;
328904b6cca3Slucy wang - Sun Microsystems - Beijing China 				req->pad = 0; /* complete solid 16-byte block */
329004b6cca3Slucy wang - Sun Microsystems - Beijing China 				req->rdma_count = 1;
329104b6cca3Slucy wang - Sun Microsystems - Beijing China 				req->cksum_offset = cksum_offset;
329204b6cca3Slucy wang - Sun Microsystems - Beijing China 				req->length = htons(seglen);
329304b6cca3Slucy wang - Sun Microsystems - Beijing China 				req->flags = flags | ((cum_len & 1) *
329404b6cca3Slucy wang - Sun Microsystems - Beijing China 				    MXGEFW_FLAGS_ALIGN_ODD);
329504b6cca3Slucy wang - Sun Microsystems - Beijing China 				if (cksum_offset > seglen)
329604b6cca3Slucy wang - Sun Microsystems - Beijing China 					cksum_offset -= seglen;
329704b6cca3Slucy wang - Sun Microsystems - Beijing China 				else
329804b6cca3Slucy wang - Sun Microsystems - Beijing China 					cksum_offset = 0;
329904b6cca3Slucy wang - Sun Microsystems - Beijing China 				low += seglen;
330004b6cca3Slucy wang - Sun Microsystems - Beijing China 				len -= seglen;
330104b6cca3Slucy wang - Sun Microsystems - Beijing China 				cum_len = cum_len_next;
330204b6cca3Slucy wang - Sun Microsystems - Beijing China 				req++;
330304b6cca3Slucy wang - Sun Microsystems - Beijing China 				req->flags = 0;
330404b6cca3Slucy wang - Sun Microsystems - Beijing China 				flags = flags_next;
330504b6cca3Slucy wang - Sun Microsystems - Beijing China 				count++;
330604b6cca3Slucy wang - Sun Microsystems - Beijing China 				rdma_count++;
330704b6cca3Slucy wang - Sun Microsystems - Beijing China 			}
330804b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
330904b6cca3Slucy wang - Sun Microsystems - Beijing China 		tx_req++;
331004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
331104b6cca3Slucy wang - Sun Microsystems - Beijing China 	(req-rdma_count)->rdma_count = (uint8_t)rdma_count;
331204b6cca3Slucy wang - Sun Microsystems - Beijing China 	do {
331304b6cca3Slucy wang - Sun Microsystems - Beijing China 		req--;
331404b6cca3Slucy wang - Sun Microsystems - Beijing China 		req->flags |= MXGEFW_FLAGS_TSO_LAST;
331504b6cca3Slucy wang - Sun Microsystems - Beijing China 	} while (!(req->flags & (MXGEFW_FLAGS_TSO_CHOP |
331604b6cca3Slucy wang - Sun Microsystems - Beijing China 	    MXGEFW_FLAGS_FIRST)));
331704b6cca3Slucy wang - Sun Microsystems - Beijing China 
331804b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_submit_req(tx, req_list, count);
331904b6cca3Slucy wang - Sun Microsystems - Beijing China done:
332004b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&tx->lock);
332104b6cca3Slucy wang - Sun Microsystems - Beijing China 	freemsg(mp);
332204b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
332304b6cca3Slucy wang - Sun Microsystems - Beijing China }
332404b6cca3Slucy wang - Sun Microsystems - Beijing China 
332504b6cca3Slucy wang - Sun Microsystems - Beijing China /*
332604b6cca3Slucy wang - Sun Microsystems - Beijing China  * Try to send the chain of buffers described by the mp.  We must not
332704b6cca3Slucy wang - Sun Microsystems - Beijing China  * encapsulate more than eth->tx.req - eth->tx.done, or
332804b6cca3Slucy wang - Sun Microsystems - Beijing China  * MXGEFW_MAX_SEND_DESC, whichever is more.
332904b6cca3Slucy wang - Sun Microsystems - Beijing China  */
333004b6cca3Slucy wang - Sun Microsystems - Beijing China 
333104b6cca3Slucy wang - Sun Microsystems - Beijing China static int
333204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_send(struct myri10ge_slice_state *ss, mblk_t *mp,
333304b6cca3Slucy wang - Sun Microsystems - Beijing China     mcp_kreq_ether_send_t *req_list, struct myri10ge_tx_buffer_state *tx_info)
333404b6cca3Slucy wang - Sun Microsystems - Beijing China {
333504b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp = ss->mgp;
333604b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_tx_ring_t *tx = &ss->tx;
333704b6cca3Slucy wang - Sun Microsystems - Beijing China 	mcp_kreq_ether_send_t *req;
333804b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_tx_dma_handle *handles, *dma_handle = NULL;
333904b6cca3Slucy wang - Sun Microsystems - Beijing China 	mblk_t  *bp;
334004b6cca3Slucy wang - Sun Microsystems - Beijing China 	ddi_dma_cookie_t cookie;
334104b6cca3Slucy wang - Sun Microsystems - Beijing China 	int err, rv, count, avail, mblen, try_pullup, i, max_segs, maclen,
334204b6cca3Slucy wang - Sun Microsystems - Beijing China 	    rdma_count, cum_len, lso_hdr_size;
334304b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint32_t start, stuff, tx_offload_flags;
334404b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint32_t seglen, len, mss, boundary, low, high_swapped;
334504b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint_t ncookies;
334604b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint16_t pseudo_hdr_offset;
334704b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint8_t flags, cksum_offset, odd_flag;
334804b6cca3Slucy wang - Sun Microsystems - Beijing China 	int pkt_size;
334904b6cca3Slucy wang - Sun Microsystems - Beijing China 	int lso_copy = myri10ge_lso_copy;
335004b6cca3Slucy wang - Sun Microsystems - Beijing China 	try_pullup = 1;
335104b6cca3Slucy wang - Sun Microsystems - Beijing China 
335204b6cca3Slucy wang - Sun Microsystems - Beijing China again:
335304b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* Setup checksum offloading, if needed */
33540dc2366fSVenugopal Iyer 	mac_hcksum_get(mp, &start, &stuff, NULL, NULL, &tx_offload_flags);
335504b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_lso_info_get(mp, &mss, &tx_offload_flags);
335604b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (tx_offload_flags & HW_LSO) {
335704b6cca3Slucy wang - Sun Microsystems - Beijing China 		max_segs = MYRI10GE_MAX_SEND_DESC_TSO;
335804b6cca3Slucy wang - Sun Microsystems - Beijing China 		if ((tx_offload_flags & HCK_PARTIALCKSUM) == 0) {
335904b6cca3Slucy wang - Sun Microsystems - Beijing China 			MYRI10GE_ATOMIC_SLICE_STAT_INC(xmit_lsobadflags);
336004b6cca3Slucy wang - Sun Microsystems - Beijing China 			freemsg(mp);
336104b6cca3Slucy wang - Sun Microsystems - Beijing China 			return (DDI_SUCCESS);
336204b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
336304b6cca3Slucy wang - Sun Microsystems - Beijing China 	} else {
336404b6cca3Slucy wang - Sun Microsystems - Beijing China 		max_segs = MXGEFW_MAX_SEND_DESC;
336504b6cca3Slucy wang - Sun Microsystems - Beijing China 		mss = 0;
336604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
336704b6cca3Slucy wang - Sun Microsystems - Beijing China 	req = req_list;
336804b6cca3Slucy wang - Sun Microsystems - Beijing China 	cksum_offset = 0;
336904b6cca3Slucy wang - Sun Microsystems - Beijing China 	pseudo_hdr_offset = 0;
337004b6cca3Slucy wang - Sun Microsystems - Beijing China 
337104b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* leave an extra slot keep the ring from wrapping */
337204b6cca3Slucy wang - Sun Microsystems - Beijing China 	avail = tx->mask - (tx->req - tx->done);
337304b6cca3Slucy wang - Sun Microsystems - Beijing China 
337404b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
337504b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * If we have > MXGEFW_MAX_SEND_DESC, then any over-length
337604b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * message will need to be pulled up in order to fit.
337704b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * Otherwise, we are low on transmit descriptors, it is
337804b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * probably better to stall and try again rather than pullup a
337904b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * message to fit.
338004b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
338104b6cca3Slucy wang - Sun Microsystems - Beijing China 
338204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (avail < max_segs) {
338304b6cca3Slucy wang - Sun Microsystems - Beijing China 		err = EBUSY;
33841a5e258fSJosef 'Jeff' Sipek 		atomic_inc_32(&tx->stall_early);
338504b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto stall;
338604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
338704b6cca3Slucy wang - Sun Microsystems - Beijing China 
338804b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* find out how long the frame is and how many segments it is */
338904b6cca3Slucy wang - Sun Microsystems - Beijing China 	count = 0;
339004b6cca3Slucy wang - Sun Microsystems - Beijing China 	odd_flag = 0;
339104b6cca3Slucy wang - Sun Microsystems - Beijing China 	pkt_size = 0;
339204b6cca3Slucy wang - Sun Microsystems - Beijing China 	flags = (MXGEFW_FLAGS_NO_TSO | MXGEFW_FLAGS_FIRST);
339304b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (bp = mp; bp != NULL; bp = bp->b_cont) {
339404b6cca3Slucy wang - Sun Microsystems - Beijing China 		dblk_t *dbp;
339504b6cca3Slucy wang - Sun Microsystems - Beijing China 		mblen = MBLKL(bp);
339604b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (mblen == 0) {
339704b6cca3Slucy wang - Sun Microsystems - Beijing China 			/*
339804b6cca3Slucy wang - Sun Microsystems - Beijing China 			 * we can't simply skip over 0-length mblks
339904b6cca3Slucy wang - Sun Microsystems - Beijing China 			 * because the hardware can't deal with them,
340004b6cca3Slucy wang - Sun Microsystems - Beijing China 			 * and we could leak them.
340104b6cca3Slucy wang - Sun Microsystems - Beijing China 			 */
340204b6cca3Slucy wang - Sun Microsystems - Beijing China 			MYRI10GE_ATOMIC_SLICE_STAT_INC(xmit_zero_len);
340304b6cca3Slucy wang - Sun Microsystems - Beijing China 			err = EIO;
340404b6cca3Slucy wang - Sun Microsystems - Beijing China 			goto pullup;
340504b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
340604b6cca3Slucy wang - Sun Microsystems - Beijing China 		/*
340704b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * There's no advantage to copying most gesballoc
340804b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * attached blocks, so disable lso copy in that case
340904b6cca3Slucy wang - Sun Microsystems - Beijing China 		 */
341004b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (mss && lso_copy == 1 && ((dbp = bp->b_datap) != NULL)) {
341104b6cca3Slucy wang - Sun Microsystems - Beijing China 			if ((void *)dbp->db_lastfree != myri10ge_db_lastfree) {
341204b6cca3Slucy wang - Sun Microsystems - Beijing China 				lso_copy = 0;
341304b6cca3Slucy wang - Sun Microsystems - Beijing China 			}
341404b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
341504b6cca3Slucy wang - Sun Microsystems - Beijing China 		pkt_size += mblen;
341604b6cca3Slucy wang - Sun Microsystems - Beijing China 		count++;
341704b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
341804b6cca3Slucy wang - Sun Microsystems - Beijing China 
341904b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* Try to pull up excessivly long chains */
342004b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (count >= max_segs) {
342104b6cca3Slucy wang - Sun Microsystems - Beijing China 		err = myri10ge_pullup(ss, mp);
342204b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (likely(err == DDI_SUCCESS)) {
342304b6cca3Slucy wang - Sun Microsystems - Beijing China 			count = 1;
342404b6cca3Slucy wang - Sun Microsystems - Beijing China 		} else {
342504b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (count <  MYRI10GE_MAX_SEND_DESC_TSO) {
342604b6cca3Slucy wang - Sun Microsystems - Beijing China 				/*
342704b6cca3Slucy wang - Sun Microsystems - Beijing China 				 * just let the h/w send it, it will be
342804b6cca3Slucy wang - Sun Microsystems - Beijing China 				 * inefficient, but us better than dropping
342904b6cca3Slucy wang - Sun Microsystems - Beijing China 				 */
343004b6cca3Slucy wang - Sun Microsystems - Beijing China 				max_segs = MYRI10GE_MAX_SEND_DESC_TSO;
343104b6cca3Slucy wang - Sun Microsystems - Beijing China 			} else {
343204b6cca3Slucy wang - Sun Microsystems - Beijing China 				/* drop it */
343304b6cca3Slucy wang - Sun Microsystems - Beijing China 				MYRI10GE_ATOMIC_SLICE_STAT_INC(xmit_err);
343404b6cca3Slucy wang - Sun Microsystems - Beijing China 				freemsg(mp);
343504b6cca3Slucy wang - Sun Microsystems - Beijing China 				return (0);
343604b6cca3Slucy wang - Sun Microsystems - Beijing China 			}
343704b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
343804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
343904b6cca3Slucy wang - Sun Microsystems - Beijing China 
344004b6cca3Slucy wang - Sun Microsystems - Beijing China 	cum_len = 0;
344104b6cca3Slucy wang - Sun Microsystems - Beijing China 	maclen = myri10ge_ether_parse_header(mp);
344204b6cca3Slucy wang - Sun Microsystems - Beijing China 
344304b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (tx_offload_flags & HCK_PARTIALCKSUM) {
344404b6cca3Slucy wang - Sun Microsystems - Beijing China 
344504b6cca3Slucy wang - Sun Microsystems - Beijing China 		cksum_offset = start + maclen;
344604b6cca3Slucy wang - Sun Microsystems - Beijing China 		pseudo_hdr_offset = htons(stuff + maclen);
344704b6cca3Slucy wang - Sun Microsystems - Beijing China 		odd_flag = MXGEFW_FLAGS_ALIGN_ODD;
344804b6cca3Slucy wang - Sun Microsystems - Beijing China 		flags |= MXGEFW_FLAGS_CKSUM;
344904b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
345004b6cca3Slucy wang - Sun Microsystems - Beijing China 
345104b6cca3Slucy wang - Sun Microsystems - Beijing China 	lso_hdr_size = 0; /* -Wunitinialized */
345204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mss) { /* LSO */
345304b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* this removes any CKSUM flag from before */
345404b6cca3Slucy wang - Sun Microsystems - Beijing China 		flags = (MXGEFW_FLAGS_TSO_HDR | MXGEFW_FLAGS_FIRST);
345504b6cca3Slucy wang - Sun Microsystems - Beijing China 		/*
345604b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * parse the headers and set cum_len to a negative
345704b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * value to reflect the offset of the TCP payload
345804b6cca3Slucy wang - Sun Microsystems - Beijing China 		 */
345904b6cca3Slucy wang - Sun Microsystems - Beijing China 		lso_hdr_size =  myri10ge_lso_parse_header(mp, maclen);
346004b6cca3Slucy wang - Sun Microsystems - Beijing China 		cum_len = -lso_hdr_size;
346104b6cca3Slucy wang - Sun Microsystems - Beijing China 		if ((mss < mgp->tx_boundary) && lso_copy) {
346204b6cca3Slucy wang - Sun Microsystems - Beijing China 			err = myri10ge_tx_tso_copy(ss, mp, req_list,
346304b6cca3Slucy wang - Sun Microsystems - Beijing China 			    lso_hdr_size, pkt_size, mss, cksum_offset);
346404b6cca3Slucy wang - Sun Microsystems - Beijing China 			return (err);
346504b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
346604b6cca3Slucy wang - Sun Microsystems - Beijing China 
346704b6cca3Slucy wang - Sun Microsystems - Beijing China 		/*
346804b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * for TSO, pseudo_hdr_offset holds mss.  The firmware
346904b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * figures out where to put the checksum by parsing
347004b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * the header.
347104b6cca3Slucy wang - Sun Microsystems - Beijing China 		 */
347204b6cca3Slucy wang - Sun Microsystems - Beijing China 
347304b6cca3Slucy wang - Sun Microsystems - Beijing China 		pseudo_hdr_offset = htons(mss);
347404b6cca3Slucy wang - Sun Microsystems - Beijing China 	} else if (pkt_size <= MXGEFW_SEND_SMALL_SIZE) {
347504b6cca3Slucy wang - Sun Microsystems - Beijing China 		flags |= MXGEFW_FLAGS_SMALL;
347604b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (pkt_size < myri10ge_tx_copylen) {
347704b6cca3Slucy wang - Sun Microsystems - Beijing China 			req->cksum_offset = cksum_offset;
347804b6cca3Slucy wang - Sun Microsystems - Beijing China 			req->pseudo_hdr_offset = pseudo_hdr_offset;
347904b6cca3Slucy wang - Sun Microsystems - Beijing China 			req->flags = flags;
348004b6cca3Slucy wang - Sun Microsystems - Beijing China 			err = myri10ge_tx_copy(ss, mp, req);
348104b6cca3Slucy wang - Sun Microsystems - Beijing China 			return (err);
348204b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
348304b6cca3Slucy wang - Sun Microsystems - Beijing China 		cum_len = 0;
348404b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
348504b6cca3Slucy wang - Sun Microsystems - Beijing China 
348604b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* pull one DMA handle for each bp from our freelist */
348704b6cca3Slucy wang - Sun Microsystems - Beijing China 	handles = NULL;
348804b6cca3Slucy wang - Sun Microsystems - Beijing China 	err = myri10ge_alloc_tx_handles(ss, count, &handles);
348904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
349004b6cca3Slucy wang - Sun Microsystems - Beijing China 		err = DDI_FAILURE;
349104b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto stall;
349204b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
349304b6cca3Slucy wang - Sun Microsystems - Beijing China 	count = 0;
349404b6cca3Slucy wang - Sun Microsystems - Beijing China 	rdma_count = 0;
349504b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (bp = mp; bp != NULL; bp = bp->b_cont) {
349604b6cca3Slucy wang - Sun Microsystems - Beijing China 		mblen = MBLKL(bp);
349704b6cca3Slucy wang - Sun Microsystems - Beijing China 		dma_handle = handles;
349804b6cca3Slucy wang - Sun Microsystems - Beijing China 		handles = handles->next;
349904b6cca3Slucy wang - Sun Microsystems - Beijing China 
350004b6cca3Slucy wang - Sun Microsystems - Beijing China 		rv = ddi_dma_addr_bind_handle(dma_handle->h, NULL,
350104b6cca3Slucy wang - Sun Microsystems - Beijing China 		    (caddr_t)bp->b_rptr, mblen,
350204b6cca3Slucy wang - Sun Microsystems - Beijing China 		    DDI_DMA_WRITE | DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL,
350304b6cca3Slucy wang - Sun Microsystems - Beijing China 		    &cookie, &ncookies);
350404b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (unlikely(rv != DDI_DMA_MAPPED)) {
350504b6cca3Slucy wang - Sun Microsystems - Beijing China 			err = EIO;
350604b6cca3Slucy wang - Sun Microsystems - Beijing China 			try_pullup = 0;
350704b6cca3Slucy wang - Sun Microsystems - Beijing China 			dma_handle->next = handles;
350804b6cca3Slucy wang - Sun Microsystems - Beijing China 			handles = dma_handle;
350904b6cca3Slucy wang - Sun Microsystems - Beijing China 			goto abort_with_handles;
351004b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
351104b6cca3Slucy wang - Sun Microsystems - Beijing China 
351204b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* reserve the slot */
351304b6cca3Slucy wang - Sun Microsystems - Beijing China 		tx_info[count].m = bp;
351404b6cca3Slucy wang - Sun Microsystems - Beijing China 		tx_info[count].handle = dma_handle;
351504b6cca3Slucy wang - Sun Microsystems - Beijing China 
351604b6cca3Slucy wang - Sun Microsystems - Beijing China 		for (; ; ) {
351704b6cca3Slucy wang - Sun Microsystems - Beijing China 			low = MYRI10GE_LOWPART_TO_U32(cookie.dmac_laddress);
351804b6cca3Slucy wang - Sun Microsystems - Beijing China 			high_swapped =
351904b6cca3Slucy wang - Sun Microsystems - Beijing China 			    htonl(MYRI10GE_HIGHPART_TO_U32(
352004b6cca3Slucy wang - Sun Microsystems - Beijing China 			    cookie.dmac_laddress));
352104b6cca3Slucy wang - Sun Microsystems - Beijing China 			len = (uint32_t)cookie.dmac_size;
352204b6cca3Slucy wang - Sun Microsystems - Beijing China 			while (len) {
352304b6cca3Slucy wang - Sun Microsystems - Beijing China 				uint8_t flags_next;
352404b6cca3Slucy wang - Sun Microsystems - Beijing China 				int cum_len_next;
352504b6cca3Slucy wang - Sun Microsystems - Beijing China 
352604b6cca3Slucy wang - Sun Microsystems - Beijing China 				boundary = (low + mgp->tx_boundary) &
352704b6cca3Slucy wang - Sun Microsystems - Beijing China 				    ~(mgp->tx_boundary - 1);
352804b6cca3Slucy wang - Sun Microsystems - Beijing China 				seglen = boundary - low;
352904b6cca3Slucy wang - Sun Microsystems - Beijing China 				if (seglen > len)
353004b6cca3Slucy wang - Sun Microsystems - Beijing China 					seglen = len;
353104b6cca3Slucy wang - Sun Microsystems - Beijing China 
353204b6cca3Slucy wang - Sun Microsystems - Beijing China 				flags_next = flags & ~MXGEFW_FLAGS_FIRST;
353304b6cca3Slucy wang - Sun Microsystems - Beijing China 				cum_len_next = cum_len + seglen;
353404b6cca3Slucy wang - Sun Microsystems - Beijing China 				if (mss) {
353504b6cca3Slucy wang - Sun Microsystems - Beijing China 					(req-rdma_count)->rdma_count =
353604b6cca3Slucy wang - Sun Microsystems - Beijing China 					    rdma_count + 1;
353704b6cca3Slucy wang - Sun Microsystems - Beijing China 					if (likely(cum_len >= 0)) {
353804b6cca3Slucy wang - Sun Microsystems - Beijing China 						/* payload */
353904b6cca3Slucy wang - Sun Microsystems - Beijing China 						int next_is_first, chop;
354004b6cca3Slucy wang - Sun Microsystems - Beijing China 
354104b6cca3Slucy wang - Sun Microsystems - Beijing China 						chop = (cum_len_next > mss);
354204b6cca3Slucy wang - Sun Microsystems - Beijing China 						cum_len_next =
354304b6cca3Slucy wang - Sun Microsystems - Beijing China 						    cum_len_next % mss;
354404b6cca3Slucy wang - Sun Microsystems - Beijing China 						next_is_first =
354504b6cca3Slucy wang - Sun Microsystems - Beijing China 						    (cum_len_next == 0);
354604b6cca3Slucy wang - Sun Microsystems - Beijing China 						flags |= chop *
354704b6cca3Slucy wang - Sun Microsystems - Beijing China 						    MXGEFW_FLAGS_TSO_CHOP;
354804b6cca3Slucy wang - Sun Microsystems - Beijing China 						flags_next |= next_is_first *
354904b6cca3Slucy wang - Sun Microsystems - Beijing China 						    MXGEFW_FLAGS_FIRST;
355004b6cca3Slucy wang - Sun Microsystems - Beijing China 						rdma_count |=
355104b6cca3Slucy wang - Sun Microsystems - Beijing China 						    -(chop | next_is_first);
355204b6cca3Slucy wang - Sun Microsystems - Beijing China 						rdma_count +=
355304b6cca3Slucy wang - Sun Microsystems - Beijing China 						    chop & !next_is_first;
355404b6cca3Slucy wang - Sun Microsystems - Beijing China 					} else if (likely(cum_len_next >= 0)) {
355504b6cca3Slucy wang - Sun Microsystems - Beijing China 						/* header ends */
355604b6cca3Slucy wang - Sun Microsystems - Beijing China 						int small;
355704b6cca3Slucy wang - Sun Microsystems - Beijing China 
355804b6cca3Slucy wang - Sun Microsystems - Beijing China 						rdma_count = -1;
355904b6cca3Slucy wang - Sun Microsystems - Beijing China 						cum_len_next = 0;
356004b6cca3Slucy wang - Sun Microsystems - Beijing China 						seglen = -cum_len;
356104b6cca3Slucy wang - Sun Microsystems - Beijing China 						small = (mss <=
356204b6cca3Slucy wang - Sun Microsystems - Beijing China 						    MXGEFW_SEND_SMALL_SIZE);
356304b6cca3Slucy wang - Sun Microsystems - Beijing China 						flags_next =
356404b6cca3Slucy wang - Sun Microsystems - Beijing China 						    MXGEFW_FLAGS_TSO_PLD
356504b6cca3Slucy wang - Sun Microsystems - Beijing China 						    | MXGEFW_FLAGS_FIRST
356604b6cca3Slucy wang - Sun Microsystems - Beijing China 						    | (small *
356704b6cca3Slucy wang - Sun Microsystems - Beijing China 						    MXGEFW_FLAGS_SMALL);
356804b6cca3Slucy wang - Sun Microsystems - Beijing China 					}
356904b6cca3Slucy wang - Sun Microsystems - Beijing China 				}
357004b6cca3Slucy wang - Sun Microsystems - Beijing China 				req->addr_high = high_swapped;
357104b6cca3Slucy wang - Sun Microsystems - Beijing China 				req->addr_low = htonl(low);
357204b6cca3Slucy wang - Sun Microsystems - Beijing China 				req->pseudo_hdr_offset = pseudo_hdr_offset;
357304b6cca3Slucy wang - Sun Microsystems - Beijing China 				req->pad = 0; /* complete solid 16-byte block */
357404b6cca3Slucy wang - Sun Microsystems - Beijing China 				req->rdma_count = 1;
357504b6cca3Slucy wang - Sun Microsystems - Beijing China 				req->cksum_offset = cksum_offset;
357604b6cca3Slucy wang - Sun Microsystems - Beijing China 				req->length = htons(seglen);
357704b6cca3Slucy wang - Sun Microsystems - Beijing China 				req->flags = flags | ((cum_len & 1) * odd_flag);
357804b6cca3Slucy wang - Sun Microsystems - Beijing China 				if (cksum_offset > seglen)
357904b6cca3Slucy wang - Sun Microsystems - Beijing China 					cksum_offset -= seglen;
358004b6cca3Slucy wang - Sun Microsystems - Beijing China 				else
358104b6cca3Slucy wang - Sun Microsystems - Beijing China 					cksum_offset = 0;
358204b6cca3Slucy wang - Sun Microsystems - Beijing China 				low += seglen;
358304b6cca3Slucy wang - Sun Microsystems - Beijing China 				len -= seglen;
358404b6cca3Slucy wang - Sun Microsystems - Beijing China 				cum_len = cum_len_next;
358504b6cca3Slucy wang - Sun Microsystems - Beijing China 				count++;
358604b6cca3Slucy wang - Sun Microsystems - Beijing China 				rdma_count++;
358704b6cca3Slucy wang - Sun Microsystems - Beijing China 				/*  make sure all the segments will fit */
358804b6cca3Slucy wang - Sun Microsystems - Beijing China 				if (unlikely(count >= max_segs)) {
358904b6cca3Slucy wang - Sun Microsystems - Beijing China 					MYRI10GE_ATOMIC_SLICE_STAT_INC(
359004b6cca3Slucy wang - Sun Microsystems - Beijing China 					    xmit_lowbuf);
359104b6cca3Slucy wang - Sun Microsystems - Beijing China 					/* may try a pullup */
359204b6cca3Slucy wang - Sun Microsystems - Beijing China 					err = EBUSY;
359304b6cca3Slucy wang - Sun Microsystems - Beijing China 					if (try_pullup)
359404b6cca3Slucy wang - Sun Microsystems - Beijing China 						try_pullup = 2;
359504b6cca3Slucy wang - Sun Microsystems - Beijing China 					goto abort_with_handles;
359604b6cca3Slucy wang - Sun Microsystems - Beijing China 				}
359704b6cca3Slucy wang - Sun Microsystems - Beijing China 				req++;
359804b6cca3Slucy wang - Sun Microsystems - Beijing China 				req->flags = 0;
359904b6cca3Slucy wang - Sun Microsystems - Beijing China 				flags = flags_next;
360004b6cca3Slucy wang - Sun Microsystems - Beijing China 				tx_info[count].m = 0;
360104b6cca3Slucy wang - Sun Microsystems - Beijing China 			}
360204b6cca3Slucy wang - Sun Microsystems - Beijing China 			ncookies--;
360304b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (ncookies == 0)
360404b6cca3Slucy wang - Sun Microsystems - Beijing China 				break;
360504b6cca3Slucy wang - Sun Microsystems - Beijing China 			ddi_dma_nextcookie(dma_handle->h, &cookie);
360604b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
360704b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
360804b6cca3Slucy wang - Sun Microsystems - Beijing China 	(req-rdma_count)->rdma_count = (uint8_t)rdma_count;
360904b6cca3Slucy wang - Sun Microsystems - Beijing China 
361004b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mss) {
361104b6cca3Slucy wang - Sun Microsystems - Beijing China 		do {
361204b6cca3Slucy wang - Sun Microsystems - Beijing China 			req--;
361304b6cca3Slucy wang - Sun Microsystems - Beijing China 			req->flags |= MXGEFW_FLAGS_TSO_LAST;
361404b6cca3Slucy wang - Sun Microsystems - Beijing China 		} while (!(req->flags & (MXGEFW_FLAGS_TSO_CHOP |
361504b6cca3Slucy wang - Sun Microsystems - Beijing China 		    MXGEFW_FLAGS_FIRST)));
361604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
361704b6cca3Slucy wang - Sun Microsystems - Beijing China 
361804b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* calculate tx stats */
361904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mss) {
362004b6cca3Slucy wang - Sun Microsystems - Beijing China 		uint16_t opackets;
362104b6cca3Slucy wang - Sun Microsystems - Beijing China 		int payload;
362204b6cca3Slucy wang - Sun Microsystems - Beijing China 
362304b6cca3Slucy wang - Sun Microsystems - Beijing China 		payload = pkt_size - lso_hdr_size;
362404b6cca3Slucy wang - Sun Microsystems - Beijing China 		opackets = (payload / mss) + ((payload % mss) != 0);
362504b6cca3Slucy wang - Sun Microsystems - Beijing China 		tx_info[0].stat.un.all = 0;
362604b6cca3Slucy wang - Sun Microsystems - Beijing China 		tx_info[0].ostat.opackets = opackets;
362704b6cca3Slucy wang - Sun Microsystems - Beijing China 		tx_info[0].ostat.obytes = (opackets - 1) * lso_hdr_size
362804b6cca3Slucy wang - Sun Microsystems - Beijing China 		    + pkt_size;
362904b6cca3Slucy wang - Sun Microsystems - Beijing China 	} else {
363004b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_tx_stat(&tx_info[0].stat,
363104b6cca3Slucy wang - Sun Microsystems - Beijing China 		    (struct ether_header *)(void *)mp->b_rptr, 1, pkt_size);
363204b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
363304b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&tx->lock);
363404b6cca3Slucy wang - Sun Microsystems - Beijing China 
363504b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* check to see if the slots are really there */
363604b6cca3Slucy wang - Sun Microsystems - Beijing China 	avail = tx->mask - (tx->req - tx->done);
363704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (unlikely(avail <= count)) {
363804b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_exit(&tx->lock);
363904b6cca3Slucy wang - Sun Microsystems - Beijing China 		err = 0;
364004b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto late_stall;
364104b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
364204b6cca3Slucy wang - Sun Microsystems - Beijing China 
364304b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_send_locked(tx, req_list, tx_info, count);
364404b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&tx->lock);
364504b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
364604b6cca3Slucy wang - Sun Microsystems - Beijing China 
364704b6cca3Slucy wang - Sun Microsystems - Beijing China late_stall:
364804b6cca3Slucy wang - Sun Microsystems - Beijing China 	try_pullup = 0;
36491a5e258fSJosef 'Jeff' Sipek 	atomic_inc_32(&tx->stall_late);
365004b6cca3Slucy wang - Sun Microsystems - Beijing China 
365104b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_handles:
365204b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* unbind and free handles from previous mblks */
365304b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (i = 0; i < count; i++) {
365404b6cca3Slucy wang - Sun Microsystems - Beijing China 		bp = tx_info[i].m;
365504b6cca3Slucy wang - Sun Microsystems - Beijing China 		tx_info[i].m = 0;
365604b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (bp) {
365704b6cca3Slucy wang - Sun Microsystems - Beijing China 			dma_handle = tx_info[i].handle;
365804b6cca3Slucy wang - Sun Microsystems - Beijing China 			(void) ddi_dma_unbind_handle(dma_handle->h);
365904b6cca3Slucy wang - Sun Microsystems - Beijing China 			dma_handle->next = handles;
366004b6cca3Slucy wang - Sun Microsystems - Beijing China 			handles = dma_handle;
366104b6cca3Slucy wang - Sun Microsystems - Beijing China 			tx_info[i].handle = NULL;
366204b6cca3Slucy wang - Sun Microsystems - Beijing China 			tx_info[i].m = NULL;
366304b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
366404b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
366504b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_free_tx_handle_slist(tx, handles);
366604b6cca3Slucy wang - Sun Microsystems - Beijing China pullup:
366704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (try_pullup) {
366804b6cca3Slucy wang - Sun Microsystems - Beijing China 		err = myri10ge_pullup(ss, mp);
366904b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (err != DDI_SUCCESS && try_pullup == 2) {
367004b6cca3Slucy wang - Sun Microsystems - Beijing China 			/* drop */
367104b6cca3Slucy wang - Sun Microsystems - Beijing China 			MYRI10GE_ATOMIC_SLICE_STAT_INC(xmit_err);
367204b6cca3Slucy wang - Sun Microsystems - Beijing China 			freemsg(mp);
367304b6cca3Slucy wang - Sun Microsystems - Beijing China 			return (0);
367404b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
367504b6cca3Slucy wang - Sun Microsystems - Beijing China 		try_pullup = 0;
367604b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto again;
367704b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
367804b6cca3Slucy wang - Sun Microsystems - Beijing China 
367904b6cca3Slucy wang - Sun Microsystems - Beijing China stall:
368004b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (err != 0) {
368104b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (err == EBUSY) {
36821a5e258fSJosef 'Jeff' Sipek 			atomic_inc_32(&tx->stall);
368304b6cca3Slucy wang - Sun Microsystems - Beijing China 		} else {
368404b6cca3Slucy wang - Sun Microsystems - Beijing China 			MYRI10GE_ATOMIC_SLICE_STAT_INC(xmit_err);
368504b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
368604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
368704b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (err);
368804b6cca3Slucy wang - Sun Microsystems - Beijing China }
368904b6cca3Slucy wang - Sun Microsystems - Beijing China 
369004b6cca3Slucy wang - Sun Microsystems - Beijing China static mblk_t *
369104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_send_wrapper(void *arg, mblk_t *mp)
369204b6cca3Slucy wang - Sun Microsystems - Beijing China {
369304b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_slice_state *ss = arg;
369404b6cca3Slucy wang - Sun Microsystems - Beijing China 	int err = 0;
369504b6cca3Slucy wang - Sun Microsystems - Beijing China 	mcp_kreq_ether_send_t *req_list;
369604b6cca3Slucy wang - Sun Microsystems - Beijing China #if defined(__i386)
369704b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
369804b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * We need about 2.5KB of scratch space to handle transmits.
369904b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * i86pc has only 8KB of kernel stack space, so we malloc the
370004b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * scratch space there rather than keeping it on the stack.
370104b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
370204b6cca3Slucy wang - Sun Microsystems - Beijing China 	size_t req_size, tx_info_size;
370304b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_tx_buffer_state *tx_info;
370404b6cca3Slucy wang - Sun Microsystems - Beijing China 	caddr_t req_bytes;
370504b6cca3Slucy wang - Sun Microsystems - Beijing China 
370604b6cca3Slucy wang - Sun Microsystems - Beijing China 	req_size = sizeof (*req_list) * (MYRI10GE_MAX_SEND_DESC_TSO + 4)
370704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    + 8;
370804b6cca3Slucy wang - Sun Microsystems - Beijing China 	req_bytes = kmem_alloc(req_size, KM_SLEEP);
370904b6cca3Slucy wang - Sun Microsystems - Beijing China 	tx_info_size = sizeof (*tx_info) * (MYRI10GE_MAX_SEND_DESC_TSO + 1);
371004b6cca3Slucy wang - Sun Microsystems - Beijing China 	tx_info = kmem_alloc(tx_info_size, KM_SLEEP);
371104b6cca3Slucy wang - Sun Microsystems - Beijing China #else
371204b6cca3Slucy wang - Sun Microsystems - Beijing China 	char req_bytes[sizeof (*req_list) * (MYRI10GE_MAX_SEND_DESC_TSO + 4)
371304b6cca3Slucy wang - Sun Microsystems - Beijing China 	    + 8];
371404b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_tx_buffer_state tx_info[MYRI10GE_MAX_SEND_DESC_TSO + 1];
371504b6cca3Slucy wang - Sun Microsystems - Beijing China #endif
371604b6cca3Slucy wang - Sun Microsystems - Beijing China 
371704b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* ensure req_list entries are aligned to 8 bytes */
371804b6cca3Slucy wang - Sun Microsystems - Beijing China 	req_list = (struct mcp_kreq_ether_send *)
371904b6cca3Slucy wang - Sun Microsystems - Beijing China 	    (((unsigned long)req_bytes + 7UL) & ~7UL);
372004b6cca3Slucy wang - Sun Microsystems - Beijing China 
372104b6cca3Slucy wang - Sun Microsystems - Beijing China 	err = myri10ge_send(ss, mp, req_list, tx_info);
372204b6cca3Slucy wang - Sun Microsystems - Beijing China 
372304b6cca3Slucy wang - Sun Microsystems - Beijing China #if defined(__i386)
372404b6cca3Slucy wang - Sun Microsystems - Beijing China 	kmem_free(tx_info, tx_info_size);
372504b6cca3Slucy wang - Sun Microsystems - Beijing China 	kmem_free(req_bytes, req_size);
372604b6cca3Slucy wang - Sun Microsystems - Beijing China #endif
372704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (err)
372804b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (mp);
372904b6cca3Slucy wang - Sun Microsystems - Beijing China 	else
373004b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (NULL);
373104b6cca3Slucy wang - Sun Microsystems - Beijing China }
373204b6cca3Slucy wang - Sun Microsystems - Beijing China 
373304b6cca3Slucy wang - Sun Microsystems - Beijing China static int
373404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_addmac(void *arg, const uint8_t *mac_addr)
373504b6cca3Slucy wang - Sun Microsystems - Beijing China {
373604b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp = arg;
373704b6cca3Slucy wang - Sun Microsystems - Beijing China 	int err;
373804b6cca3Slucy wang - Sun Microsystems - Beijing China 
373904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mac_addr == NULL)
374004b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (EINVAL);
374104b6cca3Slucy wang - Sun Microsystems - Beijing China 
374204b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&mgp->intrlock);
374304b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->macaddr_cnt) {
374404b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_exit(&mgp->intrlock);
374504b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (ENOSPC);
374604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
374704b6cca3Slucy wang - Sun Microsystems - Beijing China 	err = myri10ge_m_unicst(mgp, mac_addr);
374804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (!err)
374904b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->macaddr_cnt++;
375004b6cca3Slucy wang - Sun Microsystems - Beijing China 
375104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&mgp->intrlock);
375204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (err)
375304b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (err);
375404b6cca3Slucy wang - Sun Microsystems - Beijing China 
375504b6cca3Slucy wang - Sun Microsystems - Beijing China 	bcopy(mac_addr, mgp->mac_addr, sizeof (mgp->mac_addr));
375604b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
375704b6cca3Slucy wang - Sun Microsystems - Beijing China }
375804b6cca3Slucy wang - Sun Microsystems - Beijing China 
375904b6cca3Slucy wang - Sun Microsystems - Beijing China /*ARGSUSED*/
376004b6cca3Slucy wang - Sun Microsystems - Beijing China static int
376104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_remmac(void *arg, const uint8_t *mac_addr)
376204b6cca3Slucy wang - Sun Microsystems - Beijing China {
376304b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp = arg;
376404b6cca3Slucy wang - Sun Microsystems - Beijing China 
376504b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&mgp->intrlock);
376604b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->macaddr_cnt--;
376704b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&mgp->intrlock);
376804b6cca3Slucy wang - Sun Microsystems - Beijing China 
376904b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
377004b6cca3Slucy wang - Sun Microsystems - Beijing China }
377104b6cca3Slucy wang - Sun Microsystems - Beijing China 
377204b6cca3Slucy wang - Sun Microsystems - Beijing China /*ARGSUSED*/
377304b6cca3Slucy wang - Sun Microsystems - Beijing China static void
377404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_fill_group(void *arg, mac_ring_type_t rtype, const int index,
377504b6cca3Slucy wang - Sun Microsystems - Beijing China     mac_group_info_t *infop, mac_group_handle_t gh)
377604b6cca3Slucy wang - Sun Microsystems - Beijing China {
377704b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp = arg;
377804b6cca3Slucy wang - Sun Microsystems - Beijing China 
377904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (rtype != MAC_RING_TYPE_RX)
378004b6cca3Slucy wang - Sun Microsystems - Beijing China 		return;
378104b6cca3Slucy wang - Sun Microsystems - Beijing China 
378204b6cca3Slucy wang - Sun Microsystems - Beijing China 	infop->mgi_driver = (mac_group_driver_t)mgp;
378304b6cca3Slucy wang - Sun Microsystems - Beijing China 	infop->mgi_start = NULL;
378404b6cca3Slucy wang - Sun Microsystems - Beijing China 	infop->mgi_stop = NULL;
378504b6cca3Slucy wang - Sun Microsystems - Beijing China 	infop->mgi_addmac = myri10ge_addmac;
378604b6cca3Slucy wang - Sun Microsystems - Beijing China 	infop->mgi_remmac = myri10ge_remmac;
378704b6cca3Slucy wang - Sun Microsystems - Beijing China 	infop->mgi_count = mgp->num_slices;
378804b6cca3Slucy wang - Sun Microsystems - Beijing China }
378904b6cca3Slucy wang - Sun Microsystems - Beijing China 
379004b6cca3Slucy wang - Sun Microsystems - Beijing China static int
379104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_ring_start(mac_ring_driver_t rh, uint64_t mr_gen_num)
379204b6cca3Slucy wang - Sun Microsystems - Beijing China {
379304b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_slice_state *ss;
379404b6cca3Slucy wang - Sun Microsystems - Beijing China 
379504b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss = (struct myri10ge_slice_state *)rh;
379604b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&ss->rx_lock);
379704b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->rx_gen_num = mr_gen_num;
379804b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&ss->rx_lock);
379904b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
380004b6cca3Slucy wang - Sun Microsystems - Beijing China }
380104b6cca3Slucy wang - Sun Microsystems - Beijing China 
38020dc2366fSVenugopal Iyer /*
38030dc2366fSVenugopal Iyer  * Retrieve a value for one of the statistics for a particular rx ring
38040dc2366fSVenugopal Iyer  */
38050dc2366fSVenugopal Iyer int
38060dc2366fSVenugopal Iyer myri10ge_rx_ring_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
38070dc2366fSVenugopal Iyer {
38080dc2366fSVenugopal Iyer 	struct myri10ge_slice_state *ss;
38090dc2366fSVenugopal Iyer 
38100dc2366fSVenugopal Iyer 	ss = (struct myri10ge_slice_state *)rh;
38110dc2366fSVenugopal Iyer 	switch (stat) {
38120dc2366fSVenugopal Iyer 	case MAC_STAT_RBYTES:
38130dc2366fSVenugopal Iyer 		*val = ss->rx_stats.ibytes;
38140dc2366fSVenugopal Iyer 		break;
38150dc2366fSVenugopal Iyer 
38160dc2366fSVenugopal Iyer 	case MAC_STAT_IPACKETS:
38170dc2366fSVenugopal Iyer 		*val = ss->rx_stats.ipackets;
38180dc2366fSVenugopal Iyer 		break;
38190dc2366fSVenugopal Iyer 
38200dc2366fSVenugopal Iyer 	default:
38210dc2366fSVenugopal Iyer 		*val = 0;
38220dc2366fSVenugopal Iyer 		return (ENOTSUP);
38230dc2366fSVenugopal Iyer 	}
38240dc2366fSVenugopal Iyer 
38250dc2366fSVenugopal Iyer 	return (0);
38260dc2366fSVenugopal Iyer }
38270dc2366fSVenugopal Iyer 
38280dc2366fSVenugopal Iyer /*
38290dc2366fSVenugopal Iyer  * Retrieve a value for one of the statistics for a particular tx ring
38300dc2366fSVenugopal Iyer  */
38310dc2366fSVenugopal Iyer int
38320dc2366fSVenugopal Iyer myri10ge_tx_ring_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
38330dc2366fSVenugopal Iyer {
38340dc2366fSVenugopal Iyer 	struct myri10ge_slice_state *ss;
38350dc2366fSVenugopal Iyer 
38360dc2366fSVenugopal Iyer 	ss = (struct myri10ge_slice_state *)rh;
38370dc2366fSVenugopal Iyer 	switch (stat) {
38380dc2366fSVenugopal Iyer 	case MAC_STAT_OBYTES:
38390dc2366fSVenugopal Iyer 		*val = ss->tx.stats.obytes;
38400dc2366fSVenugopal Iyer 		break;
38410dc2366fSVenugopal Iyer 
38420dc2366fSVenugopal Iyer 	case MAC_STAT_OPACKETS:
38430dc2366fSVenugopal Iyer 		*val = ss->tx.stats.opackets;
38440dc2366fSVenugopal Iyer 		break;
38450dc2366fSVenugopal Iyer 
38460dc2366fSVenugopal Iyer 	default:
38470dc2366fSVenugopal Iyer 		*val = 0;
38480dc2366fSVenugopal Iyer 		return (ENOTSUP);
38490dc2366fSVenugopal Iyer 	}
38500dc2366fSVenugopal Iyer 
38510dc2366fSVenugopal Iyer 	return (0);
38520dc2366fSVenugopal Iyer }
38530dc2366fSVenugopal Iyer 
385404b6cca3Slucy wang - Sun Microsystems - Beijing China static int
385504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rx_ring_intr_disable(mac_intr_handle_t intrh)
385604b6cca3Slucy wang - Sun Microsystems - Beijing China {
385704b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_slice_state *ss;
385804b6cca3Slucy wang - Sun Microsystems - Beijing China 
385904b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss = (struct myri10ge_slice_state *)intrh;
386004b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&ss->poll_lock);
386104b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->rx_polling = B_TRUE;
386204b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&ss->poll_lock);
386304b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
386404b6cca3Slucy wang - Sun Microsystems - Beijing China }
386504b6cca3Slucy wang - Sun Microsystems - Beijing China 
386604b6cca3Slucy wang - Sun Microsystems - Beijing China static int
386704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rx_ring_intr_enable(mac_intr_handle_t intrh)
386804b6cca3Slucy wang - Sun Microsystems - Beijing China {
386904b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_slice_state *ss;
387004b6cca3Slucy wang - Sun Microsystems - Beijing China 
387104b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss = (struct myri10ge_slice_state *)intrh;
387204b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&ss->poll_lock);
387304b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->rx_polling = B_FALSE;
387404b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (ss->rx_token) {
387504b6cca3Slucy wang - Sun Microsystems - Beijing China 		*ss->irq_claim = BE_32(3);
387604b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->rx_token = 0;
387704b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
387804b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&ss->poll_lock);
387904b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
388004b6cca3Slucy wang - Sun Microsystems - Beijing China }
388104b6cca3Slucy wang - Sun Microsystems - Beijing China 
388204b6cca3Slucy wang - Sun Microsystems - Beijing China /*ARGSUSED*/
388304b6cca3Slucy wang - Sun Microsystems - Beijing China static void
388404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_fill_ring(void *arg, mac_ring_type_t rtype, const int rg_index,
388504b6cca3Slucy wang - Sun Microsystems - Beijing China     const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh)
388604b6cca3Slucy wang - Sun Microsystems - Beijing China {
388704b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp = arg;
388804b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_slice_state *ss;
388904b6cca3Slucy wang - Sun Microsystems - Beijing China 	mac_intr_t *mintr = &infop->mri_intr;
389004b6cca3Slucy wang - Sun Microsystems - Beijing China 
389104b6cca3Slucy wang - Sun Microsystems - Beijing China 	ASSERT((unsigned int)ring_index < mgp->num_slices);
389204b6cca3Slucy wang - Sun Microsystems - Beijing China 
389304b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss = &mgp->ss[ring_index];
389404b6cca3Slucy wang - Sun Microsystems - Beijing China 	switch (rtype) {
389504b6cca3Slucy wang - Sun Microsystems - Beijing China 	case MAC_RING_TYPE_RX:
389604b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->rx_rh = rh;
389704b6cca3Slucy wang - Sun Microsystems - Beijing China 		infop->mri_driver = (mac_ring_driver_t)ss;
389804b6cca3Slucy wang - Sun Microsystems - Beijing China 		infop->mri_start = myri10ge_ring_start;
389904b6cca3Slucy wang - Sun Microsystems - Beijing China 		infop->mri_stop = NULL;
390004b6cca3Slucy wang - Sun Microsystems - Beijing China 		infop->mri_poll = myri10ge_poll_rx;
39010dc2366fSVenugopal Iyer 		infop->mri_stat = myri10ge_rx_ring_stat;
390204b6cca3Slucy wang - Sun Microsystems - Beijing China 		mintr->mi_handle = (mac_intr_handle_t)ss;
390304b6cca3Slucy wang - Sun Microsystems - Beijing China 		mintr->mi_enable = myri10ge_rx_ring_intr_enable;
390404b6cca3Slucy wang - Sun Microsystems - Beijing China 		mintr->mi_disable = myri10ge_rx_ring_intr_disable;
390504b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
390604b6cca3Slucy wang - Sun Microsystems - Beijing China 	case MAC_RING_TYPE_TX:
390704b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->tx.rh = rh;
390804b6cca3Slucy wang - Sun Microsystems - Beijing China 		infop->mri_driver = (mac_ring_driver_t)ss;
390904b6cca3Slucy wang - Sun Microsystems - Beijing China 		infop->mri_start = NULL;
391004b6cca3Slucy wang - Sun Microsystems - Beijing China 		infop->mri_stop = NULL;
391104b6cca3Slucy wang - Sun Microsystems - Beijing China 		infop->mri_tx = myri10ge_send_wrapper;
39120dc2366fSVenugopal Iyer 		infop->mri_stat = myri10ge_tx_ring_stat;
391304b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
391404b6cca3Slucy wang - Sun Microsystems - Beijing China 	default:
391504b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
391604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
391704b6cca3Slucy wang - Sun Microsystems - Beijing China }
391804b6cca3Slucy wang - Sun Microsystems - Beijing China 
391904b6cca3Slucy wang - Sun Microsystems - Beijing China static void
392004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_nic_stat_destroy(struct myri10ge_priv *mgp)
392104b6cca3Slucy wang - Sun Microsystems - Beijing China {
392204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->ksp_stat == NULL)
392304b6cca3Slucy wang - Sun Microsystems - Beijing China 		return;
392404b6cca3Slucy wang - Sun Microsystems - Beijing China 
392504b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_delete(mgp->ksp_stat);
392604b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->ksp_stat = NULL;
392704b6cca3Slucy wang - Sun Microsystems - Beijing China }
392804b6cca3Slucy wang - Sun Microsystems - Beijing China 
392904b6cca3Slucy wang - Sun Microsystems - Beijing China static void
393004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_slice_stat_destroy(struct myri10ge_slice_state *ss)
393104b6cca3Slucy wang - Sun Microsystems - Beijing China {
393204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (ss->ksp_stat == NULL)
393304b6cca3Slucy wang - Sun Microsystems - Beijing China 		return;
393404b6cca3Slucy wang - Sun Microsystems - Beijing China 
393504b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_delete(ss->ksp_stat);
393604b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->ksp_stat = NULL;
393704b6cca3Slucy wang - Sun Microsystems - Beijing China }
393804b6cca3Slucy wang - Sun Microsystems - Beijing China 
393904b6cca3Slucy wang - Sun Microsystems - Beijing China static void
394004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_info_destroy(struct myri10ge_priv *mgp)
394104b6cca3Slucy wang - Sun Microsystems - Beijing China {
394204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->ksp_info == NULL)
394304b6cca3Slucy wang - Sun Microsystems - Beijing China 		return;
394404b6cca3Slucy wang - Sun Microsystems - Beijing China 
394504b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_delete(mgp->ksp_info);
394604b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->ksp_info = NULL;
394704b6cca3Slucy wang - Sun Microsystems - Beijing China }
394804b6cca3Slucy wang - Sun Microsystems - Beijing China 
394904b6cca3Slucy wang - Sun Microsystems - Beijing China static int
395004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_nic_stat_kstat_update(kstat_t *ksp, int rw)
395104b6cca3Slucy wang - Sun Microsystems - Beijing China {
395204b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_nic_stat *ethstat;
395304b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp;
395404b6cca3Slucy wang - Sun Microsystems - Beijing China 	mcp_irq_data_t *fw_stats;
395504b6cca3Slucy wang - Sun Microsystems - Beijing China 
395604b6cca3Slucy wang - Sun Microsystems - Beijing China 
395704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (rw == KSTAT_WRITE)
395804b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (EACCES);
395904b6cca3Slucy wang - Sun Microsystems - Beijing China 
396004b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat = (struct myri10ge_nic_stat *)ksp->ks_data;
396104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp = (struct myri10ge_priv *)ksp->ks_private;
396204b6cca3Slucy wang - Sun Microsystems - Beijing China 	fw_stats = mgp->ss[0].fw_stats;
396304b6cca3Slucy wang - Sun Microsystems - Beijing China 
396404b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->dma_read_bw_MBs.value.ul = mgp->read_dma;
396504b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->dma_write_bw_MBs.value.ul = mgp->write_dma;
396604b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->dma_read_write_bw_MBs.value.ul = mgp->read_write_dma;
396704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (myri10ge_tx_dma_attr.dma_attr_flags & DDI_DMA_FORCE_PHYSICAL)
396804b6cca3Slucy wang - Sun Microsystems - Beijing China 		ethstat->dma_force_physical.value.ul = 1;
396904b6cca3Slucy wang - Sun Microsystems - Beijing China 	else
397004b6cca3Slucy wang - Sun Microsystems - Beijing China 		ethstat->dma_force_physical.value.ul = 0;
397104b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->lanes.value.ul = mgp->pcie_link_width;
397204b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->dropped_bad_crc32.value.ul =
397304b6cca3Slucy wang - Sun Microsystems - Beijing China 	    ntohl(fw_stats->dropped_bad_crc32);
397404b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->dropped_bad_phy.value.ul =
397504b6cca3Slucy wang - Sun Microsystems - Beijing China 	    ntohl(fw_stats->dropped_bad_phy);
397604b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->dropped_link_error_or_filtered.value.ul =
397704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    ntohl(fw_stats->dropped_link_error_or_filtered);
397804b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->dropped_link_overflow.value.ul =
397904b6cca3Slucy wang - Sun Microsystems - Beijing China 	    ntohl(fw_stats->dropped_link_overflow);
398004b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->dropped_multicast_filtered.value.ul =
398104b6cca3Slucy wang - Sun Microsystems - Beijing China 	    ntohl(fw_stats->dropped_multicast_filtered);
398204b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->dropped_no_big_buffer.value.ul =
398304b6cca3Slucy wang - Sun Microsystems - Beijing China 	    ntohl(fw_stats->dropped_no_big_buffer);
398404b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->dropped_no_small_buffer.value.ul =
398504b6cca3Slucy wang - Sun Microsystems - Beijing China 	    ntohl(fw_stats->dropped_no_small_buffer);
398604b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->dropped_overrun.value.ul =
398704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    ntohl(fw_stats->dropped_overrun);
398804b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->dropped_pause.value.ul =
398904b6cca3Slucy wang - Sun Microsystems - Beijing China 	    ntohl(fw_stats->dropped_pause);
399004b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->dropped_runt.value.ul =
399104b6cca3Slucy wang - Sun Microsystems - Beijing China 	    ntohl(fw_stats->dropped_runt);
399204b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->link_up.value.ul =
399304b6cca3Slucy wang - Sun Microsystems - Beijing China 	    ntohl(fw_stats->link_up);
399404b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->dropped_unicast_filtered.value.ul =
399504b6cca3Slucy wang - Sun Microsystems - Beijing China 	    ntohl(fw_stats->dropped_unicast_filtered);
399604b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
399704b6cca3Slucy wang - Sun Microsystems - Beijing China }
399804b6cca3Slucy wang - Sun Microsystems - Beijing China 
399904b6cca3Slucy wang - Sun Microsystems - Beijing China static int
400004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_slice_stat_kstat_update(kstat_t *ksp, int rw)
400104b6cca3Slucy wang - Sun Microsystems - Beijing China {
400204b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_slice_stat *ethstat;
400304b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_slice_state *ss;
400404b6cca3Slucy wang - Sun Microsystems - Beijing China 
400504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (rw == KSTAT_WRITE)
400604b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (EACCES);
400704b6cca3Slucy wang - Sun Microsystems - Beijing China 
400804b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat = (struct myri10ge_slice_stat *)ksp->ks_data;
400904b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss = (struct myri10ge_slice_state *)ksp->ks_private;
401004b6cca3Slucy wang - Sun Microsystems - Beijing China 
401104b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->rx_big.value.ul = ss->j_rx_cnt;
401204b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->rx_bigbuf_firmware.value.ul = ss->rx_big.cnt - ss->j_rx_cnt;
401304b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->rx_bigbuf_pool.value.ul =
401404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    ss->jpool.num_alloc - ss->jbufs_for_smalls;
401504b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->rx_bigbuf_smalls.value.ul = ss->jbufs_for_smalls;
401604b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->rx_small.value.ul = ss->rx_small.cnt -
401704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    (ss->rx_small.mask + 1);
401804b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->tx_done.value.ul = ss->tx.done;
401904b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->tx_req.value.ul = ss->tx.req;
402004b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->tx_activate.value.ul = ss->tx.activate;
402104b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->xmit_sched.value.ul = ss->tx.sched;
402204b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->xmit_stall.value.ul = ss->tx.stall;
402304b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->xmit_stall_early.value.ul = ss->tx.stall_early;
402404b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->xmit_stall_late.value.ul = ss->tx.stall_late;
402504b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat->xmit_err.value.ul =  MYRI10GE_SLICE_STAT(xmit_err);
402604b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
402704b6cca3Slucy wang - Sun Microsystems - Beijing China }
402804b6cca3Slucy wang - Sun Microsystems - Beijing China 
402904b6cca3Slucy wang - Sun Microsystems - Beijing China static int
403004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_info_kstat_update(kstat_t *ksp, int rw)
403104b6cca3Slucy wang - Sun Microsystems - Beijing China {
403204b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_info *info;
403304b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp;
403404b6cca3Slucy wang - Sun Microsystems - Beijing China 
403504b6cca3Slucy wang - Sun Microsystems - Beijing China 
403604b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (rw == KSTAT_WRITE)
403704b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (EACCES);
403804b6cca3Slucy wang - Sun Microsystems - Beijing China 
403904b6cca3Slucy wang - Sun Microsystems - Beijing China 	info = (struct myri10ge_info *)ksp->ks_data;
404004b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp = (struct myri10ge_priv *)ksp->ks_private;
404104b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_setstr(&info->driver_version, MYRI10GE_VERSION_STR);
404204b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_setstr(&info->firmware_version, mgp->fw_version);
404304b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_setstr(&info->firmware_name, mgp->fw_name);
404404b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_setstr(&info->interrupt_type, mgp->intr_type);
404504b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_setstr(&info->product_code, mgp->pc_str);
404604b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_setstr(&info->serial_number, mgp->sn_str);
404704b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
404804b6cca3Slucy wang - Sun Microsystems - Beijing China }
404904b6cca3Slucy wang - Sun Microsystems - Beijing China 
405004b6cca3Slucy wang - Sun Microsystems - Beijing China static struct myri10ge_info myri10ge_info_template = {
405104b6cca3Slucy wang - Sun Microsystems - Beijing China 	{ "driver_version",	KSTAT_DATA_STRING },
405204b6cca3Slucy wang - Sun Microsystems - Beijing China 	{ "firmware_version",	KSTAT_DATA_STRING },
405304b6cca3Slucy wang - Sun Microsystems - Beijing China 	{ "firmware_name",	KSTAT_DATA_STRING },
405404b6cca3Slucy wang - Sun Microsystems - Beijing China 	{ "interrupt_type",	KSTAT_DATA_STRING },
405504b6cca3Slucy wang - Sun Microsystems - Beijing China 	{ "product_code",	KSTAT_DATA_STRING },
405604b6cca3Slucy wang - Sun Microsystems - Beijing China 	{ "serial_number",	KSTAT_DATA_STRING },
405704b6cca3Slucy wang - Sun Microsystems - Beijing China };
405804b6cca3Slucy wang - Sun Microsystems - Beijing China static kmutex_t myri10ge_info_template_lock;
405904b6cca3Slucy wang - Sun Microsystems - Beijing China 
406004b6cca3Slucy wang - Sun Microsystems - Beijing China 
406104b6cca3Slucy wang - Sun Microsystems - Beijing China static int
406204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_info_init(struct myri10ge_priv *mgp)
406304b6cca3Slucy wang - Sun Microsystems - Beijing China {
406404b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct kstat *ksp;
406504b6cca3Slucy wang - Sun Microsystems - Beijing China 
406604b6cca3Slucy wang - Sun Microsystems - Beijing China 	ksp = kstat_create("myri10ge", ddi_get_instance(mgp->dip),
406704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_info", "net", KSTAT_TYPE_NAMED,
406804b6cca3Slucy wang - Sun Microsystems - Beijing China 	    sizeof (myri10ge_info_template) /
406904b6cca3Slucy wang - Sun Microsystems - Beijing China 	    sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL);
407004b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (ksp == NULL) {
407104b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN,
407204b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "%s: myri10ge_info_init: kstat_create failed", mgp->name);
407304b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
407404b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
407504b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->ksp_info = ksp;
407604b6cca3Slucy wang - Sun Microsystems - Beijing China 	ksp->ks_update = myri10ge_info_kstat_update;
407704b6cca3Slucy wang - Sun Microsystems - Beijing China 	ksp->ks_private = (void *) mgp;
407804b6cca3Slucy wang - Sun Microsystems - Beijing China 	ksp->ks_data = &myri10ge_info_template;
407904b6cca3Slucy wang - Sun Microsystems - Beijing China 	ksp->ks_lock = &myri10ge_info_template_lock;
408004b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (MYRI10GE_VERSION_STR != NULL)
408104b6cca3Slucy wang - Sun Microsystems - Beijing China 		ksp->ks_data_size += strlen(MYRI10GE_VERSION_STR) + 1;
408204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->fw_version != NULL)
408304b6cca3Slucy wang - Sun Microsystems - Beijing China 		ksp->ks_data_size += strlen(mgp->fw_version) + 1;
408404b6cca3Slucy wang - Sun Microsystems - Beijing China 	ksp->ks_data_size += strlen(mgp->fw_name) + 1;
408504b6cca3Slucy wang - Sun Microsystems - Beijing China 	ksp->ks_data_size += strlen(mgp->intr_type) + 1;
408604b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->pc_str != NULL)
408704b6cca3Slucy wang - Sun Microsystems - Beijing China 		ksp->ks_data_size += strlen(mgp->pc_str) + 1;
408804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->sn_str != NULL)
408904b6cca3Slucy wang - Sun Microsystems - Beijing China 		ksp->ks_data_size += strlen(mgp->sn_str) + 1;
409004b6cca3Slucy wang - Sun Microsystems - Beijing China 
409104b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_install(ksp);
409204b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
409304b6cca3Slucy wang - Sun Microsystems - Beijing China }
409404b6cca3Slucy wang - Sun Microsystems - Beijing China 
409504b6cca3Slucy wang - Sun Microsystems - Beijing China 
409604b6cca3Slucy wang - Sun Microsystems - Beijing China static int
409704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_nic_stat_init(struct myri10ge_priv *mgp)
409804b6cca3Slucy wang - Sun Microsystems - Beijing China {
409904b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct kstat *ksp;
410004b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_nic_stat *ethstat;
410104b6cca3Slucy wang - Sun Microsystems - Beijing China 
410204b6cca3Slucy wang - Sun Microsystems - Beijing China 	ksp = kstat_create("myri10ge", ddi_get_instance(mgp->dip),
410304b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_nic_stats", "net", KSTAT_TYPE_NAMED,
410404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    sizeof (*ethstat) / sizeof (kstat_named_t), 0);
410504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (ksp == NULL) {
410604b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN,
410704b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "%s: myri10ge_stat_init: kstat_create failed", mgp->name);
410804b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
410904b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
411004b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->ksp_stat = ksp;
411104b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat = (struct myri10ge_nic_stat *)(ksp->ks_data);
411204b6cca3Slucy wang - Sun Microsystems - Beijing China 
411304b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->dma_read_bw_MBs,
411404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "dma_read_bw_MBs", KSTAT_DATA_ULONG);
411504b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->dma_write_bw_MBs,
411604b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "dma_write_bw_MBs", KSTAT_DATA_ULONG);
411704b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->dma_read_write_bw_MBs,
411804b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "dma_read_write_bw_MBs", KSTAT_DATA_ULONG);
411904b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->dma_force_physical,
412004b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "dma_force_physical", KSTAT_DATA_ULONG);
412104b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->lanes,
412204b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "lanes", KSTAT_DATA_ULONG);
412304b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->dropped_bad_crc32,
412404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "dropped_bad_crc32", KSTAT_DATA_ULONG);
412504b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->dropped_bad_phy,
412604b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "dropped_bad_phy", KSTAT_DATA_ULONG);
412704b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->dropped_link_error_or_filtered,
412804b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "dropped_link_error_or_filtered", KSTAT_DATA_ULONG);
412904b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->dropped_link_overflow,
413004b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "dropped_link_overflow", KSTAT_DATA_ULONG);
413104b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->dropped_multicast_filtered,
413204b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "dropped_multicast_filtered", KSTAT_DATA_ULONG);
413304b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->dropped_no_big_buffer,
413404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "dropped_no_big_buffer", KSTAT_DATA_ULONG);
413504b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->dropped_no_small_buffer,
413604b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "dropped_no_small_buffer", KSTAT_DATA_ULONG);
413704b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->dropped_overrun,
413804b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "dropped_overrun", KSTAT_DATA_ULONG);
413904b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->dropped_pause,
414004b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "dropped_pause", KSTAT_DATA_ULONG);
414104b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->dropped_runt,
414204b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "dropped_runt", KSTAT_DATA_ULONG);
414304b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->dropped_unicast_filtered,
414404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "dropped_unicast_filtered", KSTAT_DATA_ULONG);
414504b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->dropped_runt, "dropped_runt",
414604b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
414704b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->link_up, "link_up", KSTAT_DATA_ULONG);
414804b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->link_changes, "link_changes",
414904b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
415004b6cca3Slucy wang - Sun Microsystems - Beijing China 	ksp->ks_update = myri10ge_nic_stat_kstat_update;
415104b6cca3Slucy wang - Sun Microsystems - Beijing China 	ksp->ks_private = (void *) mgp;
415204b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_install(ksp);
415304b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
415404b6cca3Slucy wang - Sun Microsystems - Beijing China }
415504b6cca3Slucy wang - Sun Microsystems - Beijing China 
415604b6cca3Slucy wang - Sun Microsystems - Beijing China static int
415704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_slice_stat_init(struct myri10ge_slice_state *ss)
415804b6cca3Slucy wang - Sun Microsystems - Beijing China {
415904b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp = ss->mgp;
416004b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct kstat *ksp;
416104b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_slice_stat *ethstat;
416204b6cca3Slucy wang - Sun Microsystems - Beijing China 	int instance;
416304b6cca3Slucy wang - Sun Microsystems - Beijing China 
416404b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
416504b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * fake an instance so that the same slice numbers from
416604b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * different instances do not collide
416704b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
416804b6cca3Slucy wang - Sun Microsystems - Beijing China 	instance = (ddi_get_instance(mgp->dip) * 1000) +  (int)(ss - mgp->ss);
416904b6cca3Slucy wang - Sun Microsystems - Beijing China 	ksp = kstat_create("myri10ge", instance,
417004b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_slice_stats", "net", KSTAT_TYPE_NAMED,
417104b6cca3Slucy wang - Sun Microsystems - Beijing China 	    sizeof (*ethstat) / sizeof (kstat_named_t), 0);
417204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (ksp == NULL) {
417304b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN,
417404b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "%s: myri10ge_stat_init: kstat_create failed", mgp->name);
417504b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
417604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
417704b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->ksp_stat = ksp;
417804b6cca3Slucy wang - Sun Microsystems - Beijing China 	ethstat = (struct myri10ge_slice_stat *)(ksp->ks_data);
417904b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->lro_bad_csum, "lro_bad_csum",
418004b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
418104b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->lro_flushed, "lro_flushed",
418204b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
418304b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->lro_queued, "lro_queued",
418404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
418504b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->rx_bigbuf_firmware, "rx_bigbuf_firmware",
418604b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
418704b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->rx_bigbuf_pool, "rx_bigbuf_pool",
418804b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
418904b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->rx_bigbuf_smalls, "rx_bigbuf_smalls",
419004b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
419104b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->rx_copy, "rx_copy",
419204b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
419304b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->rx_big_nobuf, "rx_big_nobuf",
419404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
419504b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->rx_small_nobuf, "rx_small_nobuf",
419604b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
419704b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->xmit_zero_len, "xmit_zero_len",
419804b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
419904b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->xmit_pullup, "xmit_pullup",
420004b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
420104b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->xmit_pullup_first, "xmit_pullup_first",
420204b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
420304b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->xmit_lowbuf, "xmit_lowbuf",
420404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
420504b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->xmit_lsobadflags, "xmit_lsobadflags",
420604b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
420704b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->xmit_sched, "xmit_sched",
420804b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
420904b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->xmit_stall, "xmit_stall",
421004b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
421104b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->xmit_stall_early, "xmit_stall_early",
421204b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
421304b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->xmit_stall_late, "xmit_stall_late",
421404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
421504b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->xmit_err, "xmit_err",
421604b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
421704b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->tx_req, "tx_req",
421804b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
421904b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->tx_activate, "tx_activate",
422004b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
422104b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->tx_done, "tx_done",
422204b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
422304b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->tx_handles_alloced, "tx_handles_alloced",
422404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
422504b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->rx_big, "rx_big",
422604b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
422704b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_named_init(&ethstat->rx_small, "rx_small",
422804b6cca3Slucy wang - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
422904b6cca3Slucy wang - Sun Microsystems - Beijing China 	ksp->ks_update = myri10ge_slice_stat_kstat_update;
423004b6cca3Slucy wang - Sun Microsystems - Beijing China 	ksp->ks_private = (void *) ss;
423104b6cca3Slucy wang - Sun Microsystems - Beijing China 	kstat_install(ksp);
423204b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
423304b6cca3Slucy wang - Sun Microsystems - Beijing China }
423404b6cca3Slucy wang - Sun Microsystems - Beijing China 
423504b6cca3Slucy wang - Sun Microsystems - Beijing China 
423604b6cca3Slucy wang - Sun Microsystems - Beijing China 
42375ee6ac27SRichard Lowe #if defined __i386 || defined i386 || defined __i386__ || defined __x86_64__
423804b6cca3Slucy wang - Sun Microsystems - Beijing China 
423904b6cca3Slucy wang - Sun Microsystems - Beijing China #include <vm/hat.h>
4240a56d24eaSMark Johnson #include <sys/ddi_isa.h>
424104b6cca3Slucy wang - Sun Microsystems - Beijing China void *device_arena_alloc(size_t size, int vm_flag);
424204b6cca3Slucy wang - Sun Microsystems - Beijing China void device_arena_free(void *vaddr, size_t size);
424304b6cca3Slucy wang - Sun Microsystems - Beijing China 
424404b6cca3Slucy wang - Sun Microsystems - Beijing China static void
424504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_enable_nvidia_ecrc(struct myri10ge_priv *mgp)
424604b6cca3Slucy wang - Sun Microsystems - Beijing China {
424704b6cca3Slucy wang - Sun Microsystems - Beijing China 	dev_info_t *parent_dip;
424804b6cca3Slucy wang - Sun Microsystems - Beijing China 	ddi_acc_handle_t handle;
424904b6cca3Slucy wang - Sun Microsystems - Beijing China 	unsigned long bus_number, dev_number, func_number;
425004b6cca3Slucy wang - Sun Microsystems - Beijing China 	unsigned long cfg_pa, paddr, base, pgoffset;
425104b6cca3Slucy wang - Sun Microsystems - Beijing China 	char 		*cvaddr, *ptr;
425204b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint32_t	*ptr32;
425304b6cca3Slucy wang - Sun Microsystems - Beijing China 	int 		retval = DDI_FAILURE;
425404b6cca3Slucy wang - Sun Microsystems - Beijing China 	int dontcare;
425504b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint16_t read_vid, read_did, vendor_id, device_id;
425604b6cca3Slucy wang - Sun Microsystems - Beijing China 
425704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (!myri10ge_nvidia_ecrc_enable)
425804b6cca3Slucy wang - Sun Microsystems - Beijing China 		return;
425904b6cca3Slucy wang - Sun Microsystems - Beijing China 
426004b6cca3Slucy wang - Sun Microsystems - Beijing China 	parent_dip = ddi_get_parent(mgp->dip);
426104b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (parent_dip == NULL) {
426204b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: I'm an orphan?", mgp->name);
426304b6cca3Slucy wang - Sun Microsystems - Beijing China 		return;
426404b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
426504b6cca3Slucy wang - Sun Microsystems - Beijing China 
426604b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (pci_config_setup(parent_dip, &handle) != DDI_SUCCESS) {
426704b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN,
426804b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "%s: Could not access my parent's registers", mgp->name);
426904b6cca3Slucy wang - Sun Microsystems - Beijing China 		return;
427004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
427104b6cca3Slucy wang - Sun Microsystems - Beijing China 
427204b6cca3Slucy wang - Sun Microsystems - Beijing China 	vendor_id = pci_config_get16(handle, PCI_CONF_VENID);
427304b6cca3Slucy wang - Sun Microsystems - Beijing China 	device_id = pci_config_get16(handle, PCI_CONF_DEVID);
427404b6cca3Slucy wang - Sun Microsystems - Beijing China 	pci_config_teardown(&handle);
427504b6cca3Slucy wang - Sun Microsystems - Beijing China 
427604b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (myri10ge_verbose) {
427704b6cca3Slucy wang - Sun Microsystems - Beijing China 		unsigned long 	bus_number, dev_number, func_number;
427804b6cca3Slucy wang - Sun Microsystems - Beijing China 		int 		reg_set, span;
427904b6cca3Slucy wang - Sun Microsystems - Beijing China 		(void) myri10ge_reg_set(parent_dip, &reg_set, &span,
428004b6cca3Slucy wang - Sun Microsystems - Beijing China 		    &bus_number, &dev_number, &func_number);
428104b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (myri10ge_verbose)
428204b6cca3Slucy wang - Sun Microsystems - Beijing China 			printf("%s: parent at %ld:%ld:%ld\n", mgp->name,
428304b6cca3Slucy wang - Sun Microsystems - Beijing China 			    bus_number, dev_number, func_number);
428404b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
428504b6cca3Slucy wang - Sun Microsystems - Beijing China 
428604b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (vendor_id !=  0x10de)
428704b6cca3Slucy wang - Sun Microsystems - Beijing China 		return;
428804b6cca3Slucy wang - Sun Microsystems - Beijing China 
428904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (device_id != 0x005d /* CK804 */ &&
429004b6cca3Slucy wang - Sun Microsystems - Beijing China 	    (device_id < 0x374 || device_id > 0x378) /* MCP55 */) {
429104b6cca3Slucy wang - Sun Microsystems - Beijing China 		return;
429204b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
429304b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) myri10ge_reg_set(parent_dip, &dontcare, &dontcare,
429404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    &bus_number, &dev_number, &func_number);
429504b6cca3Slucy wang - Sun Microsystems - Beijing China 
429604b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (cfg_pa = 0xf0000000UL;
429704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    retval != DDI_SUCCESS && cfg_pa >= 0xe0000000UL;
429804b6cca3Slucy wang - Sun Microsystems - Beijing China 	    cfg_pa -= 0x10000000UL) {
429904b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* find the config space address for the nvidia bridge */
430004b6cca3Slucy wang - Sun Microsystems - Beijing China 		paddr = (cfg_pa + bus_number * 0x00100000UL +
430104b6cca3Slucy wang - Sun Microsystems - Beijing China 		    (dev_number * 8 + func_number) * 0x00001000UL);
430204b6cca3Slucy wang - Sun Microsystems - Beijing China 
430304b6cca3Slucy wang - Sun Microsystems - Beijing China 		base = paddr & (~MMU_PAGEOFFSET);
430404b6cca3Slucy wang - Sun Microsystems - Beijing China 		pgoffset = paddr & MMU_PAGEOFFSET;
430504b6cca3Slucy wang - Sun Microsystems - Beijing China 
430604b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* map it into the kernel */
430704b6cca3Slucy wang - Sun Microsystems - Beijing China 		cvaddr =  device_arena_alloc(ptob(1), VM_NOSLEEP);
430804b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (cvaddr == NULL)
430904b6cca3Slucy wang - Sun Microsystems - Beijing China 			cmn_err(CE_WARN, "%s: failed to map nf4: cvaddr\n",
431004b6cca3Slucy wang - Sun Microsystems - Beijing China 			    mgp->name);
431104b6cca3Slucy wang - Sun Microsystems - Beijing China 
4312a56d24eaSMark Johnson 		hat_devload(kas.a_hat, cvaddr, mmu_ptob(1),
4313a56d24eaSMark Johnson 		    i_ddi_paddr_to_pfn(base),
431404b6cca3Slucy wang - Sun Microsystems - Beijing China 		    PROT_WRITE|HAT_STRICTORDER, HAT_LOAD_LOCK);
431504b6cca3Slucy wang - Sun Microsystems - Beijing China 
431604b6cca3Slucy wang - Sun Microsystems - Beijing China 		ptr = cvaddr + pgoffset;
431704b6cca3Slucy wang - Sun Microsystems - Beijing China 		read_vid = *(uint16_t *)(void *)(ptr + PCI_CONF_VENID);
431804b6cca3Slucy wang - Sun Microsystems - Beijing China 		read_did = *(uint16_t *)(void *)(ptr + PCI_CONF_DEVID);
431904b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (vendor_id ==  read_did || device_id == read_did) {
432004b6cca3Slucy wang - Sun Microsystems - Beijing China 			ptr32 = (uint32_t *)(void *)(ptr + 0x178);
432104b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (myri10ge_verbose)
432204b6cca3Slucy wang - Sun Microsystems - Beijing China 				printf("%s: Enabling ECRC on upstream "
432304b6cca3Slucy wang - Sun Microsystems - Beijing China 				    "Nvidia bridge (0x%x:0x%x) "
432404b6cca3Slucy wang - Sun Microsystems - Beijing China 				    "at %ld:%ld:%ld\n", mgp->name,
432504b6cca3Slucy wang - Sun Microsystems - Beijing China 				    read_vid, read_did, bus_number,
432604b6cca3Slucy wang - Sun Microsystems - Beijing China 				    dev_number, func_number);
432704b6cca3Slucy wang - Sun Microsystems - Beijing China 			*ptr32 |= 0x40;
432804b6cca3Slucy wang - Sun Microsystems - Beijing China 			retval = DDI_SUCCESS;
432904b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
433004b6cca3Slucy wang - Sun Microsystems - Beijing China 		hat_unload(kas.a_hat, cvaddr, ptob(1), HAT_UNLOAD_UNLOCK);
433104b6cca3Slucy wang - Sun Microsystems - Beijing China 		device_arena_free(cvaddr, ptob(1));
433204b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
433304b6cca3Slucy wang - Sun Microsystems - Beijing China }
433404b6cca3Slucy wang - Sun Microsystems - Beijing China 
433504b6cca3Slucy wang - Sun Microsystems - Beijing China #else
433604b6cca3Slucy wang - Sun Microsystems - Beijing China /*ARGSUSED*/
433704b6cca3Slucy wang - Sun Microsystems - Beijing China static void
433804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_enable_nvidia_ecrc(struct myri10ge_priv *mgp)
433904b6cca3Slucy wang - Sun Microsystems - Beijing China {
434004b6cca3Slucy wang - Sun Microsystems - Beijing China }
434104b6cca3Slucy wang - Sun Microsystems - Beijing China #endif /* i386 */
434204b6cca3Slucy wang - Sun Microsystems - Beijing China 
434304b6cca3Slucy wang - Sun Microsystems - Beijing China 
434404b6cca3Slucy wang - Sun Microsystems - Beijing China /*
434504b6cca3Slucy wang - Sun Microsystems - Beijing China  * The Lanai Z8E PCI-E interface achieves higher Read-DMA throughput
434604b6cca3Slucy wang - Sun Microsystems - Beijing China  * when the PCI-E Completion packets are aligned on an 8-byte
434704b6cca3Slucy wang - Sun Microsystems - Beijing China  * boundary.  Some PCI-E chip sets always align Completion packets; on
434804b6cca3Slucy wang - Sun Microsystems - Beijing China  * the ones that do not, the alignment can be enforced by enabling
434904b6cca3Slucy wang - Sun Microsystems - Beijing China  * ECRC generation (if supported).
435004b6cca3Slucy wang - Sun Microsystems - Beijing China  *
435104b6cca3Slucy wang - Sun Microsystems - Beijing China  * When PCI-E Completion packets are not aligned, it is actually more
435204b6cca3Slucy wang - Sun Microsystems - Beijing China  * efficient to limit Read-DMA transactions to 2KB, rather than 4KB.
435304b6cca3Slucy wang - Sun Microsystems - Beijing China  *
435404b6cca3Slucy wang - Sun Microsystems - Beijing China  * If the driver can neither enable ECRC nor verify that it has
435504b6cca3Slucy wang - Sun Microsystems - Beijing China  * already been enabled, then it must use a firmware image which works
435604b6cca3Slucy wang - Sun Microsystems - Beijing China  * around unaligned completion packets (ethp_z8e.dat), and it should
435704b6cca3Slucy wang - Sun Microsystems - Beijing China  * also ensure that it never gives the device a Read-DMA which is
435804b6cca3Slucy wang - Sun Microsystems - Beijing China  * larger than 2KB by setting the tx.boundary to 2KB.  If ECRC is
435904b6cca3Slucy wang - Sun Microsystems - Beijing China  * enabled, then the driver should use the aligned (eth_z8e.dat)
436004b6cca3Slucy wang - Sun Microsystems - Beijing China  * firmware image, and set tx.boundary to 4KB.
436104b6cca3Slucy wang - Sun Microsystems - Beijing China  */
436204b6cca3Slucy wang - Sun Microsystems - Beijing China 
436304b6cca3Slucy wang - Sun Microsystems - Beijing China 
436404b6cca3Slucy wang - Sun Microsystems - Beijing China static int
436504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_firmware_probe(struct myri10ge_priv *mgp)
436604b6cca3Slucy wang - Sun Microsystems - Beijing China {
436704b6cca3Slucy wang - Sun Microsystems - Beijing China 	int status;
436804b6cca3Slucy wang - Sun Microsystems - Beijing China 
436904b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->tx_boundary = 4096;
437004b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
437104b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * Verify the max read request size was set to 4KB
437204b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * before trying the test with 4KB.
437304b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
437404b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->max_read_request_4k == 0)
437504b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->tx_boundary = 2048;
437604b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
437704b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * load the optimized firmware which assumes aligned PCIe
437804b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * completions in order to see if it works on this host.
437904b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
438004b6cca3Slucy wang - Sun Microsystems - Beijing China 
438104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->fw_name = "rss_eth_z8e";
438204b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->eth_z8e = (unsigned char *)rss_eth_z8e;
438304b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->eth_z8e_length = rss_eth_z8e_length;
438404b6cca3Slucy wang - Sun Microsystems - Beijing China 
438504b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_load_firmware(mgp);
438604b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != 0) {
438704b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (status);
438804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
438904b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
439004b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * Enable ECRC if possible
439104b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
439204b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_enable_nvidia_ecrc(mgp);
439304b6cca3Slucy wang - Sun Microsystems - Beijing China 
439404b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
439504b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * Run a DMA test which watches for unaligned completions and
439604b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * aborts on the first one seen.
439704b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
439804b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_dma_test(mgp, MXGEFW_CMD_UNALIGNED_TEST);
439904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status == 0)
440004b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (0); /* keep the aligned firmware */
440104b6cca3Slucy wang - Sun Microsystems - Beijing China 
440204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != E2BIG)
440304b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: DMA test failed: %d\n",
440404b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->name, status);
440504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status == ENOSYS)
440604b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: Falling back to ethp! "
440704b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "Please install up to date fw\n", mgp->name);
440804b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (status);
440904b6cca3Slucy wang - Sun Microsystems - Beijing China }
441004b6cca3Slucy wang - Sun Microsystems - Beijing China 
441104b6cca3Slucy wang - Sun Microsystems - Beijing China static int
441204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_select_firmware(struct myri10ge_priv *mgp)
441304b6cca3Slucy wang - Sun Microsystems - Beijing China {
441404b6cca3Slucy wang - Sun Microsystems - Beijing China 	int aligned;
441504b6cca3Slucy wang - Sun Microsystems - Beijing China 
441604b6cca3Slucy wang - Sun Microsystems - Beijing China 	aligned = 0;
441704b6cca3Slucy wang - Sun Microsystems - Beijing China 
441804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (myri10ge_force_firmware == 1) {
441904b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (myri10ge_verbose)
442004b6cca3Slucy wang - Sun Microsystems - Beijing China 			printf("%s: Assuming aligned completions (forced)\n",
442104b6cca3Slucy wang - Sun Microsystems - Beijing China 			    mgp->name);
442204b6cca3Slucy wang - Sun Microsystems - Beijing China 		aligned = 1;
442304b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto done;
442404b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
442504b6cca3Slucy wang - Sun Microsystems - Beijing China 
442604b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (myri10ge_force_firmware == 2) {
442704b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (myri10ge_verbose)
442804b6cca3Slucy wang - Sun Microsystems - Beijing China 			printf("%s: Assuming unaligned completions (forced)\n",
442904b6cca3Slucy wang - Sun Microsystems - Beijing China 			    mgp->name);
443004b6cca3Slucy wang - Sun Microsystems - Beijing China 		aligned = 0;
443104b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto done;
443204b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
443304b6cca3Slucy wang - Sun Microsystems - Beijing China 
443404b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* If the width is less than 8, we may used the aligned firmware */
443504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->pcie_link_width != 0 && mgp->pcie_link_width < 8) {
443604b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "!%s: PCIe link running at x%d\n",
443704b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->name, mgp->pcie_link_width);
443804b6cca3Slucy wang - Sun Microsystems - Beijing China 		aligned = 1;
443904b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto done;
444004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
444104b6cca3Slucy wang - Sun Microsystems - Beijing China 
444204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (0 == myri10ge_firmware_probe(mgp))
444304b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (0);  /* keep optimized firmware */
444404b6cca3Slucy wang - Sun Microsystems - Beijing China 
444504b6cca3Slucy wang - Sun Microsystems - Beijing China done:
444604b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (aligned) {
444704b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->fw_name = "rss_eth_z8e";
444804b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->eth_z8e = (unsigned char *)rss_eth_z8e;
444904b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->eth_z8e_length = rss_eth_z8e_length;
445004b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->tx_boundary = 4096;
445104b6cca3Slucy wang - Sun Microsystems - Beijing China 	} else {
445204b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->fw_name = "rss_ethp_z8e";
445304b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->eth_z8e = (unsigned char *)rss_ethp_z8e;
445404b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->eth_z8e_length = rss_ethp_z8e_length;
445504b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->tx_boundary = 2048;
445604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
445704b6cca3Slucy wang - Sun Microsystems - Beijing China 
445804b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (myri10ge_load_firmware(mgp));
445904b6cca3Slucy wang - Sun Microsystems - Beijing China }
446004b6cca3Slucy wang - Sun Microsystems - Beijing China 
446104b6cca3Slucy wang - Sun Microsystems - Beijing China static int
446204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_add_intrs(struct myri10ge_priv *mgp, int add_handler)
446304b6cca3Slucy wang - Sun Microsystems - Beijing China {
446404b6cca3Slucy wang - Sun Microsystems - Beijing China 	dev_info_t *devinfo = mgp->dip;
446504b6cca3Slucy wang - Sun Microsystems - Beijing China 	int count, avail, actual, intr_types;
446604b6cca3Slucy wang - Sun Microsystems - Beijing China 	int x, y, rc, inum = 0;
446704b6cca3Slucy wang - Sun Microsystems - Beijing China 
446804b6cca3Slucy wang - Sun Microsystems - Beijing China 
446904b6cca3Slucy wang - Sun Microsystems - Beijing China 	rc = ddi_intr_get_supported_types(devinfo, &intr_types);
447004b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (rc != DDI_SUCCESS) {
447104b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN,
447204b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "!%s: ddi_intr_get_nintrs() failure, rc = %d\n", mgp->name,
447304b6cca3Slucy wang - Sun Microsystems - Beijing China 		    rc);
447404b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
447504b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
447604b6cca3Slucy wang - Sun Microsystems - Beijing China 
447704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (!myri10ge_use_msi)
447804b6cca3Slucy wang - Sun Microsystems - Beijing China 		intr_types &= ~DDI_INTR_TYPE_MSI;
447904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (!myri10ge_use_msix)
448004b6cca3Slucy wang - Sun Microsystems - Beijing China 		intr_types &= ~DDI_INTR_TYPE_MSIX;
448104b6cca3Slucy wang - Sun Microsystems - Beijing China 
448204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (intr_types & DDI_INTR_TYPE_MSIX) {
448304b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->ddi_intr_type = DDI_INTR_TYPE_MSIX;
448404b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->intr_type = "MSI-X";
448504b6cca3Slucy wang - Sun Microsystems - Beijing China 	} else if (intr_types & DDI_INTR_TYPE_MSI) {
448604b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->ddi_intr_type = DDI_INTR_TYPE_MSI;
448704b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->intr_type = "MSI";
448804b6cca3Slucy wang - Sun Microsystems - Beijing China 	} else {
448904b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->ddi_intr_type = DDI_INTR_TYPE_FIXED;
449004b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->intr_type = "Legacy";
449104b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
449204b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* Get number of interrupts */
449304b6cca3Slucy wang - Sun Microsystems - Beijing China 	rc = ddi_intr_get_nintrs(devinfo, mgp->ddi_intr_type, &count);
449404b6cca3Slucy wang - Sun Microsystems - Beijing China 	if ((rc != DDI_SUCCESS) || (count == 0)) {
449504b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: ddi_intr_get_nintrs() failure, rc: %d, "
449604b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "count: %d", mgp->name, rc, count);
449704b6cca3Slucy wang - Sun Microsystems - Beijing China 
449804b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
449904b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
450004b6cca3Slucy wang - Sun Microsystems - Beijing China 
450104b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* Get number of available interrupts */
450204b6cca3Slucy wang - Sun Microsystems - Beijing China 	rc = ddi_intr_get_navail(devinfo, mgp->ddi_intr_type, &avail);
450304b6cca3Slucy wang - Sun Microsystems - Beijing China 	if ((rc != DDI_SUCCESS) || (avail == 0)) {
450404b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: ddi_intr_get_navail() failure, "
450504b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "rc: %d, avail: %d\n", mgp->name, rc, avail);
450604b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
450704b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
450804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (avail < count) {
450904b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_NOTE,
451004b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "!%s: nintrs() returned %d, navail returned %d",
451104b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->name, count, avail);
451204b6cca3Slucy wang - Sun Microsystems - Beijing China 		count = avail;
451304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
451404b6cca3Slucy wang - Sun Microsystems - Beijing China 
451504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (count < mgp->num_slices)
451604b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
451704b6cca3Slucy wang - Sun Microsystems - Beijing China 
451804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (count > mgp->num_slices)
451904b6cca3Slucy wang - Sun Microsystems - Beijing China 		count = mgp->num_slices;
452004b6cca3Slucy wang - Sun Microsystems - Beijing China 
452104b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* Allocate memory for MSI interrupts */
452204b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->intr_size = count * sizeof (ddi_intr_handle_t);
452304b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->htable = kmem_alloc(mgp->intr_size, KM_SLEEP);
452404b6cca3Slucy wang - Sun Microsystems - Beijing China 
452504b6cca3Slucy wang - Sun Microsystems - Beijing China 	rc = ddi_intr_alloc(devinfo, mgp->htable, mgp->ddi_intr_type, inum,
452604b6cca3Slucy wang - Sun Microsystems - Beijing China 	    count, &actual, DDI_INTR_ALLOC_NORMAL);
452704b6cca3Slucy wang - Sun Microsystems - Beijing China 
452804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if ((rc != DDI_SUCCESS) || (actual == 0)) {
452904b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: ddi_intr_alloc() failed: %d",
453004b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->name, rc);
453104b6cca3Slucy wang - Sun Microsystems - Beijing China 
453204b6cca3Slucy wang - Sun Microsystems - Beijing China 		kmem_free(mgp->htable, mgp->intr_size);
453304b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->htable = NULL;
453404b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
453504b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
453604b6cca3Slucy wang - Sun Microsystems - Beijing China 
453704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if ((actual < count) && myri10ge_verbose) {
453804b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_NOTE, "%s: got %d/%d slices",
453904b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->name, actual, count);
454004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
454104b6cca3Slucy wang - Sun Microsystems - Beijing China 
454204b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->intr_cnt = actual;
454304b6cca3Slucy wang - Sun Microsystems - Beijing China 
454404b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
454504b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * Get priority for first irq, assume remaining are all the same
454604b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
454704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (ddi_intr_get_pri(mgp->htable[0], &mgp->intr_pri)
454804b6cca3Slucy wang - Sun Microsystems - Beijing China 	    != DDI_SUCCESS) {
454904b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: ddi_intr_get_pri() failed", mgp->name);
455004b6cca3Slucy wang - Sun Microsystems - Beijing China 
455104b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* Free already allocated intr */
455204b6cca3Slucy wang - Sun Microsystems - Beijing China 		for (y = 0; y < actual; y++) {
455304b6cca3Slucy wang - Sun Microsystems - Beijing China 			(void) ddi_intr_free(mgp->htable[y]);
455404b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
455504b6cca3Slucy wang - Sun Microsystems - Beijing China 
455604b6cca3Slucy wang - Sun Microsystems - Beijing China 		kmem_free(mgp->htable, mgp->intr_size);
455704b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->htable = NULL;
455804b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
455904b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
456004b6cca3Slucy wang - Sun Microsystems - Beijing China 
456104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->icookie = (void *)(uintptr_t)mgp->intr_pri;
456204b6cca3Slucy wang - Sun Microsystems - Beijing China 
456304b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (!add_handler)
456404b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_SUCCESS);
456504b6cca3Slucy wang - Sun Microsystems - Beijing China 
456604b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* Call ddi_intr_add_handler() */
456704b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (x = 0; x < actual; x++) {
456804b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (ddi_intr_add_handler(mgp->htable[x], myri10ge_intr,
456904b6cca3Slucy wang - Sun Microsystems - Beijing China 		    (caddr_t)&mgp->ss[x], NULL) != DDI_SUCCESS) {
457004b6cca3Slucy wang - Sun Microsystems - Beijing China 			cmn_err(CE_WARN, "%s: ddi_intr_add_handler() failed",
457104b6cca3Slucy wang - Sun Microsystems - Beijing China 			    mgp->name);
457204b6cca3Slucy wang - Sun Microsystems - Beijing China 
457304b6cca3Slucy wang - Sun Microsystems - Beijing China 			/* Free already allocated intr */
457404b6cca3Slucy wang - Sun Microsystems - Beijing China 			for (y = 0; y < actual; y++) {
457504b6cca3Slucy wang - Sun Microsystems - Beijing China 				(void) ddi_intr_free(mgp->htable[y]);
457604b6cca3Slucy wang - Sun Microsystems - Beijing China 			}
457704b6cca3Slucy wang - Sun Microsystems - Beijing China 
457804b6cca3Slucy wang - Sun Microsystems - Beijing China 			kmem_free(mgp->htable, mgp->intr_size);
457904b6cca3Slucy wang - Sun Microsystems - Beijing China 			mgp->htable = NULL;
458004b6cca3Slucy wang - Sun Microsystems - Beijing China 			return (DDI_FAILURE);
458104b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
458204b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
458304b6cca3Slucy wang - Sun Microsystems - Beijing China 
458404b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) ddi_intr_get_cap(mgp->htable[0], &mgp->intr_cap);
458504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->intr_cap & DDI_INTR_FLAG_BLOCK) {
458604b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* Call ddi_intr_block_enable() for MSI */
458704b6cca3Slucy wang - Sun Microsystems - Beijing China 		(void) ddi_intr_block_enable(mgp->htable, mgp->intr_cnt);
458804b6cca3Slucy wang - Sun Microsystems - Beijing China 	} else {
458904b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* Call ddi_intr_enable() for MSI non block enable */
459004b6cca3Slucy wang - Sun Microsystems - Beijing China 		for (x = 0; x < mgp->intr_cnt; x++) {
459104b6cca3Slucy wang - Sun Microsystems - Beijing China 			(void) ddi_intr_enable(mgp->htable[x]);
459204b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
459304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
459404b6cca3Slucy wang - Sun Microsystems - Beijing China 
459504b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
459604b6cca3Slucy wang - Sun Microsystems - Beijing China }
459704b6cca3Slucy wang - Sun Microsystems - Beijing China 
459804b6cca3Slucy wang - Sun Microsystems - Beijing China static void
459904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rem_intrs(struct myri10ge_priv *mgp, int handler_installed)
460004b6cca3Slucy wang - Sun Microsystems - Beijing China {
460104b6cca3Slucy wang - Sun Microsystems - Beijing China 	int x, err;
460204b6cca3Slucy wang - Sun Microsystems - Beijing China 
460304b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* Disable all interrupts */
460404b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (handler_installed) {
460504b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (mgp->intr_cap & DDI_INTR_FLAG_BLOCK) {
460604b6cca3Slucy wang - Sun Microsystems - Beijing China 			/* Call ddi_intr_block_disable() */
460704b6cca3Slucy wang - Sun Microsystems - Beijing China 			(void) ddi_intr_block_disable(mgp->htable,
460804b6cca3Slucy wang - Sun Microsystems - Beijing China 			    mgp->intr_cnt);
460904b6cca3Slucy wang - Sun Microsystems - Beijing China 		} else {
461004b6cca3Slucy wang - Sun Microsystems - Beijing China 			for (x = 0; x < mgp->intr_cnt; x++) {
461104b6cca3Slucy wang - Sun Microsystems - Beijing China 				(void) ddi_intr_disable(mgp->htable[x]);
461204b6cca3Slucy wang - Sun Microsystems - Beijing China 			}
461304b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
461404b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
461504b6cca3Slucy wang - Sun Microsystems - Beijing China 
461604b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (x = 0; x < mgp->intr_cnt; x++) {
461704b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (handler_installed) {
461804b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* Call ddi_intr_remove_handler() */
461904b6cca3Slucy wang - Sun Microsystems - Beijing China 			err = ddi_intr_remove_handler(mgp->htable[x]);
462004b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (err != DDI_SUCCESS) {
462104b6cca3Slucy wang - Sun Microsystems - Beijing China 				cmn_err(CE_WARN,
462204b6cca3Slucy wang - Sun Microsystems - Beijing China 				    "%s: ddi_intr_remove_handler for"
462304b6cca3Slucy wang - Sun Microsystems - Beijing China 				    "vec %d returned %d\n", mgp->name,
462404b6cca3Slucy wang - Sun Microsystems - Beijing China 				    x, err);
462504b6cca3Slucy wang - Sun Microsystems - Beijing China 			}
462604b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
462704b6cca3Slucy wang - Sun Microsystems - Beijing China 		err = ddi_intr_free(mgp->htable[x]);
462804b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (err != DDI_SUCCESS) {
462904b6cca3Slucy wang - Sun Microsystems - Beijing China 			cmn_err(CE_WARN,
463004b6cca3Slucy wang - Sun Microsystems - Beijing China 			    "%s: ddi_intr_free for vec %d returned %d\n",
463104b6cca3Slucy wang - Sun Microsystems - Beijing China 			    mgp->name, x, err);
463204b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
463304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
463404b6cca3Slucy wang - Sun Microsystems - Beijing China 	kmem_free(mgp->htable, mgp->intr_size);
463504b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->htable = NULL;
463604b6cca3Slucy wang - Sun Microsystems - Beijing China }
463704b6cca3Slucy wang - Sun Microsystems - Beijing China 
463804b6cca3Slucy wang - Sun Microsystems - Beijing China static void
463904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_test_physical(dev_info_t *dip)
464004b6cca3Slucy wang - Sun Microsystems - Beijing China {
464104b6cca3Slucy wang - Sun Microsystems - Beijing China 	ddi_dma_handle_t	handle;
464204b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_dma_stuff dma;
464304b6cca3Slucy wang - Sun Microsystems - Beijing China 	void *addr;
464404b6cca3Slucy wang - Sun Microsystems - Beijing China 	int err;
464504b6cca3Slucy wang - Sun Microsystems - Beijing China 
464604b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* test #1, sufficient for older sparc systems */
464704b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_tx_dma_attr.dma_attr_flags = DDI_DMA_FORCE_PHYSICAL;
464804b6cca3Slucy wang - Sun Microsystems - Beijing China 	err = ddi_dma_alloc_handle(dip, &myri10ge_tx_dma_attr,
464904b6cca3Slucy wang - Sun Microsystems - Beijing China 	    DDI_DMA_DONTWAIT, NULL, &handle);
465004b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (err == DDI_DMA_BADATTR)
465104b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto fail;
465204b6cca3Slucy wang - Sun Microsystems - Beijing China 	ddi_dma_free_handle(&handle);
465304b6cca3Slucy wang - Sun Microsystems - Beijing China 
465404b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* test #2, required on Olympis where the bind is what fails */
465504b6cca3Slucy wang - Sun Microsystems - Beijing China 	addr = myri10ge_dma_alloc(dip, 128, &myri10ge_tx_dma_attr,
465604b6cca3Slucy wang - Sun Microsystems - Beijing China 	    &myri10ge_dev_access_attr, DDI_DMA_STREAMING,
465704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    DDI_DMA_WRITE|DDI_DMA_STREAMING, &dma, 0, DDI_DMA_DONTWAIT);
465804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (addr == NULL)
465904b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto fail;
466004b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_dma_free(&dma);
466104b6cca3Slucy wang - Sun Microsystems - Beijing China 	return;
466204b6cca3Slucy wang - Sun Microsystems - Beijing China 
466304b6cca3Slucy wang - Sun Microsystems - Beijing China fail:
466404b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (myri10ge_verbose)
466504b6cca3Slucy wang - Sun Microsystems - Beijing China 		printf("myri10ge%d: DDI_DMA_FORCE_PHYSICAL failed, "
466604b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "using IOMMU\n", ddi_get_instance(dip));
466704b6cca3Slucy wang - Sun Microsystems - Beijing China 
466804b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_tx_dma_attr.dma_attr_flags &= ~DDI_DMA_FORCE_PHYSICAL;
466904b6cca3Slucy wang - Sun Microsystems - Beijing China }
467004b6cca3Slucy wang - Sun Microsystems - Beijing China 
467104b6cca3Slucy wang - Sun Microsystems - Beijing China static void
467204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_get_props(dev_info_t *dip)
467304b6cca3Slucy wang - Sun Microsystems - Beijing China {
467404b6cca3Slucy wang - Sun Microsystems - Beijing China 
467504b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_flow_control =  ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
467604b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_flow_control", myri10ge_flow_control);
467704b6cca3Slucy wang - Sun Microsystems - Beijing China 
467804b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_intr_coal_delay = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
467904b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_intr_coal_delay", myri10ge_intr_coal_delay);
468004b6cca3Slucy wang - Sun Microsystems - Beijing China 
46815ee6ac27SRichard Lowe #if defined __i386 || defined i386 || defined __i386__ || defined __x86_64__
468204b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_nvidia_ecrc_enable = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
468304b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_nvidia_ecrc_enable", 1);
468404b6cca3Slucy wang - Sun Microsystems - Beijing China #endif
468504b6cca3Slucy wang - Sun Microsystems - Beijing China 
468604b6cca3Slucy wang - Sun Microsystems - Beijing China 
468704b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_use_msi = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
468804b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_use_msi", myri10ge_use_msi);
468904b6cca3Slucy wang - Sun Microsystems - Beijing China 
469004b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_deassert_wait = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
469104b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_deassert_wait",  myri10ge_deassert_wait);
469204b6cca3Slucy wang - Sun Microsystems - Beijing China 
469304b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_verbose = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
469404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_verbose", myri10ge_verbose);
469504b6cca3Slucy wang - Sun Microsystems - Beijing China 
469604b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_tx_copylen = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
469704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_tx_copylen", myri10ge_tx_copylen);
469804b6cca3Slucy wang - Sun Microsystems - Beijing China 
469904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (myri10ge_tx_copylen < 60) {
470004b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN,
470104b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "myri10ge_tx_copylen must be >= 60 bytes\n");
470204b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_tx_copylen = 60;
470304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
470404b6cca3Slucy wang - Sun Microsystems - Beijing China 
470504b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_mtu_override = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
470604b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_mtu_override", myri10ge_mtu_override);
470704b6cca3Slucy wang - Sun Microsystems - Beijing China 
4708*6d0043d8SRobert Mustacchi 	if (myri10ge_mtu_override >= MYRI10GE_MIN_GLD_MTU &&
4709*6d0043d8SRobert Mustacchi 	    myri10ge_mtu_override <= MYRI10GE_MAX_GLD_MTU)
471004b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_mtu = myri10ge_mtu_override +
471104b6cca3Slucy wang - Sun Microsystems - Beijing China 		    sizeof (struct ether_header) + MXGEFW_PAD + VLAN_TAGSZ;
471204b6cca3Slucy wang - Sun Microsystems - Beijing China 	else if (myri10ge_mtu_override != 0) {
471304b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN,
471404b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "myri10ge_mtu_override must be between 1500 and "
471504b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "9000 bytes\n");
471604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
471704b6cca3Slucy wang - Sun Microsystems - Beijing China 
471804b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_bigbufs_initial = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
471904b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_bigbufs_initial", myri10ge_bigbufs_initial);
472004b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_bigbufs_max = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
472104b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_bigbufs_max", myri10ge_bigbufs_max);
472204b6cca3Slucy wang - Sun Microsystems - Beijing China 
472304b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_watchdog_reset = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
472404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_watchdog_reset", myri10ge_watchdog_reset);
472504b6cca3Slucy wang - Sun Microsystems - Beijing China 
472604b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (myri10ge_bigbufs_initial < 128) {
472704b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN,
472804b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "myri10ge_bigbufs_initial be at least 128\n");
472904b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_bigbufs_initial = 128;
473004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
473104b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (myri10ge_bigbufs_max < 128) {
473204b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN,
473304b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "myri10ge_bigbufs_max be at least 128\n");
473404b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_bigbufs_max = 128;
473504b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
473604b6cca3Slucy wang - Sun Microsystems - Beijing China 
473704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (myri10ge_bigbufs_max < myri10ge_bigbufs_initial) {
473804b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN,
473904b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "myri10ge_bigbufs_max must be >=  "
474004b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "myri10ge_bigbufs_initial\n");
474104b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_bigbufs_max = myri10ge_bigbufs_initial;
474204b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
474304b6cca3Slucy wang - Sun Microsystems - Beijing China 
474404b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_force_firmware = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
474504b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_force_firmware", myri10ge_force_firmware);
474604b6cca3Slucy wang - Sun Microsystems - Beijing China 
474704b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_max_slices = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
474804b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_max_slices", myri10ge_max_slices);
474904b6cca3Slucy wang - Sun Microsystems - Beijing China 
475004b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_use_msix = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
475104b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_use_msix", myri10ge_use_msix);
475204b6cca3Slucy wang - Sun Microsystems - Beijing China 
475304b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_rss_hash = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
475404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_rss_hash", myri10ge_rss_hash);
475504b6cca3Slucy wang - Sun Microsystems - Beijing China 
475604b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (myri10ge_rss_hash > MXGEFW_RSS_HASH_TYPE_MAX ||
475704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    myri10ge_rss_hash < MXGEFW_RSS_HASH_TYPE_IPV4) {
475804b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "myri10ge: Illegal rssh hash type %d\n",
475904b6cca3Slucy wang - Sun Microsystems - Beijing China 		    myri10ge_rss_hash);
476004b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_rss_hash = MXGEFW_RSS_HASH_TYPE_SRC_DST_PORT;
476104b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
476204b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_lro = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
476304b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_lro", myri10ge_lro);
476404b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_lro_cnt = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
476504b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_lro_cnt", myri10ge_lro_cnt);
476604b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_lro_max_aggr = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
476704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_lro_max_aggr", myri10ge_lro_max_aggr);
476804b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_tx_hash = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
476904b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_tx_hash", myri10ge_tx_hash);
477004b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_use_lso = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
477104b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_use_lso", myri10ge_use_lso);
477204b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_lso_copy = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
477304b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_lso_copy", myri10ge_lso_copy);
477404b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_tx_handles_initial = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
477504b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_tx_handles_initial", myri10ge_tx_handles_initial);
477604b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_small_bytes = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
477704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    "myri10ge_small_bytes", myri10ge_small_bytes);
477804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if ((myri10ge_small_bytes + MXGEFW_PAD) & (128 -1)) {
477904b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "myri10ge: myri10ge_small_bytes (%d)\n",
478004b6cca3Slucy wang - Sun Microsystems - Beijing China 		    myri10ge_small_bytes);
478104b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "must be aligned on 128b bndry -2\n");
478204b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_small_bytes += 128;
478304b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_small_bytes &= ~(128 -1);
478404b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_small_bytes -= MXGEFW_PAD;
478504b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "rounded up to %d\n",
478604b6cca3Slucy wang - Sun Microsystems - Beijing China 		    myri10ge_small_bytes);
478704b6cca3Slucy wang - Sun Microsystems - Beijing China 
478804b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_rss_hash = MXGEFW_RSS_HASH_TYPE_SRC_DST_PORT;
478904b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
479004b6cca3Slucy wang - Sun Microsystems - Beijing China }
479104b6cca3Slucy wang - Sun Microsystems - Beijing China 
479204b6cca3Slucy wang - Sun Microsystems - Beijing China #ifndef	PCI_EXP_LNKSTA
479304b6cca3Slucy wang - Sun Microsystems - Beijing China #define	PCI_EXP_LNKSTA 18
479404b6cca3Slucy wang - Sun Microsystems - Beijing China #endif
479504b6cca3Slucy wang - Sun Microsystems - Beijing China 
479604b6cca3Slucy wang - Sun Microsystems - Beijing China static int
479704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_find_cap(ddi_acc_handle_t handle, uint8_t *capptr, uint8_t capid)
479804b6cca3Slucy wang - Sun Microsystems - Beijing China {
479904b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint16_t	status;
480004b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint8_t 	ptr;
480104b6cca3Slucy wang - Sun Microsystems - Beijing China 
480204b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* check to see if we have capabilities */
480304b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = pci_config_get16(handle, PCI_CONF_STAT);
480404b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (!(status & PCI_STAT_CAP)) {
480504b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "PCI_STAT_CAP not found\n");
480604b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (ENXIO);
480704b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
480804b6cca3Slucy wang - Sun Microsystems - Beijing China 
480904b6cca3Slucy wang - Sun Microsystems - Beijing China 	ptr = pci_config_get8(handle, PCI_CONF_CAP_PTR);
481004b6cca3Slucy wang - Sun Microsystems - Beijing China 
481104b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* Walk the capabilities list, looking for a PCI Express cap */
481204b6cca3Slucy wang - Sun Microsystems - Beijing China 	while (ptr != PCI_CAP_NEXT_PTR_NULL) {
481304b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (pci_config_get8(handle, ptr + PCI_CAP_ID) == capid)
481404b6cca3Slucy wang - Sun Microsystems - Beijing China 			break;
481504b6cca3Slucy wang - Sun Microsystems - Beijing China 		ptr = pci_config_get8(handle, ptr + PCI_CAP_NEXT_PTR);
481604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
481704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (ptr < 64) {
481804b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "Bad capability offset %d\n", ptr);
481904b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (ENXIO);
482004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
482104b6cca3Slucy wang - Sun Microsystems - Beijing China 	*capptr = ptr;
482204b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
482304b6cca3Slucy wang - Sun Microsystems - Beijing China }
482404b6cca3Slucy wang - Sun Microsystems - Beijing China 
482504b6cca3Slucy wang - Sun Microsystems - Beijing China static int
482604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_set_max_readreq(ddi_acc_handle_t handle)
482704b6cca3Slucy wang - Sun Microsystems - Beijing China {
482804b6cca3Slucy wang - Sun Microsystems - Beijing China 	int err;
482904b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint16_t	val;
483004b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint8_t		ptr;
483104b6cca3Slucy wang - Sun Microsystems - Beijing China 
483204b6cca3Slucy wang - Sun Microsystems - Beijing China 	err = myri10ge_find_cap(handle, &ptr, PCI_CAP_ID_PCI_E);
483304b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (err != 0) {
483404b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "could not find PCIe cap\n");
483504b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (ENXIO);
483604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
483704b6cca3Slucy wang - Sun Microsystems - Beijing China 
483804b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* set max read req to 4096 */
483904b6cca3Slucy wang - Sun Microsystems - Beijing China 	val = pci_config_get16(handle, ptr + PCIE_DEVCTL);
484004b6cca3Slucy wang - Sun Microsystems - Beijing China 	val = (val & ~PCIE_DEVCTL_MAX_READ_REQ_MASK) |
484104b6cca3Slucy wang - Sun Microsystems - Beijing China 	    PCIE_DEVCTL_MAX_READ_REQ_4096;
484204b6cca3Slucy wang - Sun Microsystems - Beijing China 	pci_config_put16(handle, ptr + PCIE_DEVCTL, val);
484304b6cca3Slucy wang - Sun Microsystems - Beijing China 	val = pci_config_get16(handle, ptr + PCIE_DEVCTL);
484404b6cca3Slucy wang - Sun Microsystems - Beijing China 	if ((val & (PCIE_DEVCTL_MAX_READ_REQ_4096)) !=
484504b6cca3Slucy wang - Sun Microsystems - Beijing China 	    PCIE_DEVCTL_MAX_READ_REQ_4096) {
484604b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "could not set max read req (%x)\n", val);
484704b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (EINVAL);
484804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
484904b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
485004b6cca3Slucy wang - Sun Microsystems - Beijing China }
485104b6cca3Slucy wang - Sun Microsystems - Beijing China 
485204b6cca3Slucy wang - Sun Microsystems - Beijing China static int
485304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_read_pcie_link_width(ddi_acc_handle_t handle, int *link)
485404b6cca3Slucy wang - Sun Microsystems - Beijing China {
485504b6cca3Slucy wang - Sun Microsystems - Beijing China 	int err;
485604b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint16_t	val;
485704b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint8_t		ptr;
485804b6cca3Slucy wang - Sun Microsystems - Beijing China 
485904b6cca3Slucy wang - Sun Microsystems - Beijing China 	err = myri10ge_find_cap(handle, &ptr, PCI_CAP_ID_PCI_E);
486004b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (err != 0) {
486104b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "could not set max read req\n");
486204b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (ENXIO);
486304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
486404b6cca3Slucy wang - Sun Microsystems - Beijing China 
486504b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* read link width */
486604b6cca3Slucy wang - Sun Microsystems - Beijing China 	val = pci_config_get16(handle, ptr + PCIE_LINKSTS);
486704b6cca3Slucy wang - Sun Microsystems - Beijing China 	val &= PCIE_LINKSTS_NEG_WIDTH_MASK;
486804b6cca3Slucy wang - Sun Microsystems - Beijing China 	*link = (val >> 4);
486904b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
487004b6cca3Slucy wang - Sun Microsystems - Beijing China }
487104b6cca3Slucy wang - Sun Microsystems - Beijing China 
487204b6cca3Slucy wang - Sun Microsystems - Beijing China static int
487304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_reset_nic(struct myri10ge_priv *mgp)
487404b6cca3Slucy wang - Sun Microsystems - Beijing China {
487504b6cca3Slucy wang - Sun Microsystems - Beijing China 	ddi_acc_handle_t handle = mgp->cfg_hdl;
487604b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint32_t reboot;
487704b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint16_t cmd;
487804b6cca3Slucy wang - Sun Microsystems - Beijing China 	int err;
487904b6cca3Slucy wang - Sun Microsystems - Beijing China 
488004b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd = pci_config_get16(handle, PCI_CONF_COMM);
488104b6cca3Slucy wang - Sun Microsystems - Beijing China 	if ((cmd & PCI_COMM_ME) == 0) {
488204b6cca3Slucy wang - Sun Microsystems - Beijing China 		/*
488304b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * Bus master DMA disabled?  Check to see if the card
488404b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * rebooted due to a parity error For now, just report
488504b6cca3Slucy wang - Sun Microsystems - Beijing China 		 * it
488604b6cca3Slucy wang - Sun Microsystems - Beijing China 		 */
488704b6cca3Slucy wang - Sun Microsystems - Beijing China 
488804b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* enter read32 mode */
488904b6cca3Slucy wang - Sun Microsystems - Beijing China 		pci_config_put8(handle, mgp->vso + 0x10, 0x3);
489004b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* read REBOOT_STATUS (0xfffffff0) */
489104b6cca3Slucy wang - Sun Microsystems - Beijing China 		pci_config_put32(handle, mgp->vso + 0x18, 0xfffffff0);
489204b6cca3Slucy wang - Sun Microsystems - Beijing China 		reboot = pci_config_get16(handle, mgp->vso + 0x14);
489304b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s NIC rebooted 0x%x\n", mgp->name, reboot);
489404b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (0);
489504b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
489604b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (!myri10ge_watchdog_reset) {
489704b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: not resetting\n", mgp->name);
489804b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (1);
489904b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
490004b6cca3Slucy wang - Sun Microsystems - Beijing China 
490104b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_stop_locked(mgp);
490204b6cca3Slucy wang - Sun Microsystems - Beijing China 	err = myri10ge_start_locked(mgp);
490304b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (err == DDI_FAILURE) {
490404b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (0);
490504b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
490604b6cca3Slucy wang - Sun Microsystems - Beijing China 	mac_tx_update(mgp->mh);
490704b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (1);
490804b6cca3Slucy wang - Sun Microsystems - Beijing China }
490904b6cca3Slucy wang - Sun Microsystems - Beijing China 
491004b6cca3Slucy wang - Sun Microsystems - Beijing China static inline int
491104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_ring_stalled(myri10ge_tx_ring_t *tx)
491204b6cca3Slucy wang - Sun Microsystems - Beijing China {
491304b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (tx->sched != tx->stall &&
491404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    tx->done == tx->watchdog_done &&
491504b6cca3Slucy wang - Sun Microsystems - Beijing China 	    tx->watchdog_req != tx->watchdog_done)
491604b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (1);
491704b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
491804b6cca3Slucy wang - Sun Microsystems - Beijing China }
491904b6cca3Slucy wang - Sun Microsystems - Beijing China 
492004b6cca3Slucy wang - Sun Microsystems - Beijing China static void
492104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_watchdog(void *arg)
492204b6cca3Slucy wang - Sun Microsystems - Beijing China {
492304b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp;
492404b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_slice_state *ss;
492504b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_tx_ring_t *tx;
492604b6cca3Slucy wang - Sun Microsystems - Beijing China 	int nic_ok = 1;
492704b6cca3Slucy wang - Sun Microsystems - Beijing China 	int slices_stalled, rx_pause, i;
492804b6cca3Slucy wang - Sun Microsystems - Beijing China 	int add_rx;
492904b6cca3Slucy wang - Sun Microsystems - Beijing China 
493004b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp = arg;
493104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&mgp->intrlock);
493204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->running != MYRI10GE_ETH_RUNNING) {
493304b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN,
493404b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "%s not running, not rearming watchdog (%d)\n",
493504b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->name, mgp->running);
493604b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_exit(&mgp->intrlock);
493704b6cca3Slucy wang - Sun Microsystems - Beijing China 		return;
493804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
493904b6cca3Slucy wang - Sun Microsystems - Beijing China 
494004b6cca3Slucy wang - Sun Microsystems - Beijing China 	rx_pause = ntohl(mgp->ss[0].fw_stats->dropped_pause);
494104b6cca3Slucy wang - Sun Microsystems - Beijing China 
494204b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
494304b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * make sure nic is stalled before we reset the nic, so as to
494404b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * ensure we don't rip the transmit data structures out from
494504b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * under a pending transmit
494604b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
494704b6cca3Slucy wang - Sun Microsystems - Beijing China 
494804b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (slices_stalled = 0, i = 0; i < mgp->num_slices; i++) {
494904b6cca3Slucy wang - Sun Microsystems - Beijing China 		tx = &mgp->ss[i].tx;
495004b6cca3Slucy wang - Sun Microsystems - Beijing China 		slices_stalled = myri10ge_ring_stalled(tx);
495104b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (slices_stalled)
495204b6cca3Slucy wang - Sun Microsystems - Beijing China 			break;
495304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
495404b6cca3Slucy wang - Sun Microsystems - Beijing China 
495504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (slices_stalled) {
495604b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (mgp->watchdog_rx_pause == rx_pause) {
495704b6cca3Slucy wang - Sun Microsystems - Beijing China 			cmn_err(CE_WARN,
495804b6cca3Slucy wang - Sun Microsystems - Beijing China 			    "%s slice %d stalled:(%d, %d, %d, %d, %d %d %d\n)",
495904b6cca3Slucy wang - Sun Microsystems - Beijing China 			    mgp->name, i, tx->sched, tx->stall,
496004b6cca3Slucy wang - Sun Microsystems - Beijing China 			    tx->done, tx->watchdog_done, tx->req, tx->pkt_done,
496104b6cca3Slucy wang - Sun Microsystems - Beijing China 			    (int)ntohl(mgp->ss[i].fw_stats->send_done_count));
496204b6cca3Slucy wang - Sun Microsystems - Beijing China 			nic_ok = myri10ge_reset_nic(mgp);
496304b6cca3Slucy wang - Sun Microsystems - Beijing China 		} else {
496404b6cca3Slucy wang - Sun Microsystems - Beijing China 			cmn_err(CE_WARN,
496504b6cca3Slucy wang - Sun Microsystems - Beijing China 			    "%s Flow controlled, check link partner\n",
496604b6cca3Slucy wang - Sun Microsystems - Beijing China 			    mgp->name);
496704b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
496804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
496904b6cca3Slucy wang - Sun Microsystems - Beijing China 
497004b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (!nic_ok) {
497104b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN,
497204b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "%s Nic dead, not rearming watchdog\n", mgp->name);
497304b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_exit(&mgp->intrlock);
497404b6cca3Slucy wang - Sun Microsystems - Beijing China 		return;
497504b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
497604b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (i = 0; i < mgp->num_slices; i++) {
497704b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss = &mgp->ss[i];
497804b6cca3Slucy wang - Sun Microsystems - Beijing China 		tx = &ss->tx;
497904b6cca3Slucy wang - Sun Microsystems - Beijing China 		tx->watchdog_done = tx->done;
498004b6cca3Slucy wang - Sun Microsystems - Beijing China 		tx->watchdog_req = tx->req;
498104b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (ss->watchdog_rx_copy != MYRI10GE_SLICE_STAT(rx_copy)) {
498204b6cca3Slucy wang - Sun Microsystems - Beijing China 			ss->watchdog_rx_copy = MYRI10GE_SLICE_STAT(rx_copy);
498304b6cca3Slucy wang - Sun Microsystems - Beijing China 			add_rx =
498404b6cca3Slucy wang - Sun Microsystems - Beijing China 			    min(ss->jpool.num_alloc,
498504b6cca3Slucy wang - Sun Microsystems - Beijing China 			    myri10ge_bigbufs_max -
498604b6cca3Slucy wang - Sun Microsystems - Beijing China 			    (ss->jpool.num_alloc -
498704b6cca3Slucy wang - Sun Microsystems - Beijing China 			    ss->jbufs_for_smalls));
498804b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (add_rx != 0) {
498904b6cca3Slucy wang - Sun Microsystems - Beijing China 				(void) myri10ge_add_jbufs(ss, add_rx, 0);
499004b6cca3Slucy wang - Sun Microsystems - Beijing China 				/* now feed them to the firmware */
499104b6cca3Slucy wang - Sun Microsystems - Beijing China 				mutex_enter(&ss->jpool.mtx);
499204b6cca3Slucy wang - Sun Microsystems - Beijing China 				myri10ge_restock_jumbos(ss);
499304b6cca3Slucy wang - Sun Microsystems - Beijing China 				mutex_exit(&ss->jpool.mtx);
499404b6cca3Slucy wang - Sun Microsystems - Beijing China 			}
499504b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
499604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
499704b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->watchdog_rx_pause = rx_pause;
499804b6cca3Slucy wang - Sun Microsystems - Beijing China 
499904b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->timer_id = timeout(myri10ge_watchdog, mgp,
500004b6cca3Slucy wang - Sun Microsystems - Beijing China 	    mgp->timer_ticks);
500104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&mgp->intrlock);
500204b6cca3Slucy wang - Sun Microsystems - Beijing China }
500304b6cca3Slucy wang - Sun Microsystems - Beijing China 
500404b6cca3Slucy wang - Sun Microsystems - Beijing China /*ARGSUSED*/
500504b6cca3Slucy wang - Sun Microsystems - Beijing China static int
500604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_get_coalesce(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
500704b6cca3Slucy wang - Sun Microsystems - Beijing China 
500804b6cca3Slucy wang - Sun Microsystems - Beijing China {
500904b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp = (struct myri10ge_priv *)(void *)cp;
501004b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) mi_mpprintf(mp, "%d", mgp->intr_coal_delay);
501104b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
501204b6cca3Slucy wang - Sun Microsystems - Beijing China }
501304b6cca3Slucy wang - Sun Microsystems - Beijing China 
501404b6cca3Slucy wang - Sun Microsystems - Beijing China /*ARGSUSED*/
501504b6cca3Slucy wang - Sun Microsystems - Beijing China static int
501604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_set_coalesce(queue_t *q, mblk_t *mp, char *value,
501704b6cca3Slucy wang - Sun Microsystems - Beijing China     caddr_t cp, cred_t *credp)
501804b6cca3Slucy wang - Sun Microsystems - Beijing China 
501904b6cca3Slucy wang - Sun Microsystems - Beijing China {
502004b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp = (struct myri10ge_priv *)(void *)cp;
502104b6cca3Slucy wang - Sun Microsystems - Beijing China 	char *end;
502204b6cca3Slucy wang - Sun Microsystems - Beijing China 	size_t new_value;
502304b6cca3Slucy wang - Sun Microsystems - Beijing China 
502404b6cca3Slucy wang - Sun Microsystems - Beijing China 	new_value = mi_strtol(value, &end, 10);
502504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (end == value)
502604b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (EINVAL);
502704b6cca3Slucy wang - Sun Microsystems - Beijing China 
502804b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&myri10ge_param_lock);
502904b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->intr_coal_delay = (int)new_value;
503004b6cca3Slucy wang - Sun Microsystems - Beijing China 	*mgp->intr_coal_delay_ptr = htonl(mgp->intr_coal_delay);
503104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&myri10ge_param_lock);
503204b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
503304b6cca3Slucy wang - Sun Microsystems - Beijing China }
503404b6cca3Slucy wang - Sun Microsystems - Beijing China 
503504b6cca3Slucy wang - Sun Microsystems - Beijing China /*ARGSUSED*/
503604b6cca3Slucy wang - Sun Microsystems - Beijing China static int
503704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_get_pauseparam(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
503804b6cca3Slucy wang - Sun Microsystems - Beijing China 
503904b6cca3Slucy wang - Sun Microsystems - Beijing China {
504004b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp = (struct myri10ge_priv *)(void *)cp;
504104b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) mi_mpprintf(mp, "%d", mgp->pause);
504204b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
504304b6cca3Slucy wang - Sun Microsystems - Beijing China }
504404b6cca3Slucy wang - Sun Microsystems - Beijing China 
504504b6cca3Slucy wang - Sun Microsystems - Beijing China /*ARGSUSED*/
504604b6cca3Slucy wang - Sun Microsystems - Beijing China static int
504704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_set_pauseparam(queue_t *q, mblk_t *mp, char *value,
504804b6cca3Slucy wang - Sun Microsystems - Beijing China 			caddr_t cp, cred_t *credp)
504904b6cca3Slucy wang - Sun Microsystems - Beijing China 
505004b6cca3Slucy wang - Sun Microsystems - Beijing China {
505104b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp = (struct myri10ge_priv *)(void *)cp;
505204b6cca3Slucy wang - Sun Microsystems - Beijing China 	char *end;
505304b6cca3Slucy wang - Sun Microsystems - Beijing China 	size_t new_value;
505404b6cca3Slucy wang - Sun Microsystems - Beijing China 	int err = 0;
505504b6cca3Slucy wang - Sun Microsystems - Beijing China 
505604b6cca3Slucy wang - Sun Microsystems - Beijing China 	new_value = mi_strtol(value, &end, 10);
505704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (end == value)
505804b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (EINVAL);
505904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (new_value != 0)
506004b6cca3Slucy wang - Sun Microsystems - Beijing China 		new_value = 1;
506104b6cca3Slucy wang - Sun Microsystems - Beijing China 
506204b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&myri10ge_param_lock);
506304b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (new_value != mgp->pause)
506404b6cca3Slucy wang - Sun Microsystems - Beijing China 		err = myri10ge_change_pause(mgp, new_value);
506504b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&myri10ge_param_lock);
506604b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (err);
506704b6cca3Slucy wang - Sun Microsystems - Beijing China }
506804b6cca3Slucy wang - Sun Microsystems - Beijing China 
506904b6cca3Slucy wang - Sun Microsystems - Beijing China /*ARGSUSED*/
507004b6cca3Slucy wang - Sun Microsystems - Beijing China static int
507104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_get_int(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
507204b6cca3Slucy wang - Sun Microsystems - Beijing China 
507304b6cca3Slucy wang - Sun Microsystems - Beijing China {
507404b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) mi_mpprintf(mp, "%d", *(int *)(void *)cp);
507504b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
507604b6cca3Slucy wang - Sun Microsystems - Beijing China }
507704b6cca3Slucy wang - Sun Microsystems - Beijing China 
507804b6cca3Slucy wang - Sun Microsystems - Beijing China /*ARGSUSED*/
507904b6cca3Slucy wang - Sun Microsystems - Beijing China static int
508004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_set_int(queue_t *q, mblk_t *mp, char *value,
508104b6cca3Slucy wang - Sun Microsystems - Beijing China     caddr_t cp, cred_t *credp)
508204b6cca3Slucy wang - Sun Microsystems - Beijing China 
508304b6cca3Slucy wang - Sun Microsystems - Beijing China {
508404b6cca3Slucy wang - Sun Microsystems - Beijing China 	char *end;
508504b6cca3Slucy wang - Sun Microsystems - Beijing China 	size_t new_value;
508604b6cca3Slucy wang - Sun Microsystems - Beijing China 
508704b6cca3Slucy wang - Sun Microsystems - Beijing China 	new_value = mi_strtol(value, &end, 10);
508804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (end == value)
508904b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (EINVAL);
509004b6cca3Slucy wang - Sun Microsystems - Beijing China 	*(int *)(void *)cp = new_value;
509104b6cca3Slucy wang - Sun Microsystems - Beijing China 
509204b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
509304b6cca3Slucy wang - Sun Microsystems - Beijing China }
509404b6cca3Slucy wang - Sun Microsystems - Beijing China 
509504b6cca3Slucy wang - Sun Microsystems - Beijing China static void
509604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_ndd_init(struct myri10ge_priv *mgp)
509704b6cca3Slucy wang - Sun Microsystems - Beijing China {
509804b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->nd_head = NULL;
509904b6cca3Slucy wang - Sun Microsystems - Beijing China 
510004b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) nd_load(&mgp->nd_head, "myri10ge_intr_coal_delay",
510104b6cca3Slucy wang - Sun Microsystems - Beijing China 	    myri10ge_get_coalesce, myri10ge_set_coalesce, (caddr_t)mgp);
510204b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) nd_load(&mgp->nd_head, "myri10ge_flow_control",
510304b6cca3Slucy wang - Sun Microsystems - Beijing China 	    myri10ge_get_pauseparam, myri10ge_set_pauseparam, (caddr_t)mgp);
510404b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) nd_load(&mgp->nd_head, "myri10ge_verbose",
510504b6cca3Slucy wang - Sun Microsystems - Beijing China 	    myri10ge_get_int, myri10ge_set_int, (caddr_t)&myri10ge_verbose);
510604b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) nd_load(&mgp->nd_head, "myri10ge_deassert_wait",
510704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    myri10ge_get_int, myri10ge_set_int,
510804b6cca3Slucy wang - Sun Microsystems - Beijing China 	    (caddr_t)&myri10ge_deassert_wait);
510904b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) nd_load(&mgp->nd_head, "myri10ge_bigbufs_max",
511004b6cca3Slucy wang - Sun Microsystems - Beijing China 	    myri10ge_get_int, myri10ge_set_int,
511104b6cca3Slucy wang - Sun Microsystems - Beijing China 	    (caddr_t)&myri10ge_bigbufs_max);
511204b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) nd_load(&mgp->nd_head, "myri10ge_lro",
511304b6cca3Slucy wang - Sun Microsystems - Beijing China 	    myri10ge_get_int, myri10ge_set_int,
511404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    (caddr_t)&myri10ge_lro);
511504b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) nd_load(&mgp->nd_head, "myri10ge_lro_max_aggr",
511604b6cca3Slucy wang - Sun Microsystems - Beijing China 	    myri10ge_get_int, myri10ge_set_int,
511704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    (caddr_t)&myri10ge_lro_max_aggr);
511804b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) nd_load(&mgp->nd_head, "myri10ge_tx_hash",
511904b6cca3Slucy wang - Sun Microsystems - Beijing China 	    myri10ge_get_int, myri10ge_set_int,
512004b6cca3Slucy wang - Sun Microsystems - Beijing China 	    (caddr_t)&myri10ge_tx_hash);
512104b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) nd_load(&mgp->nd_head, "myri10ge_lso_copy",
512204b6cca3Slucy wang - Sun Microsystems - Beijing China 	    myri10ge_get_int, myri10ge_set_int,
512304b6cca3Slucy wang - Sun Microsystems - Beijing China 	    (caddr_t)&myri10ge_lso_copy);
512404b6cca3Slucy wang - Sun Microsystems - Beijing China }
512504b6cca3Slucy wang - Sun Microsystems - Beijing China 
512604b6cca3Slucy wang - Sun Microsystems - Beijing China static void
512704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_ndd_fini(struct myri10ge_priv *mgp)
512804b6cca3Slucy wang - Sun Microsystems - Beijing China {
512904b6cca3Slucy wang - Sun Microsystems - Beijing China 	nd_free(&mgp->nd_head);
513004b6cca3Slucy wang - Sun Microsystems - Beijing China }
513104b6cca3Slucy wang - Sun Microsystems - Beijing China 
513204b6cca3Slucy wang - Sun Microsystems - Beijing China static void
513304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
513404b6cca3Slucy wang - Sun Microsystems - Beijing China {
513504b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct iocblk *iocp;
513604b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp = arg;
513704b6cca3Slucy wang - Sun Microsystems - Beijing China 	int cmd, ok, err;
513804b6cca3Slucy wang - Sun Microsystems - Beijing China 
513904b6cca3Slucy wang - Sun Microsystems - Beijing China 	iocp = (struct iocblk *)(void *)mp->b_rptr;
514004b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd = iocp->ioc_cmd;
514104b6cca3Slucy wang - Sun Microsystems - Beijing China 
514204b6cca3Slucy wang - Sun Microsystems - Beijing China 	ok = 0;
514304b6cca3Slucy wang - Sun Microsystems - Beijing China 	err = 0;
514404b6cca3Slucy wang - Sun Microsystems - Beijing China 
514504b6cca3Slucy wang - Sun Microsystems - Beijing China 	switch (cmd) {
514604b6cca3Slucy wang - Sun Microsystems - Beijing China 	case ND_GET:
514704b6cca3Slucy wang - Sun Microsystems - Beijing China 	case ND_SET:
514804b6cca3Slucy wang - Sun Microsystems - Beijing China 		ok = nd_getset(wq, mgp->nd_head, mp);
514904b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
515004b6cca3Slucy wang - Sun Microsystems - Beijing China 	default:
515104b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
515204b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
515304b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (!ok)
515404b6cca3Slucy wang - Sun Microsystems - Beijing China 		err = EINVAL;
515504b6cca3Slucy wang - Sun Microsystems - Beijing China 	else
515604b6cca3Slucy wang - Sun Microsystems - Beijing China 		err = iocp->ioc_error;
515704b6cca3Slucy wang - Sun Microsystems - Beijing China 
515804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (!err)
515904b6cca3Slucy wang - Sun Microsystems - Beijing China 		miocack(wq, mp, iocp->ioc_count, err);
516004b6cca3Slucy wang - Sun Microsystems - Beijing China 	else
516104b6cca3Slucy wang - Sun Microsystems - Beijing China 		miocnak(wq, mp, 0, err);
516204b6cca3Slucy wang - Sun Microsystems - Beijing China }
516304b6cca3Slucy wang - Sun Microsystems - Beijing China 
516404b6cca3Slucy wang - Sun Microsystems - Beijing China static struct myri10ge_priv *mgp_list;
516504b6cca3Slucy wang - Sun Microsystems - Beijing China 
516604b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *
516704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_get_instance(uint_t unit)
516804b6cca3Slucy wang - Sun Microsystems - Beijing China {
516904b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp;
517004b6cca3Slucy wang - Sun Microsystems - Beijing China 
517104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&myri10ge_param_lock);
517204b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (mgp = mgp_list; mgp != NULL; mgp = mgp->next) {
517304b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (unit == ddi_get_instance(mgp->dip)) {
517404b6cca3Slucy wang - Sun Microsystems - Beijing China 			mgp->refcnt++;
517504b6cca3Slucy wang - Sun Microsystems - Beijing China 			break;
517604b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
517704b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
517804b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&myri10ge_param_lock);
517904b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (mgp);
518004b6cca3Slucy wang - Sun Microsystems - Beijing China }
518104b6cca3Slucy wang - Sun Microsystems - Beijing China 
518204b6cca3Slucy wang - Sun Microsystems - Beijing China void
518304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_put_instance(struct myri10ge_priv *mgp)
518404b6cca3Slucy wang - Sun Microsystems - Beijing China {
518504b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&myri10ge_param_lock);
518604b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->refcnt--;
518704b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&myri10ge_param_lock);
518804b6cca3Slucy wang - Sun Microsystems - Beijing China }
518904b6cca3Slucy wang - Sun Microsystems - Beijing China 
519004b6cca3Slucy wang - Sun Microsystems - Beijing China static boolean_t
519104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
519204b6cca3Slucy wang - Sun Microsystems - Beijing China {
519304b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp = arg;
519404b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint32_t *cap_hcksum;
519504b6cca3Slucy wang - Sun Microsystems - Beijing China 	mac_capab_lso_t *cap_lso;
519604b6cca3Slucy wang - Sun Microsystems - Beijing China 	mac_capab_rings_t *cap_rings;
519704b6cca3Slucy wang - Sun Microsystems - Beijing China 
519804b6cca3Slucy wang - Sun Microsystems - Beijing China 	switch (cap) {
519904b6cca3Slucy wang - Sun Microsystems - Beijing China 	case MAC_CAPAB_HCKSUM:
520004b6cca3Slucy wang - Sun Microsystems - Beijing China 		cap_hcksum = cap_data;
520104b6cca3Slucy wang - Sun Microsystems - Beijing China 		*cap_hcksum = HCKSUM_INET_PARTIAL;
520204b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
520304b6cca3Slucy wang - Sun Microsystems - Beijing China 	case MAC_CAPAB_RINGS:
520404b6cca3Slucy wang - Sun Microsystems - Beijing China 		cap_rings = cap_data;
520504b6cca3Slucy wang - Sun Microsystems - Beijing China 		switch (cap_rings->mr_type) {
520604b6cca3Slucy wang - Sun Microsystems - Beijing China 		case MAC_RING_TYPE_RX:
520704b6cca3Slucy wang - Sun Microsystems - Beijing China 			cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
520804b6cca3Slucy wang - Sun Microsystems - Beijing China 			cap_rings->mr_rnum = mgp->num_slices;
520904b6cca3Slucy wang - Sun Microsystems - Beijing China 			cap_rings->mr_gnum = 1;
521004b6cca3Slucy wang - Sun Microsystems - Beijing China 			cap_rings->mr_rget = myri10ge_fill_ring;
521104b6cca3Slucy wang - Sun Microsystems - Beijing China 			cap_rings->mr_gget = myri10ge_fill_group;
521204b6cca3Slucy wang - Sun Microsystems - Beijing China 			break;
521304b6cca3Slucy wang - Sun Microsystems - Beijing China 		case MAC_RING_TYPE_TX:
521404b6cca3Slucy wang - Sun Microsystems - Beijing China 			cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
521504b6cca3Slucy wang - Sun Microsystems - Beijing China 			cap_rings->mr_rnum = mgp->num_slices;
521604b6cca3Slucy wang - Sun Microsystems - Beijing China 			cap_rings->mr_gnum = 0;
521704b6cca3Slucy wang - Sun Microsystems - Beijing China 			cap_rings->mr_rget = myri10ge_fill_ring;
521804b6cca3Slucy wang - Sun Microsystems - Beijing China 			cap_rings->mr_gget = NULL;
521904b6cca3Slucy wang - Sun Microsystems - Beijing China 			break;
522004b6cca3Slucy wang - Sun Microsystems - Beijing China 		default:
522104b6cca3Slucy wang - Sun Microsystems - Beijing China 			return (B_FALSE);
522204b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
522304b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
522404b6cca3Slucy wang - Sun Microsystems - Beijing China 	case MAC_CAPAB_LSO:
522504b6cca3Slucy wang - Sun Microsystems - Beijing China 		cap_lso = cap_data;
522604b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (!myri10ge_use_lso)
522704b6cca3Slucy wang - Sun Microsystems - Beijing China 			return (B_FALSE);
522804b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (!(mgp->features & MYRI10GE_TSO))
522904b6cca3Slucy wang - Sun Microsystems - Beijing China 			return (B_FALSE);
523004b6cca3Slucy wang - Sun Microsystems - Beijing China 		cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
523104b6cca3Slucy wang - Sun Microsystems - Beijing China 		cap_lso->lso_basic_tcp_ipv4.lso_max = (uint16_t)-1;
523204b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
523304b6cca3Slucy wang - Sun Microsystems - Beijing China 
523404b6cca3Slucy wang - Sun Microsystems - Beijing China 	default:
523504b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (B_FALSE);
523604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
523704b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (B_TRUE);
523804b6cca3Slucy wang - Sun Microsystems - Beijing China }
523904b6cca3Slucy wang - Sun Microsystems - Beijing China 
524004b6cca3Slucy wang - Sun Microsystems - Beijing China 
524104b6cca3Slucy wang - Sun Microsystems - Beijing China static int
524204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_m_stat(void *arg, uint_t stat, uint64_t *val)
524304b6cca3Slucy wang - Sun Microsystems - Beijing China {
524404b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp = arg;
524504b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_rx_ring_stats *rstat;
524604b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_tx_ring_stats *tstat;
524704b6cca3Slucy wang - Sun Microsystems - Beijing China 	mcp_irq_data_t *fw_stats = mgp->ss[0].fw_stats;
524804b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_slice_state *ss;
524904b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint64_t tmp = 0;
525004b6cca3Slucy wang - Sun Microsystems - Beijing China 	int i;
525104b6cca3Slucy wang - Sun Microsystems - Beijing China 
525204b6cca3Slucy wang - Sun Microsystems - Beijing China 	switch (stat) {
525304b6cca3Slucy wang - Sun Microsystems - Beijing China 	case MAC_STAT_IFSPEED:
525404b6cca3Slucy wang - Sun Microsystems - Beijing China 		*val = 10ull * 1000ull * 1000000ull;
525504b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
525604b6cca3Slucy wang - Sun Microsystems - Beijing China 
525704b6cca3Slucy wang - Sun Microsystems - Beijing China 	case MAC_STAT_MULTIRCV:
525804b6cca3Slucy wang - Sun Microsystems - Beijing China 		for (i = 0; i < mgp->num_slices; i++) {
525904b6cca3Slucy wang - Sun Microsystems - Beijing China 			rstat = &mgp->ss[i].rx_stats;
526004b6cca3Slucy wang - Sun Microsystems - Beijing China 			tmp += rstat->multircv;
526104b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
526204b6cca3Slucy wang - Sun Microsystems - Beijing China 		*val = tmp;
526304b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
526404b6cca3Slucy wang - Sun Microsystems - Beijing China 
526504b6cca3Slucy wang - Sun Microsystems - Beijing China 	case MAC_STAT_BRDCSTRCV:
526604b6cca3Slucy wang - Sun Microsystems - Beijing China 		for (i = 0; i < mgp->num_slices; i++) {
526704b6cca3Slucy wang - Sun Microsystems - Beijing China 			rstat = &mgp->ss[i].rx_stats;
526804b6cca3Slucy wang - Sun Microsystems - Beijing China 			tmp += rstat->brdcstrcv;
526904b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
527004b6cca3Slucy wang - Sun Microsystems - Beijing China 		*val = tmp;
527104b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
527204b6cca3Slucy wang - Sun Microsystems - Beijing China 
527304b6cca3Slucy wang - Sun Microsystems - Beijing China 	case MAC_STAT_MULTIXMT:
527404b6cca3Slucy wang - Sun Microsystems - Beijing China 		for (i = 0; i < mgp->num_slices; i++) {
527504b6cca3Slucy wang - Sun Microsystems - Beijing China 			tstat = &mgp->ss[i].tx.stats;
527604b6cca3Slucy wang - Sun Microsystems - Beijing China 			tmp += tstat->multixmt;
527704b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
527804b6cca3Slucy wang - Sun Microsystems - Beijing China 		*val = tmp;
527904b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
528004b6cca3Slucy wang - Sun Microsystems - Beijing China 
528104b6cca3Slucy wang - Sun Microsystems - Beijing China 	case MAC_STAT_BRDCSTXMT:
528204b6cca3Slucy wang - Sun Microsystems - Beijing China 		for (i = 0; i < mgp->num_slices; i++) {
528304b6cca3Slucy wang - Sun Microsystems - Beijing China 			tstat = &mgp->ss[i].tx.stats;
528404b6cca3Slucy wang - Sun Microsystems - Beijing China 			tmp += tstat->brdcstxmt;
528504b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
528604b6cca3Slucy wang - Sun Microsystems - Beijing China 		*val = tmp;
528704b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
528804b6cca3Slucy wang - Sun Microsystems - Beijing China 
528904b6cca3Slucy wang - Sun Microsystems - Beijing China 	case MAC_STAT_NORCVBUF:
529004b6cca3Slucy wang - Sun Microsystems - Beijing China 		tmp = ntohl(fw_stats->dropped_no_big_buffer);
529104b6cca3Slucy wang - Sun Microsystems - Beijing China 		tmp += ntohl(fw_stats->dropped_no_small_buffer);
529204b6cca3Slucy wang - Sun Microsystems - Beijing China 		tmp += ntohl(fw_stats->dropped_link_overflow);
529304b6cca3Slucy wang - Sun Microsystems - Beijing China 		for (i = 0; i < mgp->num_slices; i++) {
529404b6cca3Slucy wang - Sun Microsystems - Beijing China 			ss = &mgp->ss[i];
529504b6cca3Slucy wang - Sun Microsystems - Beijing China 			tmp += MYRI10GE_SLICE_STAT(rx_big_nobuf);
529604b6cca3Slucy wang - Sun Microsystems - Beijing China 			tmp += MYRI10GE_SLICE_STAT(rx_small_nobuf);
529704b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
529804b6cca3Slucy wang - Sun Microsystems - Beijing China 		*val = tmp;
529904b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
530004b6cca3Slucy wang - Sun Microsystems - Beijing China 
530104b6cca3Slucy wang - Sun Microsystems - Beijing China 	case MAC_STAT_IERRORS:
530204b6cca3Slucy wang - Sun Microsystems - Beijing China 		tmp += ntohl(fw_stats->dropped_bad_crc32);
530304b6cca3Slucy wang - Sun Microsystems - Beijing China 		tmp += ntohl(fw_stats->dropped_bad_phy);
530404b6cca3Slucy wang - Sun Microsystems - Beijing China 		tmp += ntohl(fw_stats->dropped_runt);
530504b6cca3Slucy wang - Sun Microsystems - Beijing China 		tmp += ntohl(fw_stats->dropped_overrun);
530604b6cca3Slucy wang - Sun Microsystems - Beijing China 		*val = tmp;
530704b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
530804b6cca3Slucy wang - Sun Microsystems - Beijing China 
530904b6cca3Slucy wang - Sun Microsystems - Beijing China 	case MAC_STAT_OERRORS:
531004b6cca3Slucy wang - Sun Microsystems - Beijing China 		for (i = 0; i < mgp->num_slices; i++) {
531104b6cca3Slucy wang - Sun Microsystems - Beijing China 			ss = &mgp->ss[i];
531204b6cca3Slucy wang - Sun Microsystems - Beijing China 			tmp += MYRI10GE_SLICE_STAT(xmit_lsobadflags);
531304b6cca3Slucy wang - Sun Microsystems - Beijing China 			tmp += MYRI10GE_SLICE_STAT(xmit_err);
531404b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
531504b6cca3Slucy wang - Sun Microsystems - Beijing China 		*val = tmp;
531604b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
531704b6cca3Slucy wang - Sun Microsystems - Beijing China 
531804b6cca3Slucy wang - Sun Microsystems - Beijing China 	case MAC_STAT_RBYTES:
531904b6cca3Slucy wang - Sun Microsystems - Beijing China 		for (i = 0; i < mgp->num_slices; i++) {
532004b6cca3Slucy wang - Sun Microsystems - Beijing China 			rstat = &mgp->ss[i].rx_stats;
532104b6cca3Slucy wang - Sun Microsystems - Beijing China 			tmp += rstat->ibytes;
532204b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
532304b6cca3Slucy wang - Sun Microsystems - Beijing China 		*val = tmp;
532404b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
532504b6cca3Slucy wang - Sun Microsystems - Beijing China 
532604b6cca3Slucy wang - Sun Microsystems - Beijing China 	case MAC_STAT_IPACKETS:
532704b6cca3Slucy wang - Sun Microsystems - Beijing China 		for (i = 0; i < mgp->num_slices; i++) {
532804b6cca3Slucy wang - Sun Microsystems - Beijing China 			rstat = &mgp->ss[i].rx_stats;
532904b6cca3Slucy wang - Sun Microsystems - Beijing China 			tmp += rstat->ipackets;
533004b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
533104b6cca3Slucy wang - Sun Microsystems - Beijing China 		*val = tmp;
533204b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
533304b6cca3Slucy wang - Sun Microsystems - Beijing China 
533404b6cca3Slucy wang - Sun Microsystems - Beijing China 	case MAC_STAT_OBYTES:
533504b6cca3Slucy wang - Sun Microsystems - Beijing China 		for (i = 0; i < mgp->num_slices; i++) {
533604b6cca3Slucy wang - Sun Microsystems - Beijing China 			tstat = &mgp->ss[i].tx.stats;
533704b6cca3Slucy wang - Sun Microsystems - Beijing China 			tmp += tstat->obytes;
533804b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
533904b6cca3Slucy wang - Sun Microsystems - Beijing China 		*val = tmp;
534004b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
534104b6cca3Slucy wang - Sun Microsystems - Beijing China 
534204b6cca3Slucy wang - Sun Microsystems - Beijing China 	case MAC_STAT_OPACKETS:
534304b6cca3Slucy wang - Sun Microsystems - Beijing China 		for (i = 0; i < mgp->num_slices; i++) {
534404b6cca3Slucy wang - Sun Microsystems - Beijing China 			tstat = &mgp->ss[i].tx.stats;
534504b6cca3Slucy wang - Sun Microsystems - Beijing China 			tmp += tstat->opackets;
534604b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
534704b6cca3Slucy wang - Sun Microsystems - Beijing China 		*val = tmp;
534804b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
534904b6cca3Slucy wang - Sun Microsystems - Beijing China 
535004b6cca3Slucy wang - Sun Microsystems - Beijing China 	case ETHER_STAT_TOOLONG_ERRORS:
535104b6cca3Slucy wang - Sun Microsystems - Beijing China 		*val = ntohl(fw_stats->dropped_overrun);
535204b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
535304b6cca3Slucy wang - Sun Microsystems - Beijing China 
535404b6cca3Slucy wang - Sun Microsystems - Beijing China #ifdef SOLARIS_S11
535504b6cca3Slucy wang - Sun Microsystems - Beijing China 	case ETHER_STAT_TOOSHORT_ERRORS:
535604b6cca3Slucy wang - Sun Microsystems - Beijing China 		*val = ntohl(fw_stats->dropped_runt);
535704b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
535804b6cca3Slucy wang - Sun Microsystems - Beijing China #endif
535904b6cca3Slucy wang - Sun Microsystems - Beijing China 
536004b6cca3Slucy wang - Sun Microsystems - Beijing China 	case ETHER_STAT_LINK_PAUSE:
536104b6cca3Slucy wang - Sun Microsystems - Beijing China 		*val = mgp->pause;
536204b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
536304b6cca3Slucy wang - Sun Microsystems - Beijing China 
536404b6cca3Slucy wang - Sun Microsystems - Beijing China 	case ETHER_STAT_LINK_AUTONEG:
536504b6cca3Slucy wang - Sun Microsystems - Beijing China 		*val = 1;
536604b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
536704b6cca3Slucy wang - Sun Microsystems - Beijing China 
536804b6cca3Slucy wang - Sun Microsystems - Beijing China 	case ETHER_STAT_LINK_DUPLEX:
536904b6cca3Slucy wang - Sun Microsystems - Beijing China 		*val = LINK_DUPLEX_FULL;
537004b6cca3Slucy wang - Sun Microsystems - Beijing China 		break;
537104b6cca3Slucy wang - Sun Microsystems - Beijing China 
537204b6cca3Slucy wang - Sun Microsystems - Beijing China 	default:
537304b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (ENOTSUP);
537404b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
537504b6cca3Slucy wang - Sun Microsystems - Beijing China 
537604b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
537704b6cca3Slucy wang - Sun Microsystems - Beijing China }
537804b6cca3Slucy wang - Sun Microsystems - Beijing China 
5379*6d0043d8SRobert Mustacchi /* ARGSUSED */
5380*6d0043d8SRobert Mustacchi static void
5381*6d0043d8SRobert Mustacchi myri10ge_m_propinfo(void *arg, const char *pr_name,
5382*6d0043d8SRobert Mustacchi     mac_prop_id_t pr_num, mac_prop_info_handle_t prh)
5383*6d0043d8SRobert Mustacchi {
5384*6d0043d8SRobert Mustacchi 	switch (pr_num) {
5385*6d0043d8SRobert Mustacchi 	case MAC_PROP_MTU:
5386*6d0043d8SRobert Mustacchi 		mac_prop_info_set_default_uint32(prh, MYRI10GE_DEFAULT_GLD_MTU);
5387*6d0043d8SRobert Mustacchi 		mac_prop_info_set_range_uint32(prh, MYRI10GE_MIN_GLD_MTU,
5388*6d0043d8SRobert Mustacchi 		    MYRI10GE_MAX_GLD_MTU);
5389*6d0043d8SRobert Mustacchi 		break;
5390*6d0043d8SRobert Mustacchi 	default:
5391*6d0043d8SRobert Mustacchi 		break;
5392*6d0043d8SRobert Mustacchi 	}
5393*6d0043d8SRobert Mustacchi }
5394*6d0043d8SRobert Mustacchi 
5395*6d0043d8SRobert Mustacchi /*ARGSUSED*/
5396*6d0043d8SRobert Mustacchi static int
5397*6d0043d8SRobert Mustacchi myri10ge_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
5398*6d0043d8SRobert Mustacchi     uint_t pr_valsize, const void *pr_val)
5399*6d0043d8SRobert Mustacchi {
5400*6d0043d8SRobert Mustacchi 	int err = 0;
5401*6d0043d8SRobert Mustacchi 	struct myri10ge_priv *mgp = arg;
5402*6d0043d8SRobert Mustacchi 
5403*6d0043d8SRobert Mustacchi 	switch (pr_num) {
5404*6d0043d8SRobert Mustacchi 	case MAC_PROP_MTU: {
5405*6d0043d8SRobert Mustacchi 		uint32_t mtu;
5406*6d0043d8SRobert Mustacchi 		if (pr_valsize < sizeof (mtu)) {
5407*6d0043d8SRobert Mustacchi 			err = EINVAL;
5408*6d0043d8SRobert Mustacchi 			break;
5409*6d0043d8SRobert Mustacchi 		}
5410*6d0043d8SRobert Mustacchi 		bcopy(pr_val, &mtu, sizeof (mtu));
5411*6d0043d8SRobert Mustacchi 		if (mtu > MYRI10GE_MAX_GLD_MTU ||
5412*6d0043d8SRobert Mustacchi 		    mtu < MYRI10GE_MIN_GLD_MTU) {
5413*6d0043d8SRobert Mustacchi 			err = EINVAL;
5414*6d0043d8SRobert Mustacchi 			break;
5415*6d0043d8SRobert Mustacchi 		}
5416*6d0043d8SRobert Mustacchi 
5417*6d0043d8SRobert Mustacchi 		mutex_enter(&mgp->intrlock);
5418*6d0043d8SRobert Mustacchi 		if (mgp->running != MYRI10GE_ETH_STOPPED) {
5419*6d0043d8SRobert Mustacchi 			err = EBUSY;
5420*6d0043d8SRobert Mustacchi 			mutex_exit(&mgp->intrlock);
5421*6d0043d8SRobert Mustacchi 			break;
5422*6d0043d8SRobert Mustacchi 		}
5423*6d0043d8SRobert Mustacchi 
5424*6d0043d8SRobert Mustacchi 		myri10ge_mtu = mtu + sizeof (struct ether_header) +
5425*6d0043d8SRobert Mustacchi 		    MXGEFW_PAD + VLAN_TAGSZ;
5426*6d0043d8SRobert Mustacchi 		mutex_exit(&mgp->intrlock);
5427*6d0043d8SRobert Mustacchi 		break;
5428*6d0043d8SRobert Mustacchi 	}
5429*6d0043d8SRobert Mustacchi 	default:
5430*6d0043d8SRobert Mustacchi 		err = ENOTSUP;
5431*6d0043d8SRobert Mustacchi 		break;
5432*6d0043d8SRobert Mustacchi 	}
5433*6d0043d8SRobert Mustacchi 
5434*6d0043d8SRobert Mustacchi 	return (err);
5435*6d0043d8SRobert Mustacchi }
5436*6d0043d8SRobert Mustacchi 
543704b6cca3Slucy wang - Sun Microsystems - Beijing China static mac_callbacks_t myri10ge_m_callbacks = {
5438*6d0043d8SRobert Mustacchi 	(MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_PROPINFO),
543904b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_m_stat,
544004b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_m_start,
544104b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_m_stop,
544204b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_m_promisc,
544304b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_m_multicst,
544404b6cca3Slucy wang - Sun Microsystems - Beijing China 	NULL,
544504b6cca3Slucy wang - Sun Microsystems - Beijing China 	NULL,
54460dc2366fSVenugopal Iyer 	NULL,
544704b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_m_ioctl,
5448*6d0043d8SRobert Mustacchi 	myri10ge_m_getcapab,
5449*6d0043d8SRobert Mustacchi 	NULL,
5450*6d0043d8SRobert Mustacchi 	NULL,
5451*6d0043d8SRobert Mustacchi 	myri10ge_m_setprop,
5452*6d0043d8SRobert Mustacchi 	NULL,
5453*6d0043d8SRobert Mustacchi 	myri10ge_m_propinfo
545404b6cca3Slucy wang - Sun Microsystems - Beijing China };
545504b6cca3Slucy wang - Sun Microsystems - Beijing China 
545604b6cca3Slucy wang - Sun Microsystems - Beijing China 
545704b6cca3Slucy wang - Sun Microsystems - Beijing China static int
545804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_probe_slices(struct myri10ge_priv *mgp)
545904b6cca3Slucy wang - Sun Microsystems - Beijing China {
546004b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_cmd_t cmd;
546104b6cca3Slucy wang - Sun Microsystems - Beijing China 	int status;
546204b6cca3Slucy wang - Sun Microsystems - Beijing China 
546304b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->num_slices = 1;
546404b6cca3Slucy wang - Sun Microsystems - Beijing China 
546504b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* hit the board with a reset to ensure it is alive */
546604b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) memset(&cmd, 0, sizeof (cmd));
546704b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_RESET, &cmd);
546804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != 0) {
546904b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: failed reset\n", mgp->name);
547004b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (ENXIO);
547104b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
547204b6cca3Slucy wang - Sun Microsystems - Beijing China 
547304b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (myri10ge_use_msix == 0)
547404b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (0);
547504b6cca3Slucy wang - Sun Microsystems - Beijing China 
547604b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* tell it the size of the interrupt queues */
547704b6cca3Slucy wang - Sun Microsystems - Beijing China 	cmd.data0 = mgp->max_intr_slots * sizeof (struct mcp_slot);
547804b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_SIZE, &cmd);
547904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != 0) {
548004b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: failed MXGEFW_CMD_SET_INTRQ_SIZE\n",
548104b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->name);
548204b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (ENXIO);
548304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
548404b6cca3Slucy wang - Sun Microsystems - Beijing China 
548504b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* ask the maximum number of slices it supports */
548604b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_MAX_RSS_QUEUES,
548704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    &cmd);
548804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != 0)
548904b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (0);
549004b6cca3Slucy wang - Sun Microsystems - Beijing China 
549104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->num_slices = cmd.data0;
549204b6cca3Slucy wang - Sun Microsystems - Beijing China 
549304b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
549404b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * if the admin did not specify a limit to how many
549504b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * slices we should use, cap it automatically to the
549604b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * number of CPUs currently online
549704b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
549804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (myri10ge_max_slices == -1)
549904b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_max_slices = ncpus;
550004b6cca3Slucy wang - Sun Microsystems - Beijing China 
550104b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->num_slices > myri10ge_max_slices)
550204b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->num_slices = myri10ge_max_slices;
550304b6cca3Slucy wang - Sun Microsystems - Beijing China 
550404b6cca3Slucy wang - Sun Microsystems - Beijing China 
550504b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
550604b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * Now try to allocate as many MSI-X vectors as we have
550704b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * slices. We give up on MSI-X if we can only get a single
550804b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * vector.
550904b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
551004b6cca3Slucy wang - Sun Microsystems - Beijing China 	while (mgp->num_slices > 1) {
551104b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* make sure it is a power of two */
5512de710d24SJosef 'Jeff' Sipek 		while (!ISP2(mgp->num_slices))
551304b6cca3Slucy wang - Sun Microsystems - Beijing China 			mgp->num_slices--;
551404b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (mgp->num_slices == 1)
551504b6cca3Slucy wang - Sun Microsystems - Beijing China 			return (0);
551604b6cca3Slucy wang - Sun Microsystems - Beijing China 
551704b6cca3Slucy wang - Sun Microsystems - Beijing China 		status = myri10ge_add_intrs(mgp, 0);
551804b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (status == 0) {
551904b6cca3Slucy wang - Sun Microsystems - Beijing China 			myri10ge_rem_intrs(mgp, 0);
552004b6cca3Slucy wang - Sun Microsystems - Beijing China 			if (mgp->intr_cnt == mgp->num_slices) {
552104b6cca3Slucy wang - Sun Microsystems - Beijing China 				if (myri10ge_verbose)
552204b6cca3Slucy wang - Sun Microsystems - Beijing China 					printf("Got %d slices!\n",
552304b6cca3Slucy wang - Sun Microsystems - Beijing China 					    mgp->num_slices);
552404b6cca3Slucy wang - Sun Microsystems - Beijing China 				return (0);
552504b6cca3Slucy wang - Sun Microsystems - Beijing China 			}
552604b6cca3Slucy wang - Sun Microsystems - Beijing China 			mgp->num_slices = mgp->intr_cnt;
552704b6cca3Slucy wang - Sun Microsystems - Beijing China 		} else {
552804b6cca3Slucy wang - Sun Microsystems - Beijing China 			mgp->num_slices = mgp->num_slices / 2;
552904b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
553004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
553104b6cca3Slucy wang - Sun Microsystems - Beijing China 
553204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (myri10ge_verbose)
553304b6cca3Slucy wang - Sun Microsystems - Beijing China 		printf("Got %d slices\n", mgp->num_slices);
553404b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
553504b6cca3Slucy wang - Sun Microsystems - Beijing China }
553604b6cca3Slucy wang - Sun Microsystems - Beijing China 
553704b6cca3Slucy wang - Sun Microsystems - Beijing China static void
553804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_lro_free(struct myri10ge_slice_state *ss)
553904b6cca3Slucy wang - Sun Microsystems - Beijing China {
554004b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct lro_entry *lro;
554104b6cca3Slucy wang - Sun Microsystems - Beijing China 
554204b6cca3Slucy wang - Sun Microsystems - Beijing China 	while (ss->lro_free != NULL) {
554304b6cca3Slucy wang - Sun Microsystems - Beijing China 		lro = ss->lro_free;
554404b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->lro_free = lro->next;
554504b6cca3Slucy wang - Sun Microsystems - Beijing China 		kmem_free(lro, sizeof (*lro));
554604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
554704b6cca3Slucy wang - Sun Microsystems - Beijing China }
554804b6cca3Slucy wang - Sun Microsystems - Beijing China 
554904b6cca3Slucy wang - Sun Microsystems - Beijing China static void
555004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_lro_alloc(struct myri10ge_slice_state *ss)
555104b6cca3Slucy wang - Sun Microsystems - Beijing China {
555204b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct lro_entry *lro;
555304b6cca3Slucy wang - Sun Microsystems - Beijing China 	int idx;
555404b6cca3Slucy wang - Sun Microsystems - Beijing China 
555504b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->lro_free = NULL;
555604b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss->lro_active = NULL;
555704b6cca3Slucy wang - Sun Microsystems - Beijing China 
555804b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (idx = 0; idx < myri10ge_lro_cnt; idx++) {
555904b6cca3Slucy wang - Sun Microsystems - Beijing China 		lro = kmem_zalloc(sizeof (*lro), KM_SLEEP);
556004b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (lro == NULL)
556104b6cca3Slucy wang - Sun Microsystems - Beijing China 			continue;
556204b6cca3Slucy wang - Sun Microsystems - Beijing China 		lro->next = ss->lro_free;
556304b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->lro_free = lro;
556404b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
556504b6cca3Slucy wang - Sun Microsystems - Beijing China }
556604b6cca3Slucy wang - Sun Microsystems - Beijing China 
556704b6cca3Slucy wang - Sun Microsystems - Beijing China static void
556804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_free_slices(struct myri10ge_priv *mgp)
556904b6cca3Slucy wang - Sun Microsystems - Beijing China {
557004b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_slice_state *ss;
557104b6cca3Slucy wang - Sun Microsystems - Beijing China 	size_t bytes;
557204b6cca3Slucy wang - Sun Microsystems - Beijing China 	int i;
557304b6cca3Slucy wang - Sun Microsystems - Beijing China 
557404b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->ss == NULL)
557504b6cca3Slucy wang - Sun Microsystems - Beijing China 		return;
557604b6cca3Slucy wang - Sun Microsystems - Beijing China 
557704b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (i = 0; i < mgp->num_slices; i++) {
557804b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss = &mgp->ss[i];
557904b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (ss->rx_done.entry == NULL)
558004b6cca3Slucy wang - Sun Microsystems - Beijing China 			continue;
558104b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_dma_free(&ss->rx_done.dma);
558204b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->rx_done.entry = NULL;
558304b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (ss->fw_stats == NULL)
558404b6cca3Slucy wang - Sun Microsystems - Beijing China 			continue;
558504b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_dma_free(&ss->fw_stats_dma);
558604b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->fw_stats = NULL;
558704b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_destroy(&ss->rx_lock);
558804b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_destroy(&ss->tx.lock);
558904b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_destroy(&ss->tx.handle_lock);
559004b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_destroy(&ss->poll_lock);
559104b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_jpool_fini(ss);
559204b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_slice_stat_destroy(ss);
559304b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_lro_free(ss);
559404b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
559504b6cca3Slucy wang - Sun Microsystems - Beijing China 	bytes = sizeof (*mgp->ss) * mgp->num_slices;
559604b6cca3Slucy wang - Sun Microsystems - Beijing China 	kmem_free(mgp->ss, bytes);
559704b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->ss = NULL;
559804b6cca3Slucy wang - Sun Microsystems - Beijing China }
559904b6cca3Slucy wang - Sun Microsystems - Beijing China 
560004b6cca3Slucy wang - Sun Microsystems - Beijing China 
560104b6cca3Slucy wang - Sun Microsystems - Beijing China static int
560204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_alloc_slices(struct myri10ge_priv *mgp)
560304b6cca3Slucy wang - Sun Microsystems - Beijing China {
560404b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_slice_state *ss;
560504b6cca3Slucy wang - Sun Microsystems - Beijing China 	size_t bytes;
560604b6cca3Slucy wang - Sun Microsystems - Beijing China 	int i;
560704b6cca3Slucy wang - Sun Microsystems - Beijing China 
560804b6cca3Slucy wang - Sun Microsystems - Beijing China 	bytes = sizeof (*mgp->ss) * mgp->num_slices;
560904b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->ss = kmem_zalloc(bytes, KM_SLEEP);
561004b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->ss == NULL)
561104b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (ENOMEM);
561204b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (i = 0; i < mgp->num_slices; i++) {
561304b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss = &mgp->ss[i];
561404b6cca3Slucy wang - Sun Microsystems - Beijing China 
561504b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->mgp = mgp;
561604b6cca3Slucy wang - Sun Microsystems - Beijing China 
561704b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* allocate the per-slice firmware stats */
561804b6cca3Slucy wang - Sun Microsystems - Beijing China 		bytes = sizeof (*ss->fw_stats);
561904b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->fw_stats = (mcp_irq_data_t *)(void *)
562004b6cca3Slucy wang - Sun Microsystems - Beijing China 		    myri10ge_dma_alloc(mgp->dip, bytes,
562104b6cca3Slucy wang - Sun Microsystems - Beijing China 		    &myri10ge_misc_dma_attr, &myri10ge_dev_access_attr,
562204b6cca3Slucy wang - Sun Microsystems - Beijing China 		    DDI_DMA_CONSISTENT, DDI_DMA_READ|DDI_DMA_CONSISTENT,
562304b6cca3Slucy wang - Sun Microsystems - Beijing China 		    &ss->fw_stats_dma, 1, DDI_DMA_DONTWAIT);
562404b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (ss->fw_stats == NULL)
562504b6cca3Slucy wang - Sun Microsystems - Beijing China 			goto abort;
562604b6cca3Slucy wang - Sun Microsystems - Beijing China 		(void) memset(ss->fw_stats, 0, bytes);
562704b6cca3Slucy wang - Sun Microsystems - Beijing China 
562804b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* allocate rx done ring */
562904b6cca3Slucy wang - Sun Microsystems - Beijing China 		bytes = mgp->max_intr_slots *
563004b6cca3Slucy wang - Sun Microsystems - Beijing China 		    sizeof (*ss->rx_done.entry);
563104b6cca3Slucy wang - Sun Microsystems - Beijing China 		ss->rx_done.entry = (mcp_slot_t *)(void *)
563204b6cca3Slucy wang - Sun Microsystems - Beijing China 		    myri10ge_dma_alloc(mgp->dip, bytes,
563304b6cca3Slucy wang - Sun Microsystems - Beijing China 		    &myri10ge_misc_dma_attr, &myri10ge_dev_access_attr,
563404b6cca3Slucy wang - Sun Microsystems - Beijing China 		    DDI_DMA_CONSISTENT, DDI_DMA_READ|DDI_DMA_CONSISTENT,
563504b6cca3Slucy wang - Sun Microsystems - Beijing China 		    &ss->rx_done.dma, 1, DDI_DMA_DONTWAIT);
563604b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (ss->rx_done.entry == NULL) {
563704b6cca3Slucy wang - Sun Microsystems - Beijing China 			goto abort;
563804b6cca3Slucy wang - Sun Microsystems - Beijing China 		}
563904b6cca3Slucy wang - Sun Microsystems - Beijing China 		(void) memset(ss->rx_done.entry, 0, bytes);
564004b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_init(&ss->rx_lock,   NULL, MUTEX_DEFAULT, mgp->icookie);
564104b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_init(&ss->tx.lock,   NULL, MUTEX_DEFAULT, NULL);
564204b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_init(&ss->tx.handle_lock,   NULL, MUTEX_DEFAULT, NULL);
564304b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_init(&ss->poll_lock,   NULL, MUTEX_DEFAULT, NULL);
564404b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_jpool_init(ss);
564504b6cca3Slucy wang - Sun Microsystems - Beijing China 		(void) myri10ge_slice_stat_init(ss);
564604b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_lro_alloc(ss);
564704b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
564804b6cca3Slucy wang - Sun Microsystems - Beijing China 
564904b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
565004b6cca3Slucy wang - Sun Microsystems - Beijing China 
565104b6cca3Slucy wang - Sun Microsystems - Beijing China abort:
565204b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_free_slices(mgp);
565304b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (ENOMEM);
565404b6cca3Slucy wang - Sun Microsystems - Beijing China }
565504b6cca3Slucy wang - Sun Microsystems - Beijing China 
565604b6cca3Slucy wang - Sun Microsystems - Beijing China static int
565704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_save_msi_state(struct myri10ge_priv *mgp,
565804b6cca3Slucy wang - Sun Microsystems - Beijing China     ddi_acc_handle_t handle)
565904b6cca3Slucy wang - Sun Microsystems - Beijing China {
566004b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint8_t ptr;
566104b6cca3Slucy wang - Sun Microsystems - Beijing China 	int err;
566204b6cca3Slucy wang - Sun Microsystems - Beijing China 
566304b6cca3Slucy wang - Sun Microsystems - Beijing China 	err = myri10ge_find_cap(handle, &ptr, PCI_CAP_ID_MSI);
566404b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (err != 0) {
566504b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: could not find MSI cap\n",
566604b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->name);
566704b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
566804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
566904b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->pci_saved_state.msi_ctrl =
567004b6cca3Slucy wang - Sun Microsystems - Beijing China 	    pci_config_get16(handle, ptr + PCI_MSI_CTRL);
567104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->pci_saved_state.msi_addr_low =
567204b6cca3Slucy wang - Sun Microsystems - Beijing China 	    pci_config_get32(handle, ptr + PCI_MSI_ADDR_OFFSET);
567304b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->pci_saved_state.msi_addr_high =
567404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    pci_config_get32(handle, ptr + PCI_MSI_ADDR_OFFSET + 4);
567504b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->pci_saved_state.msi_data_32 =
567604b6cca3Slucy wang - Sun Microsystems - Beijing China 	    pci_config_get16(handle, ptr + PCI_MSI_32BIT_DATA);
567704b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->pci_saved_state.msi_data_64 =
567804b6cca3Slucy wang - Sun Microsystems - Beijing China 	    pci_config_get16(handle, ptr + PCI_MSI_64BIT_DATA);
567904b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
568004b6cca3Slucy wang - Sun Microsystems - Beijing China }
568104b6cca3Slucy wang - Sun Microsystems - Beijing China 
568204b6cca3Slucy wang - Sun Microsystems - Beijing China static int
568304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_restore_msi_state(struct myri10ge_priv *mgp,
568404b6cca3Slucy wang - Sun Microsystems - Beijing China     ddi_acc_handle_t handle)
568504b6cca3Slucy wang - Sun Microsystems - Beijing China {
568604b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint8_t ptr;
568704b6cca3Slucy wang - Sun Microsystems - Beijing China 	int err;
568804b6cca3Slucy wang - Sun Microsystems - Beijing China 
568904b6cca3Slucy wang - Sun Microsystems - Beijing China 	err = myri10ge_find_cap(handle, &ptr, PCI_CAP_ID_MSI);
569004b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (err != 0) {
569104b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: could not find MSI cap\n",
569204b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->name);
569304b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
569404b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
569504b6cca3Slucy wang - Sun Microsystems - Beijing China 
569604b6cca3Slucy wang - Sun Microsystems - Beijing China 	pci_config_put16(handle, ptr + PCI_MSI_CTRL,
569704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    mgp->pci_saved_state.msi_ctrl);
569804b6cca3Slucy wang - Sun Microsystems - Beijing China 	pci_config_put32(handle, ptr + PCI_MSI_ADDR_OFFSET,
569904b6cca3Slucy wang - Sun Microsystems - Beijing China 	    mgp->pci_saved_state.msi_addr_low);
570004b6cca3Slucy wang - Sun Microsystems - Beijing China 	pci_config_put32(handle, ptr + PCI_MSI_ADDR_OFFSET + 4,
570104b6cca3Slucy wang - Sun Microsystems - Beijing China 	    mgp->pci_saved_state.msi_addr_high);
570204b6cca3Slucy wang - Sun Microsystems - Beijing China 	pci_config_put16(handle, ptr + PCI_MSI_32BIT_DATA,
570304b6cca3Slucy wang - Sun Microsystems - Beijing China 	    mgp->pci_saved_state.msi_data_32);
570404b6cca3Slucy wang - Sun Microsystems - Beijing China 	pci_config_put16(handle, ptr + PCI_MSI_64BIT_DATA,
570504b6cca3Slucy wang - Sun Microsystems - Beijing China 	    mgp->pci_saved_state.msi_data_64);
570604b6cca3Slucy wang - Sun Microsystems - Beijing China 
570704b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
570804b6cca3Slucy wang - Sun Microsystems - Beijing China }
570904b6cca3Slucy wang - Sun Microsystems - Beijing China 
571004b6cca3Slucy wang - Sun Microsystems - Beijing China static int
571104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_save_pci_state(struct myri10ge_priv *mgp)
571204b6cca3Slucy wang - Sun Microsystems - Beijing China {
571304b6cca3Slucy wang - Sun Microsystems - Beijing China 	ddi_acc_handle_t handle = mgp->cfg_hdl;
571404b6cca3Slucy wang - Sun Microsystems - Beijing China 	int i;
571504b6cca3Slucy wang - Sun Microsystems - Beijing China 	int err = DDI_SUCCESS;
571604b6cca3Slucy wang - Sun Microsystems - Beijing China 
571704b6cca3Slucy wang - Sun Microsystems - Beijing China 
571804b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* Save the non-extended PCI config space 32-bits at a time */
571904b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (i = 0; i < 16; i++)
572004b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->pci_saved_state.base[i] =
572104b6cca3Slucy wang - Sun Microsystems - Beijing China 		    pci_config_get32(handle, i*4);
572204b6cca3Slucy wang - Sun Microsystems - Beijing China 
572304b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* now save MSI interrupt state *, if needed */
572404b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->ddi_intr_type == DDI_INTR_TYPE_MSI)
572504b6cca3Slucy wang - Sun Microsystems - Beijing China 		err = myri10ge_save_msi_state(mgp, handle);
572604b6cca3Slucy wang - Sun Microsystems - Beijing China 
572704b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (err);
572804b6cca3Slucy wang - Sun Microsystems - Beijing China }
572904b6cca3Slucy wang - Sun Microsystems - Beijing China 
573004b6cca3Slucy wang - Sun Microsystems - Beijing China static int
573104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_restore_pci_state(struct myri10ge_priv *mgp)
573204b6cca3Slucy wang - Sun Microsystems - Beijing China {
573304b6cca3Slucy wang - Sun Microsystems - Beijing China 	ddi_acc_handle_t handle = mgp->cfg_hdl;
573404b6cca3Slucy wang - Sun Microsystems - Beijing China 	int i;
573504b6cca3Slucy wang - Sun Microsystems - Beijing China 	int err = DDI_SUCCESS;
573604b6cca3Slucy wang - Sun Microsystems - Beijing China 
573704b6cca3Slucy wang - Sun Microsystems - Beijing China 
573804b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* Restore the non-extended PCI config space 32-bits at a time */
573904b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (i = 15; i >= 0; i--)
574004b6cca3Slucy wang - Sun Microsystems - Beijing China 		pci_config_put32(handle, i*4, mgp->pci_saved_state.base[i]);
574104b6cca3Slucy wang - Sun Microsystems - Beijing China 
574204b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* now restore MSI interrupt state *, if needed */
574304b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->ddi_intr_type == DDI_INTR_TYPE_MSI)
574404b6cca3Slucy wang - Sun Microsystems - Beijing China 		err = myri10ge_restore_msi_state(mgp, handle);
574504b6cca3Slucy wang - Sun Microsystems - Beijing China 
574604b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->max_read_request_4k)
574704b6cca3Slucy wang - Sun Microsystems - Beijing China 		(void) myri10ge_set_max_readreq(handle);
574804b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (err);
574904b6cca3Slucy wang - Sun Microsystems - Beijing China }
575004b6cca3Slucy wang - Sun Microsystems - Beijing China 
575104b6cca3Slucy wang - Sun Microsystems - Beijing China 
575204b6cca3Slucy wang - Sun Microsystems - Beijing China static int
575304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_suspend(dev_info_t *dip)
575404b6cca3Slucy wang - Sun Microsystems - Beijing China {
575504b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp = ddi_get_driver_private(dip);
575604b6cca3Slucy wang - Sun Microsystems - Beijing China 	int status;
575704b6cca3Slucy wang - Sun Microsystems - Beijing China 
575804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp == NULL) {
575904b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "null dip in myri10ge_suspend\n");
576004b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
576104b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
576204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->dip != dip) {
576304b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "bad dip in myri10ge_suspend\n");
576404b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
576504b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
576604b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&mgp->intrlock);
576704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->running == MYRI10GE_ETH_RUNNING) {
576804b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->running = MYRI10GE_ETH_STOPPING;
576904b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_exit(&mgp->intrlock);
577004b6cca3Slucy wang - Sun Microsystems - Beijing China 		(void) untimeout(mgp->timer_id);
577104b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_enter(&mgp->intrlock);
577204b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_stop_locked(mgp);
577304b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp->running = MYRI10GE_ETH_SUSPENDED_RUNNING;
577404b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
577504b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_save_pci_state(mgp);
577604b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&mgp->intrlock);
577704b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (status);
577804b6cca3Slucy wang - Sun Microsystems - Beijing China }
577904b6cca3Slucy wang - Sun Microsystems - Beijing China 
578004b6cca3Slucy wang - Sun Microsystems - Beijing China static int
578104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_resume(dev_info_t *dip)
578204b6cca3Slucy wang - Sun Microsystems - Beijing China {
578304b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp = ddi_get_driver_private(dip);
578404b6cca3Slucy wang - Sun Microsystems - Beijing China 	int status = DDI_SUCCESS;
578504b6cca3Slucy wang - Sun Microsystems - Beijing China 
578604b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp == NULL) {
578704b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "null dip in myri10ge_resume\n");
578804b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
578904b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
579004b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->dip != dip) {
579104b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "bad dip in myri10ge_resume\n");
579204b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
579304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
579404b6cca3Slucy wang - Sun Microsystems - Beijing China 
579504b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&mgp->intrlock);
579604b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_restore_pci_state(mgp);
579704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status == DDI_SUCCESS &&
579804b6cca3Slucy wang - Sun Microsystems - Beijing China 	    mgp->running == MYRI10GE_ETH_SUSPENDED_RUNNING) {
579904b6cca3Slucy wang - Sun Microsystems - Beijing China 		status = myri10ge_start_locked(mgp);
580004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
580104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&mgp->intrlock);
580204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != DDI_SUCCESS)
580304b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (status);
580404b6cca3Slucy wang - Sun Microsystems - Beijing China 
580504b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* start the watchdog timer */
580604b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->timer_id = timeout(myri10ge_watchdog, mgp,
580704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    mgp->timer_ticks);
580804b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
580904b6cca3Slucy wang - Sun Microsystems - Beijing China }
581004b6cca3Slucy wang - Sun Microsystems - Beijing China 
581104b6cca3Slucy wang - Sun Microsystems - Beijing China static int
581204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
581304b6cca3Slucy wang - Sun Microsystems - Beijing China {
581404b6cca3Slucy wang - Sun Microsystems - Beijing China 
581504b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp;
581604b6cca3Slucy wang - Sun Microsystems - Beijing China 	mac_register_t *macp, *omacp;
581704b6cca3Slucy wang - Sun Microsystems - Beijing China 	ddi_acc_handle_t handle;
581804b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint32_t csr, hdr_offset;
581904b6cca3Slucy wang - Sun Microsystems - Beijing China 	int status, span, link_width, max_read_request_4k;
582004b6cca3Slucy wang - Sun Microsystems - Beijing China 	unsigned long bus_number, dev_number, func_number;
582104b6cca3Slucy wang - Sun Microsystems - Beijing China 	size_t bytes;
582204b6cca3Slucy wang - Sun Microsystems - Beijing China 	offset_t ss_offset;
582304b6cca3Slucy wang - Sun Microsystems - Beijing China 	uint8_t vso;
582404b6cca3Slucy wang - Sun Microsystems - Beijing China 
582504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (cmd == DDI_RESUME) {
582604b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (myri10ge_resume(dip));
582704b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
582804b6cca3Slucy wang - Sun Microsystems - Beijing China 
582904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (cmd != DDI_ATTACH)
583004b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
583104b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (pci_config_setup(dip, &handle) != DDI_SUCCESS)
583204b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
583304b6cca3Slucy wang - Sun Microsystems - Beijing China 
583404b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* enable busmater and io space access */
583504b6cca3Slucy wang - Sun Microsystems - Beijing China 	csr = pci_config_get32(handle, PCI_CONF_COMM);
583604b6cca3Slucy wang - Sun Microsystems - Beijing China 	pci_config_put32(handle, PCI_CONF_COMM,
583704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    (csr |PCI_COMM_ME|PCI_COMM_MAE));
583804b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_read_pcie_link_width(handle, &link_width);
583904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != 0) {
584004b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "could not read link width!\n");
584104b6cca3Slucy wang - Sun Microsystems - Beijing China 		link_width = 0;
584204b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
584304b6cca3Slucy wang - Sun Microsystems - Beijing China 	max_read_request_4k = !myri10ge_set_max_readreq(handle);
584404b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_find_cap(handle, &vso, PCI_CAP_ID_VS);
584504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != 0)
584604b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_cfg_hdl;
584704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if ((omacp = mac_alloc(MAC_VERSION)) == NULL)
584804b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_cfg_hdl;
584904b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
585004b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * XXXX Hack: mac_register_t grows in newer kernels.  To be
585104b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * able to write newer fields, such as m_margin, without
585204b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * writing outside allocated memory, we allocate our own macp
585304b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * and pass that to mac_register()
585404b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
585504b6cca3Slucy wang - Sun Microsystems - Beijing China 	macp = kmem_zalloc(sizeof (*macp) * 8, KM_SLEEP);
585604b6cca3Slucy wang - Sun Microsystems - Beijing China 	macp->m_version = omacp->m_version;
585704b6cca3Slucy wang - Sun Microsystems - Beijing China 
585804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if ((mgp = (struct myri10ge_priv *)
585904b6cca3Slucy wang - Sun Microsystems - Beijing China 	    kmem_zalloc(sizeof (*mgp), KM_SLEEP)) == NULL) {
586004b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_macinfo;
586104b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
586204b6cca3Slucy wang - Sun Microsystems - Beijing China 	ddi_set_driver_private(dip, mgp);
586304b6cca3Slucy wang - Sun Microsystems - Beijing China 
586404b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* setup device name for log messages */
586504b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) sprintf(mgp->name, "myri10ge%d", ddi_get_instance(dip));
586604b6cca3Slucy wang - Sun Microsystems - Beijing China 
586704b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&myri10ge_param_lock);
586804b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_get_props(dip);
586904b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->intr_coal_delay = myri10ge_intr_coal_delay;
587004b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->pause = myri10ge_flow_control;
587104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&myri10ge_param_lock);
587204b6cca3Slucy wang - Sun Microsystems - Beijing China 
587304b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->max_read_request_4k = max_read_request_4k;
587404b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->pcie_link_width = link_width;
587504b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->running = MYRI10GE_ETH_STOPPED;
587604b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->vso = vso;
587704b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->dip = dip;
587804b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->cfg_hdl = handle;
587904b6cca3Slucy wang - Sun Microsystems - Beijing China 
588004b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->timer_ticks = 5 * drv_usectohz(1000000); /* 5 seconds */
588104b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_test_physical(dip);
588204b6cca3Slucy wang - Sun Microsystems - Beijing China 
588304b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* allocate command page */
588404b6cca3Slucy wang - Sun Microsystems - Beijing China 	bytes = sizeof (*mgp->cmd);
588504b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->cmd = (mcp_cmd_response_t *)
588604b6cca3Slucy wang - Sun Microsystems - Beijing China 	    (void *)myri10ge_dma_alloc(dip, bytes,
588704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    &myri10ge_misc_dma_attr, &myri10ge_dev_access_attr,
588804b6cca3Slucy wang - Sun Microsystems - Beijing China 	    DDI_DMA_CONSISTENT,	DDI_DMA_RDWR|DDI_DMA_CONSISTENT,
588904b6cca3Slucy wang - Sun Microsystems - Beijing China 	    &mgp->cmd_dma, 1, DDI_DMA_DONTWAIT);
589004b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->cmd == NULL)
589104b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_mgp;
589204b6cca3Slucy wang - Sun Microsystems - Beijing China 
589304b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) myri10ge_reg_set(dip, &mgp->reg_set, &span, &bus_number,
589404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    &dev_number, &func_number);
589504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (myri10ge_verbose)
589604b6cca3Slucy wang - Sun Microsystems - Beijing China 		printf("%s at %ld:%ld:%ld attaching\n", mgp->name,
589704b6cca3Slucy wang - Sun Microsystems - Beijing China 		    bus_number, dev_number, func_number);
589804b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = ddi_regs_map_setup(dip, mgp->reg_set, (caddr_t *)&mgp->sram,
589904b6cca3Slucy wang - Sun Microsystems - Beijing China 	    (offset_t)0, (offset_t)span,  &myri10ge_dev_access_attr,
590004b6cca3Slucy wang - Sun Microsystems - Beijing China 	    &mgp->io_handle);
590104b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != DDI_SUCCESS) {
590204b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: couldn't map memory space", mgp->name);
590304b6cca3Slucy wang - Sun Microsystems - Beijing China 		printf("%s: reg_set = %d, span = %d, status = %d",
590404b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->name, mgp->reg_set, span, status);
590504b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_mgp;
590604b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
590704b6cca3Slucy wang - Sun Microsystems - Beijing China 
590804b6cca3Slucy wang - Sun Microsystems - Beijing China 	hdr_offset = *(uint32_t *)(void*)(mgp->sram +  MCP_HEADER_PTR_OFFSET);
590904b6cca3Slucy wang - Sun Microsystems - Beijing China 	hdr_offset = ntohl(hdr_offset) & 0xffffc;
591004b6cca3Slucy wang - Sun Microsystems - Beijing China 	ss_offset = hdr_offset +
591104b6cca3Slucy wang - Sun Microsystems - Beijing China 	    offsetof(struct mcp_gen_header, string_specs);
591204b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->sram_size = ntohl(*(uint32_t *)(void*)(mgp->sram + ss_offset));
591304b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_pio_copy32(mgp->eeprom_strings,
591404b6cca3Slucy wang - Sun Microsystems - Beijing China 	    (uint32_t *)(void*)((char *)mgp->sram + mgp->sram_size),
591504b6cca3Slucy wang - Sun Microsystems - Beijing China 	    MYRI10GE_EEPROM_STRINGS_SIZE);
591604b6cca3Slucy wang - Sun Microsystems - Beijing China 	(void) memset(mgp->eeprom_strings +
591704b6cca3Slucy wang - Sun Microsystems - Beijing China 	    MYRI10GE_EEPROM_STRINGS_SIZE - 2, 0, 2);
591804b6cca3Slucy wang - Sun Microsystems - Beijing China 
591904b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_read_mac_addr(mgp);
592004b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status) {
592104b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_mapped;
592204b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
592304b6cca3Slucy wang - Sun Microsystems - Beijing China 
592404b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_select_firmware(mgp);
592504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != 0) {
592604b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: failed to load firmware\n", mgp->name);
592704b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_mapped;
592804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
592904b6cca3Slucy wang - Sun Microsystems - Beijing China 
593004b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_probe_slices(mgp);
593104b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != 0) {
593204b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: failed to probe slices\n", mgp->name);
593304b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_dummy_rdma;
593404b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
593504b6cca3Slucy wang - Sun Microsystems - Beijing China 
593604b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_alloc_slices(mgp);
593704b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != 0) {
593804b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: failed to alloc slices\n", mgp->name);
593904b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_dummy_rdma;
594004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
594104b6cca3Slucy wang - Sun Microsystems - Beijing China 
594204b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* add the interrupt handler */
594304b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_add_intrs(mgp, 1);
594404b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != 0) {
594504b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: Failed to add interrupt\n",
594604b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->name);
594704b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_slices;
594804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
594904b6cca3Slucy wang - Sun Microsystems - Beijing China 
595004b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* now that we have an iblock_cookie, init the mutexes */
595104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_init(&mgp->cmd_lock, NULL, MUTEX_DRIVER, mgp->icookie);
595204b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_init(&mgp->intrlock, NULL, MUTEX_DRIVER, mgp->icookie);
595304b6cca3Slucy wang - Sun Microsystems - Beijing China 
595404b6cca3Slucy wang - Sun Microsystems - Beijing China 
595504b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_nic_stat_init(mgp);
595604b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != DDI_SUCCESS)
595704b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_interrupts;
595804b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_info_init(mgp);
595904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != DDI_SUCCESS)
596004b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_stats;
596104b6cca3Slucy wang - Sun Microsystems - Beijing China 
596204b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
596304b6cca3Slucy wang - Sun Microsystems - Beijing China 	 *	Initialize  GLD state
596404b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
596504b6cca3Slucy wang - Sun Microsystems - Beijing China 
596604b6cca3Slucy wang - Sun Microsystems - Beijing China 	macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
596704b6cca3Slucy wang - Sun Microsystems - Beijing China 	macp->m_driver = mgp;
596804b6cca3Slucy wang - Sun Microsystems - Beijing China 	macp->m_dip = dip;
596904b6cca3Slucy wang - Sun Microsystems - Beijing China 	macp->m_src_addr = mgp->mac_addr;
597004b6cca3Slucy wang - Sun Microsystems - Beijing China 	macp->m_callbacks = &myri10ge_m_callbacks;
597104b6cca3Slucy wang - Sun Microsystems - Beijing China 	macp->m_min_sdu = 0;
597204b6cca3Slucy wang - Sun Microsystems - Beijing China 	macp->m_max_sdu = myri10ge_mtu -
597304b6cca3Slucy wang - Sun Microsystems - Beijing China 	    (sizeof (struct ether_header) + MXGEFW_PAD + VLAN_TAGSZ);
597404b6cca3Slucy wang - Sun Microsystems - Beijing China #ifdef SOLARIS_S11
597504b6cca3Slucy wang - Sun Microsystems - Beijing China 	macp->m_margin = VLAN_TAGSZ;
597604b6cca3Slucy wang - Sun Microsystems - Beijing China #endif
597704b6cca3Slucy wang - Sun Microsystems - Beijing China 	macp->m_v12n = MAC_VIRT_LEVEL1;
597804b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = mac_register(macp, &mgp->mh);
597904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != 0) {
598004b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: mac_register failed with %d\n",
598104b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->name, status);
598204b6cca3Slucy wang - Sun Microsystems - Beijing China 		goto abort_with_info;
598304b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
598404b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_ndd_init(mgp);
598504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (myri10ge_verbose)
598604b6cca3Slucy wang - Sun Microsystems - Beijing China 		printf("%s: %s, tx bndry %d, fw %s\n", mgp->name,
598704b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->intr_type, mgp->tx_boundary, mgp->fw_name);
598804b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&myri10ge_param_lock);
598904b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp->next = mgp_list;
599004b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp_list = mgp;
599104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&myri10ge_param_lock);
599204b6cca3Slucy wang - Sun Microsystems - Beijing China 	kmem_free(macp, sizeof (*macp) * 8);
599304b6cca3Slucy wang - Sun Microsystems - Beijing China 	mac_free(omacp);
599404b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
599504b6cca3Slucy wang - Sun Microsystems - Beijing China 
599604b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_info:
599704b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_info_destroy(mgp);
599804b6cca3Slucy wang - Sun Microsystems - Beijing China 
599904b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_stats:
600004b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_nic_stat_destroy(mgp);
600104b6cca3Slucy wang - Sun Microsystems - Beijing China 
600204b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_interrupts:
600304b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_destroy(&mgp->cmd_lock);
600404b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_destroy(&mgp->intrlock);
600504b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_rem_intrs(mgp, 1);
600604b6cca3Slucy wang - Sun Microsystems - Beijing China 
600704b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_slices:
600804b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_free_slices(mgp);
600904b6cca3Slucy wang - Sun Microsystems - Beijing China 
601004b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_dummy_rdma:
601104b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_dummy_rdma(mgp, 0);
601204b6cca3Slucy wang - Sun Microsystems - Beijing China 
601304b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_mapped:
601404b6cca3Slucy wang - Sun Microsystems - Beijing China 	ddi_regs_map_free(&mgp->io_handle);
601504b6cca3Slucy wang - Sun Microsystems - Beijing China 
601604b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_dma_free(&mgp->cmd_dma);
601704b6cca3Slucy wang - Sun Microsystems - Beijing China 
601804b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_mgp:
601904b6cca3Slucy wang - Sun Microsystems - Beijing China 	kmem_free(mgp, sizeof (*mgp));
602004b6cca3Slucy wang - Sun Microsystems - Beijing China 
602104b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_macinfo:
602204b6cca3Slucy wang - Sun Microsystems - Beijing China 	kmem_free(macp, sizeof (*macp) * 8);
602304b6cca3Slucy wang - Sun Microsystems - Beijing China 	mac_free(omacp);
602404b6cca3Slucy wang - Sun Microsystems - Beijing China 
602504b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_cfg_hdl:
602604b6cca3Slucy wang - Sun Microsystems - Beijing China 	pci_config_teardown(&handle);
602704b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (DDI_FAILURE);
602804b6cca3Slucy wang - Sun Microsystems - Beijing China 
602904b6cca3Slucy wang - Sun Microsystems - Beijing China }
603004b6cca3Slucy wang - Sun Microsystems - Beijing China 
603104b6cca3Slucy wang - Sun Microsystems - Beijing China 
603204b6cca3Slucy wang - Sun Microsystems - Beijing China static int
603304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
603404b6cca3Slucy wang - Sun Microsystems - Beijing China {
603504b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv	*mgp, *tmp;
603604b6cca3Slucy wang - Sun Microsystems - Beijing China 	int 			status, i, jbufs_alloced;
603704b6cca3Slucy wang - Sun Microsystems - Beijing China 
603804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (cmd == DDI_SUSPEND) {
603904b6cca3Slucy wang - Sun Microsystems - Beijing China 		status = myri10ge_suspend(dip);
604004b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (status);
604104b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
604204b6cca3Slucy wang - Sun Microsystems - Beijing China 
604304b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (cmd != DDI_DETACH) {
604404b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
604504b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
604604b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* Get the driver private (gld_mac_info_t) structure */
604704b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp = ddi_get_driver_private(dip);
604804b6cca3Slucy wang - Sun Microsystems - Beijing China 
604904b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&mgp->intrlock);
605004b6cca3Slucy wang - Sun Microsystems - Beijing China 	jbufs_alloced = 0;
605104b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (i = 0; i < mgp->num_slices; i++) {
605204b6cca3Slucy wang - Sun Microsystems - Beijing China 		myri10ge_remove_jbufs(&mgp->ss[i]);
605304b6cca3Slucy wang - Sun Microsystems - Beijing China 		jbufs_alloced += mgp->ss[i].jpool.num_alloc;
605404b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
605504b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&mgp->intrlock);
605604b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (jbufs_alloced != 0) {
605704b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_NOTE, "%s: %d loaned rx buffers remain\n",
605804b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->name, jbufs_alloced);
605904b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
606004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
606104b6cca3Slucy wang - Sun Microsystems - Beijing China 
606204b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&myri10ge_param_lock);
606304b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->refcnt != 0) {
606404b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_exit(&myri10ge_param_lock);
606504b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_NOTE, "%s: %d external refs remain\n",
606604b6cca3Slucy wang - Sun Microsystems - Beijing China 		    mgp->name, mgp->refcnt);
606704b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
606804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
606904b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&myri10ge_param_lock);
607004b6cca3Slucy wang - Sun Microsystems - Beijing China 
607104b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = mac_unregister(mgp->mh);
607204b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status != DDI_SUCCESS)
607304b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (status);
607404b6cca3Slucy wang - Sun Microsystems - Beijing China 
607504b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_ndd_fini(mgp);
607604b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_dummy_rdma(mgp, 0);
607704b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_nic_stat_destroy(mgp);
607804b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_info_destroy(mgp);
607904b6cca3Slucy wang - Sun Microsystems - Beijing China 
608004b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_destroy(&mgp->cmd_lock);
608104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_destroy(&mgp->intrlock);
608204b6cca3Slucy wang - Sun Microsystems - Beijing China 
608304b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_rem_intrs(mgp, 1);
608404b6cca3Slucy wang - Sun Microsystems - Beijing China 
608504b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_free_slices(mgp);
608604b6cca3Slucy wang - Sun Microsystems - Beijing China 	ddi_regs_map_free(&mgp->io_handle);
608704b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_dma_free(&mgp->cmd_dma);
608804b6cca3Slucy wang - Sun Microsystems - Beijing China 	pci_config_teardown(&mgp->cfg_hdl);
608904b6cca3Slucy wang - Sun Microsystems - Beijing China 
609004b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_enter(&myri10ge_param_lock);
609104b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp_list == mgp) {
609204b6cca3Slucy wang - Sun Microsystems - Beijing China 		mgp_list = mgp->next;
609304b6cca3Slucy wang - Sun Microsystems - Beijing China 	} else {
609404b6cca3Slucy wang - Sun Microsystems - Beijing China 		tmp = mgp_list;
609504b6cca3Slucy wang - Sun Microsystems - Beijing China 		while (tmp->next != mgp && tmp->next != NULL)
609604b6cca3Slucy wang - Sun Microsystems - Beijing China 			tmp = tmp->next;
609704b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (tmp->next != NULL)
609804b6cca3Slucy wang - Sun Microsystems - Beijing China 			tmp->next = tmp->next->next;
609904b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
610004b6cca3Slucy wang - Sun Microsystems - Beijing China 	kmem_free(mgp, sizeof (*mgp));
610104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_exit(&myri10ge_param_lock);
610204b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
610304b6cca3Slucy wang - Sun Microsystems - Beijing China }
610404b6cca3Slucy wang - Sun Microsystems - Beijing China 
610504b6cca3Slucy wang - Sun Microsystems - Beijing China /*
610604b6cca3Slucy wang - Sun Microsystems - Beijing China  * Helper for quiesce entry point: Interrupt threads are not being
610704b6cca3Slucy wang - Sun Microsystems - Beijing China  * scheduled, so we must poll for the confirmation DMA to arrive in
610804b6cca3Slucy wang - Sun Microsystems - Beijing China  * the firmware stats block for slice 0.  We're essentially running
610904b6cca3Slucy wang - Sun Microsystems - Beijing China  * the guts of the interrupt handler, and just cherry picking the
611004b6cca3Slucy wang - Sun Microsystems - Beijing China  * confirmation that the NIC is queuesced (stats->link_down)
611104b6cca3Slucy wang - Sun Microsystems - Beijing China  */
611204b6cca3Slucy wang - Sun Microsystems - Beijing China 
611304b6cca3Slucy wang - Sun Microsystems - Beijing China static int
611404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_poll_down(struct myri10ge_priv *mgp)
611504b6cca3Slucy wang - Sun Microsystems - Beijing China {
611604b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_slice_state *ss = mgp->ss;
611704b6cca3Slucy wang - Sun Microsystems - Beijing China 	mcp_irq_data_t *stats = ss->fw_stats;
611804b6cca3Slucy wang - Sun Microsystems - Beijing China 	int valid;
611904b6cca3Slucy wang - Sun Microsystems - Beijing China 	int found_down = 0;
612004b6cca3Slucy wang - Sun Microsystems - Beijing China 
612104b6cca3Slucy wang - Sun Microsystems - Beijing China 
612204b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* check for a pending IRQ */
612304b6cca3Slucy wang - Sun Microsystems - Beijing China 
612404b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (! *((volatile uint8_t *)& stats->valid))
612504b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (0);
612604b6cca3Slucy wang - Sun Microsystems - Beijing China 	valid = stats->valid;
612704b6cca3Slucy wang - Sun Microsystems - Beijing China 
612804b6cca3Slucy wang - Sun Microsystems - Beijing China 	/*
612904b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * Make sure to tell the NIC to lower a legacy IRQ, else
613004b6cca3Slucy wang - Sun Microsystems - Beijing China 	 * it may have corrupt state after restarting
613104b6cca3Slucy wang - Sun Microsystems - Beijing China 	 */
613204b6cca3Slucy wang - Sun Microsystems - Beijing China 
613304b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->ddi_intr_type == DDI_INTR_TYPE_FIXED) {
613404b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* lower legacy IRQ  */
613504b6cca3Slucy wang - Sun Microsystems - Beijing China 		*mgp->irq_deassert = 0;
613604b6cca3Slucy wang - Sun Microsystems - Beijing China 		mb();
613704b6cca3Slucy wang - Sun Microsystems - Beijing China 		/* wait for irq conf DMA */
613804b6cca3Slucy wang - Sun Microsystems - Beijing China 		while (*((volatile uint8_t *)& stats->valid))
613904b6cca3Slucy wang - Sun Microsystems - Beijing China 			;
614004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
614104b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (stats->stats_updated && stats->link_down)
614204b6cca3Slucy wang - Sun Microsystems - Beijing China 		found_down = 1;
614304b6cca3Slucy wang - Sun Microsystems - Beijing China 
614404b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (valid & 0x1)
614504b6cca3Slucy wang - Sun Microsystems - Beijing China 		*ss->irq_claim = BE_32(3);
614604b6cca3Slucy wang - Sun Microsystems - Beijing China 	*(ss->irq_claim + 1) = BE_32(3);
614704b6cca3Slucy wang - Sun Microsystems - Beijing China 
614804b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (found_down);
614904b6cca3Slucy wang - Sun Microsystems - Beijing China }
615004b6cca3Slucy wang - Sun Microsystems - Beijing China 
615104b6cca3Slucy wang - Sun Microsystems - Beijing China static int
615204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_quiesce(dev_info_t *dip)
615304b6cca3Slucy wang - Sun Microsystems - Beijing China {
615404b6cca3Slucy wang - Sun Microsystems - Beijing China 	struct myri10ge_priv *mgp;
615504b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_cmd_t cmd;
615604b6cca3Slucy wang - Sun Microsystems - Beijing China 	int status, down, i;
615704b6cca3Slucy wang - Sun Microsystems - Beijing China 
615804b6cca3Slucy wang - Sun Microsystems - Beijing China 	mgp = ddi_get_driver_private(dip);
615904b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp == NULL)
616004b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
616104b6cca3Slucy wang - Sun Microsystems - Beijing China 
616204b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* if devices was unplumbed, it is guaranteed to be quiescent */
616304b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mgp->running == MYRI10GE_ETH_STOPPED)
616404b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_SUCCESS);
616504b6cca3Slucy wang - Sun Microsystems - Beijing China 
616604b6cca3Slucy wang - Sun Microsystems - Beijing China 	/* send a down CMD to queuesce NIC */
616704b6cca3Slucy wang - Sun Microsystems - Beijing China 	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_DOWN, &cmd);
616804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (status) {
616904b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: Couldn't bring down link\n", mgp->name);
617004b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
617104b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
617204b6cca3Slucy wang - Sun Microsystems - Beijing China 
617304b6cca3Slucy wang - Sun Microsystems - Beijing China 	for (i = 0; i < 20; i++) {
617404b6cca3Slucy wang - Sun Microsystems - Beijing China 		down = myri10ge_poll_down(mgp);
617504b6cca3Slucy wang - Sun Microsystems - Beijing China 		if (down)
617604b6cca3Slucy wang - Sun Microsystems - Beijing China 			break;
617704b6cca3Slucy wang - Sun Microsystems - Beijing China 		delay(drv_usectohz(100000));
617804b6cca3Slucy wang - Sun Microsystems - Beijing China 		mb();
617904b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
618004b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (down)
618104b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (DDI_SUCCESS);
618204b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (DDI_FAILURE);
618304b6cca3Slucy wang - Sun Microsystems - Beijing China }
618404b6cca3Slucy wang - Sun Microsystems - Beijing China 
618504b6cca3Slucy wang - Sun Microsystems - Beijing China /*
618604b6cca3Slucy wang - Sun Microsystems - Beijing China  * Distinguish between allocb'ed blocks, and gesballoc'ed attached
618704b6cca3Slucy wang - Sun Microsystems - Beijing China  * storage.
618804b6cca3Slucy wang - Sun Microsystems - Beijing China  */
618904b6cca3Slucy wang - Sun Microsystems - Beijing China static void
619004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_find_lastfree(void)
619104b6cca3Slucy wang - Sun Microsystems - Beijing China {
619204b6cca3Slucy wang - Sun Microsystems - Beijing China 	mblk_t *mp = allocb(1024, 0);
619304b6cca3Slucy wang - Sun Microsystems - Beijing China 	dblk_t *dbp;
619404b6cca3Slucy wang - Sun Microsystems - Beijing China 
619504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (mp == NULL) {
619604b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "myri10ge_find_lastfree failed\n");
619704b6cca3Slucy wang - Sun Microsystems - Beijing China 		return;
619804b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
619904b6cca3Slucy wang - Sun Microsystems - Beijing China 	dbp = mp->b_datap;
620004b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_db_lastfree = (void *)dbp->db_lastfree;
620104b6cca3Slucy wang - Sun Microsystems - Beijing China }
620204b6cca3Slucy wang - Sun Microsystems - Beijing China 
620304b6cca3Slucy wang - Sun Microsystems - Beijing China int
620404b6cca3Slucy wang - Sun Microsystems - Beijing China _init(void)
620504b6cca3Slucy wang - Sun Microsystems - Beijing China {
620604b6cca3Slucy wang - Sun Microsystems - Beijing China 	int i;
620704b6cca3Slucy wang - Sun Microsystems - Beijing China 
620804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (myri10ge_verbose)
620904b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_NOTE,
621004b6cca3Slucy wang - Sun Microsystems - Beijing China 		    "Myricom 10G driver (10GbE) version %s loading\n",
621104b6cca3Slucy wang - Sun Microsystems - Beijing China 		    MYRI10GE_VERSION_STR);
621204b6cca3Slucy wang - Sun Microsystems - Beijing China 	myri10ge_find_lastfree();
621304b6cca3Slucy wang - Sun Microsystems - Beijing China 	mac_init_ops(&myri10ge_ops, "myri10ge");
621404b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_init(&myri10ge_param_lock, NULL, MUTEX_DEFAULT, NULL);
621504b6cca3Slucy wang - Sun Microsystems - Beijing China 	if ((i = mod_install(&modlinkage)) != 0) {
621604b6cca3Slucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "mod_install returned %d\n", i);
621704b6cca3Slucy wang - Sun Microsystems - Beijing China 		mac_fini_ops(&myri10ge_ops);
621804b6cca3Slucy wang - Sun Microsystems - Beijing China 		mutex_destroy(&myri10ge_param_lock);
621904b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
622004b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (i);
622104b6cca3Slucy wang - Sun Microsystems - Beijing China }
622204b6cca3Slucy wang - Sun Microsystems - Beijing China 
622304b6cca3Slucy wang - Sun Microsystems - Beijing China int
622404b6cca3Slucy wang - Sun Microsystems - Beijing China _fini(void)
622504b6cca3Slucy wang - Sun Microsystems - Beijing China {
622604b6cca3Slucy wang - Sun Microsystems - Beijing China 	int i;
622704b6cca3Slucy wang - Sun Microsystems - Beijing China 	i = mod_remove(&modlinkage);
622804b6cca3Slucy wang - Sun Microsystems - Beijing China 	if (i != 0) {
622904b6cca3Slucy wang - Sun Microsystems - Beijing China 		return (i);
623004b6cca3Slucy wang - Sun Microsystems - Beijing China 	}
623104b6cca3Slucy wang - Sun Microsystems - Beijing China 	mac_fini_ops(&myri10ge_ops);
623204b6cca3Slucy wang - Sun Microsystems - Beijing China 	mutex_destroy(&myri10ge_param_lock);
623304b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (0);
623404b6cca3Slucy wang - Sun Microsystems - Beijing China }
623504b6cca3Slucy wang - Sun Microsystems - Beijing China 
623604b6cca3Slucy wang - Sun Microsystems - Beijing China int
623704b6cca3Slucy wang - Sun Microsystems - Beijing China _info(struct modinfo *modinfop)
623804b6cca3Slucy wang - Sun Microsystems - Beijing China {
623904b6cca3Slucy wang - Sun Microsystems - Beijing China 	return (mod_info(&modlinkage, modinfop));
624004b6cca3Slucy wang - Sun Microsystems - Beijing China }
624104b6cca3Slucy wang - Sun Microsystems - Beijing China 
624204b6cca3Slucy wang - Sun Microsystems - Beijing China 
624304b6cca3Slucy wang - Sun Microsystems - Beijing China /*
624404b6cca3Slucy wang - Sun Microsystems - Beijing China  *  This file uses MyriGE driver indentation.
624504b6cca3Slucy wang - Sun Microsystems - Beijing China  *
624604b6cca3Slucy wang - Sun Microsystems - Beijing China  * Local Variables:
624704b6cca3Slucy wang - Sun Microsystems - Beijing China  * c-file-style:"sun"
624804b6cca3Slucy wang - Sun Microsystems - Beijing China  * tab-width:8
624904b6cca3Slucy wang - Sun Microsystems - Beijing China  * End:
625004b6cca3Slucy wang - Sun Microsystems - Beijing China  */
6251