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