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