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