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