xref: /illumos-gate/usr/src/uts/common/io/chxge/ch.c (revision ec71f88e)
1d39a76e7Sxw /*
2d39a76e7Sxw  * CDDL HEADER START
3d39a76e7Sxw  *
4d39a76e7Sxw  * The contents of this file are subject to the terms of the
5d39a76e7Sxw  * Common Development and Distribution License (the "License").
6d39a76e7Sxw  * You may not use this file except in compliance with the License.
7d39a76e7Sxw  *
8d39a76e7Sxw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9d39a76e7Sxw  * or http://www.opensolaris.org/os/licensing.
10d39a76e7Sxw  * See the License for the specific language governing permissions
11d39a76e7Sxw  * and limitations under the License.
12d39a76e7Sxw  *
13d39a76e7Sxw  * When distributing Covered Code, include this CDDL HEADER in each
14d39a76e7Sxw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15d39a76e7Sxw  * If applicable, add the following below this CDDL HEADER, with the
16d39a76e7Sxw  * fields enclosed by brackets "[]" replaced with your own identifying
17d39a76e7Sxw  * information: Portions Copyright [yyyy] [name of copyright owner]
18d39a76e7Sxw  *
19d39a76e7Sxw  * CDDL HEADER END
20d39a76e7Sxw  */
21d39a76e7Sxw 
22d39a76e7Sxw /*
2319397407SSherry Moore  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24d39a76e7Sxw  * Use is subject to license terms.
25*ec71f88eSPatrick Mooney  * Copyright 2018 Joyent, Inc.
26d39a76e7Sxw  */
27d39a76e7Sxw 
28d39a76e7Sxw /*
29d39a76e7Sxw  * This file is part of the Chelsio T1 Ethernet driver.
30d39a76e7Sxw  *
31d39a76e7Sxw  * Copyright (C) 2003-2005 Chelsio Communications.  All rights reserved.
32d39a76e7Sxw  */
33d39a76e7Sxw 
34d39a76e7Sxw /*
35d39a76e7Sxw  * Solaris Multithreaded STREAMS DLPI Chelsio PCI Ethernet Driver
36d39a76e7Sxw  */
37d39a76e7Sxw 
38d39a76e7Sxw /* #define CH_DEBUG 1 */
39d39a76e7Sxw #ifdef CH_DEBUG
40d39a76e7Sxw #define	DEBUG_ENTER(a) debug_enter(a)
41d39a76e7Sxw #define	PRINT(a) printf a
42d39a76e7Sxw #else
43d39a76e7Sxw #define	DEBUG_ENTER(a)
44d39a76e7Sxw #define	PRINT(a)
45d39a76e7Sxw #endif
46d39a76e7Sxw 
47d39a76e7Sxw #include <sys/types.h>
48d39a76e7Sxw #include <sys/conf.h>
49d39a76e7Sxw #include <sys/debug.h>
50d39a76e7Sxw #include <sys/stropts.h>
51d39a76e7Sxw #include <sys/stream.h>
52d39a76e7Sxw #include <sys/strlog.h>
53d39a76e7Sxw #include <sys/kmem.h>
54d39a76e7Sxw #include <sys/stat.h>
55d39a76e7Sxw #include <sys/kstat.h>
56d39a76e7Sxw #include <sys/modctl.h>
57d39a76e7Sxw #include <sys/errno.h>
58d39a76e7Sxw #include <sys/cmn_err.h>
59d39a76e7Sxw #include <sys/ddi.h>
60d39a76e7Sxw #include <sys/sunddi.h>
61d39a76e7Sxw #include <sys/dlpi.h>
62d39a76e7Sxw #include <sys/ethernet.h>
63*ec71f88eSPatrick Mooney #include <sys/mac_provider.h>
64d39a76e7Sxw #include <sys/strsun.h>
65d39a76e7Sxw #include <sys/strsubr.h>
66d39a76e7Sxw #include <inet/common.h>
67d39a76e7Sxw #include <inet/nd.h>
68d39a76e7Sxw #include <inet/ip.h>
69d39a76e7Sxw #include <inet/tcp.h>
70d39a76e7Sxw #include <sys/pattr.h>
71d39a76e7Sxw #include <sys/gld.h>
72d39a76e7Sxw #include "ostypes.h"
73d39a76e7Sxw #include "common.h"
74d39a76e7Sxw #include "oschtoe.h"
75d39a76e7Sxw #include "sge.h"
7619397407SSherry Moore #include "regs.h"
77d39a76e7Sxw #include "ch.h"			/* Chelsio Driver specific parameters */
78d39a76e7Sxw #include "version.h"
79d39a76e7Sxw 
80d39a76e7Sxw /*
81d39a76e7Sxw  * Function prototypes.
82d39a76e7Sxw  */
83d39a76e7Sxw static int ch_attach(dev_info_t *, ddi_attach_cmd_t);
84d39a76e7Sxw static int ch_detach(dev_info_t *, ddi_detach_cmd_t);
8519397407SSherry Moore static int ch_quiesce(dev_info_t *);
86d39a76e7Sxw static void ch_free_dma_handles(ch_t *chp);
87d39a76e7Sxw static void ch_set_name(ch_t *chp, int unit);
88d39a76e7Sxw static void ch_free_name(ch_t *chp);
89d39a76e7Sxw static void ch_get_prop(ch_t *chp);
90d39a76e7Sxw 
91d39a76e7Sxw #if defined(__sparc)
92d39a76e7Sxw static void ch_free_dvma_handles(ch_t *chp);
93d39a76e7Sxw #endif
94d39a76e7Sxw 
95d39a76e7Sxw /* GLD interfaces */
96d39a76e7Sxw static int ch_reset(gld_mac_info_t *);
97d39a76e7Sxw static int ch_start(gld_mac_info_t *);
98d39a76e7Sxw static int ch_stop(gld_mac_info_t *);
99d39a76e7Sxw static int ch_set_mac_address(gld_mac_info_t *, uint8_t *);
100d39a76e7Sxw static int ch_set_multicast(gld_mac_info_t *, uint8_t *, int);
101d39a76e7Sxw static int ch_ioctl(gld_mac_info_t *, queue_t *, mblk_t *);
102d39a76e7Sxw static int ch_set_promiscuous(gld_mac_info_t *, int);
103d39a76e7Sxw static int ch_get_stats(gld_mac_info_t *, struct gld_stats *);
104d39a76e7Sxw static int ch_send(gld_mac_info_t *, mblk_t *);
105d39a76e7Sxw static uint_t ch_intr(gld_mac_info_t *);
106d39a76e7Sxw 
107d39a76e7Sxw /*
108d39a76e7Sxw  * Data access requirements.
109d39a76e7Sxw  */
110d39a76e7Sxw static struct ddi_device_acc_attr le_attr = {
111d39a76e7Sxw 	DDI_DEVICE_ATTR_V0,
112d39a76e7Sxw 	DDI_STRUCTURE_LE_ACC,
113d39a76e7Sxw 	DDI_STRICTORDER_ACC
114d39a76e7Sxw };
115d39a76e7Sxw 
116d39a76e7Sxw /*
117d39a76e7Sxw  * No swap mapping device attributes
118d39a76e7Sxw  */
119d39a76e7Sxw static struct ddi_device_acc_attr null_attr = {
120d39a76e7Sxw 	DDI_DEVICE_ATTR_V0,
121d39a76e7Sxw 	DDI_NEVERSWAP_ACC,
122d39a76e7Sxw 	DDI_STRICTORDER_ACC
123d39a76e7Sxw };
124d39a76e7Sxw 
125d39a76e7Sxw /*
126d39a76e7Sxw  * STREAMS driver identification struture module_info(9s)
127d39a76e7Sxw  *
128d39a76e7Sxw  * driver limit values
129d39a76e7Sxw  */
130d39a76e7Sxw 
131d39a76e7Sxw static	struct module_info ch_minfo = {
132d39a76e7Sxw 	CHIDNUM,	/* mi_idnum */
133d39a76e7Sxw 	CHNAME,		/* mi_idname */
134d39a76e7Sxw 	CHMINPSZ,	/* mi_minpsz */
135d39a76e7Sxw 	CHMAXPSZ,	/* mi_maxpsz */
136d39a76e7Sxw 	CHHIWAT,	/* mi_hiwat */
137d39a76e7Sxw 	CHLOWAT		/* mi_lowat */
138d39a76e7Sxw };
139d39a76e7Sxw 
140d39a76e7Sxw /*
141d39a76e7Sxw  * STREAMS queue processiong procedures qinit(9s)
142d39a76e7Sxw  *
143d39a76e7Sxw  * read queue procedures
144d39a76e7Sxw  */
145d39a76e7Sxw 
146d39a76e7Sxw static struct qinit ch_rinit = {
147d39a76e7Sxw 	(int (*)()) NULL, 	/* qi_putp */
148d39a76e7Sxw 	gld_rsrv,		/* qi_srvp */
149d39a76e7Sxw 	gld_open,		/* qi_qopen */
150d39a76e7Sxw 	gld_close,		/* qi_qclose */
151d39a76e7Sxw 	(int (*)()) NULL, 	/* qi_qadmin */
152d39a76e7Sxw 	&ch_minfo,		/* qi_minfo */
153d39a76e7Sxw 	NULL			/* qi_mstat */
154d39a76e7Sxw };
155d39a76e7Sxw 
156d39a76e7Sxw /*
157d39a76e7Sxw  * STREAMS queue processiong procedures qinit(9s)
158d39a76e7Sxw  *
159d39a76e7Sxw  * write queue procedures
160d39a76e7Sxw  */
161d39a76e7Sxw 
162d39a76e7Sxw static struct qinit ch_winit = {
163d39a76e7Sxw 	gld_wput,		/* qi_putp */
164d39a76e7Sxw 	gld_wsrv,		/* qi_srvp */
165d39a76e7Sxw 	(int (*)()) NULL, 	/* qi_qopen */
166d39a76e7Sxw 	(int (*)()) NULL, 	/* qi_qclose */
167d39a76e7Sxw 	(int (*)()) NULL, 	/* qi_qadmin */
168d39a76e7Sxw 	&ch_minfo,		/* qi_minfo */
169d39a76e7Sxw 	NULL			/* qi_mstat */
170d39a76e7Sxw };
171d39a76e7Sxw 
172d39a76e7Sxw /*
173d39a76e7Sxw  * STREAMS entity declaration structure - streamtab(9s)
174d39a76e7Sxw  */
175d39a76e7Sxw static struct streamtab	chinfo = {
176d39a76e7Sxw 	&ch_rinit,	/* read queue information */
177d39a76e7Sxw 	&ch_winit,	/* write queue information */
178d39a76e7Sxw 	NULL,		/* st_muxrinit */
179d39a76e7Sxw 	NULL		/* st_muxwrinit */
180d39a76e7Sxw };
181d39a76e7Sxw 
182d39a76e7Sxw /*
183d39a76e7Sxw  * Device driver ops vector - cb_ops(9s)
184d39a76e7Sxw  *
185d39a76e7Sxw  * charater/block entry points structure.
186d39a76e7Sxw  * chinfo identifies driver as a STREAMS driver.
187d39a76e7Sxw  */
188d39a76e7Sxw 
189d39a76e7Sxw static struct cb_ops cb_ch_ops = {
190d39a76e7Sxw 	nulldev,	/* cb_open */
191d39a76e7Sxw 	nulldev,	/* cb_close */
192d39a76e7Sxw 	nodev,		/* cb_strategy */
193d39a76e7Sxw 	nodev,		/* cb_print */
194d39a76e7Sxw 	nodev,		/* cb_dump */
195d39a76e7Sxw 	nodev,		/* cb_read */
196d39a76e7Sxw 	nodev,		/* cb_write */
197d39a76e7Sxw 	nodev,		/* cb_ioctl */
198d39a76e7Sxw 	nodev,		/* cb_devmap */
199d39a76e7Sxw 	nodev,		/* cb_mmap */
200d39a76e7Sxw 	nodev,		/* cb_segmap */
201d39a76e7Sxw 	nochpoll,	/* cb_chpoll */
202d39a76e7Sxw 	ddi_prop_op,	/* report driver property information - prop_op(9e) */
203d39a76e7Sxw 	&chinfo,	/* cb_stream */
204d39a76e7Sxw #if defined(__sparc)
205d39a76e7Sxw 	D_MP | D_64BIT,
206d39a76e7Sxw #else
207d39a76e7Sxw 	D_MP,		/* cb_flag (supports multi-threading) */
208d39a76e7Sxw #endif
209d39a76e7Sxw 	CB_REV,		/* cb_rev */
210d39a76e7Sxw 	nodev,		/* cb_aread */
211d39a76e7Sxw 	nodev		/* cb_awrite */
212d39a76e7Sxw };
213d39a76e7Sxw 
214d39a76e7Sxw /*
215d39a76e7Sxw  * dev_ops(9S) structure
216d39a76e7Sxw  *
217d39a76e7Sxw  * Device Operations table, for autoconfiguration
218d39a76e7Sxw  */
219d39a76e7Sxw 
220d39a76e7Sxw static	struct dev_ops ch_ops = {
221d39a76e7Sxw 	DEVO_REV,	/* Driver build version */
222d39a76e7Sxw 	0,		/* Initial driver reference count */
223d39a76e7Sxw 	gld_getinfo,	/* funcp: get driver information - getinfo(9e) */
224d39a76e7Sxw 	nulldev,	/* funcp: entry point obsolute - identify(9e) */
225d39a76e7Sxw 	nulldev,	/* funp: probe for device - probe(9e) */
226d39a76e7Sxw 	ch_attach,	/* funp: attach driver to dev_info - attach(9e) */
227d39a76e7Sxw 	ch_detach,	/* funp: detach driver to unload - detach(9e) */
228d39a76e7Sxw 	nodev,		/* funp: reset device (not supported) - dev_ops(9s) */
229d39a76e7Sxw 	&cb_ch_ops,	/* ptr to cb_ops structure */
230d39a76e7Sxw 	NULL,		/* ptr to nexus bus operations structure (leaf) */
23119397407SSherry Moore 	NULL,		/* funp: change device power level - power(9e) */
23219397407SSherry Moore 	ch_quiesce,	/* devo_quiesce */
233d39a76e7Sxw };
234d39a76e7Sxw 
235d39a76e7Sxw /*
236d39a76e7Sxw  * modldrv(9s) structure
237d39a76e7Sxw  *
238d39a76e7Sxw  * Definition for module specific device driver linkage structures (modctl.h)
239d39a76e7Sxw  */
240d39a76e7Sxw 
241d39a76e7Sxw static struct modldrv modldrv = {
242d39a76e7Sxw 	&mod_driverops,		/* driver module */
243d39a76e7Sxw 	VERSION,
244d39a76e7Sxw 	&ch_ops,		/* driver ops */
245d39a76e7Sxw };
246d39a76e7Sxw 
247d39a76e7Sxw /*
248d39a76e7Sxw  * modlinkage(9s) structure
249d39a76e7Sxw  *
250d39a76e7Sxw  * module linkage base structure (modctl.h)
251d39a76e7Sxw  */
252d39a76e7Sxw 
253d39a76e7Sxw static struct modlinkage modlinkage = {
254d39a76e7Sxw 	MODREV_1,		/* revision # of system */
255d39a76e7Sxw 	&modldrv,		/* NULL terminated list of linkage strucures */
256d39a76e7Sxw 	NULL
257d39a76e7Sxw };
258d39a76e7Sxw 
259d39a76e7Sxw /* ===================== start of STREAMS driver code ================== */
260d39a76e7Sxw 
261d39a76e7Sxw #ifdef CONFIG_CHELSIO_T1_OFFLOAD
262d39a76e7Sxw /*
263d39a76e7Sxw  * global pointer to toe per-driver control structure.
264d39a76e7Sxw  */
265d39a76e7Sxw #define	MAX_CARDS	4
266d39a76e7Sxw ch_t *gchp[MAX_CARDS];
267d39a76e7Sxw #endif
268d39a76e7Sxw 
269d39a76e7Sxw kmutex_t in_use_l;
270d39a76e7Sxw uint32_t buffers_in_use[SZ_INUSE];
271d39a76e7Sxw uint32_t in_use_index;
272d39a76e7Sxw 
273d39a76e7Sxw /*
274d39a76e7Sxw  * Ethernet broadcast address definition.
275d39a76e7Sxw  */
276d39a76e7Sxw static struct ether_addr etherbroadcastaddr = {
277d39a76e7Sxw 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff
278d39a76e7Sxw };
279d39a76e7Sxw 
280d39a76e7Sxw /*
281d39a76e7Sxw  * Module initialization functions.
282d39a76e7Sxw  *
283d39a76e7Sxw  *      Routine         Called by
284d39a76e7Sxw  *      _init(9E)       modload(9F)
285d39a76e7Sxw  *      _info(9E)       modinfo(9F)
286d39a76e7Sxw  *      _fini(9E)       modunload(9F)
287d39a76e7Sxw  */
288d39a76e7Sxw 
289d39a76e7Sxw /*
290d39a76e7Sxw  * _init(9E):
291d39a76e7Sxw  *
292d39a76e7Sxw  * Initial, one-time, resource allocation and data initialization.
293d39a76e7Sxw  */
294d39a76e7Sxw 
295d39a76e7Sxw int
_init(void)296d39a76e7Sxw _init(void)
297d39a76e7Sxw {
298d39a76e7Sxw 	int status;
299d39a76e7Sxw 
300d39a76e7Sxw 	status = mod_install(&modlinkage);
301d39a76e7Sxw 
302d39a76e7Sxw 	mutex_init(&in_use_l, NULL, MUTEX_DRIVER, NULL);
303d39a76e7Sxw 
304d39a76e7Sxw 	return (status);
305d39a76e7Sxw }
306d39a76e7Sxw 
307d39a76e7Sxw /*
308d39a76e7Sxw  * _fini(9E): It is here that any device information that was allocated
309d39a76e7Sxw  * during the _init(9E) routine should be released and the module removed
310d39a76e7Sxw  * from the system.  In the case of per-instance information, that information
311d39a76e7Sxw  * should be released in the _detach(9E) routine.
312d39a76e7Sxw  */
313d39a76e7Sxw 
314d39a76e7Sxw int
_fini(void)315d39a76e7Sxw _fini(void)
316d39a76e7Sxw {
317d39a76e7Sxw 	int status;
318d39a76e7Sxw 	int i;
319d39a76e7Sxw 	uint32_t t = 0;
320d39a76e7Sxw 
321d39a76e7Sxw 	for (i = 0; i < SZ_INUSE; i++)
322d39a76e7Sxw 		t += buffers_in_use[i];
323d39a76e7Sxw 
32411abda1eSToomas Soome 	if (t != 0)
325d39a76e7Sxw 		return (DDI_FAILURE);
326d39a76e7Sxw 
327d39a76e7Sxw 	status = mod_remove(&modlinkage);
328d39a76e7Sxw 
329d39a76e7Sxw 	if (status == DDI_SUCCESS)
330d39a76e7Sxw 		mutex_destroy(&in_use_l);
331d39a76e7Sxw 
332d39a76e7Sxw 	return (status);
333d39a76e7Sxw }
334d39a76e7Sxw 
335d39a76e7Sxw int
_info(struct modinfo * modinfop)336d39a76e7Sxw _info(struct modinfo *modinfop)
337d39a76e7Sxw {
338d39a76e7Sxw 	int status;
339d39a76e7Sxw 
340d39a76e7Sxw 
341d39a76e7Sxw 	status = mod_info(&modlinkage, modinfop);
342d39a76e7Sxw 
343d39a76e7Sxw 	return (status);
344d39a76e7Sxw }
345d39a76e7Sxw 
346d39a76e7Sxw /*
347d39a76e7Sxw  * Attach(9E) - This is called on the open to the device.  It creates
348d39a76e7Sxw  * an instance of the driver.  In this routine we create the minor
349d39a76e7Sxw  * device node.  The routine also initializes all per-unit
350d39a76e7Sxw  * mutex's and conditional variables.
351d39a76e7Sxw  *
352d39a76e7Sxw  * If we were resuming a suspended instance of a device due to power
353d39a76e7Sxw  * management, then that would be handled here as well.  For more on
354d39a76e7Sxw  * that subject see the man page for pm(9E)
355d39a76e7Sxw  *
356d39a76e7Sxw  * Interface exists: make available by filling in network interface
357d39a76e7Sxw  * record.  System will initialize the interface when it is ready
358d39a76e7Sxw  * to accept packets.
359d39a76e7Sxw  */
360d39a76e7Sxw int chdebug = 0;
361d39a76e7Sxw int ch_abort_debug = 0;
362d39a76e7Sxw 
363d39a76e7Sxw static int
ch_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)364d39a76e7Sxw ch_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
365d39a76e7Sxw {
366d39a76e7Sxw 	ch_t *chp;
367d39a76e7Sxw 	int rv;
368d39a76e7Sxw 	int unit;
369d39a76e7Sxw #ifdef CH_DEBUG
370d39a76e7Sxw 	int Version;
371d39a76e7Sxw 	int VendorID;
372d39a76e7Sxw 	int DeviceID;
373d39a76e7Sxw 	int SubDeviceID;
374d39a76e7Sxw 	int Command;
375d39a76e7Sxw #endif
376d39a76e7Sxw 	gld_mac_info_t *macinfo;		/* GLD stuff follows */
377d39a76e7Sxw 	char *driver;
378d39a76e7Sxw 
379d39a76e7Sxw 	if (ch_abort_debug)
380d39a76e7Sxw 		debug_enter("ch_attach");
381d39a76e7Sxw 
382d39a76e7Sxw 	if (chdebug)
383d39a76e7Sxw 		return (DDI_FAILURE);
384d39a76e7Sxw 
385d39a76e7Sxw 
386d39a76e7Sxw 	if (cmd == DDI_ATTACH) {
387d39a76e7Sxw 
388d39a76e7Sxw 		unit = ddi_get_instance(dip);
389d39a76e7Sxw 
390d39a76e7Sxw 		driver = (char *)ddi_driver_name(dip);
391d39a76e7Sxw 
392d39a76e7Sxw 		PRINT(("driver %s unit: %d\n", driver, unit));
393d39a76e7Sxw 
394d39a76e7Sxw 		macinfo = gld_mac_alloc(dip);
395d39a76e7Sxw 		if (macinfo == NULL) {
396d39a76e7Sxw 			PRINT(("macinfo allocation failed\n"));
397d39a76e7Sxw 			DEBUG_ENTER("ch_attach");
398d39a76e7Sxw 			return (DDI_FAILURE);
399d39a76e7Sxw 		}
400d39a76e7Sxw 
401d39a76e7Sxw 		chp = (ch_t *)kmem_zalloc(sizeof (ch_t), KM_SLEEP);
402d39a76e7Sxw 
403d39a76e7Sxw 		if (chp == NULL) {
404d39a76e7Sxw 			PRINT(("zalloc of chp failed\n"));
405d39a76e7Sxw 			DEBUG_ENTER("ch_attach");
406d39a76e7Sxw 
407d39a76e7Sxw 			gld_mac_free(macinfo);
408d39a76e7Sxw 
409d39a76e7Sxw 			return (DDI_FAILURE);
410d39a76e7Sxw 		}
411d39a76e7Sxw 
412d39a76e7Sxw #ifdef CONFIG_CHELSIO_T1_OFFLOAD
413d39a76e7Sxw 		/* Solaris TOE support */
414d39a76e7Sxw 		gchp[unit] = chp;
415d39a76e7Sxw #endif
416d39a76e7Sxw 
417d39a76e7Sxw 		PRINT(("attach macinfo: %p chp: %p\n", macinfo, chp));
418d39a76e7Sxw 
419d39a76e7Sxw 		chp->ch_dip  = dip;
420d39a76e7Sxw 		chp->ch_macp = macinfo;
421d39a76e7Sxw 		chp->ch_unit = unit;
422d39a76e7Sxw 		ch_set_name(chp, unit);
423d39a76e7Sxw 
424d39a76e7Sxw 		/*
425d39a76e7Sxw 		 * map in PCI register spaces
426d39a76e7Sxw 		 *
427d39a76e7Sxw 		 * PCI register set 0 - PCI configuration space
428d39a76e7Sxw 		 * PCI register set 1 - T101 card register space #1
429d39a76e7Sxw 		 */
430d39a76e7Sxw 
431d39a76e7Sxw 		/* map in T101 PCI configuration space */
432d39a76e7Sxw 		rv = pci_config_setup(
43319397407SSherry Moore 		    dip,		/* ptr to dev's dev_info struct */
43419397407SSherry Moore 		    &chp->ch_hpci);	/* ptr to data access handle */
435d39a76e7Sxw 
436d39a76e7Sxw 		if (rv != DDI_SUCCESS) {
437d39a76e7Sxw 			PRINT(("PCI config setup failed\n"));
438d39a76e7Sxw 			DEBUG_ENTER("ch_attach");
439d39a76e7Sxw #ifdef CONFIG_CHELSIO_T1_OFFLOAD
440d39a76e7Sxw 			gchp[unit] = NULL;
441d39a76e7Sxw #endif
442d39a76e7Sxw 			cmn_err(CE_WARN, "%s: ddi_config_setup PCI error %d\n",
44319397407SSherry Moore 			    chp->ch_name, rv);
444d39a76e7Sxw 
445d39a76e7Sxw 			ch_free_name(chp);
446d39a76e7Sxw 			kmem_free(chp, sizeof (ch_t));
447d39a76e7Sxw 			gld_mac_free(macinfo);
448d39a76e7Sxw 
449d39a76e7Sxw 			return (DDI_FAILURE);
450d39a76e7Sxw 		}
451d39a76e7Sxw 
452d39a76e7Sxw 		ch_get_prop(chp);
453d39a76e7Sxw 
454d39a76e7Sxw 		macinfo->gldm_devinfo = dip;
455d39a76e7Sxw 		macinfo->gldm_private = (caddr_t)chp;
456d39a76e7Sxw 		macinfo->gldm_reset = ch_reset;
457d39a76e7Sxw 		macinfo->gldm_start = ch_start;
458d39a76e7Sxw 		macinfo->gldm_stop = ch_stop;
459d39a76e7Sxw 		macinfo->gldm_set_mac_addr = ch_set_mac_address;
460d39a76e7Sxw 		macinfo->gldm_send = ch_send;
461d39a76e7Sxw 		macinfo->gldm_set_promiscuous = ch_set_promiscuous;
462d39a76e7Sxw 		macinfo->gldm_get_stats = ch_get_stats;
463d39a76e7Sxw 		macinfo->gldm_ioctl = ch_ioctl;
464d39a76e7Sxw 		macinfo->gldm_set_multicast = ch_set_multicast;
465d39a76e7Sxw 		macinfo->gldm_intr = ch_intr;
466d39a76e7Sxw 		macinfo->gldm_mctl = NULL;
467d39a76e7Sxw 
468d39a76e7Sxw 		macinfo->gldm_ident = driver;
469d39a76e7Sxw 		macinfo->gldm_type = DL_ETHER;
470d39a76e7Sxw 		macinfo->gldm_minpkt = 0;
471d39a76e7Sxw 		macinfo->gldm_maxpkt = chp->ch_mtu;
472d39a76e7Sxw 		macinfo->gldm_addrlen = ETHERADDRL;
473d39a76e7Sxw 		macinfo->gldm_saplen = -2;
474d39a76e7Sxw 		macinfo->gldm_ppa = unit;
475d39a76e7Sxw 		macinfo->gldm_broadcast_addr =
47619397407SSherry Moore 		    etherbroadcastaddr.ether_addr_octet;
477d39a76e7Sxw 
478d39a76e7Sxw 
479d39a76e7Sxw 		/*
480d39a76e7Sxw 		 * do a power reset of card
481d39a76e7Sxw 		 *
482d39a76e7Sxw 		 * 1. set PwrState to D3hot (3)
483d39a76e7Sxw 		 * 2. clear PwrState flags
484d39a76e7Sxw 		 */
485d39a76e7Sxw 		pci_config_put32(chp->ch_hpci, 0x44, 3);
486d39a76e7Sxw 		pci_config_put32(chp->ch_hpci, 0x44, 0);
487d39a76e7Sxw 
488d39a76e7Sxw 		/* delay .5 sec */
489d39a76e7Sxw 		DELAY(500000);
490d39a76e7Sxw 
491d39a76e7Sxw #ifdef CH_DEBUG
492d39a76e7Sxw 		VendorID    = pci_config_get16(chp->ch_hpci, 0);
493d39a76e7Sxw 		DeviceID    = pci_config_get16(chp->ch_hpci, 2);
494d39a76e7Sxw 		SubDeviceID = pci_config_get16(chp->ch_hpci, 0x2e);
495d39a76e7Sxw 		Command = pci_config_get16(chp->ch_hpci, 4);
496d39a76e7Sxw 
497d39a76e7Sxw 		PRINT(("IDs: %x,%x,%x\n", VendorID, DeviceID, SubDeviceID));
498d39a76e7Sxw 		PRINT(("Command: %x\n", Command));
499d39a76e7Sxw #endif
500d39a76e7Sxw 		/* map in T101 register space (BAR0) */
501d39a76e7Sxw 		rv = ddi_regs_map_setup(
50219397407SSherry Moore 		    dip,		/* ptr to dev's dev_info struct */
50319397407SSherry Moore 		    BAR0,		/* register address space */
50419397407SSherry Moore 		    &chp->ch_bar0,	/* address of offset */
50519397407SSherry Moore 		    0,		/* offset into register address space */
50619397407SSherry Moore 		    0,		/* length mapped (everything) */
50719397407SSherry Moore 		    &le_attr,	/* ptr to device attr structure */
50819397407SSherry Moore 		    &chp->ch_hbar0);	/* ptr to data access handle */
509d39a76e7Sxw 
510d39a76e7Sxw 		if (rv != DDI_SUCCESS) {
511d39a76e7Sxw 			PRINT(("map registers failed\n"));
512d39a76e7Sxw 			DEBUG_ENTER("ch_attach");
513d39a76e7Sxw #ifdef CONFIG_CHELSIO_T1_OFFLOAD
514d39a76e7Sxw 			gchp[unit] = NULL;
515d39a76e7Sxw #endif
516d39a76e7Sxw 			cmn_err(CE_WARN,
51719397407SSherry Moore 			    "%s: ddi_regs_map_setup BAR0 error %d\n",
51819397407SSherry Moore 			    chp->ch_name, rv);
519d39a76e7Sxw 
520d39a76e7Sxw 			pci_config_teardown(&chp->ch_hpci);
521d39a76e7Sxw 			ch_free_name(chp);
522d39a76e7Sxw 			kmem_free(chp, sizeof (ch_t));
523d39a76e7Sxw 			gld_mac_free(macinfo);
524d39a76e7Sxw 
525d39a76e7Sxw 			return (DDI_FAILURE);
526d39a76e7Sxw 		}
527d39a76e7Sxw 
528d39a76e7Sxw #ifdef CH_DEBUG
529d39a76e7Sxw 		Version  = ddi_get32(chp->ch_hbar0,
53019397407SSherry Moore 		    (uint32_t *)(chp->ch_bar0+0x6c));
531d39a76e7Sxw #endif
532d39a76e7Sxw 
533d39a76e7Sxw 		(void) ddi_dev_regsize(dip, 1, &chp->ch_bar0sz);
534d39a76e7Sxw 
535d39a76e7Sxw 		PRINT(("PCI BAR0 space addr: %p\n", chp->ch_bar0));
536d39a76e7Sxw 		PRINT(("PCI BAR0 space size: %x\n", chp->ch_bar0sz));
537d39a76e7Sxw 		PRINT(("PE Version: %x\n", Version));
538d39a76e7Sxw 
539d39a76e7Sxw 		/*
540d39a76e7Sxw 		 * Add interrupt to system.
541d39a76e7Sxw 		 */
542d39a76e7Sxw 		rv = ddi_get_iblock_cookie(
54319397407SSherry Moore 		    dip,		   /* ptr to dev's dev_info struct */
54419397407SSherry Moore 		    0,		   /* interrupt # (0) */
54519397407SSherry Moore 		    &chp->ch_icookp); /* ptr to interrupt block cookie */
546d39a76e7Sxw 
547d39a76e7Sxw 		if (rv != DDI_SUCCESS) {
548d39a76e7Sxw 			PRINT(("iblock cookie failed\n"));
549d39a76e7Sxw 			DEBUG_ENTER("ch_attach");
550d39a76e7Sxw #ifdef CONFIG_CHELSIO_T1_OFFLOAD
551d39a76e7Sxw 			gchp[unit] = NULL;
552d39a76e7Sxw #endif
553d39a76e7Sxw 			cmn_err(CE_WARN,
55419397407SSherry Moore 			    "%s: ddi_get_iblock_cookie error %d\n",
55519397407SSherry Moore 			    chp->ch_name, rv);
556d39a76e7Sxw 
557d39a76e7Sxw 			ddi_regs_map_free(&chp->ch_hbar0);
558d39a76e7Sxw 			pci_config_teardown(&chp->ch_hpci);
559d39a76e7Sxw 			ch_free_name(chp);
560d39a76e7Sxw 			kmem_free(chp, sizeof (ch_t));
561d39a76e7Sxw 			gld_mac_free(macinfo);
562d39a76e7Sxw 
563d39a76e7Sxw 			return (DDI_FAILURE);
564d39a76e7Sxw 		}
565d39a76e7Sxw 
566d39a76e7Sxw 		/*
567d39a76e7Sxw 		 * add interrupt handler before card setup.
568d39a76e7Sxw 		 */
569d39a76e7Sxw 		rv = ddi_add_intr(
57019397407SSherry Moore 		    dip,		/* ptr to dev's dev_info struct */
57119397407SSherry Moore 		    0,		/* interrupt # (0) */
57219397407SSherry Moore 		    0,		/* iblock cookie ptr (NULL) */
57319397407SSherry Moore 		    0,		/* idevice cookie ptr (NULL) */
57419397407SSherry Moore 		    gld_intr,	/* function ptr to interrupt handler */
57519397407SSherry Moore 		    (caddr_t)macinfo);	/* handler argument */
576d39a76e7Sxw 
577d39a76e7Sxw 		if (rv != DDI_SUCCESS) {
578d39a76e7Sxw 			PRINT(("add_intr failed\n"));
579d39a76e7Sxw 			DEBUG_ENTER("ch_attach");
580d39a76e7Sxw #ifdef CONFIG_CHELSIO_T1_OFFLOAD
581d39a76e7Sxw 			gchp[unit] = NULL;
582d39a76e7Sxw #endif
583d39a76e7Sxw 			cmn_err(CE_WARN, "%s: ddi_add_intr error %d\n",
58419397407SSherry Moore 			    chp->ch_name, rv);
585d39a76e7Sxw 
586d39a76e7Sxw 			ddi_regs_map_free(&chp->ch_hbar0);
587d39a76e7Sxw 			pci_config_teardown(&chp->ch_hpci);
588d39a76e7Sxw 			ch_free_name(chp);
589d39a76e7Sxw 			kmem_free(chp, sizeof (ch_t));
590d39a76e7Sxw 			gld_mac_free(macinfo);
591d39a76e7Sxw 
592d39a76e7Sxw 			return (DDI_FAILURE);
593d39a76e7Sxw 		}
594d39a76e7Sxw 
595d39a76e7Sxw 		/* initalize all the remaining per-card locks */
596d39a76e7Sxw 		mutex_init(&chp->ch_lock, NULL, MUTEX_DRIVER,
59719397407SSherry Moore 		    (void *)chp->ch_icookp);
598d39a76e7Sxw 		mutex_init(&chp->ch_intr, NULL, MUTEX_DRIVER,
59919397407SSherry Moore 		    (void *)chp->ch_icookp);
600d39a76e7Sxw 		mutex_init(&chp->ch_mc_lck, NULL, MUTEX_DRIVER, NULL);
601d39a76e7Sxw 		mutex_init(&chp->ch_dh_lck, NULL, MUTEX_DRIVER, NULL);
602d39a76e7Sxw 		mutex_init(&chp->mac_lock, NULL, MUTEX_DRIVER, NULL);
603d39a76e7Sxw 
604d39a76e7Sxw 		/* ------- initialize Chelsio card ------- */
605d39a76e7Sxw 
606d39a76e7Sxw 		if (pe_attach(chp)) {
607d39a76e7Sxw 			PRINT(("card initialization failed\n"));
608d39a76e7Sxw 			DEBUG_ENTER("ch_attach");
609d39a76e7Sxw #ifdef CONFIG_CHELSIO_T1_OFFLOAD
610d39a76e7Sxw 			gchp[unit] = NULL;
611d39a76e7Sxw #endif
612d39a76e7Sxw 			cmn_err(CE_WARN, "%s: pe_attach failed\n",
61319397407SSherry Moore 			    chp->ch_name);
614d39a76e7Sxw 
615d39a76e7Sxw 			mutex_destroy(&chp->ch_lock);
616d39a76e7Sxw 			mutex_destroy(&chp->ch_intr);
617d39a76e7Sxw 			mutex_destroy(&chp->ch_mc_lck);
618d39a76e7Sxw 			mutex_destroy(&chp->ch_dh_lck);
619d39a76e7Sxw 			mutex_destroy(&chp->mac_lock);
620d39a76e7Sxw 			ddi_remove_intr(dip, 0, chp->ch_icookp);
621d39a76e7Sxw 			ddi_regs_map_free(&chp->ch_hbar0);
622d39a76e7Sxw 			pci_config_teardown(&chp->ch_hpci);
623d39a76e7Sxw 			ch_free_name(chp);
624d39a76e7Sxw 			kmem_free(chp, sizeof (ch_t));
625d39a76e7Sxw 			gld_mac_free(macinfo);
626d39a76e7Sxw 
627d39a76e7Sxw 			return (DDI_FAILURE);
628d39a76e7Sxw 		}
629d39a76e7Sxw 
630d39a76e7Sxw 		/* ------- done with Chelsio card ------- */
631d39a76e7Sxw 
632d39a76e7Sxw 		/* now can  set mac address */
633d39a76e7Sxw 		macinfo->gldm_vendor_addr = pe_get_mac(chp);
634d39a76e7Sxw 
635d39a76e7Sxw 		macinfo->gldm_cookie = chp->ch_icookp;
636d39a76e7Sxw 
637d39a76e7Sxw 		/*
638d39a76e7Sxw 		 * We only active checksum offload for T2 architectures.
639d39a76e7Sxw 		 */
640d39a76e7Sxw 		if (is_T2(chp)) {
641d39a76e7Sxw 			if (chp->ch_config.cksum_enabled)
642d39a76e7Sxw 				macinfo->gldm_capabilities |=
643d39a76e7Sxw 				    GLD_CAP_CKSUM_FULL_V4;
644d39a76e7Sxw 		} else
645d39a76e7Sxw 			chp->ch_config.cksum_enabled = 0;
646d39a76e7Sxw 
647d39a76e7Sxw 		rv = gld_register(
64819397407SSherry Moore 		    dip,		/* ptr to dev's dev_info struct */
64919397407SSherry Moore 		    (char *)ddi_driver_name(dip),	/* driver name */
65019397407SSherry Moore 		    macinfo);	/* ptr to gld macinfo buffer */
651d39a76e7Sxw 
652d39a76e7Sxw 		/*
653d39a76e7Sxw 		 * The Jumbo frames capability is not yet available
654d39a76e7Sxw 		 * in Solaris 10 so registration will fail. MTU > 1500 is
655d39a76e7Sxw 		 * supported in Update 1.
656d39a76e7Sxw 		 */
657d39a76e7Sxw 		if (rv != DDI_SUCCESS) {
658d39a76e7Sxw 			cmn_err(CE_NOTE, "MTU > 1500 not supported by GLD.\n");
659d39a76e7Sxw 			cmn_err(CE_NOTE, "Setting MTU to 1500. \n");
660d39a76e7Sxw 			macinfo->gldm_maxpkt = chp->ch_mtu = 1500;
661d39a76e7Sxw 			rv = gld_register(
66219397407SSherry Moore 			    dip,	/* ptr to dev's dev_info struct */
66319397407SSherry Moore 			    (char *)ddi_driver_name(dip), /* driver name */
66419397407SSherry Moore 			    macinfo); /* ptr to gld macinfo buffer */
665d39a76e7Sxw 		}
666d39a76e7Sxw 
667d39a76e7Sxw 
668d39a76e7Sxw 		if (rv != DDI_SUCCESS) {
669d39a76e7Sxw 			PRINT(("gld_register failed\n"));
670d39a76e7Sxw 			DEBUG_ENTER("ch_attach");
671d39a76e7Sxw 
672d39a76e7Sxw 			cmn_err(CE_WARN, "%s: gld_register error %d\n",
67319397407SSherry Moore 			    chp->ch_name, rv);
674d39a76e7Sxw 
675d39a76e7Sxw 			pe_detach(chp);
676d39a76e7Sxw 
677d39a76e7Sxw 			mutex_destroy(&chp->ch_lock);
678d39a76e7Sxw 			mutex_destroy(&chp->ch_intr);
679d39a76e7Sxw 			mutex_destroy(&chp->ch_mc_lck);
680d39a76e7Sxw 			mutex_destroy(&chp->ch_dh_lck);
681d39a76e7Sxw 			mutex_destroy(&chp->mac_lock);
682d39a76e7Sxw 			ddi_remove_intr(dip, 0, chp->ch_icookp);
683d39a76e7Sxw 			ddi_regs_map_free(&chp->ch_hbar0);
684d39a76e7Sxw 			pci_config_teardown(&chp->ch_hpci);
685d39a76e7Sxw 			ch_free_name(chp);
686d39a76e7Sxw 			kmem_free(chp, sizeof (ch_t));
687d39a76e7Sxw 			gld_mac_free(macinfo);
688d39a76e7Sxw 
689d39a76e7Sxw 			return (DDI_FAILURE);
690d39a76e7Sxw 		}
691d39a76e7Sxw 
692d39a76e7Sxw 		/*
693d39a76e7Sxw 		 * print a banner at boot time (verbose mode), announcing
694d39a76e7Sxw 		 * the device pointed to by dip
695d39a76e7Sxw 		 */
696d39a76e7Sxw 		ddi_report_dev(dip);
697d39a76e7Sxw 
698d39a76e7Sxw 		if (ch_abort_debug)
699d39a76e7Sxw 			debug_enter("ch_attach");
700d39a76e7Sxw 
701d39a76e7Sxw 		return (DDI_SUCCESS);
702d39a76e7Sxw 
703d39a76e7Sxw 	} else if (cmd == DDI_RESUME) {
704d39a76e7Sxw 		PRINT(("attach resume\n"));
705d39a76e7Sxw 		DEBUG_ENTER("ch_attach");
706d39a76e7Sxw 		if ((chp = (ch_t *)ddi_get_driver_private(dip)) == NULL)
707d39a76e7Sxw 			return (DDI_FAILURE);
708d39a76e7Sxw 
709d39a76e7Sxw 		mutex_enter(&chp->ch_lock);
710d39a76e7Sxw 		chp->ch_flags &= ~PESUSPENDED;
711d39a76e7Sxw 		mutex_exit(&chp->ch_lock);
712d39a76e7Sxw 		return (DDI_SUCCESS);
713d39a76e7Sxw 	} else {
714d39a76e7Sxw 		PRINT(("attach: bad command\n"));
715d39a76e7Sxw 		DEBUG_ENTER("ch_attach");
716d39a76e7Sxw 
717d39a76e7Sxw 		return (DDI_FAILURE);
718d39a76e7Sxw 	}
719d39a76e7Sxw }
720d39a76e7Sxw 
72119397407SSherry Moore /*
72219397407SSherry Moore  * quiesce(9E) entry point.
72319397407SSherry Moore  *
72419397407SSherry Moore  * This function is called when the system is single-threaded at high
72519397407SSherry Moore  * PIL with preemption disabled. Therefore, this function must not be
72619397407SSherry Moore  * blocked.
72719397407SSherry Moore  *
72819397407SSherry Moore  * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
72919397407SSherry Moore  * DDI_FAILURE indicates an error condition and should almost never happen.
73019397407SSherry Moore  */
73119397407SSherry Moore static int
ch_quiesce(dev_info_t * dip)73219397407SSherry Moore ch_quiesce(dev_info_t *dip)
73319397407SSherry Moore {
73419397407SSherry Moore 	ch_t *chp;
73519397407SSherry Moore 	gld_mac_info_t *macinfo =
73619397407SSherry Moore 	    (gld_mac_info_t *)ddi_get_driver_private(dip);
73719397407SSherry Moore 
73819397407SSherry Moore 	chp = (ch_t *)macinfo->gldm_private;
73919397407SSherry Moore 	chdebug = 0;
74019397407SSherry Moore 	ch_abort_debug = 0;
74119397407SSherry Moore 
74219397407SSherry Moore #ifdef CONFIG_CHELSIO_T1_OFFLOAD
74319397407SSherry Moore 	gchp[chp->ch_unit] = NULL;
74419397407SSherry Moore #endif
74519397407SSherry Moore 
74619397407SSherry Moore 	/* Set driver state for this card to IDLE */
74719397407SSherry Moore 	chp->ch_state = PEIDLE;
74819397407SSherry Moore 
74919397407SSherry Moore 	/*
75019397407SSherry Moore 	 * Do a power reset of card
75119397407SSherry Moore 	 * 1. set PwrState to D3hot (3)
75219397407SSherry Moore 	 * 2. clear PwrState flags
75319397407SSherry Moore 	 */
75419397407SSherry Moore 	pci_config_put32(chp->ch_hpci, 0x44, 3);
75519397407SSherry Moore 	pci_config_put32(chp->ch_hpci, 0x44, 0);
75619397407SSherry Moore 
75719397407SSherry Moore 	/* Wait 0.5 sec */
75819397407SSherry Moore 	drv_usecwait(500000);
75919397407SSherry Moore 
76019397407SSherry Moore 	/*
76119397407SSherry Moore 	 * Now stop the chip
76219397407SSherry Moore 	 */
76319397407SSherry Moore 	chp->ch_refcnt = 0;
76419397407SSherry Moore 	chp->ch_state = PESTOP;
76519397407SSherry Moore 
76619397407SSherry Moore 	/* Disables all interrupts */
76719397407SSherry Moore 	t1_interrupts_disable(chp);
76819397407SSherry Moore 
76919397407SSherry Moore 	/* Disables SGE queues */
77019397407SSherry Moore 	t1_write_reg_4(chp->sge->obj, A_SG_CONTROL, 0x0);
77119397407SSherry Moore 	t1_write_reg_4(chp->sge->obj, A_SG_INT_CAUSE, 0x0);
77219397407SSherry Moore 
77319397407SSherry Moore 	return (DDI_SUCCESS);
77419397407SSherry Moore }
77519397407SSherry Moore 
776d39a76e7Sxw static int
ch_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)777d39a76e7Sxw ch_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
778d39a76e7Sxw {
779d39a76e7Sxw 	gld_mac_info_t *macinfo;
780d39a76e7Sxw 	ch_t *chp;
781d39a76e7Sxw 
782d39a76e7Sxw 	if (cmd == DDI_DETACH) {
783d39a76e7Sxw 		macinfo = (gld_mac_info_t *)ddi_get_driver_private(dip);
784d39a76e7Sxw 		chp = (ch_t *)macinfo->gldm_private;
785d39a76e7Sxw 
786d39a76e7Sxw 		/*
787d39a76e7Sxw 		 * fail detach if there are outstanding mblks still
788d39a76e7Sxw 		 * in use somewhere.
789d39a76e7Sxw 		 */
790d39a76e7Sxw 		DEBUG_ENTER("ch_detach");
791d39a76e7Sxw #ifdef CONFIG_CHELSIO_T1_OFFLOAD
792d39a76e7Sxw 		mutex_enter(&chp->ch_lock);
793d39a76e7Sxw 		if (chp->ch_refcnt > 0) {
794d39a76e7Sxw 			mutex_exit(&chp->ch_lock);
795d39a76e7Sxw 			return (DDI_FAILURE);
796d39a76e7Sxw 		}
797d39a76e7Sxw 		mutex_exit(&chp->ch_lock);
798d39a76e7Sxw 		gchp[chp->ch_unit] = NULL;
799d39a76e7Sxw #endif
800d39a76e7Sxw 		/*
801d39a76e7Sxw 		 * set driver state for this card to IDLE. We're
802d39a76e7Sxw 		 * shutting down.
803d39a76e7Sxw 		 */
804d39a76e7Sxw 		mutex_enter(&chp->ch_lock);
805d39a76e7Sxw 		chp->ch_state = PEIDLE;
806d39a76e7Sxw 		mutex_exit(&chp->ch_lock);
807d39a76e7Sxw 
808d39a76e7Sxw 		/*
809d39a76e7Sxw 		 * do a power reset of card
810d39a76e7Sxw 		 *
811d39a76e7Sxw 		 * 1. set PwrState to D3hot (3)
812d39a76e7Sxw 		 * 2. clear PwrState flags
813d39a76e7Sxw 		 */
814d39a76e7Sxw 		pci_config_put32(chp->ch_hpci, 0x44, 3);
815d39a76e7Sxw 		pci_config_put32(chp->ch_hpci, 0x44, 0);
816d39a76e7Sxw 
817d39a76e7Sxw 		/* delay .5 sec */
818d39a76e7Sxw 		DELAY(500000);
819d39a76e7Sxw 
820d39a76e7Sxw 		/* free register resources */
821d39a76e7Sxw 		(void) gld_unregister(macinfo);
822d39a76e7Sxw 
823d39a76e7Sxw 		/* make sure no interrupts while shutting down card */
824d39a76e7Sxw 		ddi_remove_intr(dip, 0, chp->ch_icookp);
825d39a76e7Sxw 
826d39a76e7Sxw 		/*
827d39a76e7Sxw 		 * reset device and recover resources
828d39a76e7Sxw 		 */
829d39a76e7Sxw 		pe_detach(chp);
830d39a76e7Sxw 
831d39a76e7Sxw 		ddi_regs_map_free(&chp->ch_hbar0);
832d39a76e7Sxw 		pci_config_teardown(&chp->ch_hpci);
833d39a76e7Sxw 		mutex_destroy(&chp->ch_lock);
834d39a76e7Sxw 		mutex_destroy(&chp->ch_intr);
835d39a76e7Sxw 		mutex_destroy(&chp->ch_mc_lck);
836d39a76e7Sxw 		mutex_destroy(&chp->ch_dh_lck);
837d39a76e7Sxw 		mutex_destroy(&chp->mac_lock);
838d39a76e7Sxw 		ch_free_dma_handles(chp);
839d39a76e7Sxw #if defined(__sparc)
840d39a76e7Sxw 		ch_free_dvma_handles(chp);
841d39a76e7Sxw #endif
842d39a76e7Sxw 		ch_free_name(chp);
843d39a76e7Sxw 		kmem_free(chp, sizeof (ch_t));
844d39a76e7Sxw 		gld_mac_free(macinfo);
845d39a76e7Sxw 
846d39a76e7Sxw 		DEBUG_ENTER("ch_detach end");
847d39a76e7Sxw 
848d39a76e7Sxw 		return (DDI_SUCCESS);
849d39a76e7Sxw 
850d39a76e7Sxw 	} else if ((cmd == DDI_SUSPEND) || (cmd == DDI_PM_SUSPEND)) {
851d39a76e7Sxw 		DEBUG_ENTER("suspend");
852d39a76e7Sxw 		if ((chp = (ch_t *)ddi_get_driver_private(dip)) == NULL)
853d39a76e7Sxw 			return (DDI_FAILURE);
854d39a76e7Sxw 		mutex_enter(&chp->ch_lock);
855d39a76e7Sxw 		chp->ch_flags |= PESUSPENDED;
856d39a76e7Sxw 		mutex_exit(&chp->ch_lock);
857d39a76e7Sxw #ifdef TODO
858d39a76e7Sxw 		/* Un-initialize (STOP) T101 */
859d39a76e7Sxw #endif
860d39a76e7Sxw 		return (DDI_SUCCESS);
861d39a76e7Sxw 	} else
862d39a76e7Sxw 		return (DDI_FAILURE);
863d39a76e7Sxw }
864d39a76e7Sxw 
865d39a76e7Sxw /*
866d39a76e7Sxw  * ch_alloc_dma_mem
867d39a76e7Sxw  *
868d39a76e7Sxw  * allocates DMA handle
869d39a76e7Sxw  * allocates kernel memory
870d39a76e7Sxw  * allocates DMA access handle
871d39a76e7Sxw  *
872d39a76e7Sxw  * chp - per-board descriptor
873d39a76e7Sxw  * type - byteswap mapping?
874d39a76e7Sxw  * flags - type of mapping
875d39a76e7Sxw  * size - # bytes mapped
876d39a76e7Sxw  * paddr - physical address
877d39a76e7Sxw  * dh - ddi dma handle
878d39a76e7Sxw  * ah - ddi access handle
879d39a76e7Sxw  */
880d39a76e7Sxw 
881d39a76e7Sxw void *
ch_alloc_dma_mem(ch_t * chp,int type,int flags,int size,uint64_t * paddr,ulong_t * dh,ulong_t * ah)882d39a76e7Sxw ch_alloc_dma_mem(ch_t *chp, int type, int flags, int size, uint64_t *paddr,
883d39a76e7Sxw 	ulong_t *dh, ulong_t *ah)
884d39a76e7Sxw {
885d39a76e7Sxw 	ddi_dma_attr_t ch_dma_attr;
886d39a76e7Sxw 	ddi_dma_cookie_t cookie;
887d39a76e7Sxw 	ddi_dma_handle_t ch_dh;
888d39a76e7Sxw 	ddi_acc_handle_t ch_ah;
889d39a76e7Sxw 	ddi_device_acc_attr_t *dev_attrp;
890d39a76e7Sxw 	caddr_t ch_vaddr;
891d39a76e7Sxw 	size_t rlen;
892d39a76e7Sxw 	uint_t count;
893d39a76e7Sxw 	uint_t mapping;
894d39a76e7Sxw 	uint_t align;
895d39a76e7Sxw 	uint_t rv;
896d39a76e7Sxw 	uint_t direction;
897d39a76e7Sxw 
898d39a76e7Sxw 	mapping = (flags&DMA_STREAM)?DDI_DMA_STREAMING:DDI_DMA_CONSISTENT;
899d39a76e7Sxw 	if (flags & DMA_4KALN)
900d39a76e7Sxw 		align = 0x4000;
901d39a76e7Sxw 	else if (flags & DMA_SMALN)
902d39a76e7Sxw 		align = chp->ch_sm_buf_aln;
903d39a76e7Sxw 	else if (flags & DMA_BGALN)
904d39a76e7Sxw 		align = chp->ch_bg_buf_aln;
905d39a76e7Sxw 	else {
906d39a76e7Sxw 		cmn_err(CE_WARN, "ch_alloc_dma_mem(%s): bad alignment flag\n",
907d39a76e7Sxw 		    chp->ch_name);
908d39a76e7Sxw 		return (0);
909d39a76e7Sxw 	}
910d39a76e7Sxw 	direction = (flags&DMA_OUT)?DDI_DMA_WRITE:DDI_DMA_READ;
911d39a76e7Sxw 
912d39a76e7Sxw 	/*
913d39a76e7Sxw 	 * dynamically create a dma attribute structure
914d39a76e7Sxw 	 */
915d39a76e7Sxw 	ch_dma_attr.dma_attr_version = DMA_ATTR_V0;
916d39a76e7Sxw 	ch_dma_attr.dma_attr_addr_lo = 0;
917d39a76e7Sxw 	ch_dma_attr.dma_attr_addr_hi = 0xffffffffffffffff;
918d39a76e7Sxw 	ch_dma_attr.dma_attr_count_max = 0x00ffffff;
919d39a76e7Sxw 	ch_dma_attr.dma_attr_align = align;
920d39a76e7Sxw 	ch_dma_attr.dma_attr_burstsizes = 0xfff;
921d39a76e7Sxw 	ch_dma_attr.dma_attr_minxfer = 1;
922d39a76e7Sxw 	ch_dma_attr.dma_attr_maxxfer = 0x00ffffff;
923d39a76e7Sxw 	ch_dma_attr.dma_attr_seg = 0xffffffff;
924d39a76e7Sxw 	ch_dma_attr.dma_attr_sgllen = 1;
925d39a76e7Sxw 	ch_dma_attr.dma_attr_granular = 1;
926d39a76e7Sxw 	ch_dma_attr.dma_attr_flags = 0;
927d39a76e7Sxw 
928d39a76e7Sxw 	rv = ddi_dma_alloc_handle(
929d39a76e7Sxw 	    chp->ch_dip,		/* device dev_info structure */
930d39a76e7Sxw 	    &ch_dma_attr,		/* DMA attributes */
931d39a76e7Sxw 	    DDI_DMA_SLEEP,		/* Wait if no memory */
932d39a76e7Sxw 	    NULL,			/* no argument to callback */
933d39a76e7Sxw 	    &ch_dh);			/* DMA handle */
934d39a76e7Sxw 	if (rv != DDI_SUCCESS) {
935d39a76e7Sxw 
936d39a76e7Sxw 		cmn_err(CE_WARN,
93719397407SSherry Moore 		    "%s: ch_alloc_dma_mem: ddi_dma_alloc_handle error %d\n",
93819397407SSherry Moore 		    chp->ch_name, rv);
939d39a76e7Sxw 
940d39a76e7Sxw 		return (0);
941d39a76e7Sxw 	}
942d39a76e7Sxw 
943d39a76e7Sxw 	/* set byte order for data xfer */
944d39a76e7Sxw 	if (type)
945d39a76e7Sxw 		dev_attrp = &null_attr;
946d39a76e7Sxw 	else
947d39a76e7Sxw 		dev_attrp = &le_attr;
948d39a76e7Sxw 
949d39a76e7Sxw 	rv = ddi_dma_mem_alloc(
950d39a76e7Sxw 	    ch_dh,		/* dma handle */
951d39a76e7Sxw 	    size,		/* size desired allocate */
952d39a76e7Sxw 	    dev_attrp,		/* access attributes */
953d39a76e7Sxw 	    mapping,
954d39a76e7Sxw 	    DDI_DMA_SLEEP,	/* wait for resources */
955d39a76e7Sxw 	    NULL,		/* no argument */
956d39a76e7Sxw 	    &ch_vaddr,		/* allocated memory */
957d39a76e7Sxw 	    &rlen,		/* real size allocated */
958d39a76e7Sxw 	    &ch_ah);		/* data access handle */
959d39a76e7Sxw 	if (rv != DDI_SUCCESS) {
960d39a76e7Sxw 		ddi_dma_free_handle(&ch_dh);
961d39a76e7Sxw 
962d39a76e7Sxw 		cmn_err(CE_WARN,
96319397407SSherry Moore 		    "%s: ch_alloc_dma_mem: ddi_dma_mem_alloc error %d\n",
96419397407SSherry Moore 		    chp->ch_name, rv);
965d39a76e7Sxw 
966d39a76e7Sxw 		return (0);
967d39a76e7Sxw 	}
968d39a76e7Sxw 
969d39a76e7Sxw 	rv = ddi_dma_addr_bind_handle(
970d39a76e7Sxw 	    ch_dh,				/* dma handle */
971d39a76e7Sxw 	    (struct as *)0,			/* kernel address space */
972d39a76e7Sxw 	    ch_vaddr,				/* virtual address */
973d39a76e7Sxw 	    rlen,				/* length of object */
974d39a76e7Sxw 	    direction|mapping,
975d39a76e7Sxw 	    DDI_DMA_SLEEP,			/* Wait for resources */
976d39a76e7Sxw 	    NULL,				/* no argument */
977d39a76e7Sxw 	    &cookie,				/* dma cookie */
978d39a76e7Sxw 	    &count);
979d39a76e7Sxw 	if (rv != DDI_DMA_MAPPED) {
980d39a76e7Sxw 		ddi_dma_mem_free(&ch_ah);
981d39a76e7Sxw 		ddi_dma_free_handle(&ch_dh);
982d39a76e7Sxw 
983d39a76e7Sxw 		cmn_err(CE_WARN,
984d39a76e7Sxw 		    "%s: ch_alloc_dma_mem: ddi_dma_addr_bind_handle error %d\n",
98519397407SSherry Moore 		    chp->ch_name, rv);
986d39a76e7Sxw 
987d39a76e7Sxw 		return (0);
988d39a76e7Sxw 	}
989d39a76e7Sxw 
990d39a76e7Sxw 	if (count != 1) {
991d39a76e7Sxw 		cmn_err(CE_WARN,
992d39a76e7Sxw 		    "%s: ch_alloc_dma_mem: ch_alloc_dma_mem cookie count %d\n",
99319397407SSherry Moore 		    chp->ch_name, count);
994d39a76e7Sxw 		PRINT(("ch_alloc_dma_mem cookie count %d\n", count));
995d39a76e7Sxw 
996d39a76e7Sxw 		ddi_dma_mem_free(&ch_ah);
997d39a76e7Sxw 		ddi_dma_free_handle(&ch_dh);
998d39a76e7Sxw 
999d39a76e7Sxw 		return (0);
1000d39a76e7Sxw 	}
1001d39a76e7Sxw 
1002d39a76e7Sxw 	*paddr = cookie.dmac_laddress;
1003d39a76e7Sxw 
1004d39a76e7Sxw 	*(ddi_dma_handle_t *)dh = ch_dh;
1005d39a76e7Sxw 	*(ddi_acc_handle_t *)ah = ch_ah;
1006d39a76e7Sxw 
1007d39a76e7Sxw 	return ((void *)ch_vaddr);
1008d39a76e7Sxw }
1009d39a76e7Sxw 
1010d39a76e7Sxw /*
1011d39a76e7Sxw  * ch_free_dma_mem
1012d39a76e7Sxw  *
1013d39a76e7Sxw  * frees resources allocated by ch_alloc_dma_mem()
1014d39a76e7Sxw  *
1015d39a76e7Sxw  * frees DMA handle
1016d39a76e7Sxw  * frees kernel memory
1017d39a76e7Sxw  * frees DMA access handle
1018d39a76e7Sxw  */
1019d39a76e7Sxw 
1020d39a76e7Sxw void
ch_free_dma_mem(ulong_t dh,ulong_t ah)1021d39a76e7Sxw ch_free_dma_mem(ulong_t dh, ulong_t ah)
1022d39a76e7Sxw {
1023d39a76e7Sxw 	ddi_dma_handle_t ch_dh = (ddi_dma_handle_t)dh;
1024d39a76e7Sxw 	ddi_acc_handle_t ch_ah = (ddi_acc_handle_t)ah;
1025d39a76e7Sxw 
1026d39a76e7Sxw 	(void) ddi_dma_unbind_handle(ch_dh);
1027d39a76e7Sxw 	ddi_dma_mem_free(&ch_ah);
1028d39a76e7Sxw 	ddi_dma_free_handle(&ch_dh);
1029d39a76e7Sxw }
1030d39a76e7Sxw 
1031d39a76e7Sxw /*
1032d39a76e7Sxw  * create a dma handle and return a dma handle entry.
1033d39a76e7Sxw  */
1034d39a76e7Sxw free_dh_t *
ch_get_dma_handle(ch_t * chp)1035d39a76e7Sxw ch_get_dma_handle(ch_t *chp)
1036d39a76e7Sxw {
1037d39a76e7Sxw 	ddi_dma_handle_t ch_dh;
1038d39a76e7Sxw 	ddi_dma_attr_t ch_dma_attr;
1039d39a76e7Sxw 	free_dh_t *dhe;
1040d39a76e7Sxw 	int rv;
1041d39a76e7Sxw 
1042d39a76e7Sxw 	dhe = (free_dh_t *)kmem_zalloc(sizeof (*dhe), KM_SLEEP);
1043d39a76e7Sxw 
1044d39a76e7Sxw 	ch_dma_attr.dma_attr_version = DMA_ATTR_V0;
1045d39a76e7Sxw 	ch_dma_attr.dma_attr_addr_lo = 0;
1046d39a76e7Sxw 	ch_dma_attr.dma_attr_addr_hi = 0xffffffffffffffff;
1047d39a76e7Sxw 	ch_dma_attr.dma_attr_count_max = 0x00ffffff;
1048d39a76e7Sxw 	ch_dma_attr.dma_attr_align = 1;
1049d39a76e7Sxw 	ch_dma_attr.dma_attr_burstsizes = 0xfff;
1050d39a76e7Sxw 	ch_dma_attr.dma_attr_minxfer = 1;
1051d39a76e7Sxw 	ch_dma_attr.dma_attr_maxxfer = 0x00ffffff;
1052d39a76e7Sxw 	ch_dma_attr.dma_attr_seg = 0xffffffff;
1053d39a76e7Sxw 	ch_dma_attr.dma_attr_sgllen = 5;
1054d39a76e7Sxw 	ch_dma_attr.dma_attr_granular = 1;
1055d39a76e7Sxw 	ch_dma_attr.dma_attr_flags = 0;
1056d39a76e7Sxw 
1057d39a76e7Sxw 	rv = ddi_dma_alloc_handle(
1058d39a76e7Sxw 	    chp->ch_dip,		/* device dev_info */
1059d39a76e7Sxw 	    &ch_dma_attr,		/* DMA attributes */
1060d39a76e7Sxw 	    DDI_DMA_SLEEP,		/* Wait if no memory */
1061d39a76e7Sxw 	    NULL,			/* no argument */
1062d39a76e7Sxw 	    &ch_dh);			/* DMA handle */
1063d39a76e7Sxw 	if (rv != DDI_SUCCESS) {
1064d39a76e7Sxw 
1065d39a76e7Sxw 		cmn_err(CE_WARN,
1066d39a76e7Sxw 		    "%s: ch_get_dma_handle: ddi_dma_alloc_handle error %d\n",
106719397407SSherry Moore 		    chp->ch_name, rv);
1068d39a76e7Sxw 
1069d39a76e7Sxw 		kmem_free(dhe, sizeof (*dhe));
1070d39a76e7Sxw 
1071d39a76e7Sxw 		return ((free_dh_t *)0);
1072d39a76e7Sxw 	}
1073d39a76e7Sxw 
1074d39a76e7Sxw 	dhe->dhe_dh = (ulong_t)ch_dh;
1075d39a76e7Sxw 
1076d39a76e7Sxw 	return (dhe);
1077d39a76e7Sxw }
1078d39a76e7Sxw 
1079d39a76e7Sxw /*
1080d39a76e7Sxw  * free the linked list of dma descriptor entries.
1081d39a76e7Sxw  */
1082d39a76e7Sxw static void
ch_free_dma_handles(ch_t * chp)1083d39a76e7Sxw ch_free_dma_handles(ch_t *chp)
1084d39a76e7Sxw {
1085d39a76e7Sxw 	free_dh_t *dhe, *the;
1086d39a76e7Sxw 
1087d39a76e7Sxw 	dhe = chp->ch_dh;
1088d39a76e7Sxw 	while (dhe) {
1089d39a76e7Sxw 		ddi_dma_free_handle((ddi_dma_handle_t *)&dhe->dhe_dh);
1090d39a76e7Sxw 		the = dhe;
1091d39a76e7Sxw 		dhe = dhe->dhe_next;
1092d39a76e7Sxw 		kmem_free(the, sizeof (*the));
1093d39a76e7Sxw 	}
1094d39a76e7Sxw 	chp->ch_dh = NULL;
1095d39a76e7Sxw }
1096d39a76e7Sxw 
1097d39a76e7Sxw /*
1098d39a76e7Sxw  * ch_bind_dma_handle()
1099d39a76e7Sxw  *
1100d39a76e7Sxw  * returns # of entries used off of cmdQ_ce_t array to hold physical addrs.
1101d39a76e7Sxw  *
1102d39a76e7Sxw  * chp - per-board descriptor
1103d39a76e7Sxw  * size - # bytes mapped
1104d39a76e7Sxw  * vaddr - virtual address
1105d39a76e7Sxw  * cmp - array of cmdQ_ce_t entries
1106d39a76e7Sxw  * cnt - # free entries in cmp array
1107d39a76e7Sxw  */
1108d39a76e7Sxw 
1109d39a76e7Sxw uint32_t
ch_bind_dma_handle(ch_t * chp,int size,caddr_t vaddr,cmdQ_ce_t * cmp,uint32_t cnt)1110d39a76e7Sxw ch_bind_dma_handle(ch_t *chp, int size, caddr_t vaddr, cmdQ_ce_t *cmp,
1111d39a76e7Sxw 	uint32_t cnt)
1112d39a76e7Sxw {
1113d39a76e7Sxw 	ddi_dma_cookie_t cookie;
1114d39a76e7Sxw 	ddi_dma_handle_t ch_dh;
1115d39a76e7Sxw 	uint_t count;
1116d39a76e7Sxw 	uint32_t n = 1;
1117d39a76e7Sxw 	free_dh_t *dhe;
1118d39a76e7Sxw 	uint_t rv;
1119d39a76e7Sxw 
1120d39a76e7Sxw 	mutex_enter(&chp->ch_dh_lck);
1121d39a76e7Sxw 	if ((dhe = chp->ch_dh) != NULL) {
1122d39a76e7Sxw 		chp->ch_dh = dhe->dhe_next;
1123d39a76e7Sxw 	}
1124d39a76e7Sxw 	mutex_exit(&chp->ch_dh_lck);
1125d39a76e7Sxw 
1126d39a76e7Sxw 	if (dhe == NULL) {
1127d39a76e7Sxw 		return (0);
1128d39a76e7Sxw 	}
1129d39a76e7Sxw 
1130d39a76e7Sxw 	ch_dh = (ddi_dma_handle_t)dhe->dhe_dh;
1131d39a76e7Sxw 
1132d39a76e7Sxw 	rv = ddi_dma_addr_bind_handle(
1133d39a76e7Sxw 	    ch_dh,		/* dma handle */
1134d39a76e7Sxw 	    (struct as *)0,	/* kernel address space */
1135d39a76e7Sxw 	    vaddr,		/* virtual address */
1136d39a76e7Sxw 	    size,		/* length of object */
1137d39a76e7Sxw 	    DDI_DMA_WRITE|DDI_DMA_STREAMING,
1138d39a76e7Sxw 	    DDI_DMA_SLEEP,	/* Wait for resources */
1139d39a76e7Sxw 	    NULL,		/* no argument */
1140d39a76e7Sxw 	    &cookie,	/* dma cookie */
1141d39a76e7Sxw 	    &count);
1142d39a76e7Sxw 	if (rv != DDI_DMA_MAPPED) {
1143d39a76e7Sxw 
1144d39a76e7Sxw 		/* return dma header descriptor back to free list */
1145d39a76e7Sxw 		mutex_enter(&chp->ch_dh_lck);
1146d39a76e7Sxw 		dhe->dhe_next = chp->ch_dh;
1147d39a76e7Sxw 		chp->ch_dh = dhe;
1148d39a76e7Sxw 		mutex_exit(&chp->ch_dh_lck);
1149d39a76e7Sxw 
1150d39a76e7Sxw 		cmn_err(CE_WARN,
1151d39a76e7Sxw 		    "%s: ch_bind_dma_handle: ddi_dma_addr_bind_handle err %d\n",
115219397407SSherry Moore 		    chp->ch_name, rv);
1153d39a76e7Sxw 
1154d39a76e7Sxw 		return (0);
1155d39a76e7Sxw 	}
1156d39a76e7Sxw 
1157d39a76e7Sxw 	/*
1158d39a76e7Sxw 	 * abort if we've run out of space
1159d39a76e7Sxw 	 */
1160d39a76e7Sxw 	if (count > cnt) {
1161d39a76e7Sxw 		/* return dma header descriptor back to free list */
1162d39a76e7Sxw 		mutex_enter(&chp->ch_dh_lck);
1163d39a76e7Sxw 		dhe->dhe_next = chp->ch_dh;
1164d39a76e7Sxw 		chp->ch_dh = dhe;
1165d39a76e7Sxw 		mutex_exit(&chp->ch_dh_lck);
1166d39a76e7Sxw 
1167d39a76e7Sxw 		return (0);
1168d39a76e7Sxw 	}
1169d39a76e7Sxw 
1170d39a76e7Sxw 	cmp->ce_pa = cookie.dmac_laddress;
1171d39a76e7Sxw 	cmp->ce_dh = NULL;
1172d39a76e7Sxw 	cmp->ce_len = cookie.dmac_size;
1173d39a76e7Sxw 	cmp->ce_mp = NULL;
1174d39a76e7Sxw 	cmp->ce_flg = DH_DMA;
1175d39a76e7Sxw 
1176d39a76e7Sxw 	while (--count) {
1177d39a76e7Sxw 		cmp++;
1178d39a76e7Sxw 		n++;
1179d39a76e7Sxw 		ddi_dma_nextcookie(ch_dh, &cookie);
1180d39a76e7Sxw 		cmp->ce_pa = cookie.dmac_laddress;
1181d39a76e7Sxw 		cmp->ce_dh = NULL;
1182d39a76e7Sxw 		cmp->ce_len = cookie.dmac_size;
1183d39a76e7Sxw 		cmp->ce_mp = NULL;
1184d39a76e7Sxw 		cmp->ce_flg = DH_DMA;
1185d39a76e7Sxw 	}
1186d39a76e7Sxw 
1187d39a76e7Sxw 	cmp->ce_dh = dhe;
1188d39a76e7Sxw 
1189d39a76e7Sxw 	return (n);
1190d39a76e7Sxw }
1191d39a76e7Sxw 
1192d39a76e7Sxw /*
1193d39a76e7Sxw  * ch_unbind_dma_handle()
1194d39a76e7Sxw  *
1195d39a76e7Sxw  * frees resources alloacted by ch_bind_dma_handle().
1196d39a76e7Sxw  *
1197d39a76e7Sxw  * frees DMA handle
1198d39a76e7Sxw  */
1199d39a76e7Sxw 
1200d39a76e7Sxw void
ch_unbind_dma_handle(ch_t * chp,free_dh_t * dhe)1201d39a76e7Sxw ch_unbind_dma_handle(ch_t *chp, free_dh_t *dhe)
1202d39a76e7Sxw {
1203d39a76e7Sxw 	ddi_dma_handle_t ch_dh = (ddi_dma_handle_t)dhe->dhe_dh;
1204d39a76e7Sxw 
1205d39a76e7Sxw 	if (ddi_dma_unbind_handle(ch_dh))
1206d39a76e7Sxw 		cmn_err(CE_WARN, "%s: ddi_dma_unbind_handle failed",
120719397407SSherry Moore 		    chp->ch_name);
1208d39a76e7Sxw 
1209d39a76e7Sxw 	mutex_enter(&chp->ch_dh_lck);
1210d39a76e7Sxw 	dhe->dhe_next = chp->ch_dh;
1211d39a76e7Sxw 	chp->ch_dh = dhe;
1212d39a76e7Sxw 	mutex_exit(&chp->ch_dh_lck);
1213d39a76e7Sxw }
1214d39a76e7Sxw 
1215d39a76e7Sxw #if defined(__sparc)
1216d39a76e7Sxw /*
1217d39a76e7Sxw  * DVMA stuff. Solaris only.
1218d39a76e7Sxw  */
1219d39a76e7Sxw 
1220d39a76e7Sxw /*
1221d39a76e7Sxw  * create a dvma handle and return a dma handle entry.
1222d39a76e7Sxw  * DVMA is on sparc only!
1223d39a76e7Sxw  */
1224d39a76e7Sxw 
1225d39a76e7Sxw free_dh_t *
ch_get_dvma_handle(ch_t * chp)1226d39a76e7Sxw ch_get_dvma_handle(ch_t *chp)
1227d39a76e7Sxw {
1228d39a76e7Sxw 	ddi_dma_handle_t ch_dh;
1229d39a76e7Sxw 	ddi_dma_lim_t ch_dvma_attr;
1230d39a76e7Sxw 	free_dh_t *dhe;
1231d39a76e7Sxw 	int rv;
1232d39a76e7Sxw 
1233d39a76e7Sxw 	dhe = (free_dh_t *)kmem_zalloc(sizeof (*dhe), KM_SLEEP);
1234d39a76e7Sxw 
1235d39a76e7Sxw 	ch_dvma_attr.dlim_addr_lo = 0;
1236d39a76e7Sxw 	ch_dvma_attr.dlim_addr_hi = 0xffffffff;
1237d39a76e7Sxw 	ch_dvma_attr.dlim_cntr_max = 0xffffffff;
1238d39a76e7Sxw 	ch_dvma_attr.dlim_burstsizes = 0xfff;
1239d39a76e7Sxw 	ch_dvma_attr.dlim_minxfer = 1;
1240d39a76e7Sxw 	ch_dvma_attr.dlim_dmaspeed = 0;
1241d39a76e7Sxw 
1242d39a76e7Sxw 	rv = dvma_reserve(
124319397407SSherry Moore 	    chp->ch_dip,		/* device dev_info */
124419397407SSherry Moore 	    &ch_dvma_attr,		/* DVMA attributes */
124519397407SSherry Moore 	    3,			/* number of pages */
124619397407SSherry Moore 	    &ch_dh);		/* DVMA handle */
1247d39a76e7Sxw 
1248d39a76e7Sxw 	if (rv != DDI_SUCCESS) {
1249d39a76e7Sxw 
1250d39a76e7Sxw 		cmn_err(CE_WARN,
1251d39a76e7Sxw 		    "%s: ch_get_dvma_handle: dvma_reserve() error %d\n",
125219397407SSherry Moore 		    chp->ch_name, rv);
1253d39a76e7Sxw 
1254d39a76e7Sxw 		kmem_free(dhe, sizeof (*dhe));
1255d39a76e7Sxw 
1256d39a76e7Sxw 		return ((free_dh_t *)0);
1257d39a76e7Sxw 	}
1258d39a76e7Sxw 
1259d39a76e7Sxw 	dhe->dhe_dh = (ulong_t)ch_dh;
1260d39a76e7Sxw 
1261d39a76e7Sxw 	return (dhe);
1262d39a76e7Sxw }
1263d39a76e7Sxw 
1264d39a76e7Sxw /*
1265d39a76e7Sxw  * free the linked list of dvma descriptor entries.
1266d39a76e7Sxw  * DVMA is only on sparc!
1267d39a76e7Sxw  */
1268d39a76e7Sxw 
1269d39a76e7Sxw static void
ch_free_dvma_handles(ch_t * chp)1270d39a76e7Sxw ch_free_dvma_handles(ch_t *chp)
1271d39a76e7Sxw {
1272d39a76e7Sxw 	free_dh_t *dhe, *the;
1273d39a76e7Sxw 
1274d39a76e7Sxw 	dhe = chp->ch_vdh;
1275d39a76e7Sxw 	while (dhe) {
1276d39a76e7Sxw 		dvma_release((ddi_dma_handle_t)dhe->dhe_dh);
1277d39a76e7Sxw 		the = dhe;
1278d39a76e7Sxw 		dhe = dhe->dhe_next;
1279d39a76e7Sxw 		kmem_free(the, sizeof (*the));
1280d39a76e7Sxw 	}
1281d39a76e7Sxw 	chp->ch_vdh = NULL;
1282d39a76e7Sxw }
1283d39a76e7Sxw 
1284d39a76e7Sxw /*
1285d39a76e7Sxw  * ch_bind_dvma_handle()
1286d39a76e7Sxw  *
1287d39a76e7Sxw  * returns # of entries used off of cmdQ_ce_t array to hold physical addrs.
1288d39a76e7Sxw  * DVMA in sparc only
1289d39a76e7Sxw  *
1290d39a76e7Sxw  * chp - per-board descriptor
1291d39a76e7Sxw  * size - # bytes mapped
1292d39a76e7Sxw  * vaddr - virtual address
1293d39a76e7Sxw  * cmp - array of cmdQ_ce_t entries
1294d39a76e7Sxw  * cnt - # free entries in cmp array
1295d39a76e7Sxw  */
1296d39a76e7Sxw 
1297d39a76e7Sxw uint32_t
ch_bind_dvma_handle(ch_t * chp,int size,caddr_t vaddr,cmdQ_ce_t * cmp,uint32_t cnt)1298d39a76e7Sxw ch_bind_dvma_handle(ch_t *chp, int size, caddr_t vaddr, cmdQ_ce_t *cmp,
1299d39a76e7Sxw 	uint32_t cnt)
1300d39a76e7Sxw {
1301d39a76e7Sxw 	ddi_dma_cookie_t cookie;
1302d39a76e7Sxw 	ddi_dma_handle_t ch_dh;
1303d39a76e7Sxw 	uint32_t n = 1;
1304d39a76e7Sxw 	free_dh_t *dhe;
1305d39a76e7Sxw 
1306d39a76e7Sxw 	mutex_enter(&chp->ch_dh_lck);
1307d39a76e7Sxw 	if ((dhe = chp->ch_vdh) != NULL) {
1308d39a76e7Sxw 		chp->ch_vdh = dhe->dhe_next;
1309d39a76e7Sxw 	}
1310d39a76e7Sxw 	mutex_exit(&chp->ch_dh_lck);
1311d39a76e7Sxw 
1312d39a76e7Sxw 	if (dhe == NULL) {
1313d39a76e7Sxw 		return (0);
1314d39a76e7Sxw 	}
1315d39a76e7Sxw 
1316d39a76e7Sxw 	ch_dh = (ddi_dma_handle_t)dhe->dhe_dh;
1317d39a76e7Sxw 	n = cnt;
1318d39a76e7Sxw 
1319d39a76e7Sxw 	dvma_kaddr_load(
132019397407SSherry Moore 	    ch_dh,		/* dvma handle */
132119397407SSherry Moore 	    vaddr,		/* virtual address */
132219397407SSherry Moore 	    size,		/* length of object */
132319397407SSherry Moore 	    0,		/* start at index 0 */
132419397407SSherry Moore 	    &cookie);
1325d39a76e7Sxw 
1326d39a76e7Sxw 	dvma_sync(ch_dh, 0, DDI_DMA_SYNC_FORDEV);
1327d39a76e7Sxw 
1328d39a76e7Sxw 	cookie.dmac_notused = 0;
1329d39a76e7Sxw 	n = 1;
1330d39a76e7Sxw 
1331d39a76e7Sxw 	cmp->ce_pa = cookie.dmac_laddress;
1332d39a76e7Sxw 	cmp->ce_dh = dhe;
1333d39a76e7Sxw 	cmp->ce_len = cookie.dmac_size;
1334d39a76e7Sxw 	cmp->ce_mp = NULL;
1335d39a76e7Sxw 	cmp->ce_flg = DH_DVMA;	/* indicate a dvma descriptor */
1336d39a76e7Sxw 
1337d39a76e7Sxw 	return (n);
1338d39a76e7Sxw }
1339d39a76e7Sxw 
1340d39a76e7Sxw /*
1341d39a76e7Sxw  * ch_unbind_dvma_handle()
1342d39a76e7Sxw  *
1343d39a76e7Sxw  * frees resources alloacted by ch_bind_dvma_handle().
1344d39a76e7Sxw  *
1345d39a76e7Sxw  * frees DMA handle
1346d39a76e7Sxw  */
1347d39a76e7Sxw 
1348d39a76e7Sxw void
ch_unbind_dvma_handle(ch_t * chp,free_dh_t * dhe)1349d39a76e7Sxw ch_unbind_dvma_handle(ch_t *chp, free_dh_t *dhe)
1350d39a76e7Sxw {
1351d39a76e7Sxw 	ddi_dma_handle_t ch_dh = (ddi_dma_handle_t)dhe->dhe_dh;
1352d39a76e7Sxw 
1353d39a76e7Sxw 	dvma_unload(ch_dh, 0, -1);
1354d39a76e7Sxw 
1355d39a76e7Sxw 	mutex_enter(&chp->ch_dh_lck);
1356d39a76e7Sxw 	dhe->dhe_next = chp->ch_vdh;
1357d39a76e7Sxw 	chp->ch_vdh = dhe;
1358d39a76e7Sxw 	mutex_exit(&chp->ch_dh_lck);
1359d39a76e7Sxw }
1360d39a76e7Sxw 
1361d39a76e7Sxw #endif	/* defined(__sparc) */
1362d39a76e7Sxw 
1363d39a76e7Sxw /*
1364d39a76e7Sxw  * send received packet up stream.
1365d39a76e7Sxw  *
1366d39a76e7Sxw  * if driver has been stopped, then we drop the message.
1367d39a76e7Sxw  */
1368d39a76e7Sxw void
ch_send_up(ch_t * chp,mblk_t * mp,uint32_t cksum,int flg)1369d39a76e7Sxw ch_send_up(ch_t *chp, mblk_t *mp, uint32_t cksum, int flg)
1370d39a76e7Sxw {
1371d39a76e7Sxw 	/*
1372d39a76e7Sxw 	 * probably do not need a lock here. When we set PESTOP in
1373d39a76e7Sxw 	 * ch_stop() a packet could have just passed here and gone
1374d39a76e7Sxw 	 * upstream. The next one will be dropped.
1375d39a76e7Sxw 	 */
1376d39a76e7Sxw 	if (chp->ch_state == PERUNNING) {
1377d39a76e7Sxw 		/*
1378d39a76e7Sxw 		 * note that flg will not be set unless enable_checksum_offload
1379d39a76e7Sxw 		 * set in /etc/system (see sge.c).
1380d39a76e7Sxw 		 */
1381d39a76e7Sxw 		if (flg)
1382*ec71f88eSPatrick Mooney 			mac_hcksum_set(mp, 0, 0, 0, cksum, HCK_FULLCKSUM);
1383d39a76e7Sxw 		gld_recv(chp->ch_macp, mp);
1384d39a76e7Sxw 	} else {
1385d39a76e7Sxw 		freemsg(mp);
1386d39a76e7Sxw 	}
1387d39a76e7Sxw }
1388d39a76e7Sxw 
1389d39a76e7Sxw /*
1390d39a76e7Sxw  * unblock gld driver.
1391d39a76e7Sxw  */
1392d39a76e7Sxw void
ch_gld_ok(ch_t * chp)1393d39a76e7Sxw ch_gld_ok(ch_t *chp)
1394d39a76e7Sxw {
1395d39a76e7Sxw 	gld_sched(chp->ch_macp);
1396d39a76e7Sxw }
1397d39a76e7Sxw 
1398d39a76e7Sxw 
1399d39a76e7Sxw /*
1400d39a76e7Sxw  * reset the card.
1401d39a76e7Sxw  *
1402d39a76e7Sxw  * Note: we only do this after the card has been initialized.
1403d39a76e7Sxw  */
1404d39a76e7Sxw static int
ch_reset(gld_mac_info_t * mp)1405d39a76e7Sxw ch_reset(gld_mac_info_t *mp)
1406d39a76e7Sxw {
1407d39a76e7Sxw 	ch_t *chp;
1408d39a76e7Sxw 
1409d39a76e7Sxw 	if (mp == NULL) {
1410d39a76e7Sxw 		return (GLD_FAILURE);
1411d39a76e7Sxw 	}
1412d39a76e7Sxw 
1413d39a76e7Sxw 	chp = (ch_t *)mp->gldm_private;
1414d39a76e7Sxw 
1415d39a76e7Sxw 	if (chp == NULL) {
1416d39a76e7Sxw 		return (GLD_FAILURE);
1417d39a76e7Sxw 	}
1418d39a76e7Sxw 
1419d39a76e7Sxw #ifdef NOTYET
1420d39a76e7Sxw 	/*
1421d39a76e7Sxw 	 * do a reset of card
1422d39a76e7Sxw 	 *
1423d39a76e7Sxw 	 * 1. set PwrState to D3hot (3)
1424d39a76e7Sxw 	 * 2. clear PwrState flags
1425d39a76e7Sxw 	 */
1426d39a76e7Sxw 	/*
1427d39a76e7Sxw 	 * When we did this, the card didn't start. First guess is that
1428d39a76e7Sxw 	 * the initialization is not quite correct. For now, we don't
1429d39a76e7Sxw 	 * reset things.
1430d39a76e7Sxw 	 */
1431d39a76e7Sxw 	if (chp->ch_hpci) {
1432d39a76e7Sxw 		pci_config_put32(chp->ch_hpci, 0x44, 3);
1433d39a76e7Sxw 		pci_config_put32(chp->ch_hpci, 0x44, 0);
1434d39a76e7Sxw 
1435d39a76e7Sxw 		/* delay .5 sec */
1436d39a76e7Sxw 		DELAY(500000);
1437d39a76e7Sxw 	}
1438d39a76e7Sxw #endif
1439d39a76e7Sxw 
1440d39a76e7Sxw 	return (GLD_SUCCESS);
1441d39a76e7Sxw }
1442d39a76e7Sxw 
1443d39a76e7Sxw static int
ch_start(gld_mac_info_t * macinfo)1444d39a76e7Sxw ch_start(gld_mac_info_t *macinfo)
1445d39a76e7Sxw {
1446d39a76e7Sxw 	ch_t *chp = (ch_t *)macinfo->gldm_private;
1447d39a76e7Sxw #ifdef CONFIG_CHELSIO_T1_OFFLOAD
1448d39a76e7Sxw 	/* only initialize card on first attempt */
1449d39a76e7Sxw 	mutex_enter(&chp->ch_lock);
1450d39a76e7Sxw 	chp->ch_refcnt++;
1451d39a76e7Sxw 	if (chp->ch_refcnt == 1) {
1452d39a76e7Sxw 		chp->ch_state = PERUNNING;
1453d39a76e7Sxw 		mutex_exit(&chp->ch_lock);
1454d39a76e7Sxw 		pe_init((void *)chp);
1455d39a76e7Sxw 	} else
1456d39a76e7Sxw 		mutex_exit(&chp->ch_lock);
1457d39a76e7Sxw #else
1458d39a76e7Sxw 	pe_init((void *)chp);
1459d39a76e7Sxw 
1460d39a76e7Sxw 	/* go to running state, we're being started */
1461d39a76e7Sxw 	mutex_enter(&chp->ch_lock);
1462d39a76e7Sxw 	chp->ch_state = PERUNNING;
1463d39a76e7Sxw 	mutex_exit(&chp->ch_lock);
1464d39a76e7Sxw #endif
1465d39a76e7Sxw 
1466d39a76e7Sxw 	return (GLD_SUCCESS);
1467d39a76e7Sxw }
1468d39a76e7Sxw 
1469d39a76e7Sxw static int
ch_stop(gld_mac_info_t * mp)1470d39a76e7Sxw ch_stop(gld_mac_info_t *mp)
1471d39a76e7Sxw {
1472d39a76e7Sxw 	ch_t *chp = (ch_t *)mp->gldm_private;
1473d39a76e7Sxw 
1474d39a76e7Sxw 	/*
1475d39a76e7Sxw 	 * can only stop the chip if it's been initialized
1476d39a76e7Sxw 	 */
1477d39a76e7Sxw 	mutex_enter(&chp->ch_lock);
1478d39a76e7Sxw 	if (chp->ch_state == PEIDLE) {
1479d39a76e7Sxw 		mutex_exit(&chp->ch_lock);
1480d39a76e7Sxw 		return (GLD_FAILURE);
1481d39a76e7Sxw 	}
1482d39a76e7Sxw #ifdef CONFIG_CHELSIO_T1_OFFLOAD
1483d39a76e7Sxw 	chp->ch_refcnt--;
1484d39a76e7Sxw 	if (chp->ch_refcnt == 0) {
1485d39a76e7Sxw 		chp->ch_state = PESTOP;
1486d39a76e7Sxw 		mutex_exit(&chp->ch_lock);
1487d39a76e7Sxw 		pe_stop(chp);
1488d39a76e7Sxw 	} else
1489d39a76e7Sxw 		mutex_exit(&chp->ch_lock);
1490d39a76e7Sxw #else
1491d39a76e7Sxw 	chp->ch_state = PESTOP;
1492d39a76e7Sxw 	mutex_exit(&chp->ch_lock);
1493d39a76e7Sxw 	pe_stop(chp);
1494d39a76e7Sxw #endif
1495d39a76e7Sxw 	return (GLD_SUCCESS);
1496d39a76e7Sxw }
1497d39a76e7Sxw 
1498d39a76e7Sxw static int
ch_set_mac_address(gld_mac_info_t * mp,uint8_t * mac)1499d39a76e7Sxw ch_set_mac_address(gld_mac_info_t *mp, uint8_t *mac)
1500d39a76e7Sxw {
1501d39a76e7Sxw 	ch_t *chp;
1502d39a76e7Sxw 
1503d39a76e7Sxw 	if (mp) {
1504d39a76e7Sxw 		chp = (ch_t *)mp->gldm_private;
1505d39a76e7Sxw 	} else {
1506d39a76e7Sxw 		return (GLD_FAILURE);
1507d39a76e7Sxw 	}
1508d39a76e7Sxw 
1509d39a76e7Sxw 	pe_set_mac(chp, mac);
1510d39a76e7Sxw 
1511d39a76e7Sxw 	return (GLD_SUCCESS);
1512d39a76e7Sxw }
1513d39a76e7Sxw 
1514d39a76e7Sxw static int
ch_set_multicast(gld_mac_info_t * mp,uint8_t * ep,int flg)1515d39a76e7Sxw ch_set_multicast(gld_mac_info_t *mp, uint8_t *ep, int flg)
1516d39a76e7Sxw {
1517d39a76e7Sxw 	ch_t *chp = (ch_t *)mp->gldm_private;
1518d39a76e7Sxw 
1519d39a76e7Sxw 	return (pe_set_mc(chp, ep, flg));
1520d39a76e7Sxw }
1521d39a76e7Sxw 
1522d39a76e7Sxw static int
ch_ioctl(gld_mac_info_t * macinfo,queue_t * q,mblk_t * mp)1523d39a76e7Sxw ch_ioctl(gld_mac_info_t *macinfo, queue_t *q, mblk_t *mp)
1524d39a76e7Sxw {
1525d39a76e7Sxw 	struct iocblk *iocp;
1526d39a76e7Sxw 
1527d39a76e7Sxw 	switch (mp->b_datap->db_type) {
1528d39a76e7Sxw 	case M_IOCTL:
1529d39a76e7Sxw 		/* pe_ioctl() does qreply() */
1530d39a76e7Sxw 		pe_ioctl((ch_t *)(macinfo->gldm_private), q, mp);
1531d39a76e7Sxw 		break;
1532d39a76e7Sxw 
1533d39a76e7Sxw 	default:
1534d39a76e7Sxw /*
1535d39a76e7Sxw  *		cmn_err(CE_NOTE, "ch_ioctl not M_IOCTL\n");
1536d39a76e7Sxw  *		debug_enter("bad ch_ioctl");
1537d39a76e7Sxw  */
1538d39a76e7Sxw 
1539d39a76e7Sxw 		iocp = (struct iocblk *)mp->b_rptr;
1540d39a76e7Sxw 
1541d39a76e7Sxw 		if (mp->b_cont)
1542d39a76e7Sxw 			freemsg(mp->b_cont);
1543d39a76e7Sxw 		mp->b_cont = NULL;
1544d39a76e7Sxw 
1545d39a76e7Sxw 		mp->b_datap->db_type = M_IOCNAK;
1546d39a76e7Sxw 		iocp->ioc_error = EINVAL;
1547d39a76e7Sxw 		qreply(q, mp);
1548d39a76e7Sxw 		break;
1549d39a76e7Sxw 	}
1550d39a76e7Sxw 
1551d39a76e7Sxw 	return (GLD_SUCCESS);
1552d39a76e7Sxw }
1553d39a76e7Sxw 
1554d39a76e7Sxw static int
ch_set_promiscuous(gld_mac_info_t * mp,int flag)1555d39a76e7Sxw ch_set_promiscuous(gld_mac_info_t *mp, int flag)
1556d39a76e7Sxw {
1557d39a76e7Sxw 	ch_t *chp = (ch_t *)mp->gldm_private;
1558d39a76e7Sxw 
1559d39a76e7Sxw 	switch (flag) {
1560d39a76e7Sxw 	case GLD_MAC_PROMISC_MULTI:
1561d39a76e7Sxw 		pe_set_promiscuous(chp, 2);
1562d39a76e7Sxw 		break;
1563d39a76e7Sxw 
1564d39a76e7Sxw 	case GLD_MAC_PROMISC_NONE:
1565d39a76e7Sxw 		pe_set_promiscuous(chp, 0);
1566d39a76e7Sxw 		break;
1567d39a76e7Sxw 
1568d39a76e7Sxw 	case GLD_MAC_PROMISC_PHYS:
1569d39a76e7Sxw 	default:
1570d39a76e7Sxw 		pe_set_promiscuous(chp, 1);
1571d39a76e7Sxw 		break;
1572d39a76e7Sxw 	}
1573d39a76e7Sxw 
1574d39a76e7Sxw 	return (GLD_SUCCESS);
1575d39a76e7Sxw }
1576d39a76e7Sxw 
1577d39a76e7Sxw static int
ch_get_stats(gld_mac_info_t * mp,struct gld_stats * gs)1578d39a76e7Sxw ch_get_stats(gld_mac_info_t *mp, struct gld_stats *gs)
1579d39a76e7Sxw {
1580d39a76e7Sxw 	ch_t *chp = (ch_t *)mp->gldm_private;
1581d39a76e7Sxw 	uint64_t speed;
1582d39a76e7Sxw 	uint32_t intrcnt;
1583d39a76e7Sxw 	uint32_t norcvbuf;
1584d39a76e7Sxw 	uint32_t oerrors;
1585d39a76e7Sxw 	uint32_t ierrors;
1586d39a76e7Sxw 	uint32_t underrun;
1587d39a76e7Sxw 	uint32_t overrun;
1588d39a76e7Sxw 	uint32_t framing;
1589d39a76e7Sxw 	uint32_t crc;
1590d39a76e7Sxw 	uint32_t carrier;
1591d39a76e7Sxw 	uint32_t collisions;
1592d39a76e7Sxw 	uint32_t xcollisions;
1593d39a76e7Sxw 	uint32_t late;
1594d39a76e7Sxw 	uint32_t defer;
1595d39a76e7Sxw 	uint32_t xerrs;
1596d39a76e7Sxw 	uint32_t rerrs;
1597d39a76e7Sxw 	uint32_t toolong;
1598d39a76e7Sxw 	uint32_t runt;
1599d39a76e7Sxw 	ulong_t multixmt;
1600d39a76e7Sxw 	ulong_t multircv;
1601d39a76e7Sxw 	ulong_t brdcstxmt;
1602d39a76e7Sxw 	ulong_t brdcstrcv;
1603d39a76e7Sxw 
1604d39a76e7Sxw 	/*
1605d39a76e7Sxw 	 * race looks benign here.
1606d39a76e7Sxw 	 */
1607d39a76e7Sxw 	if (chp->ch_state != PERUNNING) {
1608d39a76e7Sxw 		return (GLD_FAILURE);
1609d39a76e7Sxw 	}
1610d39a76e7Sxw 
1611d39a76e7Sxw 	(void) pe_get_stats(chp,
161219397407SSherry Moore 	    &speed,
161319397407SSherry Moore 	    &intrcnt,
161419397407SSherry Moore 	    &norcvbuf,
161519397407SSherry Moore 	    &oerrors,
161619397407SSherry Moore 	    &ierrors,
161719397407SSherry Moore 	    &underrun,
161819397407SSherry Moore 	    &overrun,
161919397407SSherry Moore 	    &framing,
162019397407SSherry Moore 	    &crc,
162119397407SSherry Moore 	    &carrier,
162219397407SSherry Moore 	    &collisions,
162319397407SSherry Moore 	    &xcollisions,
162419397407SSherry Moore 	    &late,
162519397407SSherry Moore 	    &defer,
162619397407SSherry Moore 	    &xerrs,
162719397407SSherry Moore 	    &rerrs,
162819397407SSherry Moore 	    &toolong,
162919397407SSherry Moore 	    &runt,
163019397407SSherry Moore 	    &multixmt,
163119397407SSherry Moore 	    &multircv,
163219397407SSherry Moore 	    &brdcstxmt,
163319397407SSherry Moore 	    &brdcstrcv);
1634d39a76e7Sxw 
1635d39a76e7Sxw 	gs->glds_speed = speed;
1636d39a76e7Sxw 	gs->glds_media = GLDM_UNKNOWN;
1637d39a76e7Sxw 	gs->glds_intr  = intrcnt;
1638d39a76e7Sxw 	gs->glds_norcvbuf = norcvbuf;
1639d39a76e7Sxw 	gs->glds_errxmt = oerrors;
1640d39a76e7Sxw 	gs->glds_errrcv = ierrors;
1641d39a76e7Sxw 	gs->glds_missed = ierrors;	/* ??? */
1642d39a76e7Sxw 	gs->glds_underflow = underrun;
1643d39a76e7Sxw 	gs->glds_overflow = overrun;
1644d39a76e7Sxw 	gs->glds_frame = framing;
1645d39a76e7Sxw 	gs->glds_crc = crc;
1646d39a76e7Sxw 	gs->glds_duplex = GLD_DUPLEX_FULL;
1647d39a76e7Sxw 	gs->glds_nocarrier = carrier;
1648d39a76e7Sxw 	gs->glds_collisions = collisions;
1649d39a76e7Sxw 	gs->glds_excoll = xcollisions;
1650d39a76e7Sxw 	gs->glds_xmtlatecoll = late;
1651d39a76e7Sxw 	gs->glds_defer = defer;
1652d39a76e7Sxw 	gs->glds_dot3_first_coll = 0;	/* Not available */
1653d39a76e7Sxw 	gs->glds_dot3_multi_coll = 0;	/* Not available */
1654d39a76e7Sxw 	gs->glds_dot3_sqe_error = 0;	/* Not available */
1655d39a76e7Sxw 	gs->glds_dot3_mac_xmt_error = xerrs;
1656d39a76e7Sxw 	gs->glds_dot3_mac_rcv_error = rerrs;
1657d39a76e7Sxw 	gs->glds_dot3_frame_too_long = toolong;
1658d39a76e7Sxw 	gs->glds_short = runt;
1659d39a76e7Sxw 
1660d39a76e7Sxw 	gs->glds_noxmtbuf = 0;		/* not documented */
1661d39a76e7Sxw 	gs->glds_xmtretry = 0;		/* not documented */
1662d39a76e7Sxw 	gs->glds_multixmt = multixmt;	/* not documented */
1663d39a76e7Sxw 	gs->glds_multircv = multircv;	/* not documented */
1664d39a76e7Sxw 	gs->glds_brdcstxmt = brdcstxmt;	/* not documented */
1665d39a76e7Sxw 	gs->glds_brdcstrcv = brdcstrcv;	/* not documented */
1666d39a76e7Sxw 
1667d39a76e7Sxw 	return (GLD_SUCCESS);
1668d39a76e7Sxw }
1669d39a76e7Sxw 
1670d39a76e7Sxw 
1671d39a76e7Sxw static int
ch_send(gld_mac_info_t * macinfo,mblk_t * mp)1672d39a76e7Sxw ch_send(gld_mac_info_t *macinfo, mblk_t *mp)
1673d39a76e7Sxw {
1674d39a76e7Sxw 	ch_t *chp = (ch_t *)macinfo->gldm_private;
1675d39a76e7Sxw 	uint32_t flg;
1676d39a76e7Sxw 	uint32_t msg_flg;
1677d39a76e7Sxw 
1678d39a76e7Sxw #ifdef TX_CKSUM_FIX
1679d39a76e7Sxw 	mblk_t *nmp;
1680d39a76e7Sxw 	int frags;
1681d39a76e7Sxw 	size_t msg_len;
1682d39a76e7Sxw 	struct ether_header *ehdr;
1683d39a76e7Sxw 	ipha_t *ihdr;
1684d39a76e7Sxw 	int tflg = 0;
1685d39a76e7Sxw #endif	/* TX_CKSUM_FIX */
1686d39a76e7Sxw 
1687d39a76e7Sxw 	/*
1688d39a76e7Sxw 	 * race looks benign here.
1689d39a76e7Sxw 	 */
1690d39a76e7Sxw 	if (chp->ch_state != PERUNNING) {
1691d39a76e7Sxw 		return (GLD_FAILURE);
1692d39a76e7Sxw 	}
1693d39a76e7Sxw 
1694d39a76e7Sxw 	msg_flg = 0;
1695d39a76e7Sxw 	if (chp->ch_config.cksum_enabled) {
1696d39a76e7Sxw 		if (is_T2(chp)) {
1697*ec71f88eSPatrick Mooney 			mac_hcksum_get(mp, NULL, NULL, NULL, NULL, &msg_flg);
1698d39a76e7Sxw 			flg = (msg_flg & HCK_FULLCKSUM)?
169919397407SSherry Moore 			    CH_NO_CPL: CH_NO_HWCKSUM|CH_NO_CPL;
1700d39a76e7Sxw 		} else
1701d39a76e7Sxw 			flg = CH_NO_CPL;
1702d39a76e7Sxw 	} else
1703d39a76e7Sxw 	flg = CH_NO_HWCKSUM | CH_NO_CPL;
1704d39a76e7Sxw 
1705d39a76e7Sxw #ifdef TX_CKSUM_FIX
1706d39a76e7Sxw 	/*
1707d39a76e7Sxw 	 * Check if the message spans more than one mblk or
1708d39a76e7Sxw 	 * if it does and the ip header is not in the first
1709d39a76e7Sxw 	 * fragment then pull up the message. This case is
1710d39a76e7Sxw 	 * expected to be rare.
1711d39a76e7Sxw 	 */
1712d39a76e7Sxw 	frags = 0;
1713d39a76e7Sxw 	msg_len = 0;
1714d39a76e7Sxw 	nmp = mp;
1715d39a76e7Sxw 	do {
1716d39a76e7Sxw 		frags++;
1717d39a76e7Sxw 		msg_len += MBLKL(nmp);
1718d39a76e7Sxw 		nmp = nmp->b_cont;
1719d39a76e7Sxw 	} while (nmp);
1720d39a76e7Sxw #define	MAX_ALL_HDRLEN SZ_CPL_TX_PKT + sizeof (struct ether_header) + \
1721d39a76e7Sxw 				TCP_MAX_COMBINED_HEADER_LENGTH
1722d39a76e7Sxw 	/*
1723d39a76e7Sxw 	 * If the first mblk has enough space at the beginning of
1724d39a76e7Sxw 	 * the data buffer to hold a CPL header, then, we'll expancd
1725d39a76e7Sxw 	 * the front of the buffer so a pullup will leave space for
1726d39a76e7Sxw 	 * pe_start() to add the CPL header in line. We need to remember
1727d39a76e7Sxw 	 * that we've done this so we can undo it after the pullup.
1728d39a76e7Sxw 	 *
1729d39a76e7Sxw 	 * Note that if we decide to do an allocb to hold the CPL header,
1730d39a76e7Sxw 	 * we need to catch the case where we've added an empty mblk for
1731d39a76e7Sxw 	 * the header but never did a pullup. This would result in the
1732d39a76e7Sxw 	 * tests for etherheader, etc. being done on the initial, empty,
1733d39a76e7Sxw 	 * mblk instead of the one with data. See PR3646 for further
1734d39a76e7Sxw 	 * details. (note this PR is closed since it is no longer relevant).
1735d39a76e7Sxw 	 *
1736d39a76e7Sxw 	 * Another point is that if we do add an allocb to add space for
1737d39a76e7Sxw 	 * a CPL header, after a pullup, the initial pointer, mp, in GLD will
1738d39a76e7Sxw 	 * no longer point to a valid mblk. When we get the mblk (by allocb),
1739d39a76e7Sxw 	 * we need to switch the mblk structure values between it and the
1740d39a76e7Sxw 	 * mp structure values referenced by GLD. This handles the case where
1741d39a76e7Sxw 	 * we've run out of cmdQ entries and report GLD_NORESOURCES back to
1742d39a76e7Sxw 	 * GLD. The pointer to the mblk data will have been modified to hold
1743d39a76e7Sxw 	 * an empty 8 bytes for the CPL header, For now, we let the pe_start()
1744d39a76e7Sxw 	 * routine prepend an 8 byte mblk.
1745d39a76e7Sxw 	 */
1746d39a76e7Sxw 	if (MBLKHEAD(mp) >= SZ_CPL_TX_PKT) {
1747d39a76e7Sxw 		mp->b_rptr -= SZ_CPL_TX_PKT;
1748d39a76e7Sxw 		tflg = 1;
1749d39a76e7Sxw 	}
1750d39a76e7Sxw 	if (frags > 3) {
1751d39a76e7Sxw 		chp->sge->intr_cnt.tx_msg_pullups++;
1752d39a76e7Sxw 		if (pullupmsg(mp, -1) == 0) {
1753d39a76e7Sxw 			freemsg(mp);
1754d39a76e7Sxw 			return (GLD_SUCCESS);
1755d39a76e7Sxw 		}
1756d39a76e7Sxw 	} else if ((msg_len > MAX_ALL_HDRLEN) &&
175719397407SSherry Moore 	    (MBLKL(mp) < MAX_ALL_HDRLEN)) {
1758d39a76e7Sxw 		chp->sge->intr_cnt.tx_hdr_pullups++;
1759d39a76e7Sxw 		if (pullupmsg(mp, MAX_ALL_HDRLEN) == 0) {
1760d39a76e7Sxw 			freemsg(mp);
1761d39a76e7Sxw 			return (GLD_SUCCESS);
1762d39a76e7Sxw 		}
1763d39a76e7Sxw 	}
1764d39a76e7Sxw 	if (tflg)
1765d39a76e7Sxw 		mp->b_rptr += SZ_CPL_TX_PKT;
1766d39a76e7Sxw 
1767d39a76e7Sxw 	ehdr = (struct ether_header *)mp->b_rptr;
1768d39a76e7Sxw 	if (ehdr->ether_type == htons(ETHERTYPE_IP)) {
1769d39a76e7Sxw 		ihdr = (ipha_t *)&mp->b_rptr[sizeof (struct ether_header)];
1770d39a76e7Sxw 		if ((ihdr->ipha_fragment_offset_and_flags & IPH_MF)) {
1771d39a76e7Sxw 			if (ihdr->ipha_protocol == IPPROTO_UDP) {
1772d39a76e7Sxw 				flg |= CH_UDP_MF;
1773d39a76e7Sxw 				chp->sge->intr_cnt.tx_udp_ip_frag++;
1774d39a76e7Sxw 			} else if (ihdr->ipha_protocol == IPPROTO_TCP) {
1775d39a76e7Sxw 				flg |= CH_TCP_MF;
1776d39a76e7Sxw 				chp->sge->intr_cnt.tx_tcp_ip_frag++;
1777d39a76e7Sxw 			}
1778d39a76e7Sxw 		} else if (ihdr->ipha_protocol == IPPROTO_UDP)
1779d39a76e7Sxw 			flg |= CH_UDP;
1780d39a76e7Sxw 	}
1781d39a76e7Sxw #endif	/* TX_CKSUM_FIX */
1782d39a76e7Sxw 
1783d39a76e7Sxw 	/*
1784d39a76e7Sxw 	 * return 0 - data send successfully
1785d39a76e7Sxw 	 * return 1 - no resources, reschedule
1786d39a76e7Sxw 	 */
1787d39a76e7Sxw 	if (pe_start(chp, mp, flg))
1788d39a76e7Sxw 		return (GLD_NORESOURCES);
1789d39a76e7Sxw 	else
1790d39a76e7Sxw 		return (GLD_SUCCESS);
1791d39a76e7Sxw }
1792d39a76e7Sxw 
1793d39a76e7Sxw static uint_t
ch_intr(gld_mac_info_t * mp)1794d39a76e7Sxw ch_intr(gld_mac_info_t *mp)
1795d39a76e7Sxw {
1796d39a76e7Sxw 	return (pe_intr((ch_t *)mp->gldm_private));
1797d39a76e7Sxw }
1798d39a76e7Sxw 
1799d39a76e7Sxw /*
1800d39a76e7Sxw  * generate name of driver with unit# postpended.
1801d39a76e7Sxw  */
1802d39a76e7Sxw void
ch_set_name(ch_t * chp,int unit)1803d39a76e7Sxw ch_set_name(ch_t *chp, int unit)
1804d39a76e7Sxw {
1805d39a76e7Sxw 	chp->ch_name = (char *)kmem_alloc(sizeof ("chxge00"), KM_SLEEP);
1806d39a76e7Sxw 	if (unit > 9) {
1807d39a76e7Sxw 		bcopy("chxge00", (void *)chp->ch_name, sizeof ("chxge00"));
1808d39a76e7Sxw 		chp->ch_name[5] += unit/10;
1809d39a76e7Sxw 		chp->ch_name[6] += unit%10;
1810d39a76e7Sxw 	} else {
1811d39a76e7Sxw 		bcopy("chxge0", (void *)chp->ch_name, sizeof ("chxge0"));
1812d39a76e7Sxw 		chp->ch_name[5] += unit;
1813d39a76e7Sxw 	}
1814d39a76e7Sxw }
1815d39a76e7Sxw 
1816d39a76e7Sxw void
ch_free_name(ch_t * chp)1817d39a76e7Sxw ch_free_name(ch_t *chp)
1818d39a76e7Sxw {
1819d39a76e7Sxw 	if (chp->ch_name)
1820d39a76e7Sxw 		kmem_free(chp->ch_name, sizeof ("chxge00"));
1821d39a76e7Sxw 	chp->ch_name = NULL;
1822d39a76e7Sxw }
1823d39a76e7Sxw 
1824d39a76e7Sxw #ifdef CONFIG_CHELSIO_T1_OFFLOAD
1825d39a76e7Sxw /*
1826d39a76e7Sxw  * register toe offload.
1827d39a76e7Sxw  */
1828d39a76e7Sxw void *
ch_register(void * instp,void * toe_rcv,void * toe_free,void * toe_tunnel,kmutex_t * toe_tx_mx,kcondvar_t * toe_of_cv,int unit)1829d39a76e7Sxw ch_register(void *instp, void *toe_rcv, void *toe_free, void *toe_tunnel,
1830d39a76e7Sxw     kmutex_t *toe_tx_mx, kcondvar_t *toe_of_cv, int unit)
1831d39a76e7Sxw {
1832d39a76e7Sxw 	ch_t *chp = gchp[unit];
1833d39a76e7Sxw 	if (chp != NULL) {
1834d39a76e7Sxw 		mutex_enter(&chp->ch_lock);
1835d39a76e7Sxw 
1836d39a76e7Sxw 		chp->toe_rcv = (void (*)(void *, mblk_t *))toe_rcv;
1837d39a76e7Sxw 		chp->ch_toeinst = instp;
1838d39a76e7Sxw 		chp->toe_free = (void (*)(void *, tbuf_t *))toe_free;
1839d39a76e7Sxw 		chp->toe_tunnel = (int (*)(void *, mblk_t *))toe_tunnel;
1840d39a76e7Sxw 		chp->ch_tx_overflow_mutex = toe_tx_mx;
1841d39a76e7Sxw 		chp->ch_tx_overflow_cv = toe_of_cv;
1842d39a76e7Sxw 		chp->open_device_map |= TOEDEV_DEVMAP_BIT;
1843d39a76e7Sxw 
1844d39a76e7Sxw 		/* start up adapter if first user */
1845d39a76e7Sxw 		chp->ch_refcnt++;
1846d39a76e7Sxw 		if (chp->ch_refcnt == 1) {
1847d39a76e7Sxw 			chp->ch_state = PERUNNING;
1848d39a76e7Sxw 			mutex_exit(&chp->ch_lock);
1849d39a76e7Sxw 			pe_init((void *)chp);
1850d39a76e7Sxw 		} else
1851d39a76e7Sxw 			mutex_exit(&chp->ch_lock);
1852d39a76e7Sxw 	}
1853d39a76e7Sxw 	return ((void *)gchp[unit]);
1854d39a76e7Sxw }
1855d39a76e7Sxw 
1856d39a76e7Sxw /*
1857d39a76e7Sxw  * unregister toe offload.
1858d39a76e7Sxw  * XXX Need to fix races here.
1859d39a76e7Sxw  *     1. turn off SGE interrupts.
1860d39a76e7Sxw  *     2. do update
1861d39a76e7Sxw  *     3. re-enable SGE interrupts
1862d39a76e7Sxw  *     4. SGE doorbell to make sure things get restarted.
1863d39a76e7Sxw  */
1864d39a76e7Sxw void
ch_unregister(void)1865d39a76e7Sxw ch_unregister(void)
1866d39a76e7Sxw {
1867d39a76e7Sxw 	int i;
1868d39a76e7Sxw 	ch_t *chp;
1869d39a76e7Sxw 
1870d39a76e7Sxw 	for (i = 0; i < MAX_CARDS; i++) {
1871d39a76e7Sxw 		chp = gchp[i];
1872d39a76e7Sxw 		if (chp == NULL)
1873d39a76e7Sxw 			continue;
1874d39a76e7Sxw 
1875d39a76e7Sxw 		mutex_enter(&chp->ch_lock);
1876d39a76e7Sxw 
1877d39a76e7Sxw 		chp->ch_refcnt--;
1878d39a76e7Sxw 		if (chp->ch_refcnt == 0) {
1879d39a76e7Sxw 			chp->ch_state = PESTOP;
1880d39a76e7Sxw 			mutex_exit(&chp->ch_lock);
1881d39a76e7Sxw 			pe_stop(chp);
1882d39a76e7Sxw 		} else
1883d39a76e7Sxw 			mutex_exit(&chp->ch_lock);
1884d39a76e7Sxw 
1885d39a76e7Sxw 		chp->open_device_map &= ~TOEDEV_DEVMAP_BIT;
1886d39a76e7Sxw 		chp->toe_rcv = NULL;
1887d39a76e7Sxw 		chp->ch_toeinst =  NULL;
1888d39a76e7Sxw 		chp->toe_free = NULL;
1889d39a76e7Sxw 		chp->toe_tunnel = NULL;
1890d39a76e7Sxw 		chp->ch_tx_overflow_mutex = NULL;
1891d39a76e7Sxw 		chp->ch_tx_overflow_cv = NULL;
1892d39a76e7Sxw 	}
1893d39a76e7Sxw }
1894d39a76e7Sxw #endif	/* CONFIG_CHELSIO_T1_OFFLOAD */
1895d39a76e7Sxw 
1896d39a76e7Sxw /*
1897d39a76e7Sxw  * get properties from chxge.conf
1898d39a76e7Sxw  */
1899d39a76e7Sxw static void
ch_get_prop(ch_t * chp)1900d39a76e7Sxw ch_get_prop(ch_t *chp)
1901d39a76e7Sxw {
1902d39a76e7Sxw 	int val;
1903d39a76e7Sxw 	int tval = 0;
1904d39a76e7Sxw 	extern int enable_latency_timer;
1905d39a76e7Sxw 	extern uint32_t sge_cmdq0_cnt;
1906d39a76e7Sxw 	extern uint32_t sge_cmdq1_cnt;
1907d39a76e7Sxw 	extern uint32_t sge_flq0_cnt;
1908d39a76e7Sxw 	extern uint32_t sge_flq1_cnt;
1909d39a76e7Sxw 	extern uint32_t sge_respq_cnt;
1910d39a76e7Sxw 	extern uint32_t sge_cmdq0_cnt_orig;
1911d39a76e7Sxw 	extern uint32_t sge_cmdq1_cnt_orig;
1912d39a76e7Sxw 	extern uint32_t sge_flq0_cnt_orig;
1913d39a76e7Sxw 	extern uint32_t sge_flq1_cnt_orig;
1914d39a76e7Sxw 	extern uint32_t sge_respq_cnt_orig;
1915d39a76e7Sxw 	dev_info_t *pdip;
1916d39a76e7Sxw 	uint32_t vendor_id, device_id, revision_id;
1917d39a76e7Sxw 	uint32_t *prop_val = NULL;
191811abda1eSToomas Soome 	uint32_t prop_len = 0;
1919d39a76e7Sxw 
1920d39a76e7Sxw 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
192119397407SSherry Moore 	    "enable_dvma", -1);
1922d39a76e7Sxw 	if (val == -1)
1923d39a76e7Sxw 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
192419397407SSherry Moore 		    "enable-dvma", -1);
1925d39a76e7Sxw 	if (val != -1) {
1926d39a76e7Sxw 		if (val != 0)
1927d39a76e7Sxw 			chp->ch_config.enable_dvma = 1;
1928d39a76e7Sxw 	}
1929d39a76e7Sxw 
1930d39a76e7Sxw 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
193119397407SSherry Moore 	    "amd_bug_workaround", -1);
1932d39a76e7Sxw 	if (val == -1)
1933d39a76e7Sxw 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
193419397407SSherry Moore 		    "amd-bug-workaround", -1);
1935d39a76e7Sxw 
1936d39a76e7Sxw 	if (val != -1) {
1937d39a76e7Sxw 		if (val == 0) {
1938d39a76e7Sxw 			chp->ch_config.burstsize_set = 0;
1939d39a76e7Sxw 			chp->ch_config.transaction_cnt_set = 0;
1940d39a76e7Sxw 			goto fail_exit;
1941d39a76e7Sxw 		}
1942d39a76e7Sxw 	}
1943d39a76e7Sxw 	/*
1944d39a76e7Sxw 	 * Step up to the parent node,  That's the node above us
1945d39a76e7Sxw 	 * in the device tree. And will typically be the PCI host
1946d39a76e7Sxw 	 * Controller.
1947d39a76e7Sxw 	 */
1948d39a76e7Sxw 	pdip = ddi_get_parent(chp->ch_dip);
1949d39a76e7Sxw 
1950d39a76e7Sxw 	/*
1951d39a76e7Sxw 	 * Now get the 'Vendor id' properties
1952d39a76e7Sxw 	 */
1953d39a76e7Sxw 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, pdip, 0, "vendor-id",
1954d39a76e7Sxw 	    (int **)&prop_val, &prop_len) != DDI_PROP_SUCCESS) {
1955d39a76e7Sxw 		chp->ch_config.burstsize_set = 0;
1956d39a76e7Sxw 		chp->ch_config.transaction_cnt_set = 0;
1957d39a76e7Sxw 		goto fail_exit;
1958d39a76e7Sxw 	}
1959d39a76e7Sxw 	vendor_id = *(uint32_t *)prop_val;
1960d39a76e7Sxw 	ddi_prop_free(prop_val);
1961d39a76e7Sxw 
1962d39a76e7Sxw 	/*
1963d39a76e7Sxw 	 * Now get the 'Device id' properties
1964d39a76e7Sxw 	 */
1965d39a76e7Sxw 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, pdip, 0, "device-id",
1966d39a76e7Sxw 	    (int **)&prop_val, &prop_len) != DDI_PROP_SUCCESS) {
1967d39a76e7Sxw 		chp->ch_config.burstsize_set = 0;
1968d39a76e7Sxw 		chp->ch_config.transaction_cnt_set = 0;
1969d39a76e7Sxw 		goto fail_exit;
1970d39a76e7Sxw 	}
1971d39a76e7Sxw 	device_id = *(uint32_t *)prop_val;
1972d39a76e7Sxw 	ddi_prop_free(prop_val);
1973d39a76e7Sxw 
1974d39a76e7Sxw 	/*
1975d39a76e7Sxw 	 * Now get the 'Revision id' properties
1976d39a76e7Sxw 	 */
1977d39a76e7Sxw 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, pdip, 0, "revision-id",
1978d39a76e7Sxw 	    (int **)&prop_val, &prop_len) != DDI_PROP_SUCCESS) {
1979d39a76e7Sxw 		chp->ch_config.burstsize_set = 0;
1980d39a76e7Sxw 		chp->ch_config.transaction_cnt_set = 0;
1981d39a76e7Sxw 		goto fail_exit;
1982d39a76e7Sxw 	}
1983d39a76e7Sxw 	revision_id = *(uint32_t *)prop_val;
1984d39a76e7Sxw 	ddi_prop_free(prop_val);
1985d39a76e7Sxw 
1986d39a76e7Sxw 	/*
1987d39a76e7Sxw 	 * set default values based on node above us.
1988d39a76e7Sxw 	 */
1989d39a76e7Sxw 	if ((vendor_id == AMD_VENDOR_ID) && (device_id == AMD_BRIDGE) &&
1990d39a76e7Sxw 	    (revision_id <= AMD_BRIDGE_REV)) {
1991d39a76e7Sxw 		uint32_t v;
1992d39a76e7Sxw 		uint32_t burst;
1993d39a76e7Sxw 		uint32_t cnt;
1994d39a76e7Sxw 
1995d39a76e7Sxw 		/* if 133 Mhz not enabled, then do nothing - we're not PCIx */
1996d39a76e7Sxw 		v = pci_config_get32(chp->ch_hpci, 0x64);
199711abda1eSToomas Soome 		if ((v & 0x20000) == 0) {
1998d39a76e7Sxw 			chp->ch_config.burstsize_set = 0;
1999d39a76e7Sxw 			chp->ch_config.transaction_cnt_set = 0;
2000d39a76e7Sxw 			goto fail_exit;
2001d39a76e7Sxw 		}
2002d39a76e7Sxw 
2003d39a76e7Sxw 		/* check burst size and transaction count */
2004d39a76e7Sxw 		v = pci_config_get32(chp->ch_hpci, 0x60);
2005d39a76e7Sxw 		burst = (v >> 18) & 3;
2006d39a76e7Sxw 		cnt = (v >> 20) & 7;
2007d39a76e7Sxw 
2008d39a76e7Sxw 		switch (burst) {
2009d39a76e7Sxw 		case 0:	/* 512 */
2010d39a76e7Sxw 			/* 512 burst size legal with split cnts 1,2,3 */
2011d39a76e7Sxw 			if (cnt <= 2) {
2012d39a76e7Sxw 				chp->ch_config.burstsize_set = 0;
2013d39a76e7Sxw 				chp->ch_config.transaction_cnt_set = 0;
2014d39a76e7Sxw 				goto fail_exit;
2015d39a76e7Sxw 			}
2016d39a76e7Sxw 			break;
2017d39a76e7Sxw 		case 1:	/* 1024 */
2018d39a76e7Sxw 			/* 1024 burst size legal with split cnts 1,2 */
2019d39a76e7Sxw 			if (cnt <= 1) {
2020d39a76e7Sxw 				chp->ch_config.burstsize_set = 0;
2021d39a76e7Sxw 				chp->ch_config.transaction_cnt_set = 0;
2022d39a76e7Sxw 				goto fail_exit;
2023d39a76e7Sxw 			}
2024d39a76e7Sxw 			break;
2025d39a76e7Sxw 		case 2:	/* 2048 */
2026d39a76e7Sxw 			/* 2048 burst size legal with split cnts 1 */
2027d39a76e7Sxw 			if (cnt == 0) {
2028d39a76e7Sxw 				chp->ch_config.burstsize_set = 0;
2029d39a76e7Sxw 				chp->ch_config.transaction_cnt_set = 0;
2030d39a76e7Sxw 				goto fail_exit;
2031d39a76e7Sxw 			}
2032d39a76e7Sxw 			break;
2033d39a76e7Sxw 		case 3:	/* 4096 */
2034d39a76e7Sxw 			break;
2035d39a76e7Sxw 		}
2036d39a76e7Sxw 	} else {
2037d39a76e7Sxw 		goto fail_exit;
2038d39a76e7Sxw 	}
2039d39a76e7Sxw 
2040d39a76e7Sxw 	/*
2041d39a76e7Sxw 	 * if illegal burst size seen, then default to 1024 burst size
2042d39a76e7Sxw 	 */
2043d39a76e7Sxw 	chp->ch_config.burstsize = 1;
2044d39a76e7Sxw 	chp->ch_config.burstsize_set = 1;
2045d39a76e7Sxw 	/*
2046d39a76e7Sxw 	 * if illegal transaction cnt seen, then default to 2
2047d39a76e7Sxw 	 */
2048d39a76e7Sxw 	chp->ch_config.transaction_cnt = 1;
2049d39a76e7Sxw 	chp->ch_config.transaction_cnt_set = 1;
2050d39a76e7Sxw 
2051d39a76e7Sxw 
2052d39a76e7Sxw fail_exit:
2053d39a76e7Sxw 
2054d39a76e7Sxw 	/*
2055d39a76e7Sxw 	 * alter the burstsize parameter via an entry
2056d39a76e7Sxw 	 * in chxge.conf
2057d39a76e7Sxw 	 */
2058d39a76e7Sxw 
2059d39a76e7Sxw 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
206019397407SSherry Moore 	    "pci_burstsize", -1);
2061d39a76e7Sxw 	if (val == -1)
2062d39a76e7Sxw 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
206319397407SSherry Moore 		    "pci-burstsize", -1);
2064d39a76e7Sxw 
2065d39a76e7Sxw 	if (val != -1) {
2066d39a76e7Sxw 
2067d39a76e7Sxw 		switch (val) {
2068d39a76e7Sxw 		case 0:	/* use default */
2069d39a76e7Sxw 			chp->ch_config.burstsize_set = 0;
2070d39a76e7Sxw 			break;
2071d39a76e7Sxw 
2072d39a76e7Sxw 		case 1024:
2073d39a76e7Sxw 			chp->ch_config.burstsize_set = 1;
2074d39a76e7Sxw 			chp->ch_config.burstsize = 1;
2075d39a76e7Sxw 			break;
2076d39a76e7Sxw 
2077d39a76e7Sxw 		case 2048:
2078d39a76e7Sxw 			chp->ch_config.burstsize_set = 1;
2079d39a76e7Sxw 			chp->ch_config.burstsize = 2;
2080d39a76e7Sxw 			break;
2081d39a76e7Sxw 
2082d39a76e7Sxw 		case 4096:
2083d39a76e7Sxw 			cmn_err(CE_WARN, "%s not supported %d\n",
2084d39a76e7Sxw 			    chp->ch_name, val);
2085d39a76e7Sxw 			break;
2086d39a76e7Sxw 
2087d39a76e7Sxw 		default:
2088d39a76e7Sxw 			cmn_err(CE_WARN, "%s illegal burst size %d\n",
2089d39a76e7Sxw 			    chp->ch_name, val);
2090d39a76e7Sxw 			break;
2091d39a76e7Sxw 		}
2092d39a76e7Sxw 	}
2093d39a76e7Sxw 
2094d39a76e7Sxw 	/*
2095d39a76e7Sxw 	 * set transaction count
2096d39a76e7Sxw 	 */
2097d39a76e7Sxw 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
209819397407SSherry Moore 	    "pci_split_transaction_cnt", -1);
2099d39a76e7Sxw 	if (val == -1)
2100d39a76e7Sxw 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
210119397407SSherry Moore 		    "pci-split-transaction-cnt", -1);
2102d39a76e7Sxw 
2103d39a76e7Sxw 	if (val != -1) {
2104d39a76e7Sxw 		switch (val) {
2105d39a76e7Sxw 		case 0:	/* use default */
2106d39a76e7Sxw 			chp->ch_config.transaction_cnt_set = 0;
2107d39a76e7Sxw 			break;
2108d39a76e7Sxw 
2109d39a76e7Sxw 		case 1:
2110d39a76e7Sxw 			chp->ch_config.transaction_cnt_set = 1;
2111d39a76e7Sxw 			chp->ch_config.transaction_cnt = 0;
2112d39a76e7Sxw 			break;
2113d39a76e7Sxw 
2114d39a76e7Sxw 		case 2:
2115d39a76e7Sxw 			chp->ch_config.transaction_cnt_set = 1;
2116d39a76e7Sxw 			chp->ch_config.transaction_cnt = 1;
2117d39a76e7Sxw 			break;
2118d39a76e7Sxw 
2119d39a76e7Sxw 		case 3:
2120d39a76e7Sxw 			chp->ch_config.transaction_cnt_set = 1;
2121d39a76e7Sxw 			chp->ch_config.transaction_cnt = 2;
2122d39a76e7Sxw 			break;
2123d39a76e7Sxw 
2124d39a76e7Sxw 		case 4:
2125d39a76e7Sxw 			chp->ch_config.transaction_cnt_set = 1;
2126d39a76e7Sxw 			chp->ch_config.transaction_cnt = 3;
2127d39a76e7Sxw 			break;
2128d39a76e7Sxw 
2129d39a76e7Sxw 		case 8:
2130d39a76e7Sxw 			chp->ch_config.transaction_cnt_set = 1;
2131d39a76e7Sxw 			chp->ch_config.transaction_cnt = 4;
2132d39a76e7Sxw 			break;
2133d39a76e7Sxw 
2134d39a76e7Sxw 		case 12:
2135d39a76e7Sxw 			chp->ch_config.transaction_cnt_set = 1;
2136d39a76e7Sxw 			chp->ch_config.transaction_cnt = 5;
2137d39a76e7Sxw 			break;
2138d39a76e7Sxw 
2139d39a76e7Sxw 		case 16:
2140d39a76e7Sxw 			chp->ch_config.transaction_cnt_set = 1;
2141d39a76e7Sxw 			chp->ch_config.transaction_cnt = 6;
2142d39a76e7Sxw 			break;
2143d39a76e7Sxw 
2144d39a76e7Sxw 		case 32:
2145d39a76e7Sxw 			chp->ch_config.transaction_cnt_set = 1;
2146d39a76e7Sxw 			chp->ch_config.transaction_cnt = 7;
2147d39a76e7Sxw 			break;
2148d39a76e7Sxw 
2149d39a76e7Sxw 		default:
2150d39a76e7Sxw 			cmn_err(CE_WARN, "%s illegal transaction cnt %d\n",
2151d39a76e7Sxw 			    chp->ch_name, val);
2152d39a76e7Sxw 			break;
2153d39a76e7Sxw 		}
2154d39a76e7Sxw 	}
2155d39a76e7Sxw 
2156d39a76e7Sxw 	/*
2157d39a76e7Sxw 	 * set relaxed ordering bit?
2158d39a76e7Sxw 	 */
2159d39a76e7Sxw 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
216019397407SSherry Moore 	    "pci_relaxed_ordering_on", -1);
2161d39a76e7Sxw 	if (val == -1)
2162d39a76e7Sxw 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
216319397407SSherry Moore 		    "pci-relaxed-ordering-on", -1);
2164d39a76e7Sxw 
2165d39a76e7Sxw 	/*
2166d39a76e7Sxw 	 * default is to use system default value.
2167d39a76e7Sxw 	 */
2168d39a76e7Sxw 	chp->ch_config.relaxed_ordering = 0;
2169d39a76e7Sxw 
2170d39a76e7Sxw 	if (val != -1) {
2171d39a76e7Sxw 		if (val)
2172d39a76e7Sxw 			chp->ch_config.relaxed_ordering = 1;
2173d39a76e7Sxw 	}
2174d39a76e7Sxw 
2175d39a76e7Sxw 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
217619397407SSherry Moore 	    "enable_latency_timer", -1);
2177d39a76e7Sxw 	if (val == -1)
2178d39a76e7Sxw 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
217919397407SSherry Moore 		    "enable-latency-timer", -1);
2180d39a76e7Sxw 	if (val != -1)
2181d39a76e7Sxw 		enable_latency_timer = (val == 0)? 0: 1;
2182d39a76e7Sxw 
2183d39a76e7Sxw 	/*
2184d39a76e7Sxw 	 * default maximum Jumbo Frame size.
2185d39a76e7Sxw 	 */
2186d39a76e7Sxw 	chp->ch_maximum_mtu = 9198;	/* tunable via chxge.conf */
2187d39a76e7Sxw 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
218819397407SSherry Moore 	    "maximum_mtu", -1);
2189d39a76e7Sxw 	if (val == -1) {
2190d39a76e7Sxw 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
219119397407SSherry Moore 		    "maximum-mtu", -1);
2192d39a76e7Sxw 	}
2193d39a76e7Sxw 	if (val != -1) {
2194d39a76e7Sxw 		if (val > 9582) {
2195d39a76e7Sxw 			cmn_err(CE_WARN,
2196d39a76e7Sxw 			    "maximum_mtu value %d > 9582. Value set to 9582",
2197d39a76e7Sxw 			    val);
2198d39a76e7Sxw 			val = 9582;
2199d39a76e7Sxw 		} else if (val < 1500) {
2200d39a76e7Sxw 			cmn_err(CE_WARN,
2201d39a76e7Sxw 			    "maximum_mtu value %d < 1500. Value set to 1500",
2202d39a76e7Sxw 			    val);
2203d39a76e7Sxw 			val = 1500;
2204d39a76e7Sxw 		}
2205d39a76e7Sxw 
2206d39a76e7Sxw 		if (val)
2207d39a76e7Sxw 			chp->ch_maximum_mtu = val;
2208d39a76e7Sxw 	}
2209d39a76e7Sxw 
2210d39a76e7Sxw 	/*
2211d39a76e7Sxw 	 * default value for this instance mtu
2212d39a76e7Sxw 	 */
2213d39a76e7Sxw 	chp->ch_mtu = ETHERMTU;
2214d39a76e7Sxw 
2215d39a76e7Sxw 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
221619397407SSherry Moore 	    "accept_jumbo", -1);
2217d39a76e7Sxw 	if (val == -1) {
2218d39a76e7Sxw 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
221919397407SSherry Moore 		    "accept-jumbo", -1);
2220d39a76e7Sxw 	}
2221d39a76e7Sxw 	if (val != -1) {
2222d39a76e7Sxw 		if (val)
2223d39a76e7Sxw 			chp->ch_mtu = chp->ch_maximum_mtu;
2224d39a76e7Sxw 	}
2225d39a76e7Sxw #ifdef CONFIG_CHELSIO_T1_OFFLOAD
2226d39a76e7Sxw 	chp->ch_sm_buf_sz = 0x800;
2227d39a76e7Sxw 	chp->ch_sm_buf_aln = 0x800;
2228d39a76e7Sxw 	chp->ch_bg_buf_sz = 0x4000;
2229d39a76e7Sxw 	chp->ch_bg_buf_aln = 0x4000;
2230d39a76e7Sxw #else
2231d39a76e7Sxw 	chp->ch_sm_buf_sz = 0x200;
2232d39a76e7Sxw 	chp->ch_sm_buf_aln = 0x200;
2233d39a76e7Sxw 	chp->ch_bg_buf_sz = 0x800;
2234d39a76e7Sxw 	chp->ch_bg_buf_aln = 0x800;
2235d39a76e7Sxw 	if ((chp->ch_mtu > 0x800) && (chp->ch_mtu <= 0x1000)) {
2236d39a76e7Sxw 		chp->ch_sm_buf_sz = 0x400;
2237d39a76e7Sxw 		chp->ch_sm_buf_aln = 0x400;
2238d39a76e7Sxw 		chp->ch_bg_buf_sz = 0x1000;
2239d39a76e7Sxw 		chp->ch_bg_buf_aln = 0x1000;
2240d39a76e7Sxw 	} else if ((chp->ch_mtu > 0x1000) && (chp->ch_mtu <= 0x2000)) {
2241d39a76e7Sxw 		chp->ch_sm_buf_sz = 0x400;
2242d39a76e7Sxw 		chp->ch_sm_buf_aln = 0x400;
2243d39a76e7Sxw 		chp->ch_bg_buf_sz = 0x2000;
2244d39a76e7Sxw 		chp->ch_bg_buf_aln = 0x2000;
2245d39a76e7Sxw 	} else if (chp->ch_mtu > 0x2000) {
2246d39a76e7Sxw 		chp->ch_sm_buf_sz = 0x400;
2247d39a76e7Sxw 		chp->ch_sm_buf_aln = 0x400;
2248d39a76e7Sxw 		chp->ch_bg_buf_sz = 0x3000;
2249d39a76e7Sxw 		chp->ch_bg_buf_aln = 0x4000;
2250d39a76e7Sxw 	}
2251d39a76e7Sxw #endif
2252d39a76e7Sxw 	chp->ch_config.cksum_enabled = 1;
2253d39a76e7Sxw 
2254d39a76e7Sxw 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
225519397407SSherry Moore 	    "enable_checksum_offload", -1);
2256d39a76e7Sxw 	if (val == -1)
2257d39a76e7Sxw 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
225819397407SSherry Moore 		    "enable-checksum-offload", -1);
2259d39a76e7Sxw 	if (val != -1) {
226011abda1eSToomas Soome 		if (val == 0)
2261d39a76e7Sxw 			chp->ch_config.cksum_enabled = 0;
2262d39a76e7Sxw 	}
2263d39a76e7Sxw 
2264d39a76e7Sxw 	/*
2265d39a76e7Sxw 	 * Provides a tuning capability for the command queue 0 size.
2266d39a76e7Sxw 	 */
2267d39a76e7Sxw 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
226819397407SSherry Moore 	    "sge_cmdq0_cnt", -1);
2269d39a76e7Sxw 	if (val == -1)
2270d39a76e7Sxw 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
227119397407SSherry Moore 		    "sge-cmdq0-cnt", -1);
2272d39a76e7Sxw 	if (val != -1) {
2273d39a76e7Sxw 		if (val > 10)
2274d39a76e7Sxw 			sge_cmdq0_cnt = val;
2275d39a76e7Sxw 	}
2276d39a76e7Sxw 
2277d39a76e7Sxw 	if (sge_cmdq0_cnt > 65535) {
2278d39a76e7Sxw 		cmn_err(CE_WARN,
2279d39a76e7Sxw 		    "%s: sge-cmdQ0-cnt > 65535 - resetting value to default",
228019397407SSherry Moore 		    chp->ch_name);
2281d39a76e7Sxw 		sge_cmdq0_cnt = sge_cmdq0_cnt_orig;
2282d39a76e7Sxw 	}
2283d39a76e7Sxw 	tval += sge_cmdq0_cnt;
2284d39a76e7Sxw 
2285d39a76e7Sxw 	/*
2286d39a76e7Sxw 	 * Provides a tuning capability for the command queue 1 size.
2287d39a76e7Sxw 	 */
2288d39a76e7Sxw 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
228919397407SSherry Moore 	    "sge_cmdq1_cnt", -1);
2290d39a76e7Sxw 	if (val == -1)
2291d39a76e7Sxw 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
229219397407SSherry Moore 		    "sge-cmdq1-cnt", -1);
2293d39a76e7Sxw 	if (val != -1) {
2294d39a76e7Sxw 		if (val > 10)
2295d39a76e7Sxw 			sge_cmdq1_cnt = val;
2296d39a76e7Sxw 	}
2297d39a76e7Sxw 
2298d39a76e7Sxw 	if (sge_cmdq1_cnt > 65535) {
2299d39a76e7Sxw 		cmn_err(CE_WARN,
2300d39a76e7Sxw 		    "%s: sge-cmdQ0-cnt > 65535 - resetting value to default",
230119397407SSherry Moore 		    chp->ch_name);
2302d39a76e7Sxw 		sge_cmdq1_cnt = sge_cmdq1_cnt_orig;
2303d39a76e7Sxw 	}
2304d39a76e7Sxw 
2305d39a76e7Sxw 	/*
2306d39a76e7Sxw 	 * Provides a tuning capability for the free list 0 size.
2307d39a76e7Sxw 	 */
2308d39a76e7Sxw 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
230919397407SSherry Moore 	    "sge_flq0_cnt", -1);
2310d39a76e7Sxw 	if (val == -1)
2311d39a76e7Sxw 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
231219397407SSherry Moore 		    "sge-flq0-cnt", -1);
2313d39a76e7Sxw 	if (val != -1) {
2314d39a76e7Sxw 		if (val > 512)
2315d39a76e7Sxw 			sge_flq0_cnt = val;
2316d39a76e7Sxw 	}
2317d39a76e7Sxw 
2318d39a76e7Sxw 	if (sge_flq0_cnt > 65535) {
2319d39a76e7Sxw 		cmn_err(CE_WARN,
2320d39a76e7Sxw 		    "%s: sge-flq0-cnt > 65535 - resetting value to default",
232119397407SSherry Moore 		    chp->ch_name);
2322d39a76e7Sxw 		sge_flq0_cnt = sge_flq0_cnt_orig;
2323d39a76e7Sxw 	}
2324d39a76e7Sxw 
2325d39a76e7Sxw 	tval += sge_flq0_cnt;
2326d39a76e7Sxw 
2327d39a76e7Sxw 	/*
2328d39a76e7Sxw 	 * Provides a tuning capability for the free list 1 size.
2329d39a76e7Sxw 	 */
2330d39a76e7Sxw 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
233119397407SSherry Moore 	    "sge_flq1_cnt", -1);
2332d39a76e7Sxw 	if (val == -1)
2333d39a76e7Sxw 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
233419397407SSherry Moore 		    "sge-flq1-cnt", -1);
2335d39a76e7Sxw 	if (val != -1) {
2336d39a76e7Sxw 		if (val > 512)
2337d39a76e7Sxw 			sge_flq1_cnt = val;
2338d39a76e7Sxw 	}
2339d39a76e7Sxw 
2340d39a76e7Sxw 	if (sge_flq1_cnt > 65535) {
2341d39a76e7Sxw 		cmn_err(CE_WARN,
2342d39a76e7Sxw 		    "%s: sge-flq1-cnt > 65535 - resetting value to default",
234319397407SSherry Moore 		    chp->ch_name);
2344d39a76e7Sxw 		sge_flq1_cnt = sge_flq1_cnt_orig;
2345d39a76e7Sxw 	}
2346d39a76e7Sxw 
2347d39a76e7Sxw 	tval += sge_flq1_cnt;
2348d39a76e7Sxw 
2349d39a76e7Sxw 	/*
2350d39a76e7Sxw 	 * Provides a tuning capability for the responce queue size.
2351d39a76e7Sxw 	 */
2352d39a76e7Sxw 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
235319397407SSherry Moore 	    "sge_respq_cnt", -1);
2354d39a76e7Sxw 	if (val == -1)
2355d39a76e7Sxw 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
235619397407SSherry Moore 		    "sge-respq-cnt", -1);
2357d39a76e7Sxw 	if (val != -1) {
2358d39a76e7Sxw 		if (val > 30)
2359d39a76e7Sxw 			sge_respq_cnt = val;
2360d39a76e7Sxw 	}
2361d39a76e7Sxw 
2362d39a76e7Sxw 	if (sge_respq_cnt > 65535) {
2363d39a76e7Sxw 		cmn_err(CE_WARN,
2364d39a76e7Sxw 		    "%s: sge-respq-cnt > 65535 - resetting value to default",
236519397407SSherry Moore 		    chp->ch_name);
2366d39a76e7Sxw 		sge_respq_cnt = sge_respq_cnt_orig;
2367d39a76e7Sxw 	}
2368d39a76e7Sxw 
2369d39a76e7Sxw 	if (tval > sge_respq_cnt) {
2370d39a76e7Sxw 		if (tval <= 65535) {
2371d39a76e7Sxw 			cmn_err(CE_WARN,
2372d39a76e7Sxw 	    "%s: sge-respq-cnt < %d - setting value to %d (cmdQ+flq0+flq1)",
2373d39a76e7Sxw 			    chp->ch_name, tval, tval);
2374d39a76e7Sxw 
2375d39a76e7Sxw 			sge_respq_cnt = tval;
2376d39a76e7Sxw 		} else {
2377d39a76e7Sxw 			cmn_err(CE_WARN,
2378d39a76e7Sxw 			    "%s: Q sizes invalid - resetting to default values",
2379d39a76e7Sxw 			    chp->ch_name);
2380d39a76e7Sxw 
2381d39a76e7Sxw 			sge_cmdq0_cnt = sge_cmdq0_cnt_orig;
2382d39a76e7Sxw 			sge_cmdq1_cnt = sge_cmdq1_cnt_orig;
2383d39a76e7Sxw 			sge_flq0_cnt = sge_flq0_cnt_orig;
2384d39a76e7Sxw 			sge_flq1_cnt = sge_flq1_cnt_orig;
2385d39a76e7Sxw 			sge_respq_cnt = sge_respq_cnt_orig;
2386d39a76e7Sxw 		}
2387d39a76e7Sxw 	}
2388d39a76e7Sxw }
2389