13833Sxw161283 /*
23833Sxw161283 * CDDL HEADER START
33833Sxw161283 *
43833Sxw161283 * The contents of this file are subject to the terms of the
53833Sxw161283 * Common Development and Distribution License (the "License").
63833Sxw161283 * You may not use this file except in compliance with the License.
73833Sxw161283 *
83833Sxw161283 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93833Sxw161283 * or http://www.opensolaris.org/os/licensing.
103833Sxw161283 * See the License for the specific language governing permissions
113833Sxw161283 * and limitations under the License.
123833Sxw161283 *
133833Sxw161283 * When distributing Covered Code, include this CDDL HEADER in each
143833Sxw161283 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153833Sxw161283 * If applicable, add the following below this CDDL HEADER, with the
163833Sxw161283 * fields enclosed by brackets "[]" replaced with your own identifying
173833Sxw161283 * information: Portions Copyright [yyyy] [name of copyright owner]
183833Sxw161283 *
193833Sxw161283 * CDDL HEADER END
203833Sxw161283 */
213833Sxw161283
223833Sxw161283 /*
23*7656SSherry.Moore@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
243833Sxw161283 * Use is subject to license terms.
253833Sxw161283 */
263833Sxw161283
273833Sxw161283 /*
283833Sxw161283 * This file is part of the Chelsio T1 Ethernet driver.
293833Sxw161283 *
303833Sxw161283 * Copyright (C) 2003-2005 Chelsio Communications. All rights reserved.
313833Sxw161283 */
323833Sxw161283
333833Sxw161283 /*
343833Sxw161283 * Solaris Multithreaded STREAMS DLPI Chelsio PCI Ethernet Driver
353833Sxw161283 */
363833Sxw161283
373833Sxw161283 /* #define CH_DEBUG 1 */
383833Sxw161283 #ifdef CH_DEBUG
393833Sxw161283 #define DEBUG_ENTER(a) debug_enter(a)
403833Sxw161283 #define PRINT(a) printf a
413833Sxw161283 #else
423833Sxw161283 #define DEBUG_ENTER(a)
433833Sxw161283 #define PRINT(a)
443833Sxw161283 #endif
453833Sxw161283
463833Sxw161283 #include <sys/types.h>
473833Sxw161283 #include <sys/conf.h>
483833Sxw161283 #include <sys/debug.h>
493833Sxw161283 #include <sys/stropts.h>
503833Sxw161283 #include <sys/stream.h>
513833Sxw161283 #include <sys/strlog.h>
523833Sxw161283 #include <sys/kmem.h>
533833Sxw161283 #include <sys/stat.h>
543833Sxw161283 #include <sys/kstat.h>
553833Sxw161283 #include <sys/modctl.h>
563833Sxw161283 #include <sys/errno.h>
573833Sxw161283 #include <sys/cmn_err.h>
583833Sxw161283 #include <sys/ddi.h>
593833Sxw161283 #include <sys/sunddi.h>
603833Sxw161283 #include <sys/dlpi.h>
613833Sxw161283 #include <sys/ethernet.h>
623833Sxw161283 #include <sys/strsun.h>
633833Sxw161283 #include <sys/strsubr.h>
643833Sxw161283 #include <inet/common.h>
653833Sxw161283 #include <inet/nd.h>
663833Sxw161283 #include <inet/ip.h>
673833Sxw161283 #include <inet/tcp.h>
683833Sxw161283 #include <sys/pattr.h>
693833Sxw161283 #include <sys/gld.h>
703833Sxw161283 #include "ostypes.h"
713833Sxw161283 #include "common.h"
723833Sxw161283 #include "oschtoe.h"
733833Sxw161283 #include "sge.h"
74*7656SSherry.Moore@Sun.COM #include "regs.h"
753833Sxw161283 #include "ch.h" /* Chelsio Driver specific parameters */
763833Sxw161283 #include "version.h"
773833Sxw161283
783833Sxw161283 /*
793833Sxw161283 * Function prototypes.
803833Sxw161283 */
813833Sxw161283 static int ch_attach(dev_info_t *, ddi_attach_cmd_t);
823833Sxw161283 static int ch_detach(dev_info_t *, ddi_detach_cmd_t);
83*7656SSherry.Moore@Sun.COM static int ch_quiesce(dev_info_t *);
843833Sxw161283 static void ch_free_dma_handles(ch_t *chp);
853833Sxw161283 static void ch_set_name(ch_t *chp, int unit);
863833Sxw161283 static void ch_free_name(ch_t *chp);
873833Sxw161283 static void ch_get_prop(ch_t *chp);
883833Sxw161283
893833Sxw161283 #if defined(__sparc)
903833Sxw161283 static void ch_free_dvma_handles(ch_t *chp);
913833Sxw161283 #endif
923833Sxw161283
933833Sxw161283 /* GLD interfaces */
943833Sxw161283 static int ch_reset(gld_mac_info_t *);
953833Sxw161283 static int ch_start(gld_mac_info_t *);
963833Sxw161283 static int ch_stop(gld_mac_info_t *);
973833Sxw161283 static int ch_set_mac_address(gld_mac_info_t *, uint8_t *);
983833Sxw161283 static int ch_set_multicast(gld_mac_info_t *, uint8_t *, int);
993833Sxw161283 static int ch_ioctl(gld_mac_info_t *, queue_t *, mblk_t *);
1003833Sxw161283 static int ch_set_promiscuous(gld_mac_info_t *, int);
1013833Sxw161283 static int ch_get_stats(gld_mac_info_t *, struct gld_stats *);
1023833Sxw161283 static int ch_send(gld_mac_info_t *, mblk_t *);
1033833Sxw161283 static uint_t ch_intr(gld_mac_info_t *);
1043833Sxw161283
1053833Sxw161283 /*
1063833Sxw161283 * Data access requirements.
1073833Sxw161283 */
1083833Sxw161283 static struct ddi_device_acc_attr le_attr = {
1093833Sxw161283 DDI_DEVICE_ATTR_V0,
1103833Sxw161283 DDI_STRUCTURE_LE_ACC,
1113833Sxw161283 DDI_STRICTORDER_ACC
1123833Sxw161283 };
1133833Sxw161283
1143833Sxw161283 /*
1153833Sxw161283 * No swap mapping device attributes
1163833Sxw161283 */
1173833Sxw161283 static struct ddi_device_acc_attr null_attr = {
1183833Sxw161283 DDI_DEVICE_ATTR_V0,
1193833Sxw161283 DDI_NEVERSWAP_ACC,
1203833Sxw161283 DDI_STRICTORDER_ACC
1213833Sxw161283 };
1223833Sxw161283
1233833Sxw161283 /*
1243833Sxw161283 * STREAMS driver identification struture module_info(9s)
1253833Sxw161283 *
1263833Sxw161283 * driver limit values
1273833Sxw161283 */
1283833Sxw161283
1293833Sxw161283 static struct module_info ch_minfo = {
1303833Sxw161283 CHIDNUM, /* mi_idnum */
1313833Sxw161283 CHNAME, /* mi_idname */
1323833Sxw161283 CHMINPSZ, /* mi_minpsz */
1333833Sxw161283 CHMAXPSZ, /* mi_maxpsz */
1343833Sxw161283 CHHIWAT, /* mi_hiwat */
1353833Sxw161283 CHLOWAT /* mi_lowat */
1363833Sxw161283 };
1373833Sxw161283
1383833Sxw161283 /*
1393833Sxw161283 * STREAMS queue processiong procedures qinit(9s)
1403833Sxw161283 *
1413833Sxw161283 * read queue procedures
1423833Sxw161283 */
1433833Sxw161283
1443833Sxw161283 static struct qinit ch_rinit = {
1453833Sxw161283 (int (*)()) NULL, /* qi_putp */
1463833Sxw161283 gld_rsrv, /* qi_srvp */
1473833Sxw161283 gld_open, /* qi_qopen */
1483833Sxw161283 gld_close, /* qi_qclose */
1493833Sxw161283 (int (*)()) NULL, /* qi_qadmin */
1503833Sxw161283 &ch_minfo, /* qi_minfo */
1513833Sxw161283 NULL /* qi_mstat */
1523833Sxw161283 };
1533833Sxw161283
1543833Sxw161283 /*
1553833Sxw161283 * STREAMS queue processiong procedures qinit(9s)
1563833Sxw161283 *
1573833Sxw161283 * write queue procedures
1583833Sxw161283 */
1593833Sxw161283
1603833Sxw161283 static struct qinit ch_winit = {
1613833Sxw161283 gld_wput, /* qi_putp */
1623833Sxw161283 gld_wsrv, /* qi_srvp */
1633833Sxw161283 (int (*)()) NULL, /* qi_qopen */
1643833Sxw161283 (int (*)()) NULL, /* qi_qclose */
1653833Sxw161283 (int (*)()) NULL, /* qi_qadmin */
1663833Sxw161283 &ch_minfo, /* qi_minfo */
1673833Sxw161283 NULL /* qi_mstat */
1683833Sxw161283 };
1693833Sxw161283
1703833Sxw161283 /*
1713833Sxw161283 * STREAMS entity declaration structure - streamtab(9s)
1723833Sxw161283 */
1733833Sxw161283 static struct streamtab chinfo = {
1743833Sxw161283 &ch_rinit, /* read queue information */
1753833Sxw161283 &ch_winit, /* write queue information */
1763833Sxw161283 NULL, /* st_muxrinit */
1773833Sxw161283 NULL /* st_muxwrinit */
1783833Sxw161283 };
1793833Sxw161283
1803833Sxw161283 /*
1813833Sxw161283 * Device driver ops vector - cb_ops(9s)
1823833Sxw161283 *
1833833Sxw161283 * charater/block entry points structure.
1843833Sxw161283 * chinfo identifies driver as a STREAMS driver.
1853833Sxw161283 */
1863833Sxw161283
1873833Sxw161283 static struct cb_ops cb_ch_ops = {
1883833Sxw161283 nulldev, /* cb_open */
1893833Sxw161283 nulldev, /* cb_close */
1903833Sxw161283 nodev, /* cb_strategy */
1913833Sxw161283 nodev, /* cb_print */
1923833Sxw161283 nodev, /* cb_dump */
1933833Sxw161283 nodev, /* cb_read */
1943833Sxw161283 nodev, /* cb_write */
1953833Sxw161283 nodev, /* cb_ioctl */
1963833Sxw161283 nodev, /* cb_devmap */
1973833Sxw161283 nodev, /* cb_mmap */
1983833Sxw161283 nodev, /* cb_segmap */
1993833Sxw161283 nochpoll, /* cb_chpoll */
2003833Sxw161283 ddi_prop_op, /* report driver property information - prop_op(9e) */
2013833Sxw161283 &chinfo, /* cb_stream */
2023833Sxw161283 #if defined(__sparc)
2033833Sxw161283 D_MP | D_64BIT,
2043833Sxw161283 #else
2053833Sxw161283 D_MP, /* cb_flag (supports multi-threading) */
2063833Sxw161283 #endif
2073833Sxw161283 CB_REV, /* cb_rev */
2083833Sxw161283 nodev, /* cb_aread */
2093833Sxw161283 nodev /* cb_awrite */
2103833Sxw161283 };
2113833Sxw161283
2123833Sxw161283 /*
2133833Sxw161283 * dev_ops(9S) structure
2143833Sxw161283 *
2153833Sxw161283 * Device Operations table, for autoconfiguration
2163833Sxw161283 */
2173833Sxw161283
2183833Sxw161283 static struct dev_ops ch_ops = {
2193833Sxw161283 DEVO_REV, /* Driver build version */
2203833Sxw161283 0, /* Initial driver reference count */
2213833Sxw161283 gld_getinfo, /* funcp: get driver information - getinfo(9e) */
2223833Sxw161283 nulldev, /* funcp: entry point obsolute - identify(9e) */
2233833Sxw161283 nulldev, /* funp: probe for device - probe(9e) */
2243833Sxw161283 ch_attach, /* funp: attach driver to dev_info - attach(9e) */
2253833Sxw161283 ch_detach, /* funp: detach driver to unload - detach(9e) */
2263833Sxw161283 nodev, /* funp: reset device (not supported) - dev_ops(9s) */
2273833Sxw161283 &cb_ch_ops, /* ptr to cb_ops structure */
2283833Sxw161283 NULL, /* ptr to nexus bus operations structure (leaf) */
229*7656SSherry.Moore@Sun.COM NULL, /* funp: change device power level - power(9e) */
230*7656SSherry.Moore@Sun.COM ch_quiesce, /* devo_quiesce */
2313833Sxw161283 };
2323833Sxw161283
2333833Sxw161283 /*
2343833Sxw161283 * modldrv(9s) structure
2353833Sxw161283 *
2363833Sxw161283 * Definition for module specific device driver linkage structures (modctl.h)
2373833Sxw161283 */
2383833Sxw161283
2393833Sxw161283 static struct modldrv modldrv = {
2403833Sxw161283 &mod_driverops, /* driver module */
2413833Sxw161283 VERSION,
2423833Sxw161283 &ch_ops, /* driver ops */
2433833Sxw161283 };
2443833Sxw161283
2453833Sxw161283 /*
2463833Sxw161283 * modlinkage(9s) structure
2473833Sxw161283 *
2483833Sxw161283 * module linkage base structure (modctl.h)
2493833Sxw161283 */
2503833Sxw161283
2513833Sxw161283 static struct modlinkage modlinkage = {
2523833Sxw161283 MODREV_1, /* revision # of system */
2533833Sxw161283 &modldrv, /* NULL terminated list of linkage strucures */
2543833Sxw161283 NULL
2553833Sxw161283 };
2563833Sxw161283
2573833Sxw161283 /* ===================== start of STREAMS driver code ================== */
2583833Sxw161283
2593833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
2603833Sxw161283 /*
2613833Sxw161283 * global pointer to toe per-driver control structure.
2623833Sxw161283 */
2633833Sxw161283 #define MAX_CARDS 4
2643833Sxw161283 ch_t *gchp[MAX_CARDS];
2653833Sxw161283 #endif
2663833Sxw161283
2673833Sxw161283 kmutex_t in_use_l;
2683833Sxw161283 uint32_t buffers_in_use[SZ_INUSE];
2693833Sxw161283 uint32_t in_use_index;
2703833Sxw161283
2713833Sxw161283 /*
2723833Sxw161283 * Ethernet broadcast address definition.
2733833Sxw161283 */
2743833Sxw161283 static struct ether_addr etherbroadcastaddr = {
2753833Sxw161283 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
2763833Sxw161283 };
2773833Sxw161283
2783833Sxw161283 /*
2793833Sxw161283 * Module initialization functions.
2803833Sxw161283 *
2813833Sxw161283 * Routine Called by
2823833Sxw161283 * _init(9E) modload(9F)
2833833Sxw161283 * _info(9E) modinfo(9F)
2843833Sxw161283 * _fini(9E) modunload(9F)
2853833Sxw161283 */
2863833Sxw161283
2873833Sxw161283 /*
2883833Sxw161283 * _init(9E):
2893833Sxw161283 *
2903833Sxw161283 * Initial, one-time, resource allocation and data initialization.
2913833Sxw161283 */
2923833Sxw161283
2933833Sxw161283 int
_init(void)2943833Sxw161283 _init(void)
2953833Sxw161283 {
2963833Sxw161283 int status;
2973833Sxw161283
2983833Sxw161283 status = mod_install(&modlinkage);
2993833Sxw161283
3003833Sxw161283 mutex_init(&in_use_l, NULL, MUTEX_DRIVER, NULL);
3013833Sxw161283
3023833Sxw161283 return (status);
3033833Sxw161283 }
3043833Sxw161283
3053833Sxw161283 /*
3063833Sxw161283 * _fini(9E): It is here that any device information that was allocated
3073833Sxw161283 * during the _init(9E) routine should be released and the module removed
3083833Sxw161283 * from the system. In the case of per-instance information, that information
3093833Sxw161283 * should be released in the _detach(9E) routine.
3103833Sxw161283 */
3113833Sxw161283
3123833Sxw161283 int
_fini(void)3133833Sxw161283 _fini(void)
3143833Sxw161283 {
3153833Sxw161283 int status;
3163833Sxw161283 int i;
3173833Sxw161283 uint32_t t = 0;
3183833Sxw161283
3193833Sxw161283 for (i = 0; i < SZ_INUSE; i++)
3203833Sxw161283 t += buffers_in_use[i];
3213833Sxw161283
3223833Sxw161283 if (t != NULL)
3233833Sxw161283 return (DDI_FAILURE);
3243833Sxw161283
3253833Sxw161283 status = mod_remove(&modlinkage);
3263833Sxw161283
3273833Sxw161283 if (status == DDI_SUCCESS)
3283833Sxw161283 mutex_destroy(&in_use_l);
3293833Sxw161283
3303833Sxw161283 return (status);
3313833Sxw161283 }
3323833Sxw161283
3333833Sxw161283 int
_info(struct modinfo * modinfop)3343833Sxw161283 _info(struct modinfo *modinfop)
3353833Sxw161283 {
3363833Sxw161283 int status;
3373833Sxw161283
3383833Sxw161283
3393833Sxw161283 status = mod_info(&modlinkage, modinfop);
3403833Sxw161283
3413833Sxw161283 return (status);
3423833Sxw161283 }
3433833Sxw161283
3443833Sxw161283 /*
3453833Sxw161283 * Attach(9E) - This is called on the open to the device. It creates
3463833Sxw161283 * an instance of the driver. In this routine we create the minor
3473833Sxw161283 * device node. The routine also initializes all per-unit
3483833Sxw161283 * mutex's and conditional variables.
3493833Sxw161283 *
3503833Sxw161283 * If we were resuming a suspended instance of a device due to power
3513833Sxw161283 * management, then that would be handled here as well. For more on
3523833Sxw161283 * that subject see the man page for pm(9E)
3533833Sxw161283 *
3543833Sxw161283 * Interface exists: make available by filling in network interface
3553833Sxw161283 * record. System will initialize the interface when it is ready
3563833Sxw161283 * to accept packets.
3573833Sxw161283 */
3583833Sxw161283 int chdebug = 0;
3593833Sxw161283 int ch_abort_debug = 0;
3603833Sxw161283
3613833Sxw161283 static int
ch_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)3623833Sxw161283 ch_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
3633833Sxw161283 {
3643833Sxw161283 ch_t *chp;
3653833Sxw161283 int rv;
3663833Sxw161283 int unit;
3673833Sxw161283 #ifdef CH_DEBUG
3683833Sxw161283 int Version;
3693833Sxw161283 int VendorID;
3703833Sxw161283 int DeviceID;
3713833Sxw161283 int SubDeviceID;
3723833Sxw161283 int Command;
3733833Sxw161283 #endif
3743833Sxw161283 gld_mac_info_t *macinfo; /* GLD stuff follows */
3753833Sxw161283 char *driver;
3763833Sxw161283
3773833Sxw161283 if (ch_abort_debug)
3783833Sxw161283 debug_enter("ch_attach");
3793833Sxw161283
3803833Sxw161283 if (chdebug)
3813833Sxw161283 return (DDI_FAILURE);
3823833Sxw161283
3833833Sxw161283
3843833Sxw161283 if (cmd == DDI_ATTACH) {
3853833Sxw161283
3863833Sxw161283 unit = ddi_get_instance(dip);
3873833Sxw161283
3883833Sxw161283 driver = (char *)ddi_driver_name(dip);
3893833Sxw161283
3903833Sxw161283 PRINT(("driver %s unit: %d\n", driver, unit));
3913833Sxw161283
3923833Sxw161283 macinfo = gld_mac_alloc(dip);
3933833Sxw161283 if (macinfo == NULL) {
3943833Sxw161283 PRINT(("macinfo allocation failed\n"));
3953833Sxw161283 DEBUG_ENTER("ch_attach");
3963833Sxw161283 return (DDI_FAILURE);
3973833Sxw161283 }
3983833Sxw161283
3993833Sxw161283 chp = (ch_t *)kmem_zalloc(sizeof (ch_t), KM_SLEEP);
4003833Sxw161283
4013833Sxw161283 if (chp == NULL) {
4023833Sxw161283 PRINT(("zalloc of chp failed\n"));
4033833Sxw161283 DEBUG_ENTER("ch_attach");
4043833Sxw161283
4053833Sxw161283 gld_mac_free(macinfo);
4063833Sxw161283
4073833Sxw161283 return (DDI_FAILURE);
4083833Sxw161283 }
4093833Sxw161283
4103833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
4113833Sxw161283 /* Solaris TOE support */
4123833Sxw161283 gchp[unit] = chp;
4133833Sxw161283 #endif
4143833Sxw161283
4153833Sxw161283 PRINT(("attach macinfo: %p chp: %p\n", macinfo, chp));
4163833Sxw161283
4173833Sxw161283 chp->ch_dip = dip;
4183833Sxw161283 chp->ch_macp = macinfo;
4193833Sxw161283 chp->ch_unit = unit;
4203833Sxw161283 ch_set_name(chp, unit);
4213833Sxw161283
4223833Sxw161283 /*
4233833Sxw161283 * map in PCI register spaces
4243833Sxw161283 *
4253833Sxw161283 * PCI register set 0 - PCI configuration space
4263833Sxw161283 * PCI register set 1 - T101 card register space #1
4273833Sxw161283 */
4283833Sxw161283
4293833Sxw161283 /* map in T101 PCI configuration space */
4303833Sxw161283 rv = pci_config_setup(
431*7656SSherry.Moore@Sun.COM dip, /* ptr to dev's dev_info struct */
432*7656SSherry.Moore@Sun.COM &chp->ch_hpci); /* ptr to data access handle */
4333833Sxw161283
4343833Sxw161283 if (rv != DDI_SUCCESS) {
4353833Sxw161283 PRINT(("PCI config setup failed\n"));
4363833Sxw161283 DEBUG_ENTER("ch_attach");
4373833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
4383833Sxw161283 gchp[unit] = NULL;
4393833Sxw161283 #endif
4403833Sxw161283 cmn_err(CE_WARN, "%s: ddi_config_setup PCI error %d\n",
441*7656SSherry.Moore@Sun.COM chp->ch_name, rv);
4423833Sxw161283
4433833Sxw161283 ch_free_name(chp);
4443833Sxw161283 kmem_free(chp, sizeof (ch_t));
4453833Sxw161283 gld_mac_free(macinfo);
4463833Sxw161283
4473833Sxw161283 return (DDI_FAILURE);
4483833Sxw161283 }
4493833Sxw161283
4503833Sxw161283 ch_get_prop(chp);
4513833Sxw161283
4523833Sxw161283 macinfo->gldm_devinfo = dip;
4533833Sxw161283 macinfo->gldm_private = (caddr_t)chp;
4543833Sxw161283 macinfo->gldm_reset = ch_reset;
4553833Sxw161283 macinfo->gldm_start = ch_start;
4563833Sxw161283 macinfo->gldm_stop = ch_stop;
4573833Sxw161283 macinfo->gldm_set_mac_addr = ch_set_mac_address;
4583833Sxw161283 macinfo->gldm_send = ch_send;
4593833Sxw161283 macinfo->gldm_set_promiscuous = ch_set_promiscuous;
4603833Sxw161283 macinfo->gldm_get_stats = ch_get_stats;
4613833Sxw161283 macinfo->gldm_ioctl = ch_ioctl;
4623833Sxw161283 macinfo->gldm_set_multicast = ch_set_multicast;
4633833Sxw161283 macinfo->gldm_intr = ch_intr;
4643833Sxw161283 macinfo->gldm_mctl = NULL;
4653833Sxw161283
4663833Sxw161283 macinfo->gldm_ident = driver;
4673833Sxw161283 macinfo->gldm_type = DL_ETHER;
4683833Sxw161283 macinfo->gldm_minpkt = 0;
4693833Sxw161283 macinfo->gldm_maxpkt = chp->ch_mtu;
4703833Sxw161283 macinfo->gldm_addrlen = ETHERADDRL;
4713833Sxw161283 macinfo->gldm_saplen = -2;
4723833Sxw161283 macinfo->gldm_ppa = unit;
4733833Sxw161283 macinfo->gldm_broadcast_addr =
474*7656SSherry.Moore@Sun.COM etherbroadcastaddr.ether_addr_octet;
4753833Sxw161283
4763833Sxw161283
4773833Sxw161283 /*
4783833Sxw161283 * do a power reset of card
4793833Sxw161283 *
4803833Sxw161283 * 1. set PwrState to D3hot (3)
4813833Sxw161283 * 2. clear PwrState flags
4823833Sxw161283 */
4833833Sxw161283 pci_config_put32(chp->ch_hpci, 0x44, 3);
4843833Sxw161283 pci_config_put32(chp->ch_hpci, 0x44, 0);
4853833Sxw161283
4863833Sxw161283 /* delay .5 sec */
4873833Sxw161283 DELAY(500000);
4883833Sxw161283
4893833Sxw161283 #ifdef CH_DEBUG
4903833Sxw161283 VendorID = pci_config_get16(chp->ch_hpci, 0);
4913833Sxw161283 DeviceID = pci_config_get16(chp->ch_hpci, 2);
4923833Sxw161283 SubDeviceID = pci_config_get16(chp->ch_hpci, 0x2e);
4933833Sxw161283 Command = pci_config_get16(chp->ch_hpci, 4);
4943833Sxw161283
4953833Sxw161283 PRINT(("IDs: %x,%x,%x\n", VendorID, DeviceID, SubDeviceID));
4963833Sxw161283 PRINT(("Command: %x\n", Command));
4973833Sxw161283 #endif
4983833Sxw161283 /* map in T101 register space (BAR0) */
4993833Sxw161283 rv = ddi_regs_map_setup(
500*7656SSherry.Moore@Sun.COM dip, /* ptr to dev's dev_info struct */
501*7656SSherry.Moore@Sun.COM BAR0, /* register address space */
502*7656SSherry.Moore@Sun.COM &chp->ch_bar0, /* address of offset */
503*7656SSherry.Moore@Sun.COM 0, /* offset into register address space */
504*7656SSherry.Moore@Sun.COM 0, /* length mapped (everything) */
505*7656SSherry.Moore@Sun.COM &le_attr, /* ptr to device attr structure */
506*7656SSherry.Moore@Sun.COM &chp->ch_hbar0); /* ptr to data access handle */
5073833Sxw161283
5083833Sxw161283 if (rv != DDI_SUCCESS) {
5093833Sxw161283 PRINT(("map registers failed\n"));
5103833Sxw161283 DEBUG_ENTER("ch_attach");
5113833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
5123833Sxw161283 gchp[unit] = NULL;
5133833Sxw161283 #endif
5143833Sxw161283 cmn_err(CE_WARN,
515*7656SSherry.Moore@Sun.COM "%s: ddi_regs_map_setup BAR0 error %d\n",
516*7656SSherry.Moore@Sun.COM chp->ch_name, rv);
5173833Sxw161283
5183833Sxw161283 pci_config_teardown(&chp->ch_hpci);
5193833Sxw161283 ch_free_name(chp);
5203833Sxw161283 kmem_free(chp, sizeof (ch_t));
5213833Sxw161283 gld_mac_free(macinfo);
5223833Sxw161283
5233833Sxw161283 return (DDI_FAILURE);
5243833Sxw161283 }
5253833Sxw161283
5263833Sxw161283 #ifdef CH_DEBUG
5273833Sxw161283 Version = ddi_get32(chp->ch_hbar0,
528*7656SSherry.Moore@Sun.COM (uint32_t *)(chp->ch_bar0+0x6c));
5293833Sxw161283 #endif
5303833Sxw161283
5313833Sxw161283 (void) ddi_dev_regsize(dip, 1, &chp->ch_bar0sz);
5323833Sxw161283
5333833Sxw161283 PRINT(("PCI BAR0 space addr: %p\n", chp->ch_bar0));
5343833Sxw161283 PRINT(("PCI BAR0 space size: %x\n", chp->ch_bar0sz));
5353833Sxw161283 PRINT(("PE Version: %x\n", Version));
5363833Sxw161283
5373833Sxw161283 /*
5383833Sxw161283 * Add interrupt to system.
5393833Sxw161283 */
5403833Sxw161283 rv = ddi_get_iblock_cookie(
541*7656SSherry.Moore@Sun.COM dip, /* ptr to dev's dev_info struct */
542*7656SSherry.Moore@Sun.COM 0, /* interrupt # (0) */
543*7656SSherry.Moore@Sun.COM &chp->ch_icookp); /* ptr to interrupt block cookie */
5443833Sxw161283
5453833Sxw161283 if (rv != DDI_SUCCESS) {
5463833Sxw161283 PRINT(("iblock cookie failed\n"));
5473833Sxw161283 DEBUG_ENTER("ch_attach");
5483833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
5493833Sxw161283 gchp[unit] = NULL;
5503833Sxw161283 #endif
5513833Sxw161283 cmn_err(CE_WARN,
552*7656SSherry.Moore@Sun.COM "%s: ddi_get_iblock_cookie error %d\n",
553*7656SSherry.Moore@Sun.COM chp->ch_name, rv);
5543833Sxw161283
5553833Sxw161283 ddi_regs_map_free(&chp->ch_hbar0);
5563833Sxw161283 pci_config_teardown(&chp->ch_hpci);
5573833Sxw161283 ch_free_name(chp);
5583833Sxw161283 kmem_free(chp, sizeof (ch_t));
5593833Sxw161283 gld_mac_free(macinfo);
5603833Sxw161283
5613833Sxw161283 return (DDI_FAILURE);
5623833Sxw161283 }
5633833Sxw161283
5643833Sxw161283 /*
5653833Sxw161283 * add interrupt handler before card setup.
5663833Sxw161283 */
5673833Sxw161283 rv = ddi_add_intr(
568*7656SSherry.Moore@Sun.COM dip, /* ptr to dev's dev_info struct */
569*7656SSherry.Moore@Sun.COM 0, /* interrupt # (0) */
570*7656SSherry.Moore@Sun.COM 0, /* iblock cookie ptr (NULL) */
571*7656SSherry.Moore@Sun.COM 0, /* idevice cookie ptr (NULL) */
572*7656SSherry.Moore@Sun.COM gld_intr, /* function ptr to interrupt handler */
573*7656SSherry.Moore@Sun.COM (caddr_t)macinfo); /* handler argument */
5743833Sxw161283
5753833Sxw161283 if (rv != DDI_SUCCESS) {
5763833Sxw161283 PRINT(("add_intr failed\n"));
5773833Sxw161283 DEBUG_ENTER("ch_attach");
5783833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
5793833Sxw161283 gchp[unit] = NULL;
5803833Sxw161283 #endif
5813833Sxw161283 cmn_err(CE_WARN, "%s: ddi_add_intr error %d\n",
582*7656SSherry.Moore@Sun.COM chp->ch_name, rv);
5833833Sxw161283
5843833Sxw161283 ddi_regs_map_free(&chp->ch_hbar0);
5853833Sxw161283 pci_config_teardown(&chp->ch_hpci);
5863833Sxw161283 ch_free_name(chp);
5873833Sxw161283 kmem_free(chp, sizeof (ch_t));
5883833Sxw161283 gld_mac_free(macinfo);
5893833Sxw161283
5903833Sxw161283 return (DDI_FAILURE);
5913833Sxw161283 }
5923833Sxw161283
5933833Sxw161283 /* initalize all the remaining per-card locks */
5943833Sxw161283 mutex_init(&chp->ch_lock, NULL, MUTEX_DRIVER,
595*7656SSherry.Moore@Sun.COM (void *)chp->ch_icookp);
5963833Sxw161283 mutex_init(&chp->ch_intr, NULL, MUTEX_DRIVER,
597*7656SSherry.Moore@Sun.COM (void *)chp->ch_icookp);
5983833Sxw161283 mutex_init(&chp->ch_mc_lck, NULL, MUTEX_DRIVER, NULL);
5993833Sxw161283 mutex_init(&chp->ch_dh_lck, NULL, MUTEX_DRIVER, NULL);
6003833Sxw161283 mutex_init(&chp->mac_lock, NULL, MUTEX_DRIVER, NULL);
6013833Sxw161283
6023833Sxw161283 /* ------- initialize Chelsio card ------- */
6033833Sxw161283
6043833Sxw161283 if (pe_attach(chp)) {
6053833Sxw161283 PRINT(("card initialization failed\n"));
6063833Sxw161283 DEBUG_ENTER("ch_attach");
6073833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
6083833Sxw161283 gchp[unit] = NULL;
6093833Sxw161283 #endif
6103833Sxw161283 cmn_err(CE_WARN, "%s: pe_attach failed\n",
611*7656SSherry.Moore@Sun.COM chp->ch_name);
6123833Sxw161283
6133833Sxw161283 mutex_destroy(&chp->ch_lock);
6143833Sxw161283 mutex_destroy(&chp->ch_intr);
6153833Sxw161283 mutex_destroy(&chp->ch_mc_lck);
6163833Sxw161283 mutex_destroy(&chp->ch_dh_lck);
6173833Sxw161283 mutex_destroy(&chp->mac_lock);
6183833Sxw161283 ddi_remove_intr(dip, 0, chp->ch_icookp);
6193833Sxw161283 ddi_regs_map_free(&chp->ch_hbar0);
6203833Sxw161283 pci_config_teardown(&chp->ch_hpci);
6213833Sxw161283 ch_free_name(chp);
6223833Sxw161283 kmem_free(chp, sizeof (ch_t));
6233833Sxw161283 gld_mac_free(macinfo);
6243833Sxw161283
6253833Sxw161283 return (DDI_FAILURE);
6263833Sxw161283 }
6273833Sxw161283
6283833Sxw161283 /* ------- done with Chelsio card ------- */
6293833Sxw161283
6303833Sxw161283 /* now can set mac address */
6313833Sxw161283 macinfo->gldm_vendor_addr = pe_get_mac(chp);
6323833Sxw161283
6333833Sxw161283 macinfo->gldm_cookie = chp->ch_icookp;
6343833Sxw161283
6353833Sxw161283 /*
6363833Sxw161283 * We only active checksum offload for T2 architectures.
6373833Sxw161283 */
6383833Sxw161283 if (is_T2(chp)) {
6393833Sxw161283 if (chp->ch_config.cksum_enabled)
6403833Sxw161283 macinfo->gldm_capabilities |=
6413833Sxw161283 GLD_CAP_CKSUM_FULL_V4;
6423833Sxw161283 } else
6433833Sxw161283 chp->ch_config.cksum_enabled = 0;
6443833Sxw161283
6453833Sxw161283 rv = gld_register(
646*7656SSherry.Moore@Sun.COM dip, /* ptr to dev's dev_info struct */
647*7656SSherry.Moore@Sun.COM (char *)ddi_driver_name(dip), /* driver name */
648*7656SSherry.Moore@Sun.COM macinfo); /* ptr to gld macinfo buffer */
6493833Sxw161283
6503833Sxw161283 /*
6513833Sxw161283 * The Jumbo frames capability is not yet available
6523833Sxw161283 * in Solaris 10 so registration will fail. MTU > 1500 is
6533833Sxw161283 * supported in Update 1.
6543833Sxw161283 */
6553833Sxw161283 if (rv != DDI_SUCCESS) {
6563833Sxw161283 cmn_err(CE_NOTE, "MTU > 1500 not supported by GLD.\n");
6573833Sxw161283 cmn_err(CE_NOTE, "Setting MTU to 1500. \n");
6583833Sxw161283 macinfo->gldm_maxpkt = chp->ch_mtu = 1500;
6593833Sxw161283 rv = gld_register(
660*7656SSherry.Moore@Sun.COM dip, /* ptr to dev's dev_info struct */
661*7656SSherry.Moore@Sun.COM (char *)ddi_driver_name(dip), /* driver name */
662*7656SSherry.Moore@Sun.COM macinfo); /* ptr to gld macinfo buffer */
6633833Sxw161283 }
6643833Sxw161283
6653833Sxw161283
6663833Sxw161283 if (rv != DDI_SUCCESS) {
6673833Sxw161283 PRINT(("gld_register failed\n"));
6683833Sxw161283 DEBUG_ENTER("ch_attach");
6693833Sxw161283
6703833Sxw161283 cmn_err(CE_WARN, "%s: gld_register error %d\n",
671*7656SSherry.Moore@Sun.COM chp->ch_name, rv);
6723833Sxw161283
6733833Sxw161283 pe_detach(chp);
6743833Sxw161283
6753833Sxw161283 mutex_destroy(&chp->ch_lock);
6763833Sxw161283 mutex_destroy(&chp->ch_intr);
6773833Sxw161283 mutex_destroy(&chp->ch_mc_lck);
6783833Sxw161283 mutex_destroy(&chp->ch_dh_lck);
6793833Sxw161283 mutex_destroy(&chp->mac_lock);
6803833Sxw161283 ddi_remove_intr(dip, 0, chp->ch_icookp);
6813833Sxw161283 ddi_regs_map_free(&chp->ch_hbar0);
6823833Sxw161283 pci_config_teardown(&chp->ch_hpci);
6833833Sxw161283 ch_free_name(chp);
6843833Sxw161283 kmem_free(chp, sizeof (ch_t));
6853833Sxw161283 gld_mac_free(macinfo);
6863833Sxw161283
6873833Sxw161283 return (DDI_FAILURE);
6883833Sxw161283 }
6893833Sxw161283
6903833Sxw161283 /*
6913833Sxw161283 * print a banner at boot time (verbose mode), announcing
6923833Sxw161283 * the device pointed to by dip
6933833Sxw161283 */
6943833Sxw161283 ddi_report_dev(dip);
6953833Sxw161283
6963833Sxw161283 if (ch_abort_debug)
6973833Sxw161283 debug_enter("ch_attach");
6983833Sxw161283
6993833Sxw161283 return (DDI_SUCCESS);
7003833Sxw161283
7013833Sxw161283 } else if (cmd == DDI_RESUME) {
7023833Sxw161283 PRINT(("attach resume\n"));
7033833Sxw161283 DEBUG_ENTER("ch_attach");
7043833Sxw161283 if ((chp = (ch_t *)ddi_get_driver_private(dip)) == NULL)
7053833Sxw161283 return (DDI_FAILURE);
7063833Sxw161283
7073833Sxw161283 mutex_enter(&chp->ch_lock);
7083833Sxw161283 chp->ch_flags &= ~PESUSPENDED;
7093833Sxw161283 mutex_exit(&chp->ch_lock);
7103833Sxw161283 return (DDI_SUCCESS);
7113833Sxw161283 } else {
7123833Sxw161283 PRINT(("attach: bad command\n"));
7133833Sxw161283 DEBUG_ENTER("ch_attach");
7143833Sxw161283
7153833Sxw161283 return (DDI_FAILURE);
7163833Sxw161283 }
7173833Sxw161283 }
7183833Sxw161283
719*7656SSherry.Moore@Sun.COM /*
720*7656SSherry.Moore@Sun.COM * quiesce(9E) entry point.
721*7656SSherry.Moore@Sun.COM *
722*7656SSherry.Moore@Sun.COM * This function is called when the system is single-threaded at high
723*7656SSherry.Moore@Sun.COM * PIL with preemption disabled. Therefore, this function must not be
724*7656SSherry.Moore@Sun.COM * blocked.
725*7656SSherry.Moore@Sun.COM *
726*7656SSherry.Moore@Sun.COM * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
727*7656SSherry.Moore@Sun.COM * DDI_FAILURE indicates an error condition and should almost never happen.
728*7656SSherry.Moore@Sun.COM */
729*7656SSherry.Moore@Sun.COM static int
ch_quiesce(dev_info_t * dip)730*7656SSherry.Moore@Sun.COM ch_quiesce(dev_info_t *dip)
731*7656SSherry.Moore@Sun.COM {
732*7656SSherry.Moore@Sun.COM ch_t *chp;
733*7656SSherry.Moore@Sun.COM gld_mac_info_t *macinfo =
734*7656SSherry.Moore@Sun.COM (gld_mac_info_t *)ddi_get_driver_private(dip);
735*7656SSherry.Moore@Sun.COM
736*7656SSherry.Moore@Sun.COM chp = (ch_t *)macinfo->gldm_private;
737*7656SSherry.Moore@Sun.COM chdebug = 0;
738*7656SSherry.Moore@Sun.COM ch_abort_debug = 0;
739*7656SSherry.Moore@Sun.COM
740*7656SSherry.Moore@Sun.COM #ifdef CONFIG_CHELSIO_T1_OFFLOAD
741*7656SSherry.Moore@Sun.COM gchp[chp->ch_unit] = NULL;
742*7656SSherry.Moore@Sun.COM #endif
743*7656SSherry.Moore@Sun.COM
744*7656SSherry.Moore@Sun.COM /* Set driver state for this card to IDLE */
745*7656SSherry.Moore@Sun.COM chp->ch_state = PEIDLE;
746*7656SSherry.Moore@Sun.COM
747*7656SSherry.Moore@Sun.COM /*
748*7656SSherry.Moore@Sun.COM * Do a power reset of card
749*7656SSherry.Moore@Sun.COM * 1. set PwrState to D3hot (3)
750*7656SSherry.Moore@Sun.COM * 2. clear PwrState flags
751*7656SSherry.Moore@Sun.COM */
752*7656SSherry.Moore@Sun.COM pci_config_put32(chp->ch_hpci, 0x44, 3);
753*7656SSherry.Moore@Sun.COM pci_config_put32(chp->ch_hpci, 0x44, 0);
754*7656SSherry.Moore@Sun.COM
755*7656SSherry.Moore@Sun.COM /* Wait 0.5 sec */
756*7656SSherry.Moore@Sun.COM drv_usecwait(500000);
757*7656SSherry.Moore@Sun.COM
758*7656SSherry.Moore@Sun.COM /*
759*7656SSherry.Moore@Sun.COM * Now stop the chip
760*7656SSherry.Moore@Sun.COM */
761*7656SSherry.Moore@Sun.COM chp->ch_refcnt = 0;
762*7656SSherry.Moore@Sun.COM chp->ch_state = PESTOP;
763*7656SSherry.Moore@Sun.COM
764*7656SSherry.Moore@Sun.COM /* Disables all interrupts */
765*7656SSherry.Moore@Sun.COM t1_interrupts_disable(chp);
766*7656SSherry.Moore@Sun.COM
767*7656SSherry.Moore@Sun.COM /* Disables SGE queues */
768*7656SSherry.Moore@Sun.COM t1_write_reg_4(chp->sge->obj, A_SG_CONTROL, 0x0);
769*7656SSherry.Moore@Sun.COM t1_write_reg_4(chp->sge->obj, A_SG_INT_CAUSE, 0x0);
770*7656SSherry.Moore@Sun.COM
771*7656SSherry.Moore@Sun.COM return (DDI_SUCCESS);
772*7656SSherry.Moore@Sun.COM }
773*7656SSherry.Moore@Sun.COM
7743833Sxw161283 static int
ch_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)7753833Sxw161283 ch_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
7763833Sxw161283 {
7773833Sxw161283 gld_mac_info_t *macinfo;
7783833Sxw161283 ch_t *chp;
7793833Sxw161283
7803833Sxw161283 if (cmd == DDI_DETACH) {
7813833Sxw161283 macinfo = (gld_mac_info_t *)ddi_get_driver_private(dip);
7823833Sxw161283 chp = (ch_t *)macinfo->gldm_private;
7833833Sxw161283
7843833Sxw161283 /*
7853833Sxw161283 * fail detach if there are outstanding mblks still
7863833Sxw161283 * in use somewhere.
7873833Sxw161283 */
7883833Sxw161283 DEBUG_ENTER("ch_detach");
7893833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
7903833Sxw161283 mutex_enter(&chp->ch_lock);
7913833Sxw161283 if (chp->ch_refcnt > 0) {
7923833Sxw161283 mutex_exit(&chp->ch_lock);
7933833Sxw161283 return (DDI_FAILURE);
7943833Sxw161283 }
7953833Sxw161283 mutex_exit(&chp->ch_lock);
7963833Sxw161283 gchp[chp->ch_unit] = NULL;
7973833Sxw161283 #endif
7983833Sxw161283 /*
7993833Sxw161283 * set driver state for this card to IDLE. We're
8003833Sxw161283 * shutting down.
8013833Sxw161283 */
8023833Sxw161283 mutex_enter(&chp->ch_lock);
8033833Sxw161283 chp->ch_state = PEIDLE;
8043833Sxw161283 mutex_exit(&chp->ch_lock);
8053833Sxw161283
8063833Sxw161283 /*
8073833Sxw161283 * do a power reset of card
8083833Sxw161283 *
8093833Sxw161283 * 1. set PwrState to D3hot (3)
8103833Sxw161283 * 2. clear PwrState flags
8113833Sxw161283 */
8123833Sxw161283 pci_config_put32(chp->ch_hpci, 0x44, 3);
8133833Sxw161283 pci_config_put32(chp->ch_hpci, 0x44, 0);
8143833Sxw161283
8153833Sxw161283 /* delay .5 sec */
8163833Sxw161283 DELAY(500000);
8173833Sxw161283
8183833Sxw161283 /* free register resources */
8193833Sxw161283 (void) gld_unregister(macinfo);
8203833Sxw161283
8213833Sxw161283 /* make sure no interrupts while shutting down card */
8223833Sxw161283 ddi_remove_intr(dip, 0, chp->ch_icookp);
8233833Sxw161283
8243833Sxw161283 /*
8253833Sxw161283 * reset device and recover resources
8263833Sxw161283 */
8273833Sxw161283 pe_detach(chp);
8283833Sxw161283
8293833Sxw161283 ddi_regs_map_free(&chp->ch_hbar0);
8303833Sxw161283 pci_config_teardown(&chp->ch_hpci);
8313833Sxw161283 mutex_destroy(&chp->ch_lock);
8323833Sxw161283 mutex_destroy(&chp->ch_intr);
8333833Sxw161283 mutex_destroy(&chp->ch_mc_lck);
8343833Sxw161283 mutex_destroy(&chp->ch_dh_lck);
8353833Sxw161283 mutex_destroy(&chp->mac_lock);
8363833Sxw161283 ch_free_dma_handles(chp);
8373833Sxw161283 #if defined(__sparc)
8383833Sxw161283 ch_free_dvma_handles(chp);
8393833Sxw161283 #endif
8403833Sxw161283 ch_free_name(chp);
8413833Sxw161283 kmem_free(chp, sizeof (ch_t));
8423833Sxw161283 gld_mac_free(macinfo);
8433833Sxw161283
8443833Sxw161283 DEBUG_ENTER("ch_detach end");
8453833Sxw161283
8463833Sxw161283 return (DDI_SUCCESS);
8473833Sxw161283
8483833Sxw161283 } else if ((cmd == DDI_SUSPEND) || (cmd == DDI_PM_SUSPEND)) {
8493833Sxw161283 DEBUG_ENTER("suspend");
8503833Sxw161283 if ((chp = (ch_t *)ddi_get_driver_private(dip)) == NULL)
8513833Sxw161283 return (DDI_FAILURE);
8523833Sxw161283 mutex_enter(&chp->ch_lock);
8533833Sxw161283 chp->ch_flags |= PESUSPENDED;
8543833Sxw161283 mutex_exit(&chp->ch_lock);
8553833Sxw161283 #ifdef TODO
8563833Sxw161283 /* Un-initialize (STOP) T101 */
8573833Sxw161283 #endif
8583833Sxw161283 return (DDI_SUCCESS);
8593833Sxw161283 } else
8603833Sxw161283 return (DDI_FAILURE);
8613833Sxw161283 }
8623833Sxw161283
8633833Sxw161283 /*
8643833Sxw161283 * ch_alloc_dma_mem
8653833Sxw161283 *
8663833Sxw161283 * allocates DMA handle
8673833Sxw161283 * allocates kernel memory
8683833Sxw161283 * allocates DMA access handle
8693833Sxw161283 *
8703833Sxw161283 * chp - per-board descriptor
8713833Sxw161283 * type - byteswap mapping?
8723833Sxw161283 * flags - type of mapping
8733833Sxw161283 * size - # bytes mapped
8743833Sxw161283 * paddr - physical address
8753833Sxw161283 * dh - ddi dma handle
8763833Sxw161283 * ah - ddi access handle
8773833Sxw161283 */
8783833Sxw161283
8793833Sxw161283 void *
ch_alloc_dma_mem(ch_t * chp,int type,int flags,int size,uint64_t * paddr,ulong_t * dh,ulong_t * ah)8803833Sxw161283 ch_alloc_dma_mem(ch_t *chp, int type, int flags, int size, uint64_t *paddr,
8813833Sxw161283 ulong_t *dh, ulong_t *ah)
8823833Sxw161283 {
8833833Sxw161283 ddi_dma_attr_t ch_dma_attr;
8843833Sxw161283 ddi_dma_cookie_t cookie;
8853833Sxw161283 ddi_dma_handle_t ch_dh;
8863833Sxw161283 ddi_acc_handle_t ch_ah;
8873833Sxw161283 ddi_device_acc_attr_t *dev_attrp;
8883833Sxw161283 caddr_t ch_vaddr;
8893833Sxw161283 size_t rlen;
8903833Sxw161283 uint_t count;
8913833Sxw161283 uint_t mapping;
8923833Sxw161283 uint_t align;
8933833Sxw161283 uint_t rv;
8943833Sxw161283 uint_t direction;
8953833Sxw161283
8963833Sxw161283 mapping = (flags&DMA_STREAM)?DDI_DMA_STREAMING:DDI_DMA_CONSISTENT;
8973833Sxw161283 if (flags & DMA_4KALN)
8983833Sxw161283 align = 0x4000;
8993833Sxw161283 else if (flags & DMA_SMALN)
9003833Sxw161283 align = chp->ch_sm_buf_aln;
9013833Sxw161283 else if (flags & DMA_BGALN)
9023833Sxw161283 align = chp->ch_bg_buf_aln;
9033833Sxw161283 else {
9043833Sxw161283 cmn_err(CE_WARN, "ch_alloc_dma_mem(%s): bad alignment flag\n",
9053833Sxw161283 chp->ch_name);
9063833Sxw161283 return (0);
9073833Sxw161283 }
9083833Sxw161283 direction = (flags&DMA_OUT)?DDI_DMA_WRITE:DDI_DMA_READ;
9093833Sxw161283
9103833Sxw161283 /*
9113833Sxw161283 * dynamically create a dma attribute structure
9123833Sxw161283 */
9133833Sxw161283 ch_dma_attr.dma_attr_version = DMA_ATTR_V0;
9143833Sxw161283 ch_dma_attr.dma_attr_addr_lo = 0;
9153833Sxw161283 ch_dma_attr.dma_attr_addr_hi = 0xffffffffffffffff;
9163833Sxw161283 ch_dma_attr.dma_attr_count_max = 0x00ffffff;
9173833Sxw161283 ch_dma_attr.dma_attr_align = align;
9183833Sxw161283 ch_dma_attr.dma_attr_burstsizes = 0xfff;
9193833Sxw161283 ch_dma_attr.dma_attr_minxfer = 1;
9203833Sxw161283 ch_dma_attr.dma_attr_maxxfer = 0x00ffffff;
9213833Sxw161283 ch_dma_attr.dma_attr_seg = 0xffffffff;
9223833Sxw161283 ch_dma_attr.dma_attr_sgllen = 1;
9233833Sxw161283 ch_dma_attr.dma_attr_granular = 1;
9243833Sxw161283 ch_dma_attr.dma_attr_flags = 0;
9253833Sxw161283
9263833Sxw161283 rv = ddi_dma_alloc_handle(
9273833Sxw161283 chp->ch_dip, /* device dev_info structure */
9283833Sxw161283 &ch_dma_attr, /* DMA attributes */
9293833Sxw161283 DDI_DMA_SLEEP, /* Wait if no memory */
9303833Sxw161283 NULL, /* no argument to callback */
9313833Sxw161283 &ch_dh); /* DMA handle */
9323833Sxw161283 if (rv != DDI_SUCCESS) {
9333833Sxw161283
9343833Sxw161283 cmn_err(CE_WARN,
935*7656SSherry.Moore@Sun.COM "%s: ch_alloc_dma_mem: ddi_dma_alloc_handle error %d\n",
936*7656SSherry.Moore@Sun.COM chp->ch_name, rv);
9373833Sxw161283
9383833Sxw161283 return (0);
9393833Sxw161283 }
9403833Sxw161283
9413833Sxw161283 /* set byte order for data xfer */
9423833Sxw161283 if (type)
9433833Sxw161283 dev_attrp = &null_attr;
9443833Sxw161283 else
9453833Sxw161283 dev_attrp = &le_attr;
9463833Sxw161283
9473833Sxw161283 rv = ddi_dma_mem_alloc(
9483833Sxw161283 ch_dh, /* dma handle */
9493833Sxw161283 size, /* size desired allocate */
9503833Sxw161283 dev_attrp, /* access attributes */
9513833Sxw161283 mapping,
9523833Sxw161283 DDI_DMA_SLEEP, /* wait for resources */
9533833Sxw161283 NULL, /* no argument */
9543833Sxw161283 &ch_vaddr, /* allocated memory */
9553833Sxw161283 &rlen, /* real size allocated */
9563833Sxw161283 &ch_ah); /* data access handle */
9573833Sxw161283 if (rv != DDI_SUCCESS) {
9583833Sxw161283 ddi_dma_free_handle(&ch_dh);
9593833Sxw161283
9603833Sxw161283 cmn_err(CE_WARN,
961*7656SSherry.Moore@Sun.COM "%s: ch_alloc_dma_mem: ddi_dma_mem_alloc error %d\n",
962*7656SSherry.Moore@Sun.COM chp->ch_name, rv);
9633833Sxw161283
9643833Sxw161283 return (0);
9653833Sxw161283 }
9663833Sxw161283
9673833Sxw161283 rv = ddi_dma_addr_bind_handle(
9683833Sxw161283 ch_dh, /* dma handle */
9693833Sxw161283 (struct as *)0, /* kernel address space */
9703833Sxw161283 ch_vaddr, /* virtual address */
9713833Sxw161283 rlen, /* length of object */
9723833Sxw161283 direction|mapping,
9733833Sxw161283 DDI_DMA_SLEEP, /* Wait for resources */
9743833Sxw161283 NULL, /* no argument */
9753833Sxw161283 &cookie, /* dma cookie */
9763833Sxw161283 &count);
9773833Sxw161283 if (rv != DDI_DMA_MAPPED) {
9783833Sxw161283 ddi_dma_mem_free(&ch_ah);
9793833Sxw161283 ddi_dma_free_handle(&ch_dh);
9803833Sxw161283
9813833Sxw161283 cmn_err(CE_WARN,
9823833Sxw161283 "%s: ch_alloc_dma_mem: ddi_dma_addr_bind_handle error %d\n",
983*7656SSherry.Moore@Sun.COM chp->ch_name, rv);
9843833Sxw161283
9853833Sxw161283 return (0);
9863833Sxw161283 }
9873833Sxw161283
9883833Sxw161283 if (count != 1) {
9893833Sxw161283 cmn_err(CE_WARN,
9903833Sxw161283 "%s: ch_alloc_dma_mem: ch_alloc_dma_mem cookie count %d\n",
991*7656SSherry.Moore@Sun.COM chp->ch_name, count);
9923833Sxw161283 PRINT(("ch_alloc_dma_mem cookie count %d\n", count));
9933833Sxw161283
9943833Sxw161283 ddi_dma_mem_free(&ch_ah);
9953833Sxw161283 ddi_dma_free_handle(&ch_dh);
9963833Sxw161283
9973833Sxw161283 return (0);
9983833Sxw161283 }
9993833Sxw161283
10003833Sxw161283 *paddr = cookie.dmac_laddress;
10013833Sxw161283
10023833Sxw161283 *(ddi_dma_handle_t *)dh = ch_dh;
10033833Sxw161283 *(ddi_acc_handle_t *)ah = ch_ah;
10043833Sxw161283
10053833Sxw161283 return ((void *)ch_vaddr);
10063833Sxw161283 }
10073833Sxw161283
10083833Sxw161283 /*
10093833Sxw161283 * ch_free_dma_mem
10103833Sxw161283 *
10113833Sxw161283 * frees resources allocated by ch_alloc_dma_mem()
10123833Sxw161283 *
10133833Sxw161283 * frees DMA handle
10143833Sxw161283 * frees kernel memory
10153833Sxw161283 * frees DMA access handle
10163833Sxw161283 */
10173833Sxw161283
10183833Sxw161283 void
ch_free_dma_mem(ulong_t dh,ulong_t ah)10193833Sxw161283 ch_free_dma_mem(ulong_t dh, ulong_t ah)
10203833Sxw161283 {
10213833Sxw161283 ddi_dma_handle_t ch_dh = (ddi_dma_handle_t)dh;
10223833Sxw161283 ddi_acc_handle_t ch_ah = (ddi_acc_handle_t)ah;
10233833Sxw161283
10243833Sxw161283 (void) ddi_dma_unbind_handle(ch_dh);
10253833Sxw161283 ddi_dma_mem_free(&ch_ah);
10263833Sxw161283 ddi_dma_free_handle(&ch_dh);
10273833Sxw161283 }
10283833Sxw161283
10293833Sxw161283 /*
10303833Sxw161283 * create a dma handle and return a dma handle entry.
10313833Sxw161283 */
10323833Sxw161283 free_dh_t *
ch_get_dma_handle(ch_t * chp)10333833Sxw161283 ch_get_dma_handle(ch_t *chp)
10343833Sxw161283 {
10353833Sxw161283 ddi_dma_handle_t ch_dh;
10363833Sxw161283 ddi_dma_attr_t ch_dma_attr;
10373833Sxw161283 free_dh_t *dhe;
10383833Sxw161283 int rv;
10393833Sxw161283
10403833Sxw161283 dhe = (free_dh_t *)kmem_zalloc(sizeof (*dhe), KM_SLEEP);
10413833Sxw161283
10423833Sxw161283 ch_dma_attr.dma_attr_version = DMA_ATTR_V0;
10433833Sxw161283 ch_dma_attr.dma_attr_addr_lo = 0;
10443833Sxw161283 ch_dma_attr.dma_attr_addr_hi = 0xffffffffffffffff;
10453833Sxw161283 ch_dma_attr.dma_attr_count_max = 0x00ffffff;
10463833Sxw161283 ch_dma_attr.dma_attr_align = 1;
10473833Sxw161283 ch_dma_attr.dma_attr_burstsizes = 0xfff;
10483833Sxw161283 ch_dma_attr.dma_attr_minxfer = 1;
10493833Sxw161283 ch_dma_attr.dma_attr_maxxfer = 0x00ffffff;
10503833Sxw161283 ch_dma_attr.dma_attr_seg = 0xffffffff;
10513833Sxw161283 ch_dma_attr.dma_attr_sgllen = 5;
10523833Sxw161283 ch_dma_attr.dma_attr_granular = 1;
10533833Sxw161283 ch_dma_attr.dma_attr_flags = 0;
10543833Sxw161283
10553833Sxw161283 rv = ddi_dma_alloc_handle(
10563833Sxw161283 chp->ch_dip, /* device dev_info */
10573833Sxw161283 &ch_dma_attr, /* DMA attributes */
10583833Sxw161283 DDI_DMA_SLEEP, /* Wait if no memory */
10593833Sxw161283 NULL, /* no argument */
10603833Sxw161283 &ch_dh); /* DMA handle */
10613833Sxw161283 if (rv != DDI_SUCCESS) {
10623833Sxw161283
10633833Sxw161283 cmn_err(CE_WARN,
10643833Sxw161283 "%s: ch_get_dma_handle: ddi_dma_alloc_handle error %d\n",
1065*7656SSherry.Moore@Sun.COM chp->ch_name, rv);
10663833Sxw161283
10673833Sxw161283 kmem_free(dhe, sizeof (*dhe));
10683833Sxw161283
10693833Sxw161283 return ((free_dh_t *)0);
10703833Sxw161283 }
10713833Sxw161283
10723833Sxw161283 dhe->dhe_dh = (ulong_t)ch_dh;
10733833Sxw161283
10743833Sxw161283 return (dhe);
10753833Sxw161283 }
10763833Sxw161283
10773833Sxw161283 /*
10783833Sxw161283 * free the linked list of dma descriptor entries.
10793833Sxw161283 */
10803833Sxw161283 static void
ch_free_dma_handles(ch_t * chp)10813833Sxw161283 ch_free_dma_handles(ch_t *chp)
10823833Sxw161283 {
10833833Sxw161283 free_dh_t *dhe, *the;
10843833Sxw161283
10853833Sxw161283 dhe = chp->ch_dh;
10863833Sxw161283 while (dhe) {
10873833Sxw161283 ddi_dma_free_handle((ddi_dma_handle_t *)&dhe->dhe_dh);
10883833Sxw161283 the = dhe;
10893833Sxw161283 dhe = dhe->dhe_next;
10903833Sxw161283 kmem_free(the, sizeof (*the));
10913833Sxw161283 }
10923833Sxw161283 chp->ch_dh = NULL;
10933833Sxw161283 }
10943833Sxw161283
10953833Sxw161283 /*
10963833Sxw161283 * ch_bind_dma_handle()
10973833Sxw161283 *
10983833Sxw161283 * returns # of entries used off of cmdQ_ce_t array to hold physical addrs.
10993833Sxw161283 *
11003833Sxw161283 * chp - per-board descriptor
11013833Sxw161283 * size - # bytes mapped
11023833Sxw161283 * vaddr - virtual address
11033833Sxw161283 * cmp - array of cmdQ_ce_t entries
11043833Sxw161283 * cnt - # free entries in cmp array
11053833Sxw161283 */
11063833Sxw161283
11073833Sxw161283 uint32_t
ch_bind_dma_handle(ch_t * chp,int size,caddr_t vaddr,cmdQ_ce_t * cmp,uint32_t cnt)11083833Sxw161283 ch_bind_dma_handle(ch_t *chp, int size, caddr_t vaddr, cmdQ_ce_t *cmp,
11093833Sxw161283 uint32_t cnt)
11103833Sxw161283 {
11113833Sxw161283 ddi_dma_cookie_t cookie;
11123833Sxw161283 ddi_dma_handle_t ch_dh;
11133833Sxw161283 uint_t count;
11143833Sxw161283 uint32_t n = 1;
11153833Sxw161283 free_dh_t *dhe;
11163833Sxw161283 uint_t rv;
11173833Sxw161283
11183833Sxw161283 mutex_enter(&chp->ch_dh_lck);
11193833Sxw161283 if ((dhe = chp->ch_dh) != NULL) {
11203833Sxw161283 chp->ch_dh = dhe->dhe_next;
11213833Sxw161283 }
11223833Sxw161283 mutex_exit(&chp->ch_dh_lck);
11233833Sxw161283
11243833Sxw161283 if (dhe == NULL) {
11253833Sxw161283 return (0);
11263833Sxw161283 }
11273833Sxw161283
11283833Sxw161283 ch_dh = (ddi_dma_handle_t)dhe->dhe_dh;
11293833Sxw161283
11303833Sxw161283 rv = ddi_dma_addr_bind_handle(
11313833Sxw161283 ch_dh, /* dma handle */
11323833Sxw161283 (struct as *)0, /* kernel address space */
11333833Sxw161283 vaddr, /* virtual address */
11343833Sxw161283 size, /* length of object */
11353833Sxw161283 DDI_DMA_WRITE|DDI_DMA_STREAMING,
11363833Sxw161283 DDI_DMA_SLEEP, /* Wait for resources */
11373833Sxw161283 NULL, /* no argument */
11383833Sxw161283 &cookie, /* dma cookie */
11393833Sxw161283 &count);
11403833Sxw161283 if (rv != DDI_DMA_MAPPED) {
11413833Sxw161283
11423833Sxw161283 /* return dma header descriptor back to free list */
11433833Sxw161283 mutex_enter(&chp->ch_dh_lck);
11443833Sxw161283 dhe->dhe_next = chp->ch_dh;
11453833Sxw161283 chp->ch_dh = dhe;
11463833Sxw161283 mutex_exit(&chp->ch_dh_lck);
11473833Sxw161283
11483833Sxw161283 cmn_err(CE_WARN,
11493833Sxw161283 "%s: ch_bind_dma_handle: ddi_dma_addr_bind_handle err %d\n",
1150*7656SSherry.Moore@Sun.COM chp->ch_name, rv);
11513833Sxw161283
11523833Sxw161283 return (0);
11533833Sxw161283 }
11543833Sxw161283
11553833Sxw161283 /*
11563833Sxw161283 * abort if we've run out of space
11573833Sxw161283 */
11583833Sxw161283 if (count > cnt) {
11593833Sxw161283 /* return dma header descriptor back to free list */
11603833Sxw161283 mutex_enter(&chp->ch_dh_lck);
11613833Sxw161283 dhe->dhe_next = chp->ch_dh;
11623833Sxw161283 chp->ch_dh = dhe;
11633833Sxw161283 mutex_exit(&chp->ch_dh_lck);
11643833Sxw161283
11653833Sxw161283 return (0);
11663833Sxw161283 }
11673833Sxw161283
11683833Sxw161283 cmp->ce_pa = cookie.dmac_laddress;
11693833Sxw161283 cmp->ce_dh = NULL;
11703833Sxw161283 cmp->ce_len = cookie.dmac_size;
11713833Sxw161283 cmp->ce_mp = NULL;
11723833Sxw161283 cmp->ce_flg = DH_DMA;
11733833Sxw161283
11743833Sxw161283 while (--count) {
11753833Sxw161283 cmp++;
11763833Sxw161283 n++;
11773833Sxw161283 ddi_dma_nextcookie(ch_dh, &cookie);
11783833Sxw161283 cmp->ce_pa = cookie.dmac_laddress;
11793833Sxw161283 cmp->ce_dh = NULL;
11803833Sxw161283 cmp->ce_len = cookie.dmac_size;
11813833Sxw161283 cmp->ce_mp = NULL;
11823833Sxw161283 cmp->ce_flg = DH_DMA;
11833833Sxw161283 }
11843833Sxw161283
11853833Sxw161283 cmp->ce_dh = dhe;
11863833Sxw161283
11873833Sxw161283 return (n);
11883833Sxw161283 }
11893833Sxw161283
11903833Sxw161283 /*
11913833Sxw161283 * ch_unbind_dma_handle()
11923833Sxw161283 *
11933833Sxw161283 * frees resources alloacted by ch_bind_dma_handle().
11943833Sxw161283 *
11953833Sxw161283 * frees DMA handle
11963833Sxw161283 */
11973833Sxw161283
11983833Sxw161283 void
ch_unbind_dma_handle(ch_t * chp,free_dh_t * dhe)11993833Sxw161283 ch_unbind_dma_handle(ch_t *chp, free_dh_t *dhe)
12003833Sxw161283 {
12013833Sxw161283 ddi_dma_handle_t ch_dh = (ddi_dma_handle_t)dhe->dhe_dh;
12023833Sxw161283
12033833Sxw161283 if (ddi_dma_unbind_handle(ch_dh))
12043833Sxw161283 cmn_err(CE_WARN, "%s: ddi_dma_unbind_handle failed",
1205*7656SSherry.Moore@Sun.COM chp->ch_name);
12063833Sxw161283
12073833Sxw161283 mutex_enter(&chp->ch_dh_lck);
12083833Sxw161283 dhe->dhe_next = chp->ch_dh;
12093833Sxw161283 chp->ch_dh = dhe;
12103833Sxw161283 mutex_exit(&chp->ch_dh_lck);
12113833Sxw161283 }
12123833Sxw161283
12133833Sxw161283 #if defined(__sparc)
12143833Sxw161283 /*
12153833Sxw161283 * DVMA stuff. Solaris only.
12163833Sxw161283 */
12173833Sxw161283
12183833Sxw161283 /*
12193833Sxw161283 * create a dvma handle and return a dma handle entry.
12203833Sxw161283 * DVMA is on sparc only!
12213833Sxw161283 */
12223833Sxw161283
12233833Sxw161283 free_dh_t *
ch_get_dvma_handle(ch_t * chp)12243833Sxw161283 ch_get_dvma_handle(ch_t *chp)
12253833Sxw161283 {
12263833Sxw161283 ddi_dma_handle_t ch_dh;
12273833Sxw161283 ddi_dma_lim_t ch_dvma_attr;
12283833Sxw161283 free_dh_t *dhe;
12293833Sxw161283 int rv;
12303833Sxw161283
12313833Sxw161283 dhe = (free_dh_t *)kmem_zalloc(sizeof (*dhe), KM_SLEEP);
12323833Sxw161283
12333833Sxw161283 ch_dvma_attr.dlim_addr_lo = 0;
12343833Sxw161283 ch_dvma_attr.dlim_addr_hi = 0xffffffff;
12353833Sxw161283 ch_dvma_attr.dlim_cntr_max = 0xffffffff;
12363833Sxw161283 ch_dvma_attr.dlim_burstsizes = 0xfff;
12373833Sxw161283 ch_dvma_attr.dlim_minxfer = 1;
12383833Sxw161283 ch_dvma_attr.dlim_dmaspeed = 0;
12393833Sxw161283
12403833Sxw161283 rv = dvma_reserve(
1241*7656SSherry.Moore@Sun.COM chp->ch_dip, /* device dev_info */
1242*7656SSherry.Moore@Sun.COM &ch_dvma_attr, /* DVMA attributes */
1243*7656SSherry.Moore@Sun.COM 3, /* number of pages */
1244*7656SSherry.Moore@Sun.COM &ch_dh); /* DVMA handle */
12453833Sxw161283
12463833Sxw161283 if (rv != DDI_SUCCESS) {
12473833Sxw161283
12483833Sxw161283 cmn_err(CE_WARN,
12493833Sxw161283 "%s: ch_get_dvma_handle: dvma_reserve() error %d\n",
1250*7656SSherry.Moore@Sun.COM chp->ch_name, rv);
12513833Sxw161283
12523833Sxw161283 kmem_free(dhe, sizeof (*dhe));
12533833Sxw161283
12543833Sxw161283 return ((free_dh_t *)0);
12553833Sxw161283 }
12563833Sxw161283
12573833Sxw161283 dhe->dhe_dh = (ulong_t)ch_dh;
12583833Sxw161283
12593833Sxw161283 return (dhe);
12603833Sxw161283 }
12613833Sxw161283
12623833Sxw161283 /*
12633833Sxw161283 * free the linked list of dvma descriptor entries.
12643833Sxw161283 * DVMA is only on sparc!
12653833Sxw161283 */
12663833Sxw161283
12673833Sxw161283 static void
ch_free_dvma_handles(ch_t * chp)12683833Sxw161283 ch_free_dvma_handles(ch_t *chp)
12693833Sxw161283 {
12703833Sxw161283 free_dh_t *dhe, *the;
12713833Sxw161283
12723833Sxw161283 dhe = chp->ch_vdh;
12733833Sxw161283 while (dhe) {
12743833Sxw161283 dvma_release((ddi_dma_handle_t)dhe->dhe_dh);
12753833Sxw161283 the = dhe;
12763833Sxw161283 dhe = dhe->dhe_next;
12773833Sxw161283 kmem_free(the, sizeof (*the));
12783833Sxw161283 }
12793833Sxw161283 chp->ch_vdh = NULL;
12803833Sxw161283 }
12813833Sxw161283
12823833Sxw161283 /*
12833833Sxw161283 * ch_bind_dvma_handle()
12843833Sxw161283 *
12853833Sxw161283 * returns # of entries used off of cmdQ_ce_t array to hold physical addrs.
12863833Sxw161283 * DVMA in sparc only
12873833Sxw161283 *
12883833Sxw161283 * chp - per-board descriptor
12893833Sxw161283 * size - # bytes mapped
12903833Sxw161283 * vaddr - virtual address
12913833Sxw161283 * cmp - array of cmdQ_ce_t entries
12923833Sxw161283 * cnt - # free entries in cmp array
12933833Sxw161283 */
12943833Sxw161283
12953833Sxw161283 uint32_t
ch_bind_dvma_handle(ch_t * chp,int size,caddr_t vaddr,cmdQ_ce_t * cmp,uint32_t cnt)12963833Sxw161283 ch_bind_dvma_handle(ch_t *chp, int size, caddr_t vaddr, cmdQ_ce_t *cmp,
12973833Sxw161283 uint32_t cnt)
12983833Sxw161283 {
12993833Sxw161283 ddi_dma_cookie_t cookie;
13003833Sxw161283 ddi_dma_handle_t ch_dh;
13013833Sxw161283 uint32_t n = 1;
13023833Sxw161283 free_dh_t *dhe;
13033833Sxw161283
13043833Sxw161283 mutex_enter(&chp->ch_dh_lck);
13053833Sxw161283 if ((dhe = chp->ch_vdh) != NULL) {
13063833Sxw161283 chp->ch_vdh = dhe->dhe_next;
13073833Sxw161283 }
13083833Sxw161283 mutex_exit(&chp->ch_dh_lck);
13093833Sxw161283
13103833Sxw161283 if (dhe == NULL) {
13113833Sxw161283 return (0);
13123833Sxw161283 }
13133833Sxw161283
13143833Sxw161283 ch_dh = (ddi_dma_handle_t)dhe->dhe_dh;
13153833Sxw161283 n = cnt;
13163833Sxw161283
13173833Sxw161283 dvma_kaddr_load(
1318*7656SSherry.Moore@Sun.COM ch_dh, /* dvma handle */
1319*7656SSherry.Moore@Sun.COM vaddr, /* virtual address */
1320*7656SSherry.Moore@Sun.COM size, /* length of object */
1321*7656SSherry.Moore@Sun.COM 0, /* start at index 0 */
1322*7656SSherry.Moore@Sun.COM &cookie);
13233833Sxw161283
13243833Sxw161283 dvma_sync(ch_dh, 0, DDI_DMA_SYNC_FORDEV);
13253833Sxw161283
13263833Sxw161283 cookie.dmac_notused = 0;
13273833Sxw161283 n = 1;
13283833Sxw161283
13293833Sxw161283 cmp->ce_pa = cookie.dmac_laddress;
13303833Sxw161283 cmp->ce_dh = dhe;
13313833Sxw161283 cmp->ce_len = cookie.dmac_size;
13323833Sxw161283 cmp->ce_mp = NULL;
13333833Sxw161283 cmp->ce_flg = DH_DVMA; /* indicate a dvma descriptor */
13343833Sxw161283
13353833Sxw161283 return (n);
13363833Sxw161283 }
13373833Sxw161283
13383833Sxw161283 /*
13393833Sxw161283 * ch_unbind_dvma_handle()
13403833Sxw161283 *
13413833Sxw161283 * frees resources alloacted by ch_bind_dvma_handle().
13423833Sxw161283 *
13433833Sxw161283 * frees DMA handle
13443833Sxw161283 */
13453833Sxw161283
13463833Sxw161283 void
ch_unbind_dvma_handle(ch_t * chp,free_dh_t * dhe)13473833Sxw161283 ch_unbind_dvma_handle(ch_t *chp, free_dh_t *dhe)
13483833Sxw161283 {
13493833Sxw161283 ddi_dma_handle_t ch_dh = (ddi_dma_handle_t)dhe->dhe_dh;
13503833Sxw161283
13513833Sxw161283 dvma_unload(ch_dh, 0, -1);
13523833Sxw161283
13533833Sxw161283 mutex_enter(&chp->ch_dh_lck);
13543833Sxw161283 dhe->dhe_next = chp->ch_vdh;
13553833Sxw161283 chp->ch_vdh = dhe;
13563833Sxw161283 mutex_exit(&chp->ch_dh_lck);
13573833Sxw161283 }
13583833Sxw161283
13593833Sxw161283 #endif /* defined(__sparc) */
13603833Sxw161283
13613833Sxw161283 /*
13623833Sxw161283 * send received packet up stream.
13633833Sxw161283 *
13643833Sxw161283 * if driver has been stopped, then we drop the message.
13653833Sxw161283 */
13663833Sxw161283 void
ch_send_up(ch_t * chp,mblk_t * mp,uint32_t cksum,int flg)13673833Sxw161283 ch_send_up(ch_t *chp, mblk_t *mp, uint32_t cksum, int flg)
13683833Sxw161283 {
13693833Sxw161283 /*
13703833Sxw161283 * probably do not need a lock here. When we set PESTOP in
13713833Sxw161283 * ch_stop() a packet could have just passed here and gone
13723833Sxw161283 * upstream. The next one will be dropped.
13733833Sxw161283 */
13743833Sxw161283 if (chp->ch_state == PERUNNING) {
13753833Sxw161283 /*
13763833Sxw161283 * note that flg will not be set unless enable_checksum_offload
13773833Sxw161283 * set in /etc/system (see sge.c).
13783833Sxw161283 */
13793833Sxw161283 if (flg)
13803833Sxw161283 (void) hcksum_assoc(mp, NULL, NULL, 0, 0, 0, cksum,
1381*7656SSherry.Moore@Sun.COM HCK_FULLCKSUM, 0);
13823833Sxw161283 gld_recv(chp->ch_macp, mp);
13833833Sxw161283 } else {
13843833Sxw161283 freemsg(mp);
13853833Sxw161283 }
13863833Sxw161283 }
13873833Sxw161283
13883833Sxw161283 /*
13893833Sxw161283 * unblock gld driver.
13903833Sxw161283 */
13913833Sxw161283 void
ch_gld_ok(ch_t * chp)13923833Sxw161283 ch_gld_ok(ch_t *chp)
13933833Sxw161283 {
13943833Sxw161283 gld_sched(chp->ch_macp);
13953833Sxw161283 }
13963833Sxw161283
13973833Sxw161283
13983833Sxw161283 /*
13993833Sxw161283 * reset the card.
14003833Sxw161283 *
14013833Sxw161283 * Note: we only do this after the card has been initialized.
14023833Sxw161283 */
14033833Sxw161283 static int
ch_reset(gld_mac_info_t * mp)14043833Sxw161283 ch_reset(gld_mac_info_t *mp)
14053833Sxw161283 {
14063833Sxw161283 ch_t *chp;
14073833Sxw161283
14083833Sxw161283 if (mp == NULL) {
14093833Sxw161283 return (GLD_FAILURE);
14103833Sxw161283 }
14113833Sxw161283
14123833Sxw161283 chp = (ch_t *)mp->gldm_private;
14133833Sxw161283
14143833Sxw161283 if (chp == NULL) {
14153833Sxw161283 return (GLD_FAILURE);
14163833Sxw161283 }
14173833Sxw161283
14183833Sxw161283 #ifdef NOTYET
14193833Sxw161283 /*
14203833Sxw161283 * do a reset of card
14213833Sxw161283 *
14223833Sxw161283 * 1. set PwrState to D3hot (3)
14233833Sxw161283 * 2. clear PwrState flags
14243833Sxw161283 */
14253833Sxw161283 /*
14263833Sxw161283 * When we did this, the card didn't start. First guess is that
14273833Sxw161283 * the initialization is not quite correct. For now, we don't
14283833Sxw161283 * reset things.
14293833Sxw161283 */
14303833Sxw161283 if (chp->ch_hpci) {
14313833Sxw161283 pci_config_put32(chp->ch_hpci, 0x44, 3);
14323833Sxw161283 pci_config_put32(chp->ch_hpci, 0x44, 0);
14333833Sxw161283
14343833Sxw161283 /* delay .5 sec */
14353833Sxw161283 DELAY(500000);
14363833Sxw161283 }
14373833Sxw161283 #endif
14383833Sxw161283
14393833Sxw161283 return (GLD_SUCCESS);
14403833Sxw161283 }
14413833Sxw161283
14423833Sxw161283 static int
ch_start(gld_mac_info_t * macinfo)14433833Sxw161283 ch_start(gld_mac_info_t *macinfo)
14443833Sxw161283 {
14453833Sxw161283 ch_t *chp = (ch_t *)macinfo->gldm_private;
14463833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
14473833Sxw161283 /* only initialize card on first attempt */
14483833Sxw161283 mutex_enter(&chp->ch_lock);
14493833Sxw161283 chp->ch_refcnt++;
14503833Sxw161283 if (chp->ch_refcnt == 1) {
14513833Sxw161283 chp->ch_state = PERUNNING;
14523833Sxw161283 mutex_exit(&chp->ch_lock);
14533833Sxw161283 pe_init((void *)chp);
14543833Sxw161283 } else
14553833Sxw161283 mutex_exit(&chp->ch_lock);
14563833Sxw161283 #else
14573833Sxw161283 pe_init((void *)chp);
14583833Sxw161283
14593833Sxw161283 /* go to running state, we're being started */
14603833Sxw161283 mutex_enter(&chp->ch_lock);
14613833Sxw161283 chp->ch_state = PERUNNING;
14623833Sxw161283 mutex_exit(&chp->ch_lock);
14633833Sxw161283 #endif
14643833Sxw161283
14653833Sxw161283 return (GLD_SUCCESS);
14663833Sxw161283 }
14673833Sxw161283
14683833Sxw161283 static int
ch_stop(gld_mac_info_t * mp)14693833Sxw161283 ch_stop(gld_mac_info_t *mp)
14703833Sxw161283 {
14713833Sxw161283 ch_t *chp = (ch_t *)mp->gldm_private;
14723833Sxw161283
14733833Sxw161283 /*
14743833Sxw161283 * can only stop the chip if it's been initialized
14753833Sxw161283 */
14763833Sxw161283 mutex_enter(&chp->ch_lock);
14773833Sxw161283 if (chp->ch_state == PEIDLE) {
14783833Sxw161283 mutex_exit(&chp->ch_lock);
14793833Sxw161283 return (GLD_FAILURE);
14803833Sxw161283 }
14813833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
14823833Sxw161283 chp->ch_refcnt--;
14833833Sxw161283 if (chp->ch_refcnt == 0) {
14843833Sxw161283 chp->ch_state = PESTOP;
14853833Sxw161283 mutex_exit(&chp->ch_lock);
14863833Sxw161283 pe_stop(chp);
14873833Sxw161283 } else
14883833Sxw161283 mutex_exit(&chp->ch_lock);
14893833Sxw161283 #else
14903833Sxw161283 chp->ch_state = PESTOP;
14913833Sxw161283 mutex_exit(&chp->ch_lock);
14923833Sxw161283 pe_stop(chp);
14933833Sxw161283 #endif
14943833Sxw161283 return (GLD_SUCCESS);
14953833Sxw161283 }
14963833Sxw161283
14973833Sxw161283 static int
ch_set_mac_address(gld_mac_info_t * mp,uint8_t * mac)14983833Sxw161283 ch_set_mac_address(gld_mac_info_t *mp, uint8_t *mac)
14993833Sxw161283 {
15003833Sxw161283 ch_t *chp;
15013833Sxw161283
15023833Sxw161283 if (mp) {
15033833Sxw161283 chp = (ch_t *)mp->gldm_private;
15043833Sxw161283 } else {
15053833Sxw161283 return (GLD_FAILURE);
15063833Sxw161283 }
15073833Sxw161283
15083833Sxw161283 pe_set_mac(chp, mac);
15093833Sxw161283
15103833Sxw161283 return (GLD_SUCCESS);
15113833Sxw161283 }
15123833Sxw161283
15133833Sxw161283 static int
ch_set_multicast(gld_mac_info_t * mp,uint8_t * ep,int flg)15143833Sxw161283 ch_set_multicast(gld_mac_info_t *mp, uint8_t *ep, int flg)
15153833Sxw161283 {
15163833Sxw161283 ch_t *chp = (ch_t *)mp->gldm_private;
15173833Sxw161283
15183833Sxw161283 return (pe_set_mc(chp, ep, flg));
15193833Sxw161283 }
15203833Sxw161283
15213833Sxw161283 static int
ch_ioctl(gld_mac_info_t * macinfo,queue_t * q,mblk_t * mp)15223833Sxw161283 ch_ioctl(gld_mac_info_t *macinfo, queue_t *q, mblk_t *mp)
15233833Sxw161283 {
15243833Sxw161283 struct iocblk *iocp;
15253833Sxw161283
15263833Sxw161283 switch (mp->b_datap->db_type) {
15273833Sxw161283 case M_IOCTL:
15283833Sxw161283 /* pe_ioctl() does qreply() */
15293833Sxw161283 pe_ioctl((ch_t *)(macinfo->gldm_private), q, mp);
15303833Sxw161283 break;
15313833Sxw161283
15323833Sxw161283 default:
15333833Sxw161283 /*
15343833Sxw161283 * cmn_err(CE_NOTE, "ch_ioctl not M_IOCTL\n");
15353833Sxw161283 * debug_enter("bad ch_ioctl");
15363833Sxw161283 */
15373833Sxw161283
15383833Sxw161283 iocp = (struct iocblk *)mp->b_rptr;
15393833Sxw161283
15403833Sxw161283 if (mp->b_cont)
15413833Sxw161283 freemsg(mp->b_cont);
15423833Sxw161283 mp->b_cont = NULL;
15433833Sxw161283
15443833Sxw161283 mp->b_datap->db_type = M_IOCNAK;
15453833Sxw161283 iocp->ioc_error = EINVAL;
15463833Sxw161283 qreply(q, mp);
15473833Sxw161283 break;
15483833Sxw161283 }
15493833Sxw161283
15503833Sxw161283 return (GLD_SUCCESS);
15513833Sxw161283 }
15523833Sxw161283
15533833Sxw161283 static int
ch_set_promiscuous(gld_mac_info_t * mp,int flag)15543833Sxw161283 ch_set_promiscuous(gld_mac_info_t *mp, int flag)
15553833Sxw161283 {
15563833Sxw161283 ch_t *chp = (ch_t *)mp->gldm_private;
15573833Sxw161283
15583833Sxw161283 switch (flag) {
15593833Sxw161283 case GLD_MAC_PROMISC_MULTI:
15603833Sxw161283 pe_set_promiscuous(chp, 2);
15613833Sxw161283 break;
15623833Sxw161283
15633833Sxw161283 case GLD_MAC_PROMISC_NONE:
15643833Sxw161283 pe_set_promiscuous(chp, 0);
15653833Sxw161283 break;
15663833Sxw161283
15673833Sxw161283 case GLD_MAC_PROMISC_PHYS:
15683833Sxw161283 default:
15693833Sxw161283 pe_set_promiscuous(chp, 1);
15703833Sxw161283 break;
15713833Sxw161283 }
15723833Sxw161283
15733833Sxw161283 return (GLD_SUCCESS);
15743833Sxw161283 }
15753833Sxw161283
15763833Sxw161283 static int
ch_get_stats(gld_mac_info_t * mp,struct gld_stats * gs)15773833Sxw161283 ch_get_stats(gld_mac_info_t *mp, struct gld_stats *gs)
15783833Sxw161283 {
15793833Sxw161283 ch_t *chp = (ch_t *)mp->gldm_private;
15803833Sxw161283 uint64_t speed;
15813833Sxw161283 uint32_t intrcnt;
15823833Sxw161283 uint32_t norcvbuf;
15833833Sxw161283 uint32_t oerrors;
15843833Sxw161283 uint32_t ierrors;
15853833Sxw161283 uint32_t underrun;
15863833Sxw161283 uint32_t overrun;
15873833Sxw161283 uint32_t framing;
15883833Sxw161283 uint32_t crc;
15893833Sxw161283 uint32_t carrier;
15903833Sxw161283 uint32_t collisions;
15913833Sxw161283 uint32_t xcollisions;
15923833Sxw161283 uint32_t late;
15933833Sxw161283 uint32_t defer;
15943833Sxw161283 uint32_t xerrs;
15953833Sxw161283 uint32_t rerrs;
15963833Sxw161283 uint32_t toolong;
15973833Sxw161283 uint32_t runt;
15983833Sxw161283 ulong_t multixmt;
15993833Sxw161283 ulong_t multircv;
16003833Sxw161283 ulong_t brdcstxmt;
16013833Sxw161283 ulong_t brdcstrcv;
16023833Sxw161283
16033833Sxw161283 /*
16043833Sxw161283 * race looks benign here.
16053833Sxw161283 */
16063833Sxw161283 if (chp->ch_state != PERUNNING) {
16073833Sxw161283 return (GLD_FAILURE);
16083833Sxw161283 }
16093833Sxw161283
16103833Sxw161283 (void) pe_get_stats(chp,
1611*7656SSherry.Moore@Sun.COM &speed,
1612*7656SSherry.Moore@Sun.COM &intrcnt,
1613*7656SSherry.Moore@Sun.COM &norcvbuf,
1614*7656SSherry.Moore@Sun.COM &oerrors,
1615*7656SSherry.Moore@Sun.COM &ierrors,
1616*7656SSherry.Moore@Sun.COM &underrun,
1617*7656SSherry.Moore@Sun.COM &overrun,
1618*7656SSherry.Moore@Sun.COM &framing,
1619*7656SSherry.Moore@Sun.COM &crc,
1620*7656SSherry.Moore@Sun.COM &carrier,
1621*7656SSherry.Moore@Sun.COM &collisions,
1622*7656SSherry.Moore@Sun.COM &xcollisions,
1623*7656SSherry.Moore@Sun.COM &late,
1624*7656SSherry.Moore@Sun.COM &defer,
1625*7656SSherry.Moore@Sun.COM &xerrs,
1626*7656SSherry.Moore@Sun.COM &rerrs,
1627*7656SSherry.Moore@Sun.COM &toolong,
1628*7656SSherry.Moore@Sun.COM &runt,
1629*7656SSherry.Moore@Sun.COM &multixmt,
1630*7656SSherry.Moore@Sun.COM &multircv,
1631*7656SSherry.Moore@Sun.COM &brdcstxmt,
1632*7656SSherry.Moore@Sun.COM &brdcstrcv);
16333833Sxw161283
16343833Sxw161283 gs->glds_speed = speed;
16353833Sxw161283 gs->glds_media = GLDM_UNKNOWN;
16363833Sxw161283 gs->glds_intr = intrcnt;
16373833Sxw161283 gs->glds_norcvbuf = norcvbuf;
16383833Sxw161283 gs->glds_errxmt = oerrors;
16393833Sxw161283 gs->glds_errrcv = ierrors;
16403833Sxw161283 gs->glds_missed = ierrors; /* ??? */
16413833Sxw161283 gs->glds_underflow = underrun;
16423833Sxw161283 gs->glds_overflow = overrun;
16433833Sxw161283 gs->glds_frame = framing;
16443833Sxw161283 gs->glds_crc = crc;
16453833Sxw161283 gs->glds_duplex = GLD_DUPLEX_FULL;
16463833Sxw161283 gs->glds_nocarrier = carrier;
16473833Sxw161283 gs->glds_collisions = collisions;
16483833Sxw161283 gs->glds_excoll = xcollisions;
16493833Sxw161283 gs->glds_xmtlatecoll = late;
16503833Sxw161283 gs->glds_defer = defer;
16513833Sxw161283 gs->glds_dot3_first_coll = 0; /* Not available */
16523833Sxw161283 gs->glds_dot3_multi_coll = 0; /* Not available */
16533833Sxw161283 gs->glds_dot3_sqe_error = 0; /* Not available */
16543833Sxw161283 gs->glds_dot3_mac_xmt_error = xerrs;
16553833Sxw161283 gs->glds_dot3_mac_rcv_error = rerrs;
16563833Sxw161283 gs->glds_dot3_frame_too_long = toolong;
16573833Sxw161283 gs->glds_short = runt;
16583833Sxw161283
16593833Sxw161283 gs->glds_noxmtbuf = 0; /* not documented */
16603833Sxw161283 gs->glds_xmtretry = 0; /* not documented */
16613833Sxw161283 gs->glds_multixmt = multixmt; /* not documented */
16623833Sxw161283 gs->glds_multircv = multircv; /* not documented */
16633833Sxw161283 gs->glds_brdcstxmt = brdcstxmt; /* not documented */
16643833Sxw161283 gs->glds_brdcstrcv = brdcstrcv; /* not documented */
16653833Sxw161283
16663833Sxw161283 return (GLD_SUCCESS);
16673833Sxw161283 }
16683833Sxw161283
16693833Sxw161283
16703833Sxw161283 static int
ch_send(gld_mac_info_t * macinfo,mblk_t * mp)16713833Sxw161283 ch_send(gld_mac_info_t *macinfo, mblk_t *mp)
16723833Sxw161283 {
16733833Sxw161283 ch_t *chp = (ch_t *)macinfo->gldm_private;
16743833Sxw161283 uint32_t flg;
16753833Sxw161283 uint32_t msg_flg;
16763833Sxw161283
16773833Sxw161283 #ifdef TX_CKSUM_FIX
16783833Sxw161283 mblk_t *nmp;
16793833Sxw161283 int frags;
16803833Sxw161283 size_t msg_len;
16813833Sxw161283 struct ether_header *ehdr;
16823833Sxw161283 ipha_t *ihdr;
16833833Sxw161283 int tflg = 0;
16843833Sxw161283 #endif /* TX_CKSUM_FIX */
16853833Sxw161283
16863833Sxw161283 /*
16873833Sxw161283 * race looks benign here.
16883833Sxw161283 */
16893833Sxw161283 if (chp->ch_state != PERUNNING) {
16903833Sxw161283 return (GLD_FAILURE);
16913833Sxw161283 }
16923833Sxw161283
16933833Sxw161283 msg_flg = 0;
16943833Sxw161283 if (chp->ch_config.cksum_enabled) {
16953833Sxw161283 if (is_T2(chp)) {
16963833Sxw161283 hcksum_retrieve(mp, NULL, NULL, NULL, NULL, NULL,
1697*7656SSherry.Moore@Sun.COM NULL, &msg_flg);
16983833Sxw161283 flg = (msg_flg & HCK_FULLCKSUM)?
1699*7656SSherry.Moore@Sun.COM CH_NO_CPL: CH_NO_HWCKSUM|CH_NO_CPL;
17003833Sxw161283 } else
17013833Sxw161283 flg = CH_NO_CPL;
17023833Sxw161283 } else
17033833Sxw161283 flg = CH_NO_HWCKSUM | CH_NO_CPL;
17043833Sxw161283
17053833Sxw161283 #ifdef TX_CKSUM_FIX
17063833Sxw161283 /*
17073833Sxw161283 * Check if the message spans more than one mblk or
17083833Sxw161283 * if it does and the ip header is not in the first
17093833Sxw161283 * fragment then pull up the message. This case is
17103833Sxw161283 * expected to be rare.
17113833Sxw161283 */
17123833Sxw161283 frags = 0;
17133833Sxw161283 msg_len = 0;
17143833Sxw161283 nmp = mp;
17153833Sxw161283 do {
17163833Sxw161283 frags++;
17173833Sxw161283 msg_len += MBLKL(nmp);
17183833Sxw161283 nmp = nmp->b_cont;
17193833Sxw161283 } while (nmp);
17203833Sxw161283 #define MAX_ALL_HDRLEN SZ_CPL_TX_PKT + sizeof (struct ether_header) + \
17213833Sxw161283 TCP_MAX_COMBINED_HEADER_LENGTH
17223833Sxw161283 /*
17233833Sxw161283 * If the first mblk has enough space at the beginning of
17243833Sxw161283 * the data buffer to hold a CPL header, then, we'll expancd
17253833Sxw161283 * the front of the buffer so a pullup will leave space for
17263833Sxw161283 * pe_start() to add the CPL header in line. We need to remember
17273833Sxw161283 * that we've done this so we can undo it after the pullup.
17283833Sxw161283 *
17293833Sxw161283 * Note that if we decide to do an allocb to hold the CPL header,
17303833Sxw161283 * we need to catch the case where we've added an empty mblk for
17313833Sxw161283 * the header but never did a pullup. This would result in the
17323833Sxw161283 * tests for etherheader, etc. being done on the initial, empty,
17333833Sxw161283 * mblk instead of the one with data. See PR3646 for further
17343833Sxw161283 * details. (note this PR is closed since it is no longer relevant).
17353833Sxw161283 *
17363833Sxw161283 * Another point is that if we do add an allocb to add space for
17373833Sxw161283 * a CPL header, after a pullup, the initial pointer, mp, in GLD will
17383833Sxw161283 * no longer point to a valid mblk. When we get the mblk (by allocb),
17393833Sxw161283 * we need to switch the mblk structure values between it and the
17403833Sxw161283 * mp structure values referenced by GLD. This handles the case where
17413833Sxw161283 * we've run out of cmdQ entries and report GLD_NORESOURCES back to
17423833Sxw161283 * GLD. The pointer to the mblk data will have been modified to hold
17433833Sxw161283 * an empty 8 bytes for the CPL header, For now, we let the pe_start()
17443833Sxw161283 * routine prepend an 8 byte mblk.
17453833Sxw161283 */
17463833Sxw161283 if (MBLKHEAD(mp) >= SZ_CPL_TX_PKT) {
17473833Sxw161283 mp->b_rptr -= SZ_CPL_TX_PKT;
17483833Sxw161283 tflg = 1;
17493833Sxw161283 }
17503833Sxw161283 if (frags > 3) {
17513833Sxw161283 chp->sge->intr_cnt.tx_msg_pullups++;
17523833Sxw161283 if (pullupmsg(mp, -1) == 0) {
17533833Sxw161283 freemsg(mp);
17543833Sxw161283 return (GLD_SUCCESS);
17553833Sxw161283 }
17563833Sxw161283 } else if ((msg_len > MAX_ALL_HDRLEN) &&
1757*7656SSherry.Moore@Sun.COM (MBLKL(mp) < MAX_ALL_HDRLEN)) {
17583833Sxw161283 chp->sge->intr_cnt.tx_hdr_pullups++;
17593833Sxw161283 if (pullupmsg(mp, MAX_ALL_HDRLEN) == 0) {
17603833Sxw161283 freemsg(mp);
17613833Sxw161283 return (GLD_SUCCESS);
17623833Sxw161283 }
17633833Sxw161283 }
17643833Sxw161283 if (tflg)
17653833Sxw161283 mp->b_rptr += SZ_CPL_TX_PKT;
17663833Sxw161283
17673833Sxw161283 ehdr = (struct ether_header *)mp->b_rptr;
17683833Sxw161283 if (ehdr->ether_type == htons(ETHERTYPE_IP)) {
17693833Sxw161283 ihdr = (ipha_t *)&mp->b_rptr[sizeof (struct ether_header)];
17703833Sxw161283 if ((ihdr->ipha_fragment_offset_and_flags & IPH_MF)) {
17713833Sxw161283 if (ihdr->ipha_protocol == IPPROTO_UDP) {
17723833Sxw161283 flg |= CH_UDP_MF;
17733833Sxw161283 chp->sge->intr_cnt.tx_udp_ip_frag++;
17743833Sxw161283 } else if (ihdr->ipha_protocol == IPPROTO_TCP) {
17753833Sxw161283 flg |= CH_TCP_MF;
17763833Sxw161283 chp->sge->intr_cnt.tx_tcp_ip_frag++;
17773833Sxw161283 }
17783833Sxw161283 } else if (ihdr->ipha_protocol == IPPROTO_UDP)
17793833Sxw161283 flg |= CH_UDP;
17803833Sxw161283 }
17813833Sxw161283 #endif /* TX_CKSUM_FIX */
17823833Sxw161283
17833833Sxw161283 /*
17843833Sxw161283 * return 0 - data send successfully
17853833Sxw161283 * return 1 - no resources, reschedule
17863833Sxw161283 */
17873833Sxw161283 if (pe_start(chp, mp, flg))
17883833Sxw161283 return (GLD_NORESOURCES);
17893833Sxw161283 else
17903833Sxw161283 return (GLD_SUCCESS);
17913833Sxw161283 }
17923833Sxw161283
17933833Sxw161283 static uint_t
ch_intr(gld_mac_info_t * mp)17943833Sxw161283 ch_intr(gld_mac_info_t *mp)
17953833Sxw161283 {
17963833Sxw161283 return (pe_intr((ch_t *)mp->gldm_private));
17973833Sxw161283 }
17983833Sxw161283
17993833Sxw161283 /*
18003833Sxw161283 * generate name of driver with unit# postpended.
18013833Sxw161283 */
18023833Sxw161283 void
ch_set_name(ch_t * chp,int unit)18033833Sxw161283 ch_set_name(ch_t *chp, int unit)
18043833Sxw161283 {
18053833Sxw161283 chp->ch_name = (char *)kmem_alloc(sizeof ("chxge00"), KM_SLEEP);
18063833Sxw161283 if (unit > 9) {
18073833Sxw161283 bcopy("chxge00", (void *)chp->ch_name, sizeof ("chxge00"));
18083833Sxw161283 chp->ch_name[5] += unit/10;
18093833Sxw161283 chp->ch_name[6] += unit%10;
18103833Sxw161283 } else {
18113833Sxw161283 bcopy("chxge0", (void *)chp->ch_name, sizeof ("chxge0"));
18123833Sxw161283 chp->ch_name[5] += unit;
18133833Sxw161283 }
18143833Sxw161283 }
18153833Sxw161283
18163833Sxw161283 void
ch_free_name(ch_t * chp)18173833Sxw161283 ch_free_name(ch_t *chp)
18183833Sxw161283 {
18193833Sxw161283 if (chp->ch_name)
18203833Sxw161283 kmem_free(chp->ch_name, sizeof ("chxge00"));
18213833Sxw161283 chp->ch_name = NULL;
18223833Sxw161283 }
18233833Sxw161283
18243833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
18253833Sxw161283 /*
18263833Sxw161283 * register toe offload.
18273833Sxw161283 */
18283833Sxw161283 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)18293833Sxw161283 ch_register(void *instp, void *toe_rcv, void *toe_free, void *toe_tunnel,
18303833Sxw161283 kmutex_t *toe_tx_mx, kcondvar_t *toe_of_cv, int unit)
18313833Sxw161283 {
18323833Sxw161283 ch_t *chp = gchp[unit];
18333833Sxw161283 if (chp != NULL) {
18343833Sxw161283 mutex_enter(&chp->ch_lock);
18353833Sxw161283
18363833Sxw161283 chp->toe_rcv = (void (*)(void *, mblk_t *))toe_rcv;
18373833Sxw161283 chp->ch_toeinst = instp;
18383833Sxw161283 chp->toe_free = (void (*)(void *, tbuf_t *))toe_free;
18393833Sxw161283 chp->toe_tunnel = (int (*)(void *, mblk_t *))toe_tunnel;
18403833Sxw161283 chp->ch_tx_overflow_mutex = toe_tx_mx;
18413833Sxw161283 chp->ch_tx_overflow_cv = toe_of_cv;
18423833Sxw161283 chp->open_device_map |= TOEDEV_DEVMAP_BIT;
18433833Sxw161283
18443833Sxw161283 /* start up adapter if first user */
18453833Sxw161283 chp->ch_refcnt++;
18463833Sxw161283 if (chp->ch_refcnt == 1) {
18473833Sxw161283 chp->ch_state = PERUNNING;
18483833Sxw161283 mutex_exit(&chp->ch_lock);
18493833Sxw161283 pe_init((void *)chp);
18503833Sxw161283 } else
18513833Sxw161283 mutex_exit(&chp->ch_lock);
18523833Sxw161283 }
18533833Sxw161283 return ((void *)gchp[unit]);
18543833Sxw161283 }
18553833Sxw161283
18563833Sxw161283 /*
18573833Sxw161283 * unregister toe offload.
18583833Sxw161283 * XXX Need to fix races here.
18593833Sxw161283 * 1. turn off SGE interrupts.
18603833Sxw161283 * 2. do update
18613833Sxw161283 * 3. re-enable SGE interrupts
18623833Sxw161283 * 4. SGE doorbell to make sure things get restarted.
18633833Sxw161283 */
18643833Sxw161283 void
ch_unregister(void)18653833Sxw161283 ch_unregister(void)
18663833Sxw161283 {
18673833Sxw161283 int i;
18683833Sxw161283 ch_t *chp;
18693833Sxw161283
18703833Sxw161283 for (i = 0; i < MAX_CARDS; i++) {
18713833Sxw161283 chp = gchp[i];
18723833Sxw161283 if (chp == NULL)
18733833Sxw161283 continue;
18743833Sxw161283
18753833Sxw161283 mutex_enter(&chp->ch_lock);
18763833Sxw161283
18773833Sxw161283 chp->ch_refcnt--;
18783833Sxw161283 if (chp->ch_refcnt == 0) {
18793833Sxw161283 chp->ch_state = PESTOP;
18803833Sxw161283 mutex_exit(&chp->ch_lock);
18813833Sxw161283 pe_stop(chp);
18823833Sxw161283 } else
18833833Sxw161283 mutex_exit(&chp->ch_lock);
18843833Sxw161283
18853833Sxw161283 chp->open_device_map &= ~TOEDEV_DEVMAP_BIT;
18863833Sxw161283 chp->toe_rcv = NULL;
18873833Sxw161283 chp->ch_toeinst = NULL;
18883833Sxw161283 chp->toe_free = NULL;
18893833Sxw161283 chp->toe_tunnel = NULL;
18903833Sxw161283 chp->ch_tx_overflow_mutex = NULL;
18913833Sxw161283 chp->ch_tx_overflow_cv = NULL;
18923833Sxw161283 }
18933833Sxw161283 }
18943833Sxw161283 #endif /* CONFIG_CHELSIO_T1_OFFLOAD */
18953833Sxw161283
18963833Sxw161283 /*
18973833Sxw161283 * get properties from chxge.conf
18983833Sxw161283 */
18993833Sxw161283 static void
ch_get_prop(ch_t * chp)19003833Sxw161283 ch_get_prop(ch_t *chp)
19013833Sxw161283 {
19023833Sxw161283 int val;
19033833Sxw161283 int tval = 0;
19043833Sxw161283 extern int enable_latency_timer;
19053833Sxw161283 extern uint32_t sge_cmdq0_cnt;
19063833Sxw161283 extern uint32_t sge_cmdq1_cnt;
19073833Sxw161283 extern uint32_t sge_flq0_cnt;
19083833Sxw161283 extern uint32_t sge_flq1_cnt;
19093833Sxw161283 extern uint32_t sge_respq_cnt;
19103833Sxw161283 extern uint32_t sge_cmdq0_cnt_orig;
19113833Sxw161283 extern uint32_t sge_cmdq1_cnt_orig;
19123833Sxw161283 extern uint32_t sge_flq0_cnt_orig;
19133833Sxw161283 extern uint32_t sge_flq1_cnt_orig;
19143833Sxw161283 extern uint32_t sge_respq_cnt_orig;
19153833Sxw161283 dev_info_t *pdip;
19163833Sxw161283 uint32_t vendor_id, device_id, revision_id;
19173833Sxw161283 uint32_t *prop_val = NULL;
19183833Sxw161283 uint32_t prop_len = NULL;
19193833Sxw161283
19203833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
1921*7656SSherry.Moore@Sun.COM "enable_dvma", -1);
19223833Sxw161283 if (val == -1)
19233833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
1924*7656SSherry.Moore@Sun.COM "enable-dvma", -1);
19253833Sxw161283 if (val != -1) {
19263833Sxw161283 if (val != 0)
19273833Sxw161283 chp->ch_config.enable_dvma = 1;
19283833Sxw161283 }
19293833Sxw161283
19303833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
1931*7656SSherry.Moore@Sun.COM "amd_bug_workaround", -1);
19323833Sxw161283 if (val == -1)
19333833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
1934*7656SSherry.Moore@Sun.COM "amd-bug-workaround", -1);
19353833Sxw161283
19363833Sxw161283 if (val != -1) {
19373833Sxw161283 if (val == 0) {
19383833Sxw161283 chp->ch_config.burstsize_set = 0;
19393833Sxw161283 chp->ch_config.transaction_cnt_set = 0;
19403833Sxw161283 goto fail_exit;
19413833Sxw161283 }
19423833Sxw161283 }
19433833Sxw161283 /*
19443833Sxw161283 * Step up to the parent node, That's the node above us
19453833Sxw161283 * in the device tree. And will typically be the PCI host
19463833Sxw161283 * Controller.
19473833Sxw161283 */
19483833Sxw161283 pdip = ddi_get_parent(chp->ch_dip);
19493833Sxw161283
19503833Sxw161283 /*
19513833Sxw161283 * Now get the 'Vendor id' properties
19523833Sxw161283 */
19533833Sxw161283 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, pdip, 0, "vendor-id",
19543833Sxw161283 (int **)&prop_val, &prop_len) != DDI_PROP_SUCCESS) {
19553833Sxw161283 chp->ch_config.burstsize_set = 0;
19563833Sxw161283 chp->ch_config.transaction_cnt_set = 0;
19573833Sxw161283 goto fail_exit;
19583833Sxw161283 }
19593833Sxw161283 vendor_id = *(uint32_t *)prop_val;
19603833Sxw161283 ddi_prop_free(prop_val);
19613833Sxw161283
19623833Sxw161283 /*
19633833Sxw161283 * Now get the 'Device id' properties
19643833Sxw161283 */
19653833Sxw161283 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, pdip, 0, "device-id",
19663833Sxw161283 (int **)&prop_val, &prop_len) != DDI_PROP_SUCCESS) {
19673833Sxw161283 chp->ch_config.burstsize_set = 0;
19683833Sxw161283 chp->ch_config.transaction_cnt_set = 0;
19693833Sxw161283 goto fail_exit;
19703833Sxw161283 }
19713833Sxw161283 device_id = *(uint32_t *)prop_val;
19723833Sxw161283 ddi_prop_free(prop_val);
19733833Sxw161283
19743833Sxw161283 /*
19753833Sxw161283 * Now get the 'Revision id' properties
19763833Sxw161283 */
19773833Sxw161283 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, pdip, 0, "revision-id",
19783833Sxw161283 (int **)&prop_val, &prop_len) != DDI_PROP_SUCCESS) {
19793833Sxw161283 chp->ch_config.burstsize_set = 0;
19803833Sxw161283 chp->ch_config.transaction_cnt_set = 0;
19813833Sxw161283 goto fail_exit;
19823833Sxw161283 }
19833833Sxw161283 revision_id = *(uint32_t *)prop_val;
19843833Sxw161283 ddi_prop_free(prop_val);
19853833Sxw161283
19863833Sxw161283 /*
19873833Sxw161283 * set default values based on node above us.
19883833Sxw161283 */
19893833Sxw161283 if ((vendor_id == AMD_VENDOR_ID) && (device_id == AMD_BRIDGE) &&
19903833Sxw161283 (revision_id <= AMD_BRIDGE_REV)) {
19913833Sxw161283 uint32_t v;
19923833Sxw161283 uint32_t burst;
19933833Sxw161283 uint32_t cnt;
19943833Sxw161283
19953833Sxw161283 /* if 133 Mhz not enabled, then do nothing - we're not PCIx */
19963833Sxw161283 v = pci_config_get32(chp->ch_hpci, 0x64);
19973833Sxw161283 if ((v & 0x20000) == NULL) {
19983833Sxw161283 chp->ch_config.burstsize_set = 0;
19993833Sxw161283 chp->ch_config.transaction_cnt_set = 0;
20003833Sxw161283 goto fail_exit;
20013833Sxw161283 }
20023833Sxw161283
20033833Sxw161283 /* check burst size and transaction count */
20043833Sxw161283 v = pci_config_get32(chp->ch_hpci, 0x60);
20053833Sxw161283 burst = (v >> 18) & 3;
20063833Sxw161283 cnt = (v >> 20) & 7;
20073833Sxw161283
20083833Sxw161283 switch (burst) {
20093833Sxw161283 case 0: /* 512 */
20103833Sxw161283 /* 512 burst size legal with split cnts 1,2,3 */
20113833Sxw161283 if (cnt <= 2) {
20123833Sxw161283 chp->ch_config.burstsize_set = 0;
20133833Sxw161283 chp->ch_config.transaction_cnt_set = 0;
20143833Sxw161283 goto fail_exit;
20153833Sxw161283 }
20163833Sxw161283 break;
20173833Sxw161283 case 1: /* 1024 */
20183833Sxw161283 /* 1024 burst size legal with split cnts 1,2 */
20193833Sxw161283 if (cnt <= 1) {
20203833Sxw161283 chp->ch_config.burstsize_set = 0;
20213833Sxw161283 chp->ch_config.transaction_cnt_set = 0;
20223833Sxw161283 goto fail_exit;
20233833Sxw161283 }
20243833Sxw161283 break;
20253833Sxw161283 case 2: /* 2048 */
20263833Sxw161283 /* 2048 burst size legal with split cnts 1 */
20273833Sxw161283 if (cnt == 0) {
20283833Sxw161283 chp->ch_config.burstsize_set = 0;
20293833Sxw161283 chp->ch_config.transaction_cnt_set = 0;
20303833Sxw161283 goto fail_exit;
20313833Sxw161283 }
20323833Sxw161283 break;
20333833Sxw161283 case 3: /* 4096 */
20343833Sxw161283 break;
20353833Sxw161283 }
20363833Sxw161283 } else {
20373833Sxw161283 goto fail_exit;
20383833Sxw161283 }
20393833Sxw161283
20403833Sxw161283 /*
20413833Sxw161283 * if illegal burst size seen, then default to 1024 burst size
20423833Sxw161283 */
20433833Sxw161283 chp->ch_config.burstsize = 1;
20443833Sxw161283 chp->ch_config.burstsize_set = 1;
20453833Sxw161283 /*
20463833Sxw161283 * if illegal transaction cnt seen, then default to 2
20473833Sxw161283 */
20483833Sxw161283 chp->ch_config.transaction_cnt = 1;
20493833Sxw161283 chp->ch_config.transaction_cnt_set = 1;
20503833Sxw161283
20513833Sxw161283
20523833Sxw161283 fail_exit:
20533833Sxw161283
20543833Sxw161283 /*
20553833Sxw161283 * alter the burstsize parameter via an entry
20563833Sxw161283 * in chxge.conf
20573833Sxw161283 */
20583833Sxw161283
20593833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2060*7656SSherry.Moore@Sun.COM "pci_burstsize", -1);
20613833Sxw161283 if (val == -1)
20623833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2063*7656SSherry.Moore@Sun.COM "pci-burstsize", -1);
20643833Sxw161283
20653833Sxw161283 if (val != -1) {
20663833Sxw161283
20673833Sxw161283 switch (val) {
20683833Sxw161283 case 0: /* use default */
20693833Sxw161283 chp->ch_config.burstsize_set = 0;
20703833Sxw161283 break;
20713833Sxw161283
20723833Sxw161283 case 1024:
20733833Sxw161283 chp->ch_config.burstsize_set = 1;
20743833Sxw161283 chp->ch_config.burstsize = 1;
20753833Sxw161283 break;
20763833Sxw161283
20773833Sxw161283 case 2048:
20783833Sxw161283 chp->ch_config.burstsize_set = 1;
20793833Sxw161283 chp->ch_config.burstsize = 2;
20803833Sxw161283 break;
20813833Sxw161283
20823833Sxw161283 case 4096:
20833833Sxw161283 cmn_err(CE_WARN, "%s not supported %d\n",
20843833Sxw161283 chp->ch_name, val);
20853833Sxw161283 break;
20863833Sxw161283
20873833Sxw161283 default:
20883833Sxw161283 cmn_err(CE_WARN, "%s illegal burst size %d\n",
20893833Sxw161283 chp->ch_name, val);
20903833Sxw161283 break;
20913833Sxw161283 }
20923833Sxw161283 }
20933833Sxw161283
20943833Sxw161283 /*
20953833Sxw161283 * set transaction count
20963833Sxw161283 */
20973833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2098*7656SSherry.Moore@Sun.COM "pci_split_transaction_cnt", -1);
20993833Sxw161283 if (val == -1)
21003833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2101*7656SSherry.Moore@Sun.COM "pci-split-transaction-cnt", -1);
21023833Sxw161283
21033833Sxw161283 if (val != -1) {
21043833Sxw161283 switch (val) {
21053833Sxw161283 case 0: /* use default */
21063833Sxw161283 chp->ch_config.transaction_cnt_set = 0;
21073833Sxw161283 break;
21083833Sxw161283
21093833Sxw161283 case 1:
21103833Sxw161283 chp->ch_config.transaction_cnt_set = 1;
21113833Sxw161283 chp->ch_config.transaction_cnt = 0;
21123833Sxw161283 break;
21133833Sxw161283
21143833Sxw161283 case 2:
21153833Sxw161283 chp->ch_config.transaction_cnt_set = 1;
21163833Sxw161283 chp->ch_config.transaction_cnt = 1;
21173833Sxw161283 break;
21183833Sxw161283
21193833Sxw161283 case 3:
21203833Sxw161283 chp->ch_config.transaction_cnt_set = 1;
21213833Sxw161283 chp->ch_config.transaction_cnt = 2;
21223833Sxw161283 break;
21233833Sxw161283
21243833Sxw161283 case 4:
21253833Sxw161283 chp->ch_config.transaction_cnt_set = 1;
21263833Sxw161283 chp->ch_config.transaction_cnt = 3;
21273833Sxw161283 break;
21283833Sxw161283
21293833Sxw161283 case 8:
21303833Sxw161283 chp->ch_config.transaction_cnt_set = 1;
21313833Sxw161283 chp->ch_config.transaction_cnt = 4;
21323833Sxw161283 break;
21333833Sxw161283
21343833Sxw161283 case 12:
21353833Sxw161283 chp->ch_config.transaction_cnt_set = 1;
21363833Sxw161283 chp->ch_config.transaction_cnt = 5;
21373833Sxw161283 break;
21383833Sxw161283
21393833Sxw161283 case 16:
21403833Sxw161283 chp->ch_config.transaction_cnt_set = 1;
21413833Sxw161283 chp->ch_config.transaction_cnt = 6;
21423833Sxw161283 break;
21433833Sxw161283
21443833Sxw161283 case 32:
21453833Sxw161283 chp->ch_config.transaction_cnt_set = 1;
21463833Sxw161283 chp->ch_config.transaction_cnt = 7;
21473833Sxw161283 break;
21483833Sxw161283
21493833Sxw161283 default:
21503833Sxw161283 cmn_err(CE_WARN, "%s illegal transaction cnt %d\n",
21513833Sxw161283 chp->ch_name, val);
21523833Sxw161283 break;
21533833Sxw161283 }
21543833Sxw161283 }
21553833Sxw161283
21563833Sxw161283 /*
21573833Sxw161283 * set relaxed ordering bit?
21583833Sxw161283 */
21593833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2160*7656SSherry.Moore@Sun.COM "pci_relaxed_ordering_on", -1);
21613833Sxw161283 if (val == -1)
21623833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2163*7656SSherry.Moore@Sun.COM "pci-relaxed-ordering-on", -1);
21643833Sxw161283
21653833Sxw161283 /*
21663833Sxw161283 * default is to use system default value.
21673833Sxw161283 */
21683833Sxw161283 chp->ch_config.relaxed_ordering = 0;
21693833Sxw161283
21703833Sxw161283 if (val != -1) {
21713833Sxw161283 if (val)
21723833Sxw161283 chp->ch_config.relaxed_ordering = 1;
21733833Sxw161283 }
21743833Sxw161283
21753833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2176*7656SSherry.Moore@Sun.COM "enable_latency_timer", -1);
21773833Sxw161283 if (val == -1)
21783833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2179*7656SSherry.Moore@Sun.COM "enable-latency-timer", -1);
21803833Sxw161283 if (val != -1)
21813833Sxw161283 enable_latency_timer = (val == 0)? 0: 1;
21823833Sxw161283
21833833Sxw161283 /*
21843833Sxw161283 * default maximum Jumbo Frame size.
21853833Sxw161283 */
21863833Sxw161283 chp->ch_maximum_mtu = 9198; /* tunable via chxge.conf */
21873833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2188*7656SSherry.Moore@Sun.COM "maximum_mtu", -1);
21893833Sxw161283 if (val == -1) {
21903833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2191*7656SSherry.Moore@Sun.COM "maximum-mtu", -1);
21923833Sxw161283 }
21933833Sxw161283 if (val != -1) {
21943833Sxw161283 if (val > 9582) {
21953833Sxw161283 cmn_err(CE_WARN,
21963833Sxw161283 "maximum_mtu value %d > 9582. Value set to 9582",
21973833Sxw161283 val);
21983833Sxw161283 val = 9582;
21993833Sxw161283 } else if (val < 1500) {
22003833Sxw161283 cmn_err(CE_WARN,
22013833Sxw161283 "maximum_mtu value %d < 1500. Value set to 1500",
22023833Sxw161283 val);
22033833Sxw161283 val = 1500;
22043833Sxw161283 }
22053833Sxw161283
22063833Sxw161283 if (val)
22073833Sxw161283 chp->ch_maximum_mtu = val;
22083833Sxw161283 }
22093833Sxw161283
22103833Sxw161283 /*
22113833Sxw161283 * default value for this instance mtu
22123833Sxw161283 */
22133833Sxw161283 chp->ch_mtu = ETHERMTU;
22143833Sxw161283
22153833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2216*7656SSherry.Moore@Sun.COM "accept_jumbo", -1);
22173833Sxw161283 if (val == -1) {
22183833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2219*7656SSherry.Moore@Sun.COM "accept-jumbo", -1);
22203833Sxw161283 }
22213833Sxw161283 if (val != -1) {
22223833Sxw161283 if (val)
22233833Sxw161283 chp->ch_mtu = chp->ch_maximum_mtu;
22243833Sxw161283 }
22253833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
22263833Sxw161283 chp->ch_sm_buf_sz = 0x800;
22273833Sxw161283 chp->ch_sm_buf_aln = 0x800;
22283833Sxw161283 chp->ch_bg_buf_sz = 0x4000;
22293833Sxw161283 chp->ch_bg_buf_aln = 0x4000;
22303833Sxw161283 #else
22313833Sxw161283 chp->ch_sm_buf_sz = 0x200;
22323833Sxw161283 chp->ch_sm_buf_aln = 0x200;
22333833Sxw161283 chp->ch_bg_buf_sz = 0x800;
22343833Sxw161283 chp->ch_bg_buf_aln = 0x800;
22353833Sxw161283 if ((chp->ch_mtu > 0x800) && (chp->ch_mtu <= 0x1000)) {
22363833Sxw161283 chp->ch_sm_buf_sz = 0x400;
22373833Sxw161283 chp->ch_sm_buf_aln = 0x400;
22383833Sxw161283 chp->ch_bg_buf_sz = 0x1000;
22393833Sxw161283 chp->ch_bg_buf_aln = 0x1000;
22403833Sxw161283 } else if ((chp->ch_mtu > 0x1000) && (chp->ch_mtu <= 0x2000)) {
22413833Sxw161283 chp->ch_sm_buf_sz = 0x400;
22423833Sxw161283 chp->ch_sm_buf_aln = 0x400;
22433833Sxw161283 chp->ch_bg_buf_sz = 0x2000;
22443833Sxw161283 chp->ch_bg_buf_aln = 0x2000;
22453833Sxw161283 } else if (chp->ch_mtu > 0x2000) {
22463833Sxw161283 chp->ch_sm_buf_sz = 0x400;
22473833Sxw161283 chp->ch_sm_buf_aln = 0x400;
22483833Sxw161283 chp->ch_bg_buf_sz = 0x3000;
22493833Sxw161283 chp->ch_bg_buf_aln = 0x4000;
22503833Sxw161283 }
22513833Sxw161283 #endif
22523833Sxw161283 chp->ch_config.cksum_enabled = 1;
22533833Sxw161283
22543833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2255*7656SSherry.Moore@Sun.COM "enable_checksum_offload", -1);
22563833Sxw161283 if (val == -1)
22573833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2258*7656SSherry.Moore@Sun.COM "enable-checksum-offload", -1);
22593833Sxw161283 if (val != -1) {
22603833Sxw161283 if (val == NULL)
22613833Sxw161283 chp->ch_config.cksum_enabled = 0;
22623833Sxw161283 }
22633833Sxw161283
22643833Sxw161283 /*
22653833Sxw161283 * Provides a tuning capability for the command queue 0 size.
22663833Sxw161283 */
22673833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2268*7656SSherry.Moore@Sun.COM "sge_cmdq0_cnt", -1);
22693833Sxw161283 if (val == -1)
22703833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2271*7656SSherry.Moore@Sun.COM "sge-cmdq0-cnt", -1);
22723833Sxw161283 if (val != -1) {
22733833Sxw161283 if (val > 10)
22743833Sxw161283 sge_cmdq0_cnt = val;
22753833Sxw161283 }
22763833Sxw161283
22773833Sxw161283 if (sge_cmdq0_cnt > 65535) {
22783833Sxw161283 cmn_err(CE_WARN,
22793833Sxw161283 "%s: sge-cmdQ0-cnt > 65535 - resetting value to default",
2280*7656SSherry.Moore@Sun.COM chp->ch_name);
22813833Sxw161283 sge_cmdq0_cnt = sge_cmdq0_cnt_orig;
22823833Sxw161283 }
22833833Sxw161283 tval += sge_cmdq0_cnt;
22843833Sxw161283
22853833Sxw161283 /*
22863833Sxw161283 * Provides a tuning capability for the command queue 1 size.
22873833Sxw161283 */
22883833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2289*7656SSherry.Moore@Sun.COM "sge_cmdq1_cnt", -1);
22903833Sxw161283 if (val == -1)
22913833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2292*7656SSherry.Moore@Sun.COM "sge-cmdq1-cnt", -1);
22933833Sxw161283 if (val != -1) {
22943833Sxw161283 if (val > 10)
22953833Sxw161283 sge_cmdq1_cnt = val;
22963833Sxw161283 }
22973833Sxw161283
22983833Sxw161283 if (sge_cmdq1_cnt > 65535) {
22993833Sxw161283 cmn_err(CE_WARN,
23003833Sxw161283 "%s: sge-cmdQ0-cnt > 65535 - resetting value to default",
2301*7656SSherry.Moore@Sun.COM chp->ch_name);
23023833Sxw161283 sge_cmdq1_cnt = sge_cmdq1_cnt_orig;
23033833Sxw161283 }
23043833Sxw161283
23053833Sxw161283 /*
23063833Sxw161283 * Provides a tuning capability for the free list 0 size.
23073833Sxw161283 */
23083833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2309*7656SSherry.Moore@Sun.COM "sge_flq0_cnt", -1);
23103833Sxw161283 if (val == -1)
23113833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2312*7656SSherry.Moore@Sun.COM "sge-flq0-cnt", -1);
23133833Sxw161283 if (val != -1) {
23143833Sxw161283 if (val > 512)
23153833Sxw161283 sge_flq0_cnt = val;
23163833Sxw161283 }
23173833Sxw161283
23183833Sxw161283 if (sge_flq0_cnt > 65535) {
23193833Sxw161283 cmn_err(CE_WARN,
23203833Sxw161283 "%s: sge-flq0-cnt > 65535 - resetting value to default",
2321*7656SSherry.Moore@Sun.COM chp->ch_name);
23223833Sxw161283 sge_flq0_cnt = sge_flq0_cnt_orig;
23233833Sxw161283 }
23243833Sxw161283
23253833Sxw161283 tval += sge_flq0_cnt;
23263833Sxw161283
23273833Sxw161283 /*
23283833Sxw161283 * Provides a tuning capability for the free list 1 size.
23293833Sxw161283 */
23303833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2331*7656SSherry.Moore@Sun.COM "sge_flq1_cnt", -1);
23323833Sxw161283 if (val == -1)
23333833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2334*7656SSherry.Moore@Sun.COM "sge-flq1-cnt", -1);
23353833Sxw161283 if (val != -1) {
23363833Sxw161283 if (val > 512)
23373833Sxw161283 sge_flq1_cnt = val;
23383833Sxw161283 }
23393833Sxw161283
23403833Sxw161283 if (sge_flq1_cnt > 65535) {
23413833Sxw161283 cmn_err(CE_WARN,
23423833Sxw161283 "%s: sge-flq1-cnt > 65535 - resetting value to default",
2343*7656SSherry.Moore@Sun.COM chp->ch_name);
23443833Sxw161283 sge_flq1_cnt = sge_flq1_cnt_orig;
23453833Sxw161283 }
23463833Sxw161283
23473833Sxw161283 tval += sge_flq1_cnt;
23483833Sxw161283
23493833Sxw161283 /*
23503833Sxw161283 * Provides a tuning capability for the responce queue size.
23513833Sxw161283 */
23523833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2353*7656SSherry.Moore@Sun.COM "sge_respq_cnt", -1);
23543833Sxw161283 if (val == -1)
23553833Sxw161283 val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2356*7656SSherry.Moore@Sun.COM "sge-respq-cnt", -1);
23573833Sxw161283 if (val != -1) {
23583833Sxw161283 if (val > 30)
23593833Sxw161283 sge_respq_cnt = val;
23603833Sxw161283 }
23613833Sxw161283
23623833Sxw161283 if (sge_respq_cnt > 65535) {
23633833Sxw161283 cmn_err(CE_WARN,
23643833Sxw161283 "%s: sge-respq-cnt > 65535 - resetting value to default",
2365*7656SSherry.Moore@Sun.COM chp->ch_name);
23663833Sxw161283 sge_respq_cnt = sge_respq_cnt_orig;
23673833Sxw161283 }
23683833Sxw161283
23693833Sxw161283 if (tval > sge_respq_cnt) {
23703833Sxw161283 if (tval <= 65535) {
23713833Sxw161283 cmn_err(CE_WARN,
23723833Sxw161283 "%s: sge-respq-cnt < %d - setting value to %d (cmdQ+flq0+flq1)",
23733833Sxw161283 chp->ch_name, tval, tval);
23743833Sxw161283
23753833Sxw161283 sge_respq_cnt = tval;
23763833Sxw161283 } else {
23773833Sxw161283 cmn_err(CE_WARN,
23783833Sxw161283 "%s: Q sizes invalid - resetting to default values",
23793833Sxw161283 chp->ch_name);
23803833Sxw161283
23813833Sxw161283 sge_cmdq0_cnt = sge_cmdq0_cnt_orig;
23823833Sxw161283 sge_cmdq1_cnt = sge_cmdq1_cnt_orig;
23833833Sxw161283 sge_flq0_cnt = sge_flq0_cnt_orig;
23843833Sxw161283 sge_flq1_cnt = sge_flq1_cnt_orig;
23853833Sxw161283 sge_respq_cnt = sge_respq_cnt_orig;
23863833Sxw161283 }
23873833Sxw161283 }
23883833Sxw161283 }
2389