1d39a76e7Sxw161283 /* 2d39a76e7Sxw161283 * CDDL HEADER START 3d39a76e7Sxw161283 * 4d39a76e7Sxw161283 * The contents of this file are subject to the terms of the 5d39a76e7Sxw161283 * Common Development and Distribution License (the "License"). 6d39a76e7Sxw161283 * You may not use this file except in compliance with the License. 7d39a76e7Sxw161283 * 8d39a76e7Sxw161283 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9d39a76e7Sxw161283 * or http://www.opensolaris.org/os/licensing. 10d39a76e7Sxw161283 * See the License for the specific language governing permissions 11d39a76e7Sxw161283 * and limitations under the License. 12d39a76e7Sxw161283 * 13d39a76e7Sxw161283 * When distributing Covered Code, include this CDDL HEADER in each 14d39a76e7Sxw161283 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15d39a76e7Sxw161283 * If applicable, add the following below this CDDL HEADER, with the 16d39a76e7Sxw161283 * fields enclosed by brackets "[]" replaced with your own identifying 17d39a76e7Sxw161283 * information: Portions Copyright [yyyy] [name of copyright owner] 18d39a76e7Sxw161283 * 19d39a76e7Sxw161283 * CDDL HEADER END 20d39a76e7Sxw161283 */ 21d39a76e7Sxw161283 22d39a76e7Sxw161283 /* 23d39a76e7Sxw161283 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24d39a76e7Sxw161283 * Use is subject to license terms. 25d39a76e7Sxw161283 */ 26d39a76e7Sxw161283 27d39a76e7Sxw161283 /* 28d39a76e7Sxw161283 * This file is part of the Chelsio T1 Ethernet driver. 29d39a76e7Sxw161283 * 30d39a76e7Sxw161283 * Copyright (C) 2003-2005 Chelsio Communications. All rights reserved. 31d39a76e7Sxw161283 */ 32d39a76e7Sxw161283 33d39a76e7Sxw161283 /* 34d39a76e7Sxw161283 * Solaris Multithreaded STREAMS Chelsio PCI Ethernet Driver. 35d39a76e7Sxw161283 * Interface code 36d39a76e7Sxw161283 */ 37d39a76e7Sxw161283 38d39a76e7Sxw161283 #include <sys/types.h> 39d39a76e7Sxw161283 #include <sys/systm.h> 40d39a76e7Sxw161283 #include <sys/cmn_err.h> 41d39a76e7Sxw161283 #include <sys/ddi.h> 42d39a76e7Sxw161283 #include <sys/sunddi.h> 43d39a76e7Sxw161283 #include <sys/byteorder.h> 44d39a76e7Sxw161283 #include <sys/atomic.h> 45d39a76e7Sxw161283 #include <sys/ethernet.h> 46d39a76e7Sxw161283 #if PE_PROFILING_ENABLED 47d39a76e7Sxw161283 #include <sys/time.h> 48d39a76e7Sxw161283 #endif 49d39a76e7Sxw161283 #include <sys/gld.h> 50d39a76e7Sxw161283 #include "ostypes.h" 51d39a76e7Sxw161283 #include "common.h" 52d39a76e7Sxw161283 #include "oschtoe.h" 53d39a76e7Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G 54d39a76e7Sxw161283 #include "fpga_defs.h" 55d39a76e7Sxw161283 #endif 56d39a76e7Sxw161283 #include "regs.h" 57d39a76e7Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD 58d39a76e7Sxw161283 #include "mc3.h" 59d39a76e7Sxw161283 #include "mc4.h" 60d39a76e7Sxw161283 #endif 61d39a76e7Sxw161283 #include "sge.h" 62d39a76e7Sxw161283 #include "tp.h" 63d39a76e7Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD 64d39a76e7Sxw161283 #include "ulp.h" 65d39a76e7Sxw161283 #endif 66d39a76e7Sxw161283 #include "espi.h" 67d39a76e7Sxw161283 #include "elmer0.h" 68d39a76e7Sxw161283 #include "gmac.h" 69d39a76e7Sxw161283 #include "cphy.h" 70d39a76e7Sxw161283 #include "suni1x10gexp_regs.h" 71d39a76e7Sxw161283 #include "ch.h" 72d39a76e7Sxw161283 73d39a76e7Sxw161283 #define MLEN(mp) ((mp)->b_wptr - (mp)->b_rptr) 74d39a76e7Sxw161283 75d39a76e7Sxw161283 extern uint32_t buffers_in_use[]; 76d39a76e7Sxw161283 extern kmutex_t in_use_l; 77d39a76e7Sxw161283 extern uint32_t in_use_index; 78d39a76e7Sxw161283 79d39a76e7Sxw161283 static void link_start(ch_t *sa, struct pe_port_t *pp); 80d39a76e7Sxw161283 static ch_esb_t *ch_alloc_small_esbbuf(ch_t *sa, uint32_t i); 81d39a76e7Sxw161283 static ch_esb_t *ch_alloc_big_esbbuf(ch_t *sa, uint32_t i); 82d39a76e7Sxw161283 void ch_big_rbuf_recycle(ch_esb_t *rbp); 83d39a76e7Sxw161283 void ch_small_rbuf_recycle(ch_esb_t *rbp); 84d39a76e7Sxw161283 static const struct board_info *pe_sa_init(ch_t *sa); 85d39a76e7Sxw161283 static int ch_set_config_data(ch_t *chp); 86d39a76e7Sxw161283 void pe_rbuf_pool_free(ch_t *chp); 87d39a76e7Sxw161283 static void pe_free_driver_resources(ch_t *sa); 88d39a76e7Sxw161283 static void update_mtu_tab(ch_t *adapter); 89d39a76e7Sxw161283 static int pe_change_mtu(ch_t *chp); 90d39a76e7Sxw161283 91d39a76e7Sxw161283 /* 92d39a76e7Sxw161283 * CPL5 Defines (from netinet/cpl5_commands.h) 93d39a76e7Sxw161283 */ 94d39a76e7Sxw161283 #define FLITSTOBYTES 8 95d39a76e7Sxw161283 96d39a76e7Sxw161283 #define CPL_FORMAT_0_SIZE 8 97d39a76e7Sxw161283 #define CPL_FORMAT_1_SIZE 16 98d39a76e7Sxw161283 #define CPL_FORMAT_2_SIZE 24 99d39a76e7Sxw161283 #define CPL_FORMAT_3_SIZE 32 100d39a76e7Sxw161283 #define CPL_FORMAT_4_SIZE 40 101d39a76e7Sxw161283 #define CPL_FORMAT_5_SIZE 48 102d39a76e7Sxw161283 103d39a76e7Sxw161283 #define TID_MASK 0xffffff 104d39a76e7Sxw161283 105d39a76e7Sxw161283 #define PE_LINK_SPEED_AUTONEG 5 106d39a76e7Sxw161283 107d39a76e7Sxw161283 static int pe_small_rbuf_pool_init(ch_t *sa); 108d39a76e7Sxw161283 static int pe_big_rbuf_pool_init(ch_t *sa); 109d39a76e7Sxw161283 static int pe_make_fake_arp(ch_t *chp, unsigned char *arpp); 110d39a76e7Sxw161283 static uint32_t pe_get_ip(unsigned char *arpp); 111d39a76e7Sxw161283 112d39a76e7Sxw161283 /* 113d39a76e7Sxw161283 * May be set in /etc/system to 0 to use default latency timer for 10G. 114d39a76e7Sxw161283 * See PCI register 0xc definition. 115d39a76e7Sxw161283 */ 116d39a76e7Sxw161283 int enable_latency_timer = 1; 117d39a76e7Sxw161283 118d39a76e7Sxw161283 /* 119d39a76e7Sxw161283 * May be set in /etc/system to 0 to disable hardware checksum for 120d39a76e7Sxw161283 * TCP and UDP. 121d39a76e7Sxw161283 */ 122d39a76e7Sxw161283 int enable_checksum_offload = 1; 123d39a76e7Sxw161283 124d39a76e7Sxw161283 /* 125d39a76e7Sxw161283 * Multiplier for freelist pool. 126d39a76e7Sxw161283 */ 127d39a76e7Sxw161283 int fl_sz_multiplier = 6; 128d39a76e7Sxw161283 129d39a76e7Sxw161283 uint_t 130d39a76e7Sxw161283 pe_intr(ch_t *sa) 131d39a76e7Sxw161283 { 132d39a76e7Sxw161283 mutex_enter(&sa->ch_intr); 133d39a76e7Sxw161283 134d39a76e7Sxw161283 if (sge_data_in(sa->sge)) { 135d39a76e7Sxw161283 sa->isr_intr++; 136d39a76e7Sxw161283 mutex_exit(&sa->ch_intr); 137d39a76e7Sxw161283 return (DDI_INTR_CLAIMED); 138d39a76e7Sxw161283 } 139d39a76e7Sxw161283 140d39a76e7Sxw161283 mutex_exit(&sa->ch_intr); 141d39a76e7Sxw161283 142d39a76e7Sxw161283 return (DDI_INTR_UNCLAIMED); 143d39a76e7Sxw161283 } 144d39a76e7Sxw161283 145d39a76e7Sxw161283 /* 146d39a76e7Sxw161283 * Each setup struct will call this function to 147d39a76e7Sxw161283 * initialize. 148d39a76e7Sxw161283 */ 149d39a76e7Sxw161283 void 150d39a76e7Sxw161283 pe_init(void* xsa) 151d39a76e7Sxw161283 { 152d39a76e7Sxw161283 ch_t *sa = NULL; 153d39a76e7Sxw161283 int i = 0; 154d39a76e7Sxw161283 155d39a76e7Sxw161283 sa = (ch_t *)xsa; 156d39a76e7Sxw161283 157d39a76e7Sxw161283 /* 158d39a76e7Sxw161283 * Need to count the number of times this routine is called 159d39a76e7Sxw161283 * because we only want the resources to be allocated once. 160d39a76e7Sxw161283 * The 7500 has four ports and so this routine can be called 161d39a76e7Sxw161283 * once for each port. 162d39a76e7Sxw161283 */ 163d39a76e7Sxw161283 if (sa->init_counter == 0) { 164d39a76e7Sxw161283 for_each_port(sa, i) { 165d39a76e7Sxw161283 166d39a76e7Sxw161283 /* 167d39a76e7Sxw161283 * We only want to initialize the line if it is down. 168d39a76e7Sxw161283 */ 169d39a76e7Sxw161283 if (sa->port[i].line_up == 0) { 170d39a76e7Sxw161283 link_start(sa, &sa->port[i]); 171d39a76e7Sxw161283 sa->port[i].line_up = 1; 172d39a76e7Sxw161283 } 173d39a76e7Sxw161283 } 174d39a76e7Sxw161283 175d39a76e7Sxw161283 (void) t1_init_hw_modules(sa); 176d39a76e7Sxw161283 177d39a76e7Sxw161283 /* 178d39a76e7Sxw161283 * Enable/Disable checksum offloading. 179d39a76e7Sxw161283 */ 180d39a76e7Sxw161283 if (sa->ch_config.cksum_enabled) { 181d39a76e7Sxw161283 if (sa->config_data.offload_ip_cksum) { 182d39a76e7Sxw161283 /* Notify that HW will do the checksum. */ 183d39a76e7Sxw161283 t1_tp_set_ip_checksum_offload(sa->tp, 1); 184d39a76e7Sxw161283 } 185d39a76e7Sxw161283 186d39a76e7Sxw161283 if (sa->config_data.offload_tcp_cksum) { 187d39a76e7Sxw161283 /* Notify that HW will do the checksum. */ 188d39a76e7Sxw161283 t1_tp_set_tcp_checksum_offload(sa->tp, 1); 189d39a76e7Sxw161283 } 190d39a76e7Sxw161283 191d39a76e7Sxw161283 if (sa->config_data.offload_udp_cksum) { 192d39a76e7Sxw161283 /* Notify that HW will do the checksum. */ 193d39a76e7Sxw161283 t1_tp_set_udp_checksum_offload(sa->tp, 1); 194d39a76e7Sxw161283 } 195d39a76e7Sxw161283 } 196d39a76e7Sxw161283 197d39a76e7Sxw161283 sa->ch_flags |= PEINITDONE; 198d39a76e7Sxw161283 199d39a76e7Sxw161283 sa->init_counter++; 200d39a76e7Sxw161283 } 201d39a76e7Sxw161283 202d39a76e7Sxw161283 /* 203d39a76e7Sxw161283 * Enable interrupts after starting the SGE so 204d39a76e7Sxw161283 * that the SGE is ready to handle interrupts. 205d39a76e7Sxw161283 */ 206d39a76e7Sxw161283 (void) sge_start(sa->sge); 207d39a76e7Sxw161283 t1_interrupts_enable(sa); 208d39a76e7Sxw161283 209d39a76e7Sxw161283 /* 210d39a76e7Sxw161283 * set mtu (either 1500 or bigger) 211d39a76e7Sxw161283 */ 212d39a76e7Sxw161283 (void) pe_change_mtu(sa); 213d39a76e7Sxw161283 #ifdef HOST_PAUSE 214d39a76e7Sxw161283 /* 215d39a76e7Sxw161283 * get the configured value of the MAC. 216d39a76e7Sxw161283 */ 217d39a76e7Sxw161283 (void) t1_tpi_read(sa, SUNI1x10GEXP_REG_TXXG_CONFIG_1 << 2, 218d39a76e7Sxw161283 &sa->txxg_cfg1); 219d39a76e7Sxw161283 #endif 220d39a76e7Sxw161283 } 221d39a76e7Sxw161283 222d39a76e7Sxw161283 /* ARGSUSED */ 223d39a76e7Sxw161283 static void 224d39a76e7Sxw161283 link_start(ch_t *sa, struct pe_port_t *p) 225d39a76e7Sxw161283 { 226d39a76e7Sxw161283 struct cmac *mac = p->mac; 227d39a76e7Sxw161283 228d39a76e7Sxw161283 mac->ops->reset(mac); 229d39a76e7Sxw161283 if (mac->ops->macaddress_set) 230d39a76e7Sxw161283 mac->ops->macaddress_set(mac, p->enaddr); 231d39a76e7Sxw161283 (void) t1_link_start(p->phy, mac, &p->link_config); 232d39a76e7Sxw161283 mac->ops->enable(mac, MAC_DIRECTION_RX | MAC_DIRECTION_TX); 233d39a76e7Sxw161283 } 234d39a76e7Sxw161283 235d39a76e7Sxw161283 /* 236d39a76e7Sxw161283 * turn off interrupts... 237d39a76e7Sxw161283 */ 238d39a76e7Sxw161283 void 239d39a76e7Sxw161283 pe_stop(ch_t *sa) 240d39a76e7Sxw161283 { 241d39a76e7Sxw161283 t1_interrupts_disable(sa); 242d39a76e7Sxw161283 (void) sge_stop(sa->sge); 243d39a76e7Sxw161283 244d39a76e7Sxw161283 /* 245d39a76e7Sxw161283 * we can still be running an interrupt thread in sge_data_in(). 246d39a76e7Sxw161283 * If we are, we'll block on the ch_intr lock 247d39a76e7Sxw161283 */ 248d39a76e7Sxw161283 mutex_enter(&sa->ch_intr); 249d39a76e7Sxw161283 mutex_exit(&sa->ch_intr); 250d39a76e7Sxw161283 } 251d39a76e7Sxw161283 252d39a76e7Sxw161283 /* 253d39a76e7Sxw161283 * output mblk to SGE level and out to the wire. 254d39a76e7Sxw161283 */ 255d39a76e7Sxw161283 256d39a76e7Sxw161283 int 257d39a76e7Sxw161283 pe_start(ch_t *sa, mblk_t *mp, uint32_t flg) 258d39a76e7Sxw161283 { 259d39a76e7Sxw161283 mblk_t *m0 = mp; 260d39a76e7Sxw161283 cmdQ_ce_t cm[16]; 261d39a76e7Sxw161283 cmdQ_ce_t *cmp; 262d39a76e7Sxw161283 cmdQ_ce_t *hmp = &cm[0]; /* head of cm table (may be kmem_alloed) */ 263d39a76e7Sxw161283 int cm_flg = 0; /* flag (1 - if kmem-alloced) */ 264d39a76e7Sxw161283 int nseg = 0; /* number cmdQ_ce entries created */ 265d39a76e7Sxw161283 int mseg = 16; /* maximum entries in hmp arrary */ 266d39a76e7Sxw161283 int freeme = 0; /* we have an mblk to free in case of error */ 267d39a76e7Sxw161283 uint32_t ch_bind_dma_handle(ch_t *, int, caddr_t, cmdQ_ce_t *, 268d39a76e7Sxw161283 uint32_t); 269d39a76e7Sxw161283 #if defined(__sparc) 270d39a76e7Sxw161283 uint32_t ch_bind_dvma_handle(ch_t *, int, caddr_t, cmdQ_ce_t *, 271d39a76e7Sxw161283 uint32_t); 272d39a76e7Sxw161283 #endif 273d39a76e7Sxw161283 int rv; /* return value on error */ 274d39a76e7Sxw161283 275d39a76e7Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD 276d39a76e7Sxw161283 if (flg & CH_OFFLOAD) { 277d39a76e7Sxw161283 hmp->ce_pa = ((tbuf_t *)mp)->tb_pa; 278d39a76e7Sxw161283 hmp->ce_dh = NULL; 279d39a76e7Sxw161283 hmp->ce_flg = DH_TOE; 280d39a76e7Sxw161283 hmp->ce_len = ((tbuf_t *)mp)->tb_len; 281d39a76e7Sxw161283 hmp->ce_mp = mp; 282d39a76e7Sxw161283 283d39a76e7Sxw161283 /* make sure data is flushed to physical memory */ 284d39a76e7Sxw161283 (void) ddi_dma_sync((ddi_dma_handle_t)((tbuf_t *)mp)->tb_dh, 285d39a76e7Sxw161283 (off_t)0, hmp->ce_len, DDI_DMA_SYNC_FORDEV); 286d39a76e7Sxw161283 287d39a76e7Sxw161283 if (sge_data_out(sa->sge, 0, mp, hmp, 1, flg) == 0) { 288d39a76e7Sxw161283 return (0); 289d39a76e7Sxw161283 } 290d39a76e7Sxw161283 291d39a76e7Sxw161283 /* 292d39a76e7Sxw161283 * set a flag so we'll restart upper layer when 293d39a76e7Sxw161283 * resources become available. 294d39a76e7Sxw161283 */ 295d39a76e7Sxw161283 sa->ch_blked = 1; 296d39a76e7Sxw161283 return (1); 297d39a76e7Sxw161283 } 298d39a76e7Sxw161283 #endif /* CONFIG_CHELSIO_T1_OFFLOAD */ 299d39a76e7Sxw161283 300d39a76e7Sxw161283 /* writes from toe will always have CPL header in place */ 301d39a76e7Sxw161283 if (flg & CH_NO_CPL) { 302d39a76e7Sxw161283 struct cpl_tx_pkt *cpl; 303d39a76e7Sxw161283 304d39a76e7Sxw161283 /* PR2928 & PR3309 */ 305d39a76e7Sxw161283 if (sa->ch_ip == NULL) { 306d39a76e7Sxw161283 ushort_t ethertype = ntohs(*(short *)&mp->b_rptr[12]); 307d39a76e7Sxw161283 if (ethertype == ETHERTYPE_ARP) { 308d39a76e7Sxw161283 if (is_T2(sa)) { 309d39a76e7Sxw161283 /* 310d39a76e7Sxw161283 * We assume here that the arp will be 311d39a76e7Sxw161283 * contained in one mblk. 312d39a76e7Sxw161283 */ 313d39a76e7Sxw161283 if (pe_make_fake_arp(sa, mp->b_rptr)) { 314d39a76e7Sxw161283 freemsg(mp); 315d39a76e7Sxw161283 sa->oerr++; 316d39a76e7Sxw161283 return (0); 317d39a76e7Sxw161283 } 318d39a76e7Sxw161283 } else { 319d39a76e7Sxw161283 sa->ch_ip = pe_get_ip(mp->b_rptr); 320d39a76e7Sxw161283 } 321d39a76e7Sxw161283 } 322d39a76e7Sxw161283 } 323d39a76e7Sxw161283 324d39a76e7Sxw161283 /* 325d39a76e7Sxw161283 * if space in front of packet big enough for CPL 326d39a76e7Sxw161283 * header, then use it. We'll allocate an mblk 327d39a76e7Sxw161283 * otherwise. 328d39a76e7Sxw161283 */ 329d39a76e7Sxw161283 if ((mp->b_rptr - mp->b_datap->db_base) >= SZ_CPL_TX_PKT) { 330d39a76e7Sxw161283 331d39a76e7Sxw161283 mp->b_rptr -= SZ_CPL_TX_PKT; 332d39a76e7Sxw161283 333d39a76e7Sxw161283 } else { 334d39a76e7Sxw161283 335d39a76e7Sxw161283 #ifdef SUN_KSTATS 336d39a76e7Sxw161283 sa->sge->intr_cnt.tx_need_cpl_space++; 337d39a76e7Sxw161283 #endif 338d39a76e7Sxw161283 m0 = allocb(SZ_CPL_TX_PKT, BPRI_HI); 339d39a76e7Sxw161283 if (m0 == NULL) { 340d39a76e7Sxw161283 freemsg(mp); 341d39a76e7Sxw161283 sa->oerr++; 342d39a76e7Sxw161283 return (0); 343d39a76e7Sxw161283 } 344d39a76e7Sxw161283 345d39a76e7Sxw161283 m0->b_wptr = m0->b_rptr + SZ_CPL_TX_PKT; 346d39a76e7Sxw161283 m0->b_cont = mp; 347d39a76e7Sxw161283 freeme = 1; 348d39a76e7Sxw161283 349d39a76e7Sxw161283 mp = m0; 350d39a76e7Sxw161283 } 351d39a76e7Sxw161283 352d39a76e7Sxw161283 /* fill in cpl header */ 353d39a76e7Sxw161283 cpl = (struct cpl_tx_pkt *)mp->b_rptr; 354d39a76e7Sxw161283 cpl->opcode = CPL_TX_PKT; 355d39a76e7Sxw161283 cpl->iff = 0; /* XXX port 0 needs fixing with NEMO */ 356d39a76e7Sxw161283 cpl->ip_csum_dis = 1; /* no IP header cksum */ 357d39a76e7Sxw161283 cpl->l4_csum_dis = 358d39a76e7Sxw161283 flg & CH_NO_HWCKSUM; /* CH_NO_HWCKSUM == 1 */ 359d39a76e7Sxw161283 cpl->vlan_valid = 0; /* no vlan */ 360d39a76e7Sxw161283 } 361d39a76e7Sxw161283 362d39a76e7Sxw161283 if (m0->b_cont) { 363d39a76e7Sxw161283 364d39a76e7Sxw161283 #ifdef SUN_KSTATS 365d39a76e7Sxw161283 sa->sge->intr_cnt.tx_multi_mblks++; 366d39a76e7Sxw161283 #endif 367d39a76e7Sxw161283 368d39a76e7Sxw161283 while (mp) { 369d39a76e7Sxw161283 int lseg; /* added by ch_bind_dma_handle() */ 370d39a76e7Sxw161283 int len; 371d39a76e7Sxw161283 372d39a76e7Sxw161283 len = MLEN(mp); 373d39a76e7Sxw161283 /* skip mlks with no data */ 374d39a76e7Sxw161283 if (len == 0) { 375d39a76e7Sxw161283 mp = mp->b_cont; 376d39a76e7Sxw161283 continue; 377d39a76e7Sxw161283 } 378d39a76e7Sxw161283 379d39a76e7Sxw161283 /* 380d39a76e7Sxw161283 * if we've run out of space on stack, then we 381d39a76e7Sxw161283 * allocate a temporary buffer to hold the 382d39a76e7Sxw161283 * information. This will kill the the performance, 383d39a76e7Sxw161283 * but since it shouldn't really occur, we can live 384d39a76e7Sxw161283 * with it. Since jumbo frames may map multiple 385d39a76e7Sxw161283 * descriptors, we reallocate the hmp[] array before 386d39a76e7Sxw161283 * we reach the end. 387d39a76e7Sxw161283 */ 388d39a76e7Sxw161283 if (nseg >= (mseg-4)) { 389d39a76e7Sxw161283 cmdQ_ce_t *buf; 390d39a76e7Sxw161283 int j; 391d39a76e7Sxw161283 392d39a76e7Sxw161283 buf = kmem_alloc(sizeof (cmdQ_ce_t) * 2 * mseg, 393d39a76e7Sxw161283 KM_SLEEP); 394d39a76e7Sxw161283 395d39a76e7Sxw161283 for (j = 0; j < nseg; j++) 396d39a76e7Sxw161283 buf[j] = hmp[j]; 397d39a76e7Sxw161283 398d39a76e7Sxw161283 if (cm_flg) { 399d39a76e7Sxw161283 kmem_free(hmp, 400d39a76e7Sxw161283 mseg * sizeof (cmdQ_ce_t)); 401d39a76e7Sxw161283 } else 402d39a76e7Sxw161283 cm_flg = 1; 403d39a76e7Sxw161283 404d39a76e7Sxw161283 hmp = buf; 405d39a76e7Sxw161283 mseg = 2*mseg; 406d39a76e7Sxw161283 407d39a76e7Sxw161283 /* 408d39a76e7Sxw161283 * We've used up ch table on stack 409d39a76e7Sxw161283 */ 410d39a76e7Sxw161283 } 411d39a76e7Sxw161283 412d39a76e7Sxw161283 #if defined(__sparc) 413d39a76e7Sxw161283 if (sa->ch_config.enable_dvma) { 414d39a76e7Sxw161283 lseg = ch_bind_dvma_handle(sa, len, 415d39a76e7Sxw161283 (void *)mp->b_rptr, 416d39a76e7Sxw161283 &hmp[nseg], mseg - nseg); 417d39a76e7Sxw161283 if (lseg == NULL) { 418d39a76e7Sxw161283 sa->sge->intr_cnt.tx_no_dvma1++; 419d39a76e7Sxw161283 if ((lseg = ch_bind_dma_handle(sa, len, 420d39a76e7Sxw161283 (void *)mp->b_rptr, 421d39a76e7Sxw161283 &hmp[nseg], 422d39a76e7Sxw161283 mseg - nseg)) == NULL) { 423d39a76e7Sxw161283 sa->sge->intr_cnt.tx_no_dma1++; 424d39a76e7Sxw161283 425d39a76e7Sxw161283 /* 426d39a76e7Sxw161283 * ran out of space. Gonna bale 427d39a76e7Sxw161283 */ 428d39a76e7Sxw161283 rv = 0; 429d39a76e7Sxw161283 430d39a76e7Sxw161283 /* 431d39a76e7Sxw161283 * we may have processed 432d39a76e7Sxw161283 * previous mblks and have 433d39a76e7Sxw161283 * descriptors. If so, we need 434d39a76e7Sxw161283 * to free the meta struct 435d39a76e7Sxw161283 * entries before freeing 436d39a76e7Sxw161283 * the mblk. 437d39a76e7Sxw161283 */ 438d39a76e7Sxw161283 if (nseg) 439d39a76e7Sxw161283 goto error; 440d39a76e7Sxw161283 goto error1; 441d39a76e7Sxw161283 } 442d39a76e7Sxw161283 } 443d39a76e7Sxw161283 } else { 444d39a76e7Sxw161283 lseg = ch_bind_dma_handle(sa, len, 445d39a76e7Sxw161283 (void *)mp->b_rptr, &hmp[nseg], 446d39a76e7Sxw161283 mseg - nseg); 447d39a76e7Sxw161283 if (lseg == NULL) { 448d39a76e7Sxw161283 sa->sge->intr_cnt.tx_no_dma1++; 449d39a76e7Sxw161283 450d39a76e7Sxw161283 /* 451d39a76e7Sxw161283 * ran out of space. Gona bale 452d39a76e7Sxw161283 */ 453d39a76e7Sxw161283 rv = 0; 454d39a76e7Sxw161283 455d39a76e7Sxw161283 /* 456d39a76e7Sxw161283 * we may have processed previous 457d39a76e7Sxw161283 * mblks and have descriptors. If so, 458d39a76e7Sxw161283 * we need to free the meta struct 459d39a76e7Sxw161283 * entries before freeing the mblk. 460d39a76e7Sxw161283 */ 461d39a76e7Sxw161283 if (nseg) 462d39a76e7Sxw161283 goto error; 463d39a76e7Sxw161283 goto error1; 464d39a76e7Sxw161283 } 465d39a76e7Sxw161283 } 466d39a76e7Sxw161283 #else /* defined(__sparc) */ 467d39a76e7Sxw161283 lseg = ch_bind_dma_handle(sa, len, 468d39a76e7Sxw161283 (void *)mp->b_rptr, &hmp[nseg], 469d39a76e7Sxw161283 mseg - nseg); 470d39a76e7Sxw161283 if (lseg == NULL) { 471d39a76e7Sxw161283 sa->sge->intr_cnt.tx_no_dma1++; 472d39a76e7Sxw161283 473d39a76e7Sxw161283 /* 474d39a76e7Sxw161283 * ran out of space. Gona bale 475d39a76e7Sxw161283 */ 476d39a76e7Sxw161283 rv = 0; 477d39a76e7Sxw161283 478d39a76e7Sxw161283 /* 479d39a76e7Sxw161283 * we may have processed previous mblks and 480d39a76e7Sxw161283 * have descriptors. If so, we need to free 481d39a76e7Sxw161283 * the meta struct entries before freeing 482d39a76e7Sxw161283 * the mblk. 483d39a76e7Sxw161283 */ 484d39a76e7Sxw161283 if (nseg) 485d39a76e7Sxw161283 goto error; 486d39a76e7Sxw161283 goto error1; 487d39a76e7Sxw161283 } 488d39a76e7Sxw161283 #endif /* defined(__sparc) */ 489d39a76e7Sxw161283 nseg += lseg; 490d39a76e7Sxw161283 mp = mp->b_cont; 491d39a76e7Sxw161283 } 492d39a76e7Sxw161283 493d39a76e7Sxw161283 /* 494d39a76e7Sxw161283 * SHOULD NEVER OCCUR, BUT... 495d39a76e7Sxw161283 * no data if nseg 0 or 496d39a76e7Sxw161283 * nseg 1 and a CPL mblk (CPL mblk only with offload mode) 497d39a76e7Sxw161283 * and no data 498d39a76e7Sxw161283 */ 499d39a76e7Sxw161283 if ((nseg == 0) || (freeme && (nseg == 1))) { 500d39a76e7Sxw161283 rv = 0; 501d39a76e7Sxw161283 goto error1; 502d39a76e7Sxw161283 } 503d39a76e7Sxw161283 504d39a76e7Sxw161283 } else { 505d39a76e7Sxw161283 int len; 506d39a76e7Sxw161283 507d39a76e7Sxw161283 /* we assume that we always have data with one packet */ 508d39a76e7Sxw161283 len = MLEN(mp); 509d39a76e7Sxw161283 510d39a76e7Sxw161283 #if defined(__sparc) 511d39a76e7Sxw161283 if (sa->ch_config.enable_dvma) { 512d39a76e7Sxw161283 nseg = ch_bind_dvma_handle(sa, len, 513d39a76e7Sxw161283 (void *)mp->b_rptr, 514d39a76e7Sxw161283 &hmp[0], 16); 515d39a76e7Sxw161283 if (nseg == NULL) { 516d39a76e7Sxw161283 sa->sge->intr_cnt.tx_no_dvma2++; 517d39a76e7Sxw161283 nseg = ch_bind_dma_handle(sa, len, 518d39a76e7Sxw161283 (void *)mp->b_rptr, 519d39a76e7Sxw161283 &hmp[0], 16); 520d39a76e7Sxw161283 if (nseg == NULL) { 521d39a76e7Sxw161283 sa->sge->intr_cnt.tx_no_dma2++; 522d39a76e7Sxw161283 523d39a76e7Sxw161283 /* 524d39a76e7Sxw161283 * ran out of space. Gona bale 525d39a76e7Sxw161283 */ 526d39a76e7Sxw161283 rv = 0; 527d39a76e7Sxw161283 goto error1; 528d39a76e7Sxw161283 } 529d39a76e7Sxw161283 } 530d39a76e7Sxw161283 } else { 531d39a76e7Sxw161283 nseg = ch_bind_dma_handle(sa, len, 532d39a76e7Sxw161283 (void *)mp->b_rptr, &hmp[0], 16); 533d39a76e7Sxw161283 if (nseg == NULL) { 534d39a76e7Sxw161283 sa->sge->intr_cnt.tx_no_dma2++; 535d39a76e7Sxw161283 536d39a76e7Sxw161283 /* 537d39a76e7Sxw161283 * ran out of space. Gona bale 538d39a76e7Sxw161283 */ 539d39a76e7Sxw161283 rv = 0; 540d39a76e7Sxw161283 goto error1; 541d39a76e7Sxw161283 } 542d39a76e7Sxw161283 } 543d39a76e7Sxw161283 #else /* defined(__sparc) */ 544d39a76e7Sxw161283 nseg = ch_bind_dma_handle(sa, len, 545d39a76e7Sxw161283 (void *)mp->b_rptr, &hmp[0], 16); 546d39a76e7Sxw161283 if (nseg == NULL) { 547d39a76e7Sxw161283 sa->sge->intr_cnt.tx_no_dma2++; 548d39a76e7Sxw161283 549d39a76e7Sxw161283 /* 550d39a76e7Sxw161283 * ran out of space. Gona bale 551d39a76e7Sxw161283 */ 552d39a76e7Sxw161283 rv = 0; 553d39a76e7Sxw161283 goto error1; 554d39a76e7Sxw161283 } 555d39a76e7Sxw161283 #endif /* defined(__sparc) */ 556d39a76e7Sxw161283 557d39a76e7Sxw161283 /* 558d39a76e7Sxw161283 * dummy arp message to handle PR3309 & PR2928 559d39a76e7Sxw161283 */ 560d39a76e7Sxw161283 if (flg & CH_ARP) 561d39a76e7Sxw161283 hmp->ce_flg |= DH_ARP; 562d39a76e7Sxw161283 } 563d39a76e7Sxw161283 564d39a76e7Sxw161283 if (sge_data_out(sa->sge, 0, m0, hmp, nseg, flg) == 0) { 565d39a76e7Sxw161283 if (cm_flg) 566d39a76e7Sxw161283 kmem_free(hmp, mseg * sizeof (cmdQ_ce_t)); 567d39a76e7Sxw161283 return (0); 568d39a76e7Sxw161283 } 569d39a76e7Sxw161283 570d39a76e7Sxw161283 /* 571d39a76e7Sxw161283 * set a flag so we'll restart upper layer when 572d39a76e7Sxw161283 * resources become available. 573d39a76e7Sxw161283 */ 574d39a76e7Sxw161283 if ((flg & CH_ARP) == 0) 575d39a76e7Sxw161283 sa->ch_blked = 1; 576d39a76e7Sxw161283 rv = 1; 577d39a76e7Sxw161283 578d39a76e7Sxw161283 error: 579d39a76e7Sxw161283 /* 580d39a76e7Sxw161283 * unmap the physical addresses allocated earlier. 581d39a76e7Sxw161283 */ 582d39a76e7Sxw161283 cmp = hmp; 583d39a76e7Sxw161283 for (--nseg; nseg >= 0; nseg--) { 584d39a76e7Sxw161283 if (cmp->ce_dh) { 585d39a76e7Sxw161283 if (cmp->ce_flg == DH_DMA) 586d39a76e7Sxw161283 ch_unbind_dma_handle(sa, cmp->ce_dh); 587d39a76e7Sxw161283 #if defined(__sparc) 588d39a76e7Sxw161283 else 589d39a76e7Sxw161283 ch_unbind_dvma_handle(sa, cmp->ce_dh); 590d39a76e7Sxw161283 #endif 591d39a76e7Sxw161283 } 592d39a76e7Sxw161283 cmp++; 593d39a76e7Sxw161283 } 594d39a76e7Sxw161283 595d39a76e7Sxw161283 error1: 596d39a76e7Sxw161283 597d39a76e7Sxw161283 /* free the temporary array */ 598d39a76e7Sxw161283 if (cm_flg) 599d39a76e7Sxw161283 kmem_free(hmp, mseg * sizeof (cmdQ_ce_t)); 600d39a76e7Sxw161283 601d39a76e7Sxw161283 /* 602d39a76e7Sxw161283 * if we've allocated an mblk above, then we need to free it 603d39a76e7Sxw161283 * before returning. This is safe since we haven't done anything to 604d39a76e7Sxw161283 * the original message. The caller, gld, will still have a pointer 605d39a76e7Sxw161283 * to the original mblk. 606d39a76e7Sxw161283 */ 607d39a76e7Sxw161283 if (rv == 1) { 608d39a76e7Sxw161283 if (freeme) { 609d39a76e7Sxw161283 /* we had to allocate an mblk. Free it. */ 610d39a76e7Sxw161283 freeb(m0); 611d39a76e7Sxw161283 } else { 612d39a76e7Sxw161283 /* adjust the mblk back to original start */ 613d39a76e7Sxw161283 if (flg & CH_NO_CPL) 614d39a76e7Sxw161283 m0->b_rptr += SZ_CPL_TX_PKT; 615d39a76e7Sxw161283 } 616d39a76e7Sxw161283 } else { 617d39a76e7Sxw161283 freemsg(m0); 618d39a76e7Sxw161283 sa->oerr++; 619d39a76e7Sxw161283 } 620d39a76e7Sxw161283 621d39a76e7Sxw161283 return (rv); 622d39a76e7Sxw161283 } 623d39a76e7Sxw161283 624d39a76e7Sxw161283 /* KLUDGE ALERT. HARD WIRED TO PORT ZERO */ 625d39a76e7Sxw161283 void 626d39a76e7Sxw161283 pe_set_mac(ch_t *sa, unsigned char *ac_enaddr) 627d39a76e7Sxw161283 { 628d39a76e7Sxw161283 sa->port[0].mac->ops->macaddress_set(sa->port[0].mac, ac_enaddr); 629d39a76e7Sxw161283 } 630d39a76e7Sxw161283 631d39a76e7Sxw161283 /* KLUDGE ALERT. HARD WIRED TO PORT ZERO */ 632d39a76e7Sxw161283 unsigned char * 633d39a76e7Sxw161283 pe_get_mac(ch_t *sa) 634d39a76e7Sxw161283 { 635d39a76e7Sxw161283 return (sa->port[0].enaddr); 636d39a76e7Sxw161283 } 637d39a76e7Sxw161283 638d39a76e7Sxw161283 /* KLUDGE ALERT. HARD WIRED TO ONE PORT */ 639d39a76e7Sxw161283 void 640d39a76e7Sxw161283 pe_set_promiscuous(ch_t *sa, int flag) 641d39a76e7Sxw161283 { 642d39a76e7Sxw161283 struct cmac *mac = sa->port[0].mac; 643d39a76e7Sxw161283 struct t1_rx_mode rm; 644d39a76e7Sxw161283 645d39a76e7Sxw161283 switch (flag) { 646d39a76e7Sxw161283 case 0: /* turn off promiscuous mode */ 647d39a76e7Sxw161283 sa->ch_flags &= ~(PEPROMISC|PEALLMULTI); 648d39a76e7Sxw161283 break; 649d39a76e7Sxw161283 650d39a76e7Sxw161283 case 1: /* turn on promiscuous mode */ 651d39a76e7Sxw161283 sa->ch_flags |= PEPROMISC; 652d39a76e7Sxw161283 break; 653d39a76e7Sxw161283 654d39a76e7Sxw161283 case 2: /* turn on multicast reception */ 655d39a76e7Sxw161283 sa->ch_flags |= PEALLMULTI; 656d39a76e7Sxw161283 break; 657d39a76e7Sxw161283 } 658d39a76e7Sxw161283 659d39a76e7Sxw161283 mutex_enter(&sa->ch_mc_lck); 660d39a76e7Sxw161283 rm.chp = sa; 661d39a76e7Sxw161283 rm.mc = sa->ch_mc; 662d39a76e7Sxw161283 663d39a76e7Sxw161283 mac->ops->set_rx_mode(mac, &rm); 664d39a76e7Sxw161283 mutex_exit(&sa->ch_mc_lck); 665d39a76e7Sxw161283 } 666d39a76e7Sxw161283 667d39a76e7Sxw161283 int 668d39a76e7Sxw161283 pe_set_mc(ch_t *sa, uint8_t *ep, int flg) 669d39a76e7Sxw161283 { 670d39a76e7Sxw161283 struct cmac *mac = sa->port[0].mac; 671d39a76e7Sxw161283 struct t1_rx_mode rm; 672d39a76e7Sxw161283 673d39a76e7Sxw161283 if (flg == GLD_MULTI_ENABLE) { 674d39a76e7Sxw161283 ch_mc_t *mcp; 675d39a76e7Sxw161283 676d39a76e7Sxw161283 mcp = (ch_mc_t *)kmem_zalloc(sizeof (struct ch_mc), 677d39a76e7Sxw161283 KM_NOSLEEP); 678d39a76e7Sxw161283 if (mcp == NULL) 679d39a76e7Sxw161283 return (GLD_NORESOURCES); 680d39a76e7Sxw161283 681d39a76e7Sxw161283 bcopy(ep, &mcp->cmc_mca, 6); 682d39a76e7Sxw161283 683d39a76e7Sxw161283 mutex_enter(&sa->ch_mc_lck); 684d39a76e7Sxw161283 mcp->cmc_next = sa->ch_mc; 685d39a76e7Sxw161283 sa->ch_mc = mcp; 686d39a76e7Sxw161283 sa->ch_mc_cnt++; 687d39a76e7Sxw161283 mutex_exit(&sa->ch_mc_lck); 688d39a76e7Sxw161283 689d39a76e7Sxw161283 } else if (flg == GLD_MULTI_DISABLE) { 690d39a76e7Sxw161283 ch_mc_t **p = &sa->ch_mc; 691d39a76e7Sxw161283 ch_mc_t *q = NULL; 692d39a76e7Sxw161283 693d39a76e7Sxw161283 mutex_enter(&sa->ch_mc_lck); 694d39a76e7Sxw161283 p = &sa->ch_mc; 695d39a76e7Sxw161283 while (*p) { 696d39a76e7Sxw161283 if (bcmp(ep, (*p)->cmc_mca, 6) == 0) { 697d39a76e7Sxw161283 q = *p; 698d39a76e7Sxw161283 *p = (*p)->cmc_next; 699d39a76e7Sxw161283 kmem_free(q, sizeof (*q)); 700d39a76e7Sxw161283 sa->ch_mc_cnt--; 701d39a76e7Sxw161283 break; 702d39a76e7Sxw161283 } 703d39a76e7Sxw161283 704d39a76e7Sxw161283 p = &(*p)->cmc_next; 705d39a76e7Sxw161283 } 706d39a76e7Sxw161283 mutex_exit(&sa->ch_mc_lck); 707d39a76e7Sxw161283 708d39a76e7Sxw161283 if (q == NULL) 709d39a76e7Sxw161283 return (GLD_BADARG); 710d39a76e7Sxw161283 } else 711d39a76e7Sxw161283 return (GLD_BADARG); 712d39a76e7Sxw161283 713d39a76e7Sxw161283 mutex_enter(&sa->ch_mc_lck); 714d39a76e7Sxw161283 rm.chp = sa; 715d39a76e7Sxw161283 rm.mc = sa->ch_mc; 716d39a76e7Sxw161283 717d39a76e7Sxw161283 mac->ops->set_rx_mode(mac, &rm); 718d39a76e7Sxw161283 mutex_exit(&sa->ch_mc_lck); 719d39a76e7Sxw161283 720d39a76e7Sxw161283 return (GLD_SUCCESS); 721d39a76e7Sxw161283 } 722d39a76e7Sxw161283 723d39a76e7Sxw161283 /* 724d39a76e7Sxw161283 * return: speed - bandwidth of interface 725d39a76e7Sxw161283 * return: intrcnt - # interrupts 726d39a76e7Sxw161283 * return: norcvbuf - # recedived packets dropped by driver 727d39a76e7Sxw161283 * return: oerrors - # bad send packets 728d39a76e7Sxw161283 * return: ierrors - # bad receive packets 729d39a76e7Sxw161283 * return: underrun - # bad underrun xmit packets 730d39a76e7Sxw161283 * return: overrun - # bad overrun recv packets 731d39a76e7Sxw161283 * return: framing - # bad aligned recv packets 732d39a76e7Sxw161283 * return: crc - # bad FCS (crc) recv packets 733d39a76e7Sxw161283 * return: carrier - times carrier was lost 734d39a76e7Sxw161283 * return: collisions - # xmit collisions 735d39a76e7Sxw161283 * return: xcollisions - # xmit pkts dropped due to collisions 736d39a76e7Sxw161283 * return: late - # late xmit collisions 737d39a76e7Sxw161283 * return: defer - # deferred xmit packets 738d39a76e7Sxw161283 * return: xerrs - # xmit dropped packets 739d39a76e7Sxw161283 * return: rerrs - # recv dropped packets 740d39a76e7Sxw161283 * return: toolong - # recv pkts too long 741d39a76e7Sxw161283 * return: runt - # recv runt pkts 742d39a76e7Sxw161283 * return: multixmt - # multicast pkts xmitted 743d39a76e7Sxw161283 * return: multircv - # multicast pkts recved 744d39a76e7Sxw161283 * return: brdcstxmt - # broadcast pkts xmitted 745d39a76e7Sxw161283 * return: brdcstrcv - # broadcast pkts rcv 746d39a76e7Sxw161283 */ 747d39a76e7Sxw161283 748d39a76e7Sxw161283 int 749d39a76e7Sxw161283 pe_get_stats(ch_t *sa, uint64_t *speed, uint32_t *intrcnt, uint32_t *norcvbuf, 750d39a76e7Sxw161283 uint32_t *oerrors, uint32_t *ierrors, uint32_t *underrun, 751d39a76e7Sxw161283 uint32_t *overrun, uint32_t *framing, uint32_t *crc, 752d39a76e7Sxw161283 uint32_t *carrier, uint32_t *collisions, uint32_t *xcollisions, 753d39a76e7Sxw161283 uint32_t *late, uint32_t *defer, uint32_t *xerrs, uint32_t *rerrs, 754d39a76e7Sxw161283 uint32_t *toolong, uint32_t *runt, ulong_t *multixmt, ulong_t *multircv, 755d39a76e7Sxw161283 ulong_t *brdcstxmt, ulong_t *brdcstrcv) 756d39a76e7Sxw161283 { 757d39a76e7Sxw161283 struct pe_port_t *pt; 758d39a76e7Sxw161283 int line_speed; 759d39a76e7Sxw161283 int line_duplex; 760d39a76e7Sxw161283 int line_is_active; 761d39a76e7Sxw161283 uint64_t v; 762d39a76e7Sxw161283 const struct cmac_statistics *sp; 763d39a76e7Sxw161283 764d39a76e7Sxw161283 pt = &(sa->port[0]); 765d39a76e7Sxw161283 (void) pt->phy->ops->get_link_status(pt->phy, 766d39a76e7Sxw161283 &line_is_active, &line_speed, &line_duplex, NULL); 767d39a76e7Sxw161283 768d39a76e7Sxw161283 switch (line_speed) { 769d39a76e7Sxw161283 case SPEED_10: 770d39a76e7Sxw161283 *speed = 10000000; 771d39a76e7Sxw161283 break; 772d39a76e7Sxw161283 case SPEED_100: 773d39a76e7Sxw161283 *speed = 100000000; 774d39a76e7Sxw161283 break; 775d39a76e7Sxw161283 case SPEED_1000: 776d39a76e7Sxw161283 *speed = 1000000000; 777d39a76e7Sxw161283 break; 778d39a76e7Sxw161283 case SPEED_10000: 779d39a76e7Sxw161283 /* 780d39a76e7Sxw161283 * kludge to get 10,000,000,000 constant (and keep 781d39a76e7Sxw161283 * compiler happy). 782d39a76e7Sxw161283 */ 783d39a76e7Sxw161283 v = 10000000; 784d39a76e7Sxw161283 v *= 1000; 785d39a76e7Sxw161283 *speed = v; 786d39a76e7Sxw161283 break; 787d39a76e7Sxw161283 default: 788d39a76e7Sxw161283 goto error; 789d39a76e7Sxw161283 } 790d39a76e7Sxw161283 791d39a76e7Sxw161283 *intrcnt = sa->isr_intr; 792d39a76e7Sxw161283 *norcvbuf = sa->norcvbuf; 793d39a76e7Sxw161283 794d39a76e7Sxw161283 sp = sa->port[0].mac->ops->statistics_update(sa->port[0].mac, 795d39a76e7Sxw161283 MAC_STATS_UPDATE_FULL); 796d39a76e7Sxw161283 797d39a76e7Sxw161283 *ierrors = sp->RxOctetsBad; 798d39a76e7Sxw161283 799d39a76e7Sxw161283 /* 800d39a76e7Sxw161283 * not sure this is correct. # aborted at driver level + 801d39a76e7Sxw161283 * # at hardware level 802d39a76e7Sxw161283 */ 803d39a76e7Sxw161283 *oerrors = sa->oerr + sp->TxFramesAbortedDueToXSCollisions + 804d39a76e7Sxw161283 sp->TxUnderrun + sp->TxLengthErrors + 805d39a76e7Sxw161283 sp->TxInternalMACXmitError + 806d39a76e7Sxw161283 sp->TxFramesWithExcessiveDeferral + 807d39a76e7Sxw161283 sp->TxFCSErrors; 808d39a76e7Sxw161283 809d39a76e7Sxw161283 *underrun = sp->TxUnderrun; 810d39a76e7Sxw161283 *overrun = sp->RxFrameTooLongErrors; 811d39a76e7Sxw161283 *framing = sp->RxAlignErrors; 812d39a76e7Sxw161283 *crc = sp->RxFCSErrors; 813d39a76e7Sxw161283 *carrier = 0; /* need to find this */ 814d39a76e7Sxw161283 *collisions = sp->TxTotalCollisions; 815d39a76e7Sxw161283 *xcollisions = sp->TxFramesAbortedDueToXSCollisions; 816d39a76e7Sxw161283 *late = sp->TxLateCollisions; 817d39a76e7Sxw161283 *defer = sp->TxFramesWithDeferredXmissions; 818d39a76e7Sxw161283 *xerrs = sp->TxUnderrun + sp->TxLengthErrors + 819d39a76e7Sxw161283 sp->TxInternalMACXmitError + sp->TxFCSErrors; 820d39a76e7Sxw161283 *rerrs = sp->RxSymbolErrors + sp->RxSequenceErrors + sp->RxRuntErrors + 821d39a76e7Sxw161283 sp->RxJabberErrors + sp->RxInternalMACRcvError + 822d39a76e7Sxw161283 sp->RxInRangeLengthErrors + sp->RxOutOfRangeLengthField; 823d39a76e7Sxw161283 *toolong = sp->RxFrameTooLongErrors; 824d39a76e7Sxw161283 *runt = sp->RxRuntErrors; 825d39a76e7Sxw161283 826d39a76e7Sxw161283 *multixmt = sp->TxMulticastFramesOK; 827d39a76e7Sxw161283 *multircv = sp->RxMulticastFramesOK; 828d39a76e7Sxw161283 *brdcstxmt = sp->TxBroadcastFramesOK; 829d39a76e7Sxw161283 *brdcstrcv = sp->RxBroadcastFramesOK; 830d39a76e7Sxw161283 831d39a76e7Sxw161283 return (0); 832d39a76e7Sxw161283 833d39a76e7Sxw161283 error: 834d39a76e7Sxw161283 *speed = 0; 835d39a76e7Sxw161283 *intrcnt = 0; 836d39a76e7Sxw161283 *norcvbuf = 0; 837d39a76e7Sxw161283 *norcvbuf = 0; 838d39a76e7Sxw161283 *oerrors = 0; 839d39a76e7Sxw161283 *ierrors = 0; 840d39a76e7Sxw161283 *underrun = 0; 841d39a76e7Sxw161283 *overrun = 0; 842d39a76e7Sxw161283 *framing = 0; 843d39a76e7Sxw161283 *crc = 0; 844d39a76e7Sxw161283 *carrier = 0; 845d39a76e7Sxw161283 *collisions = 0; 846d39a76e7Sxw161283 *xcollisions = 0; 847d39a76e7Sxw161283 *late = 0; 848d39a76e7Sxw161283 *defer = 0; 849d39a76e7Sxw161283 *xerrs = 0; 850d39a76e7Sxw161283 *rerrs = 0; 851d39a76e7Sxw161283 *toolong = 0; 852d39a76e7Sxw161283 *runt = 0; 853d39a76e7Sxw161283 *multixmt = 0; 854d39a76e7Sxw161283 *multircv = 0; 855d39a76e7Sxw161283 *brdcstxmt = 0; 856d39a76e7Sxw161283 *brdcstrcv = 0; 857d39a76e7Sxw161283 858d39a76e7Sxw161283 return (1); 859d39a76e7Sxw161283 } 860d39a76e7Sxw161283 861d39a76e7Sxw161283 uint32_t ch_gtm = 0; /* Default: Global Tunnel Mode off */ 862d39a76e7Sxw161283 uint32_t ch_global_config = 0x07000000; /* Default: errors, warnings, status */ 863d39a76e7Sxw161283 uint32_t ch_is_asic = 0; /* Default: non-ASIC */ 864d39a76e7Sxw161283 uint32_t ch_link_speed = PE_LINK_SPEED_AUTONEG; /* Default: auto-negoiate */ 865d39a76e7Sxw161283 uint32_t ch_num_of_ports = 1; /* Default: 1 port */ 866d39a76e7Sxw161283 uint32_t ch_tp_reset_cm = 1; /* Default: reset CM memory map */ 867d39a76e7Sxw161283 uint32_t ch_phy_tx_fifo = 0; /* Default: 0 phy tx fifo depth */ 868d39a76e7Sxw161283 uint32_t ch_phy_rx_fifo = 0; /* Default: 0 phy rx fifo depth */ 869d39a76e7Sxw161283 uint32_t ch_phy_force_master = 1; /* Default: link always master mode */ 870d39a76e7Sxw161283 uint32_t ch_mc5_rtbl_size = 2048; /* Default: TCAM routing table size */ 871d39a76e7Sxw161283 uint32_t ch_mc5_dbsvr_size = 128; /* Default: TCAM server size */ 872d39a76e7Sxw161283 uint32_t ch_mc5_parity = 1; /* Default: parity error checking */ 873d39a76e7Sxw161283 uint32_t ch_mc5_issue_syn = 0; /* Default: Allow transaction overlap */ 874d39a76e7Sxw161283 uint32_t ch_packet_tracing = 0; /* Default: no packet tracing */ 875d39a76e7Sxw161283 uint32_t ch_server_region_len = 876d39a76e7Sxw161283 DEFAULT_SERVER_REGION_LEN; 877d39a76e7Sxw161283 uint32_t ch_rt_region_len = 878d39a76e7Sxw161283 DEFAULT_RT_REGION_LEN; 879d39a76e7Sxw161283 uint32_t ch_offload_ip_cksum = 0; /* Default: no checksum offloading */ 880d39a76e7Sxw161283 uint32_t ch_offload_udp_cksum = 1; /* Default: offload UDP ckecksum */ 881d39a76e7Sxw161283 uint32_t ch_offload_tcp_cksum = 1; /* Default: offload TCP checksum */ 882d39a76e7Sxw161283 uint32_t ch_sge_cmdq_threshold = 0; /* Default: threshold 0 */ 883d39a76e7Sxw161283 uint32_t ch_sge_flq_threshold = 0; /* Default: SGE flq threshold */ 884d39a76e7Sxw161283 uint32_t ch_sge_cmdq0_cnt = /* Default: cmd queue 0 size */ 885d39a76e7Sxw161283 SGE_CMDQ0_CNT; 886d39a76e7Sxw161283 uint32_t ch_sge_cmdq1_cnt = /* Default: cmd queue 1 size */ 887d39a76e7Sxw161283 SGE_CMDQ0_CNT; 888d39a76e7Sxw161283 uint32_t ch_sge_flq0_cnt = /* Default: free list queue-0 length */ 889d39a76e7Sxw161283 SGE_FLQ0_CNT; 890d39a76e7Sxw161283 uint32_t ch_sge_flq1_cnt = /* Default: free list queue-1 length */ 891d39a76e7Sxw161283 SGE_FLQ0_CNT; 892d39a76e7Sxw161283 uint32_t ch_sge_respq_cnt = /* Default: reqsponse queue size */ 893d39a76e7Sxw161283 SGE_RESPQ_CNT; 894d39a76e7Sxw161283 uint32_t ch_stats = 1; /* Default: Automatic Update MAC stats */ 895d39a76e7Sxw161283 uint32_t ch_tx_delay_us = 0; /* Default: No Msec delay to Tx pkts */ 896d39a76e7Sxw161283 int32_t ch_chip = -1; /* Default: use hardware lookup tbl */ 897d39a76e7Sxw161283 uint32_t ch_exit_early = 0; /* Default: complete initialization */ 898d39a76e7Sxw161283 uint32_t ch_rb_num_of_entries = 1000; /* Default: number ring buffer entries */ 899d39a76e7Sxw161283 uint32_t ch_rb_size_of_entries = 64; /* Default: ring buffer entry size */ 900d39a76e7Sxw161283 uint32_t ch_rb_flag = 1; /* Default: ring buffer flag */ 901d39a76e7Sxw161283 uint32_t ch_type; 902d39a76e7Sxw161283 uint64_t ch_cat_opt0 = 0; 903d39a76e7Sxw161283 uint64_t ch_cat_opt1 = 0; 904d39a76e7Sxw161283 uint32_t ch_timer_delay = 0; /* Default: use value from board entry */ 905d39a76e7Sxw161283 906d39a76e7Sxw161283 int 907d39a76e7Sxw161283 pe_attach(ch_t *chp) 908d39a76e7Sxw161283 { 909d39a76e7Sxw161283 int return_val = 1; 910d39a76e7Sxw161283 const struct board_info *bi; 911d39a76e7Sxw161283 uint32_t pcix_cmd; 912d39a76e7Sxw161283 913d39a76e7Sxw161283 (void) ch_set_config_data(chp); 914d39a76e7Sxw161283 915d39a76e7Sxw161283 bi = pe_sa_init(chp); 916d39a76e7Sxw161283 if (bi == 0) 917d39a76e7Sxw161283 return (1); 918d39a76e7Sxw161283 919d39a76e7Sxw161283 if (t1_init_sw_modules(chp, bi) < 0) 920d39a76e7Sxw161283 return (1); 921d39a76e7Sxw161283 922d39a76e7Sxw161283 if (pe_small_rbuf_pool_init(chp) == NULL) 923d39a76e7Sxw161283 return (1); 924d39a76e7Sxw161283 925d39a76e7Sxw161283 if (pe_big_rbuf_pool_init(chp) == NULL) 926d39a76e7Sxw161283 return (1); 927d39a76e7Sxw161283 928d39a76e7Sxw161283 /* 929d39a76e7Sxw161283 * We gain significaint performance improvements when we 930d39a76e7Sxw161283 * increase the PCI's maximum memory read byte count to 931d39a76e7Sxw161283 * 2K(HW doesn't support 4K at this time) and set the PCI's 932d39a76e7Sxw161283 * maximum outstanding split transactions to 4. We want to do 933d39a76e7Sxw161283 * this for 10G. Done by software utility. 934d39a76e7Sxw161283 */ 935d39a76e7Sxw161283 936d39a76e7Sxw161283 if (board_info(chp)->caps & SUPPORTED_10000baseT_Full) { 937d39a76e7Sxw161283 (void) t1_os_pci_read_config_4(chp, A_PCICFG_PCIX_CMD, 938d39a76e7Sxw161283 &pcix_cmd); 939d39a76e7Sxw161283 /* 940d39a76e7Sxw161283 * if the burstsize is set, then use it instead of default 941d39a76e7Sxw161283 */ 942d39a76e7Sxw161283 if (chp->ch_config.burstsize_set) { 943d39a76e7Sxw161283 pcix_cmd &= ~0xc0000; 944d39a76e7Sxw161283 pcix_cmd |= (chp->ch_config.burstsize << 18); 945d39a76e7Sxw161283 } 946d39a76e7Sxw161283 /* 947d39a76e7Sxw161283 * if the split transaction count is set, then use it. 948d39a76e7Sxw161283 */ 949d39a76e7Sxw161283 if (chp->ch_config.transaction_cnt_set) { 950d39a76e7Sxw161283 pcix_cmd &= ~ 0x700000; 951d39a76e7Sxw161283 pcix_cmd |= (chp->ch_config.transaction_cnt << 20); 952d39a76e7Sxw161283 } 953d39a76e7Sxw161283 954d39a76e7Sxw161283 /* 955d39a76e7Sxw161283 * set ralaxed ordering flag as configured in chxge.conf 956d39a76e7Sxw161283 */ 957d39a76e7Sxw161283 pcix_cmd |= (chp->ch_config.relaxed_ordering << 17); 958d39a76e7Sxw161283 959d39a76e7Sxw161283 (void) t1_os_pci_write_config_4(chp, A_PCICFG_PCIX_CMD, 960d39a76e7Sxw161283 pcix_cmd); 961d39a76e7Sxw161283 } 962d39a76e7Sxw161283 963d39a76e7Sxw161283 /* 964d39a76e7Sxw161283 * set the latency time to F8 for 10G cards. 965d39a76e7Sxw161283 * Done by software utiltiy. 966d39a76e7Sxw161283 */ 967d39a76e7Sxw161283 if (enable_latency_timer) { 968d39a76e7Sxw161283 if (board_info(chp)->caps & SUPPORTED_10000baseT_Full) { 969d39a76e7Sxw161283 (void) t1_os_pci_write_config_4(chp, 0xc, 0xf800); 970d39a76e7Sxw161283 } 971d39a76e7Sxw161283 } 972d39a76e7Sxw161283 973d39a76e7Sxw161283 /* 974d39a76e7Sxw161283 * update mtu table (regs: 0x404 - 0x420) with bigger values than 975d39a76e7Sxw161283 * default. 976d39a76e7Sxw161283 */ 977d39a76e7Sxw161283 update_mtu_tab(chp); 978d39a76e7Sxw161283 979d39a76e7Sxw161283 /* 980d39a76e7Sxw161283 * Clear all interrupts now. Don't enable 981d39a76e7Sxw161283 * them until later. 982d39a76e7Sxw161283 */ 983d39a76e7Sxw161283 t1_interrupts_clear(chp); 984d39a76e7Sxw161283 985d39a76e7Sxw161283 /* 986d39a76e7Sxw161283 * Function succeeded. 987d39a76e7Sxw161283 */ 988d39a76e7Sxw161283 return_val = 0; 989d39a76e7Sxw161283 990d39a76e7Sxw161283 return (return_val); 991d39a76e7Sxw161283 } 992d39a76e7Sxw161283 993d39a76e7Sxw161283 /* 994d39a76e7Sxw161283 * DESC: Read variables set in /boot/loader.conf and save 995d39a76e7Sxw161283 * them internally. These internal values are then 996d39a76e7Sxw161283 * used to make decisions at run-time on behavior thus 997d39a76e7Sxw161283 * allowing a certain level of customization. 998d39a76e7Sxw161283 * OUT: p_config - pointer to config structure that 999d39a76e7Sxw161283 * contains all of the new values. 1000d39a76e7Sxw161283 * RTN: 0 - Success; 1001d39a76e7Sxw161283 */ 1002d39a76e7Sxw161283 static int 1003d39a76e7Sxw161283 ch_set_config_data(ch_t *chp) 1004d39a76e7Sxw161283 { 1005d39a76e7Sxw161283 pe_config_data_t *p_config = (pe_config_data_t *)&chp->config_data; 1006d39a76e7Sxw161283 1007d39a76e7Sxw161283 bzero(p_config, sizeof (pe_config_data_t)); 1008d39a76e7Sxw161283 1009d39a76e7Sxw161283 /* 1010d39a76e7Sxw161283 * Global Tunnel Mode configuration 1011d39a76e7Sxw161283 */ 1012d39a76e7Sxw161283 p_config->gtm = ch_gtm; 1013d39a76e7Sxw161283 1014d39a76e7Sxw161283 p_config->global_config = ch_global_config; 1015d39a76e7Sxw161283 1016d39a76e7Sxw161283 if (p_config->gtm) 1017d39a76e7Sxw161283 p_config->global_config |= CFGMD_TUNNEL; 1018d39a76e7Sxw161283 1019d39a76e7Sxw161283 p_config->tp_reset_cm = ch_tp_reset_cm; 1020d39a76e7Sxw161283 p_config->is_asic = ch_is_asic; 1021d39a76e7Sxw161283 1022d39a76e7Sxw161283 /* 1023d39a76e7Sxw161283 * MC5 configuration. 1024d39a76e7Sxw161283 */ 1025d39a76e7Sxw161283 p_config->mc5_rtbl_size = ch_mc5_rtbl_size; 1026d39a76e7Sxw161283 p_config->mc5_dbsvr_size = ch_mc5_dbsvr_size; 1027d39a76e7Sxw161283 p_config->mc5_parity = ch_mc5_parity; 1028d39a76e7Sxw161283 p_config->mc5_issue_syn = ch_mc5_issue_syn; 1029d39a76e7Sxw161283 1030d39a76e7Sxw161283 p_config->offload_ip_cksum = ch_offload_ip_cksum; 1031d39a76e7Sxw161283 p_config->offload_udp_cksum = ch_offload_udp_cksum; 1032d39a76e7Sxw161283 p_config->offload_tcp_cksum = ch_offload_tcp_cksum; 1033d39a76e7Sxw161283 1034d39a76e7Sxw161283 p_config->packet_tracing = ch_packet_tracing; 1035d39a76e7Sxw161283 1036d39a76e7Sxw161283 p_config->server_region_len = ch_server_region_len; 1037d39a76e7Sxw161283 p_config->rt_region_len = ch_rt_region_len; 1038d39a76e7Sxw161283 1039d39a76e7Sxw161283 /* 1040d39a76e7Sxw161283 * Link configuration. 1041d39a76e7Sxw161283 * 1042d39a76e7Sxw161283 * 5-auto-neg 2-1000Gbps; 1-100Gbps; 0-10Gbps 1043d39a76e7Sxw161283 */ 1044d39a76e7Sxw161283 p_config->link_speed = ch_link_speed; 1045d39a76e7Sxw161283 p_config->num_of_ports = ch_num_of_ports; 1046d39a76e7Sxw161283 1047d39a76e7Sxw161283 /* 1048d39a76e7Sxw161283 * Catp options 1049d39a76e7Sxw161283 */ 1050d39a76e7Sxw161283 p_config->cat_opt0 = ch_cat_opt0; 1051d39a76e7Sxw161283 p_config->cat_opt1 = ch_cat_opt1; 1052d39a76e7Sxw161283 1053d39a76e7Sxw161283 /* 1054d39a76e7Sxw161283 * SGE configuration. 1055d39a76e7Sxw161283 */ 1056d39a76e7Sxw161283 p_config->sge_cmdq0_cnt = ch_sge_cmdq0_cnt; 1057d39a76e7Sxw161283 p_config->sge_cmdq1_cnt = ch_sge_cmdq1_cnt; 1058d39a76e7Sxw161283 p_config->sge_flq0_cnt = ch_sge_flq0_cnt; 1059d39a76e7Sxw161283 p_config->sge_flq1_cnt = ch_sge_flq1_cnt; 1060d39a76e7Sxw161283 p_config->sge_respq_cnt = ch_sge_respq_cnt; 1061d39a76e7Sxw161283 1062d39a76e7Sxw161283 p_config->phy_rx_fifo = ch_phy_rx_fifo; 1063d39a76e7Sxw161283 p_config->phy_tx_fifo = ch_phy_tx_fifo; 1064d39a76e7Sxw161283 1065d39a76e7Sxw161283 p_config->sge_cmdq_threshold = ch_sge_cmdq_threshold; 1066d39a76e7Sxw161283 1067d39a76e7Sxw161283 p_config->sge_flq_threshold = ch_sge_flq_threshold; 1068d39a76e7Sxw161283 1069d39a76e7Sxw161283 p_config->phy_force_master = ch_phy_force_master; 1070d39a76e7Sxw161283 1071d39a76e7Sxw161283 p_config->rb_num_of_entries = ch_rb_num_of_entries; 1072d39a76e7Sxw161283 1073d39a76e7Sxw161283 p_config->rb_size_of_entries = ch_rb_size_of_entries; 1074d39a76e7Sxw161283 1075d39a76e7Sxw161283 p_config->rb_flag = ch_rb_flag; 1076d39a76e7Sxw161283 1077d39a76e7Sxw161283 p_config->exit_early = ch_exit_early; 1078d39a76e7Sxw161283 1079d39a76e7Sxw161283 p_config->chip = ch_chip; 1080d39a76e7Sxw161283 1081d39a76e7Sxw161283 p_config->stats = ch_stats; 1082d39a76e7Sxw161283 1083d39a76e7Sxw161283 p_config->tx_delay_us = ch_tx_delay_us; 1084d39a76e7Sxw161283 1085d39a76e7Sxw161283 return (0); 1086d39a76e7Sxw161283 } 1087d39a76e7Sxw161283 1088d39a76e7Sxw161283 static const struct board_info * 1089d39a76e7Sxw161283 pe_sa_init(ch_t *sa) 1090d39a76e7Sxw161283 { 1091d39a76e7Sxw161283 uint16_t device_id; 1092d39a76e7Sxw161283 uint16_t device_subid; 1093d39a76e7Sxw161283 const struct board_info *bi; 1094d39a76e7Sxw161283 1095d39a76e7Sxw161283 sa->config = sa->config_data.global_config; 1096d39a76e7Sxw161283 device_id = pci_config_get16(sa->ch_hpci, 2); 1097d39a76e7Sxw161283 device_subid = pci_config_get16(sa->ch_hpci, 0x2e); 1098d39a76e7Sxw161283 1099d39a76e7Sxw161283 bi = t1_get_board_info_from_ids(device_id, device_subid); 1100d39a76e7Sxw161283 if (bi == NULL) { 1101d39a76e7Sxw161283 cmn_err(CE_NOTE, 1102d39a76e7Sxw161283 "The adapter with device_id %d %d is not supported.\n", 1103d39a76e7Sxw161283 device_id, device_subid); 1104d39a76e7Sxw161283 return (NULL); 1105d39a76e7Sxw161283 } 1106d39a76e7Sxw161283 1107d39a76e7Sxw161283 if (t1_get_board_rev(sa, bi, &sa->params)) { 1108d39a76e7Sxw161283 cmn_err(CE_NOTE, "unknown device_id %d %d\n", 1109d39a76e7Sxw161283 device_id, device_subid); 1110d39a76e7Sxw161283 return ((const struct board_info *)NULL); 1111d39a76e7Sxw161283 } 1112d39a76e7Sxw161283 1113d39a76e7Sxw161283 return (bi); 1114d39a76e7Sxw161283 } 1115d39a76e7Sxw161283 1116d39a76e7Sxw161283 /* 1117d39a76e7Sxw161283 * allocate pool of small receive buffers (with vaddr & paddr) and 1118d39a76e7Sxw161283 * receiver buffer control structure (ch_esb_t *rbp). 1119d39a76e7Sxw161283 * XXX we should allow better tuning of the # of preallocated 1120d39a76e7Sxw161283 * free buffers against the # of freelist entries. 1121d39a76e7Sxw161283 */ 1122d39a76e7Sxw161283 static int 1123d39a76e7Sxw161283 pe_small_rbuf_pool_init(ch_t *sa) 1124d39a76e7Sxw161283 { 1125d39a76e7Sxw161283 int i; 1126d39a76e7Sxw161283 ch_esb_t *rbp; 1127d39a76e7Sxw161283 extern uint32_t sge_flq0_cnt; 1128d39a76e7Sxw161283 extern uint32_t sge_flq1_cnt; 1129d39a76e7Sxw161283 int size; 1130d39a76e7Sxw161283 uint32_t j; 1131d39a76e7Sxw161283 1132d39a76e7Sxw161283 if (is_T2(sa)) 1133d39a76e7Sxw161283 size = sge_flq1_cnt * fl_sz_multiplier; 1134d39a76e7Sxw161283 else 1135d39a76e7Sxw161283 size = sge_flq0_cnt * fl_sz_multiplier; 1136d39a76e7Sxw161283 1137d39a76e7Sxw161283 mutex_init(&sa->ch_small_esbl, NULL, MUTEX_DRIVER, sa->ch_icookp); 1138d39a76e7Sxw161283 1139d39a76e7Sxw161283 mutex_enter(&in_use_l); 1140d39a76e7Sxw161283 j = in_use_index++; 1141d39a76e7Sxw161283 if (in_use_index >= SZ_INUSE) 1142d39a76e7Sxw161283 in_use_index = 0; 1143d39a76e7Sxw161283 mutex_exit(&in_use_l); 1144d39a76e7Sxw161283 1145d39a76e7Sxw161283 sa->ch_small_owner = NULL; 1146d39a76e7Sxw161283 sa->ch_sm_index = j; 1147d39a76e7Sxw161283 sa->ch_small_esb_free = NULL; 1148d39a76e7Sxw161283 for (i = 0; i < size; i++) { 1149d39a76e7Sxw161283 rbp = ch_alloc_small_esbbuf(sa, j); 1150d39a76e7Sxw161283 if (rbp == NULL) 1151d39a76e7Sxw161283 goto error; 1152d39a76e7Sxw161283 /* 1153d39a76e7Sxw161283 * add entry to free list 1154d39a76e7Sxw161283 */ 1155d39a76e7Sxw161283 rbp->cs_next = sa->ch_small_esb_free; 1156d39a76e7Sxw161283 sa->ch_small_esb_free = rbp; 1157d39a76e7Sxw161283 1158d39a76e7Sxw161283 /* 1159d39a76e7Sxw161283 * add entry to owned list 1160d39a76e7Sxw161283 */ 1161d39a76e7Sxw161283 rbp->cs_owner = sa->ch_small_owner; 1162d39a76e7Sxw161283 sa->ch_small_owner = rbp; 1163d39a76e7Sxw161283 } 1164d39a76e7Sxw161283 return (1); 1165d39a76e7Sxw161283 1166d39a76e7Sxw161283 error: 1167d39a76e7Sxw161283 sa->ch_small_owner = NULL; 1168d39a76e7Sxw161283 1169d39a76e7Sxw161283 /* free whatever we've already allocated */ 1170d39a76e7Sxw161283 pe_rbuf_pool_free(sa); 1171d39a76e7Sxw161283 1172d39a76e7Sxw161283 return (0); 1173d39a76e7Sxw161283 } 1174d39a76e7Sxw161283 1175d39a76e7Sxw161283 /* 1176d39a76e7Sxw161283 * allocate pool of receive buffers (with vaddr & paddr) and 1177d39a76e7Sxw161283 * receiver buffer control structure (ch_esb_t *rbp). 1178d39a76e7Sxw161283 * XXX we should allow better tuning of the # of preallocated 1179d39a76e7Sxw161283 * free buffers against the # of freelist entries. 1180d39a76e7Sxw161283 */ 1181d39a76e7Sxw161283 static int 1182d39a76e7Sxw161283 pe_big_rbuf_pool_init(ch_t *sa) 1183d39a76e7Sxw161283 { 1184d39a76e7Sxw161283 int i; 1185d39a76e7Sxw161283 ch_esb_t *rbp; 1186d39a76e7Sxw161283 extern uint32_t sge_flq0_cnt; 1187d39a76e7Sxw161283 extern uint32_t sge_flq1_cnt; 1188d39a76e7Sxw161283 int size; 1189d39a76e7Sxw161283 uint32_t j; 1190d39a76e7Sxw161283 1191d39a76e7Sxw161283 if (is_T2(sa)) 1192d39a76e7Sxw161283 size = sge_flq0_cnt * fl_sz_multiplier; 1193d39a76e7Sxw161283 else 1194d39a76e7Sxw161283 size = sge_flq1_cnt * fl_sz_multiplier; 1195d39a76e7Sxw161283 1196d39a76e7Sxw161283 mutex_init(&sa->ch_big_esbl, NULL, MUTEX_DRIVER, sa->ch_icookp); 1197d39a76e7Sxw161283 1198d39a76e7Sxw161283 mutex_enter(&in_use_l); 1199d39a76e7Sxw161283 j = in_use_index++; 1200d39a76e7Sxw161283 if (in_use_index >= SZ_INUSE) 1201d39a76e7Sxw161283 in_use_index = 0; 1202d39a76e7Sxw161283 mutex_exit(&in_use_l); 1203d39a76e7Sxw161283 1204d39a76e7Sxw161283 sa->ch_big_owner = NULL; 1205d39a76e7Sxw161283 sa->ch_big_index = j; 1206d39a76e7Sxw161283 sa->ch_big_esb_free = NULL; 1207d39a76e7Sxw161283 for (i = 0; i < size; i++) { 1208d39a76e7Sxw161283 rbp = ch_alloc_big_esbbuf(sa, j); 1209d39a76e7Sxw161283 if (rbp == NULL) 1210d39a76e7Sxw161283 goto error; 1211d39a76e7Sxw161283 rbp->cs_next = sa->ch_big_esb_free; 1212d39a76e7Sxw161283 sa->ch_big_esb_free = rbp; 1213d39a76e7Sxw161283 1214d39a76e7Sxw161283 /* 1215d39a76e7Sxw161283 * add entry to owned list 1216d39a76e7Sxw161283 */ 1217d39a76e7Sxw161283 rbp->cs_owner = sa->ch_big_owner; 1218d39a76e7Sxw161283 sa->ch_big_owner = rbp; 1219d39a76e7Sxw161283 } 1220d39a76e7Sxw161283 return (1); 1221d39a76e7Sxw161283 1222d39a76e7Sxw161283 error: 1223d39a76e7Sxw161283 sa->ch_big_owner = NULL; 1224d39a76e7Sxw161283 1225d39a76e7Sxw161283 /* free whatever we've already allocated */ 1226d39a76e7Sxw161283 pe_rbuf_pool_free(sa); 1227d39a76e7Sxw161283 1228d39a76e7Sxw161283 return (0); 1229d39a76e7Sxw161283 } 1230d39a76e7Sxw161283 1231d39a76e7Sxw161283 /* 1232d39a76e7Sxw161283 * allocate receive buffer structure and dma mapped buffer (SGE_SM_BUF_SZ bytes) 1233d39a76e7Sxw161283 * note that we will DMA at a 2 byte offset for Solaris when checksum offload 1234d39a76e7Sxw161283 * is enabled. 1235d39a76e7Sxw161283 */ 1236d39a76e7Sxw161283 static ch_esb_t * 1237d39a76e7Sxw161283 ch_alloc_small_esbbuf(ch_t *sa, uint32_t i) 1238d39a76e7Sxw161283 { 1239d39a76e7Sxw161283 ch_esb_t *rbp; 1240d39a76e7Sxw161283 1241d39a76e7Sxw161283 rbp = (ch_esb_t *)kmem_zalloc(sizeof (ch_esb_t), KM_SLEEP); 1242d39a76e7Sxw161283 if (rbp == NULL) { 1243d39a76e7Sxw161283 return ((ch_esb_t *)0); 1244d39a76e7Sxw161283 } 1245d39a76e7Sxw161283 1246d39a76e7Sxw161283 #if BYTE_ORDER == BIG_ENDIAN 1247d39a76e7Sxw161283 rbp->cs_buf = (caddr_t)ch_alloc_dma_mem(sa, 1, DMA_STREAM|DMA_SMALN, 1248d39a76e7Sxw161283 SGE_SM_BUF_SZ(sa), &rbp->cs_pa, &rbp->cs_dh, &rbp->cs_ah); 1249d39a76e7Sxw161283 #else 1250d39a76e7Sxw161283 rbp->cs_buf = (caddr_t)ch_alloc_dma_mem(sa, 0, DMA_STREAM|DMA_SMALN, 1251d39a76e7Sxw161283 SGE_SM_BUF_SZ(sa), &rbp->cs_pa, &rbp->cs_dh, &rbp->cs_ah); 1252d39a76e7Sxw161283 #endif 1253d39a76e7Sxw161283 1254d39a76e7Sxw161283 if (rbp->cs_buf == NULL) { 1255d39a76e7Sxw161283 kmem_free(rbp, sizeof (ch_esb_t)); 1256d39a76e7Sxw161283 return ((ch_esb_t *)0); 1257d39a76e7Sxw161283 } 1258d39a76e7Sxw161283 1259d39a76e7Sxw161283 rbp->cs_sa = sa; 1260d39a76e7Sxw161283 rbp->cs_index = i; 1261d39a76e7Sxw161283 1262d39a76e7Sxw161283 rbp->cs_frtn.free_func = (void (*)())&ch_small_rbuf_recycle; 1263d39a76e7Sxw161283 rbp->cs_frtn.free_arg = (caddr_t)rbp; 1264d39a76e7Sxw161283 1265d39a76e7Sxw161283 return (rbp); 1266d39a76e7Sxw161283 } 1267d39a76e7Sxw161283 1268d39a76e7Sxw161283 /* 1269d39a76e7Sxw161283 * allocate receive buffer structure and dma mapped buffer (SGE_BG_BUF_SZ bytes) 1270d39a76e7Sxw161283 * note that we will DMA at a 2 byte offset for Solaris when checksum offload 1271d39a76e7Sxw161283 * is enabled. 1272d39a76e7Sxw161283 */ 1273d39a76e7Sxw161283 static ch_esb_t * 1274d39a76e7Sxw161283 ch_alloc_big_esbbuf(ch_t *sa, uint32_t i) 1275d39a76e7Sxw161283 { 1276d39a76e7Sxw161283 ch_esb_t *rbp; 1277d39a76e7Sxw161283 1278d39a76e7Sxw161283 rbp = (ch_esb_t *)kmem_zalloc(sizeof (ch_esb_t), KM_SLEEP); 1279d39a76e7Sxw161283 if (rbp == NULL) { 1280d39a76e7Sxw161283 return ((ch_esb_t *)0); 1281d39a76e7Sxw161283 } 1282d39a76e7Sxw161283 1283d39a76e7Sxw161283 #if BYTE_ORDER == BIG_ENDIAN 1284d39a76e7Sxw161283 rbp->cs_buf = (caddr_t)ch_alloc_dma_mem(sa, 1, DMA_STREAM|DMA_BGALN, 1285d39a76e7Sxw161283 SGE_BG_BUF_SZ(sa), &rbp->cs_pa, &rbp->cs_dh, &rbp->cs_ah); 1286d39a76e7Sxw161283 #else 1287d39a76e7Sxw161283 rbp->cs_buf = (caddr_t)ch_alloc_dma_mem(sa, 0, DMA_STREAM|DMA_BGALN, 1288d39a76e7Sxw161283 SGE_BG_BUF_SZ(sa), &rbp->cs_pa, &rbp->cs_dh, &rbp->cs_ah); 1289d39a76e7Sxw161283 #endif 1290d39a76e7Sxw161283 1291d39a76e7Sxw161283 if (rbp->cs_buf == NULL) { 1292d39a76e7Sxw161283 kmem_free(rbp, sizeof (ch_esb_t)); 1293d39a76e7Sxw161283 return ((ch_esb_t *)0); 1294d39a76e7Sxw161283 } 1295d39a76e7Sxw161283 1296d39a76e7Sxw161283 rbp->cs_sa = sa; 1297d39a76e7Sxw161283 rbp->cs_index = i; 1298d39a76e7Sxw161283 1299d39a76e7Sxw161283 rbp->cs_frtn.free_func = (void (*)())&ch_big_rbuf_recycle; 1300d39a76e7Sxw161283 rbp->cs_frtn.free_arg = (caddr_t)rbp; 1301d39a76e7Sxw161283 1302d39a76e7Sxw161283 return (rbp); 1303d39a76e7Sxw161283 } 1304d39a76e7Sxw161283 1305d39a76e7Sxw161283 /* 1306d39a76e7Sxw161283 * free entries on the receive buffer list. 1307d39a76e7Sxw161283 */ 1308d39a76e7Sxw161283 void 1309d39a76e7Sxw161283 pe_rbuf_pool_free(ch_t *sa) 1310d39a76e7Sxw161283 { 1311d39a76e7Sxw161283 ch_esb_t *rbp; 1312d39a76e7Sxw161283 1313d39a76e7Sxw161283 mutex_enter(&sa->ch_small_esbl); 1314d39a76e7Sxw161283 1315d39a76e7Sxw161283 /* 1316d39a76e7Sxw161283 * Now set-up the rest to commit suicide. 1317d39a76e7Sxw161283 */ 1318d39a76e7Sxw161283 while (sa->ch_small_owner) { 1319d39a76e7Sxw161283 rbp = sa->ch_small_owner; 1320d39a76e7Sxw161283 sa->ch_small_owner = rbp->cs_owner; 1321d39a76e7Sxw161283 rbp->cs_owner = NULL; 1322d39a76e7Sxw161283 rbp->cs_flag = 1; 1323d39a76e7Sxw161283 } 1324d39a76e7Sxw161283 1325d39a76e7Sxw161283 while ((rbp = sa->ch_small_esb_free) != NULL) { 1326d39a76e7Sxw161283 /* advance head ptr to next entry */ 1327d39a76e7Sxw161283 sa->ch_small_esb_free = rbp->cs_next; 1328d39a76e7Sxw161283 /* free private buffer allocated in ch_alloc_esbbuf() */ 1329d39a76e7Sxw161283 ch_free_dma_mem(rbp->cs_dh, rbp->cs_ah); 1330d39a76e7Sxw161283 /* free descripter buffer */ 1331d39a76e7Sxw161283 kmem_free(rbp, sizeof (ch_esb_t)); 1332d39a76e7Sxw161283 } 1333d39a76e7Sxw161283 1334d39a76e7Sxw161283 mutex_exit(&sa->ch_small_esbl); 1335d39a76e7Sxw161283 1336d39a76e7Sxw161283 /* destroy ch_esbl lock */ 1337d39a76e7Sxw161283 mutex_destroy(&sa->ch_small_esbl); 1338d39a76e7Sxw161283 1339d39a76e7Sxw161283 1340d39a76e7Sxw161283 mutex_enter(&sa->ch_big_esbl); 1341d39a76e7Sxw161283 1342d39a76e7Sxw161283 /* 1343d39a76e7Sxw161283 * Now set-up the rest to commit suicide. 1344d39a76e7Sxw161283 */ 1345d39a76e7Sxw161283 while (sa->ch_big_owner) { 1346d39a76e7Sxw161283 rbp = sa->ch_big_owner; 1347d39a76e7Sxw161283 sa->ch_big_owner = rbp->cs_owner; 1348d39a76e7Sxw161283 rbp->cs_owner = NULL; 1349d39a76e7Sxw161283 rbp->cs_flag = 1; 1350d39a76e7Sxw161283 } 1351d39a76e7Sxw161283 1352d39a76e7Sxw161283 while ((rbp = sa->ch_big_esb_free) != NULL) { 1353d39a76e7Sxw161283 /* advance head ptr to next entry */ 1354d39a76e7Sxw161283 sa->ch_big_esb_free = rbp->cs_next; 1355d39a76e7Sxw161283 /* free private buffer allocated in ch_alloc_esbbuf() */ 1356d39a76e7Sxw161283 ch_free_dma_mem(rbp->cs_dh, rbp->cs_ah); 1357d39a76e7Sxw161283 /* free descripter buffer */ 1358d39a76e7Sxw161283 kmem_free(rbp, sizeof (ch_esb_t)); 1359d39a76e7Sxw161283 } 1360d39a76e7Sxw161283 1361d39a76e7Sxw161283 mutex_exit(&sa->ch_big_esbl); 1362d39a76e7Sxw161283 1363d39a76e7Sxw161283 /* destroy ch_esbl lock */ 1364d39a76e7Sxw161283 mutex_destroy(&sa->ch_big_esbl); 1365d39a76e7Sxw161283 } 1366d39a76e7Sxw161283 1367d39a76e7Sxw161283 void 1368d39a76e7Sxw161283 ch_small_rbuf_recycle(ch_esb_t *rbp) 1369d39a76e7Sxw161283 { 1370d39a76e7Sxw161283 ch_t *sa = rbp->cs_sa; 1371d39a76e7Sxw161283 1372d39a76e7Sxw161283 if (rbp->cs_flag) { 1373d39a76e7Sxw161283 uint32_t i; 1374d39a76e7Sxw161283 /* 1375d39a76e7Sxw161283 * free private buffer allocated in ch_alloc_esbbuf() 1376d39a76e7Sxw161283 */ 1377d39a76e7Sxw161283 ch_free_dma_mem(rbp->cs_dh, rbp->cs_ah); 1378d39a76e7Sxw161283 1379d39a76e7Sxw161283 i = rbp->cs_index; 1380d39a76e7Sxw161283 1381d39a76e7Sxw161283 /* 1382d39a76e7Sxw161283 * free descripter buffer 1383d39a76e7Sxw161283 */ 1384d39a76e7Sxw161283 kmem_free(rbp, sizeof (ch_esb_t)); 1385d39a76e7Sxw161283 1386d39a76e7Sxw161283 /* 1387d39a76e7Sxw161283 * decrement count of receive buffers freed by callback 1388d39a76e7Sxw161283 * We decrement here so anyone trying to do fini will 1389d39a76e7Sxw161283 * only remove the driver once the counts go to 0. 1390d39a76e7Sxw161283 */ 1391*1a5e258fSJosef 'Jeff' Sipek atomic_dec_32(&buffers_in_use[i]); 1392d39a76e7Sxw161283 1393d39a76e7Sxw161283 return; 1394d39a76e7Sxw161283 } 1395d39a76e7Sxw161283 1396d39a76e7Sxw161283 mutex_enter(&sa->ch_small_esbl); 1397d39a76e7Sxw161283 rbp->cs_next = sa->ch_small_esb_free; 1398d39a76e7Sxw161283 sa->ch_small_esb_free = rbp; 1399d39a76e7Sxw161283 mutex_exit(&sa->ch_small_esbl); 1400d39a76e7Sxw161283 1401d39a76e7Sxw161283 /* 1402d39a76e7Sxw161283 * decrement count of receive buffers freed by callback 1403d39a76e7Sxw161283 */ 1404*1a5e258fSJosef 'Jeff' Sipek atomic_dec_32(&buffers_in_use[rbp->cs_index]); 1405d39a76e7Sxw161283 } 1406d39a76e7Sxw161283 1407d39a76e7Sxw161283 /* 1408d39a76e7Sxw161283 * callback function from freeb() when esballoced mblk freed. 1409d39a76e7Sxw161283 */ 1410d39a76e7Sxw161283 void 1411d39a76e7Sxw161283 ch_big_rbuf_recycle(ch_esb_t *rbp) 1412d39a76e7Sxw161283 { 1413d39a76e7Sxw161283 ch_t *sa = rbp->cs_sa; 1414d39a76e7Sxw161283 1415d39a76e7Sxw161283 if (rbp->cs_flag) { 1416d39a76e7Sxw161283 uint32_t i; 1417d39a76e7Sxw161283 /* 1418d39a76e7Sxw161283 * free private buffer allocated in ch_alloc_esbbuf() 1419d39a76e7Sxw161283 */ 1420d39a76e7Sxw161283 ch_free_dma_mem(rbp->cs_dh, rbp->cs_ah); 1421d39a76e7Sxw161283 1422d39a76e7Sxw161283 i = rbp->cs_index; 1423d39a76e7Sxw161283 1424d39a76e7Sxw161283 /* 1425d39a76e7Sxw161283 * free descripter buffer 1426d39a76e7Sxw161283 */ 1427d39a76e7Sxw161283 kmem_free(rbp, sizeof (ch_esb_t)); 1428d39a76e7Sxw161283 1429d39a76e7Sxw161283 /* 1430d39a76e7Sxw161283 * decrement count of receive buffers freed by callback 1431d39a76e7Sxw161283 * We decrement here so anyone trying to do fini will 1432d39a76e7Sxw161283 * only remove the driver once the counts go to 0. 1433d39a76e7Sxw161283 */ 1434*1a5e258fSJosef 'Jeff' Sipek atomic_dec_32(&buffers_in_use[i]); 1435d39a76e7Sxw161283 1436d39a76e7Sxw161283 return; 1437d39a76e7Sxw161283 } 1438d39a76e7Sxw161283 1439d39a76e7Sxw161283 mutex_enter(&sa->ch_big_esbl); 1440d39a76e7Sxw161283 rbp->cs_next = sa->ch_big_esb_free; 1441d39a76e7Sxw161283 sa->ch_big_esb_free = rbp; 1442d39a76e7Sxw161283 mutex_exit(&sa->ch_big_esbl); 1443d39a76e7Sxw161283 1444d39a76e7Sxw161283 /* 1445d39a76e7Sxw161283 * decrement count of receive buffers freed by callback 1446d39a76e7Sxw161283 */ 1447*1a5e258fSJosef 'Jeff' Sipek atomic_dec_32(&buffers_in_use[rbp->cs_index]); 1448d39a76e7Sxw161283 } 1449d39a76e7Sxw161283 1450d39a76e7Sxw161283 /* 1451d39a76e7Sxw161283 * get a pre-allocated, pre-mapped receive buffer from free list. 1452d39a76e7Sxw161283 * (used sge.c) 1453d39a76e7Sxw161283 */ 1454d39a76e7Sxw161283 ch_esb_t * 1455d39a76e7Sxw161283 ch_get_small_rbuf(ch_t *sa) 1456d39a76e7Sxw161283 { 1457d39a76e7Sxw161283 ch_esb_t *rbp; 1458d39a76e7Sxw161283 1459d39a76e7Sxw161283 mutex_enter(&sa->ch_small_esbl); 1460d39a76e7Sxw161283 rbp = sa->ch_small_esb_free; 1461d39a76e7Sxw161283 if (rbp) { 1462d39a76e7Sxw161283 sa->ch_small_esb_free = rbp->cs_next; 1463d39a76e7Sxw161283 } 1464d39a76e7Sxw161283 mutex_exit(&sa->ch_small_esbl); 1465d39a76e7Sxw161283 1466d39a76e7Sxw161283 return (rbp); 1467d39a76e7Sxw161283 } 1468d39a76e7Sxw161283 1469d39a76e7Sxw161283 /* 1470d39a76e7Sxw161283 * get a pre-allocated, pre-mapped receive buffer from free list. 1471d39a76e7Sxw161283 * (used sge.c) 1472d39a76e7Sxw161283 */ 1473d39a76e7Sxw161283 1474d39a76e7Sxw161283 ch_esb_t * 1475d39a76e7Sxw161283 ch_get_big_rbuf(ch_t *sa) 1476d39a76e7Sxw161283 { 1477d39a76e7Sxw161283 ch_esb_t *rbp; 1478d39a76e7Sxw161283 1479d39a76e7Sxw161283 mutex_enter(&sa->ch_big_esbl); 1480d39a76e7Sxw161283 rbp = sa->ch_big_esb_free; 1481d39a76e7Sxw161283 if (rbp) { 1482d39a76e7Sxw161283 sa->ch_big_esb_free = rbp->cs_next; 1483d39a76e7Sxw161283 } 1484d39a76e7Sxw161283 mutex_exit(&sa->ch_big_esbl); 1485d39a76e7Sxw161283 1486d39a76e7Sxw161283 return (rbp); 1487d39a76e7Sxw161283 } 1488d39a76e7Sxw161283 1489d39a76e7Sxw161283 void 1490d39a76e7Sxw161283 pe_detach(ch_t *sa) 1491d39a76e7Sxw161283 { 1492d39a76e7Sxw161283 (void) sge_stop(sa->sge); 1493d39a76e7Sxw161283 1494d39a76e7Sxw161283 pe_free_driver_resources(sa); 1495d39a76e7Sxw161283 } 1496d39a76e7Sxw161283 1497d39a76e7Sxw161283 static void 1498d39a76e7Sxw161283 pe_free_driver_resources(ch_t *sa) 1499d39a76e7Sxw161283 { 1500d39a76e7Sxw161283 if (sa) { 1501d39a76e7Sxw161283 t1_free_sw_modules(sa); 1502d39a76e7Sxw161283 1503d39a76e7Sxw161283 /* free pool of receive buffers */ 1504d39a76e7Sxw161283 pe_rbuf_pool_free(sa); 1505d39a76e7Sxw161283 } 1506d39a76e7Sxw161283 } 1507d39a76e7Sxw161283 1508d39a76e7Sxw161283 /* 1509d39a76e7Sxw161283 * Processes elmer0 external interrupts in process context. 1510d39a76e7Sxw161283 */ 1511d39a76e7Sxw161283 static void 1512d39a76e7Sxw161283 ext_intr_task(ch_t *adapter) 1513d39a76e7Sxw161283 { 1514d39a76e7Sxw161283 u32 enable; 1515d39a76e7Sxw161283 1516d39a76e7Sxw161283 (void) elmer0_ext_intr_handler(adapter); 1517d39a76e7Sxw161283 1518d39a76e7Sxw161283 /* Now reenable external interrupts */ 1519d39a76e7Sxw161283 t1_write_reg_4(adapter, A_PL_CAUSE, F_PL_INTR_EXT); 1520d39a76e7Sxw161283 enable = t1_read_reg_4(adapter, A_PL_ENABLE); 1521d39a76e7Sxw161283 t1_write_reg_4(adapter, A_PL_ENABLE, enable | F_PL_INTR_EXT); 1522d39a76e7Sxw161283 adapter->slow_intr_mask |= F_PL_INTR_EXT; 1523d39a76e7Sxw161283 } 1524d39a76e7Sxw161283 1525d39a76e7Sxw161283 /* 1526d39a76e7Sxw161283 * Interrupt-context handler for elmer0 external interrupts. 1527d39a76e7Sxw161283 */ 1528d39a76e7Sxw161283 void 1529d39a76e7Sxw161283 t1_os_elmer0_ext_intr(ch_t *adapter) 1530d39a76e7Sxw161283 { 1531d39a76e7Sxw161283 u32 enable = t1_read_reg_4(adapter, A_PL_ENABLE); 1532d39a76e7Sxw161283 1533d39a76e7Sxw161283 adapter->slow_intr_mask &= ~F_PL_INTR_EXT; 1534d39a76e7Sxw161283 t1_write_reg_4(adapter, A_PL_ENABLE, enable & ~F_PL_INTR_EXT); 1535d39a76e7Sxw161283 #ifdef NOTYET 1536d39a76e7Sxw161283 schedule_work(&adapter->ext_intr_handler_task); 1537d39a76e7Sxw161283 #else 1538d39a76e7Sxw161283 ext_intr_task(adapter); 1539d39a76e7Sxw161283 #endif 1540d39a76e7Sxw161283 } 1541d39a76e7Sxw161283 1542d39a76e7Sxw161283 uint8_t * 1543d39a76e7Sxw161283 t1_get_next_mcaddr(struct t1_rx_mode *rmp) 1544d39a76e7Sxw161283 { 1545d39a76e7Sxw161283 uint8_t *addr = 0; 1546d39a76e7Sxw161283 if (rmp->mc) { 1547d39a76e7Sxw161283 addr = rmp->mc->cmc_mca; 1548d39a76e7Sxw161283 rmp->mc = rmp->mc->cmc_next; 1549d39a76e7Sxw161283 } 1550d39a76e7Sxw161283 return (addr); 1551d39a76e7Sxw161283 } 1552d39a76e7Sxw161283 1553d39a76e7Sxw161283 void 1554d39a76e7Sxw161283 pe_dma_handle_init(ch_t *chp, int cnt) 1555d39a76e7Sxw161283 { 1556d39a76e7Sxw161283 free_dh_t *dhe; 1557d39a76e7Sxw161283 #if defined(__sparc) 1558d39a76e7Sxw161283 int tcnt = cnt/2; 1559d39a76e7Sxw161283 1560d39a76e7Sxw161283 for (; cnt; cnt--) { 1561d39a76e7Sxw161283 dhe = ch_get_dvma_handle(chp); 1562d39a76e7Sxw161283 if (dhe == NULL) 1563d39a76e7Sxw161283 break; 1564d39a76e7Sxw161283 mutex_enter(&chp->ch_dh_lck); 1565d39a76e7Sxw161283 dhe->dhe_next = chp->ch_vdh; 1566d39a76e7Sxw161283 chp->ch_vdh = dhe; 1567d39a76e7Sxw161283 mutex_exit(&chp->ch_dh_lck); 1568d39a76e7Sxw161283 } 1569d39a76e7Sxw161283 1570d39a76e7Sxw161283 cnt += tcnt; 1571d39a76e7Sxw161283 #endif 1572d39a76e7Sxw161283 while (cnt--) { 1573d39a76e7Sxw161283 dhe = ch_get_dma_handle(chp); 1574d39a76e7Sxw161283 if (dhe == NULL) 1575d39a76e7Sxw161283 return; 1576d39a76e7Sxw161283 mutex_enter(&chp->ch_dh_lck); 1577d39a76e7Sxw161283 dhe->dhe_next = chp->ch_dh; 1578d39a76e7Sxw161283 chp->ch_dh = dhe; 1579d39a76e7Sxw161283 mutex_exit(&chp->ch_dh_lck); 1580d39a76e7Sxw161283 } 1581d39a76e7Sxw161283 } 1582d39a76e7Sxw161283 1583d39a76e7Sxw161283 /* 1584d39a76e7Sxw161283 * Write new values to the MTU table. Caller must validate that the new MTUs 1585d39a76e7Sxw161283 * are in ascending order. params.mtus[] is initialized by init_mtus() 1586d39a76e7Sxw161283 * called in t1_init_sw_modules(). 1587d39a76e7Sxw161283 */ 1588d39a76e7Sxw161283 #define MTUREG(idx) (A_TP_MTU_REG0 + (idx) * 4) 1589d39a76e7Sxw161283 1590d39a76e7Sxw161283 static void 1591d39a76e7Sxw161283 update_mtu_tab(ch_t *adapter) 1592d39a76e7Sxw161283 { 1593d39a76e7Sxw161283 int i; 1594d39a76e7Sxw161283 1595d39a76e7Sxw161283 for (i = 0; i < NMTUS; ++i) { 1596d39a76e7Sxw161283 int mtu = (unsigned int)adapter->params.mtus[i]; 1597d39a76e7Sxw161283 1598d39a76e7Sxw161283 t1_write_reg_4(adapter, MTUREG(i), mtu); 1599d39a76e7Sxw161283 } 1600d39a76e7Sxw161283 } 1601d39a76e7Sxw161283 1602d39a76e7Sxw161283 static int 1603d39a76e7Sxw161283 pe_change_mtu(ch_t *chp) 1604d39a76e7Sxw161283 { 1605d39a76e7Sxw161283 struct cmac *mac = chp->port[0].mac; 1606d39a76e7Sxw161283 int ret; 1607d39a76e7Sxw161283 1608d39a76e7Sxw161283 if (!mac->ops->set_mtu) { 1609d39a76e7Sxw161283 return (EOPNOTSUPP); 1610d39a76e7Sxw161283 } 1611d39a76e7Sxw161283 if (chp->ch_mtu < 68) { 1612d39a76e7Sxw161283 return (EINVAL); 1613d39a76e7Sxw161283 } 1614d39a76e7Sxw161283 if (ret = mac->ops->set_mtu(mac, chp->ch_mtu)) { 1615d39a76e7Sxw161283 return (ret); 1616d39a76e7Sxw161283 } 1617d39a76e7Sxw161283 1618d39a76e7Sxw161283 return (0); 1619d39a76e7Sxw161283 } 1620d39a76e7Sxw161283 1621d39a76e7Sxw161283 typedef struct fake_arp { 1622d39a76e7Sxw161283 char fa_dst[6]; /* ethernet header */ 1623d39a76e7Sxw161283 char fa_src[6]; /* ethernet header */ 1624d39a76e7Sxw161283 ushort_t fa_typ; /* ethernet header */ 1625d39a76e7Sxw161283 1626d39a76e7Sxw161283 ushort_t fa_hrd; /* arp */ 1627d39a76e7Sxw161283 ushort_t fa_pro; 1628d39a76e7Sxw161283 char fa_hln; 1629d39a76e7Sxw161283 char fa_pln; 1630d39a76e7Sxw161283 ushort_t fa_op; 1631d39a76e7Sxw161283 char fa_src_mac[6]; 1632d39a76e7Sxw161283 uint_t fa_src_ip; 1633d39a76e7Sxw161283 char fa_dst_mac[6]; 1634d39a76e7Sxw161283 char fa_dst_ip[4]; 1635d39a76e7Sxw161283 } fake_arp_t; 1636d39a76e7Sxw161283 1637d39a76e7Sxw161283 /* 1638d39a76e7Sxw161283 * PR2928 & PR3309 1639d39a76e7Sxw161283 * construct packet in mblk and attach it to sge structure. 1640d39a76e7Sxw161283 */ 1641d39a76e7Sxw161283 static int 1642d39a76e7Sxw161283 pe_make_fake_arp(ch_t *chp, unsigned char *arpp) 1643d39a76e7Sxw161283 { 1644d39a76e7Sxw161283 pesge *sge = chp->sge; 1645d39a76e7Sxw161283 mblk_t *bp; 1646d39a76e7Sxw161283 fake_arp_t *fap; 1647d39a76e7Sxw161283 static char buf[6] = {0, 7, 0x43, 0, 0, 0}; 1648d39a76e7Sxw161283 struct cpl_tx_pkt *cpl; 1649d39a76e7Sxw161283 1650d39a76e7Sxw161283 bp = allocb(sizeof (struct fake_arp) + SZ_CPL_TX_PKT, BPRI_HI); 1651d39a76e7Sxw161283 if (bp == NULL) { 1652d39a76e7Sxw161283 return (1); 1653d39a76e7Sxw161283 } 1654d39a76e7Sxw161283 bzero(bp->b_rptr, sizeof (struct fake_arp) + SZ_CPL_TX_PKT); 1655d39a76e7Sxw161283 1656d39a76e7Sxw161283 /* fill in cpl header */ 1657d39a76e7Sxw161283 cpl = (struct cpl_tx_pkt *)bp->b_rptr; 1658d39a76e7Sxw161283 cpl->opcode = CPL_TX_PKT; 1659d39a76e7Sxw161283 cpl->iff = 0; /* XXX port 0 needs fixing with NEMO */ 1660d39a76e7Sxw161283 cpl->ip_csum_dis = 1; /* no IP header cksum */ 1661d39a76e7Sxw161283 cpl->l4_csum_dis = 1; /* no tcp/udp cksum */ 1662d39a76e7Sxw161283 cpl->vlan_valid = 0; /* no vlan */ 1663d39a76e7Sxw161283 1664d39a76e7Sxw161283 fap = (fake_arp_t *)&bp->b_rptr[SZ_CPL_TX_PKT]; 1665d39a76e7Sxw161283 1666d39a76e7Sxw161283 bcopy(arpp, fap, sizeof (*fap)); /* copy first arp to mblk */ 1667d39a76e7Sxw161283 1668d39a76e7Sxw161283 bcopy(buf, fap->fa_dst, 6); /* overwrite dst mac */ 1669d39a76e7Sxw161283 chp->ch_ip = fap->fa_src_ip; /* not used yet */ 1670d39a76e7Sxw161283 bcopy(buf, fap->fa_dst_mac, 6); /* overwrite dst mac */ 1671d39a76e7Sxw161283 1672d39a76e7Sxw161283 bp->b_wptr = bp->b_rptr + sizeof (struct fake_arp)+SZ_CPL_TX_PKT; 1673d39a76e7Sxw161283 1674d39a76e7Sxw161283 sge_add_fake_arp(sge, (void *)bp); 1675d39a76e7Sxw161283 1676d39a76e7Sxw161283 return (0); 1677d39a76e7Sxw161283 } 1678d39a76e7Sxw161283 1679d39a76e7Sxw161283 /* 1680d39a76e7Sxw161283 * PR2928 & PR3309 1681d39a76e7Sxw161283 * free the fake arp's mblk on sge structure. 1682d39a76e7Sxw161283 */ 1683d39a76e7Sxw161283 void 1684d39a76e7Sxw161283 pe_free_fake_arp(void *arp) 1685d39a76e7Sxw161283 { 1686d39a76e7Sxw161283 mblk_t *bp = (mblk_t *)(arp); 1687d39a76e7Sxw161283 1688d39a76e7Sxw161283 freemsg(bp); 1689d39a76e7Sxw161283 } 1690d39a76e7Sxw161283 1691d39a76e7Sxw161283 /* 1692d39a76e7Sxw161283 * extract ip address of nic from first outgoing arp. 1693d39a76e7Sxw161283 */ 1694d39a76e7Sxw161283 static uint32_t 1695d39a76e7Sxw161283 pe_get_ip(unsigned char *arpp) 1696d39a76e7Sxw161283 { 1697d39a76e7Sxw161283 fake_arp_t fap; 1698d39a76e7Sxw161283 1699d39a76e7Sxw161283 /* 1700d39a76e7Sxw161283 * first copy packet to buffer so we know 1701d39a76e7Sxw161283 * it will be properly aligned. 1702d39a76e7Sxw161283 */ 1703d39a76e7Sxw161283 bcopy(arpp, &fap, sizeof (fap)); /* copy first arp to buffer */ 1704d39a76e7Sxw161283 return (fap.fa_src_ip); 1705d39a76e7Sxw161283 } 1706d39a76e7Sxw161283 1707d39a76e7Sxw161283 /* ARGSUSED */ 1708d39a76e7Sxw161283 void 1709d39a76e7Sxw161283 t1_os_link_changed(ch_t *obj, int port_id, int link_status, 1710d39a76e7Sxw161283 int speed, int duplex, int fc) 1711d39a76e7Sxw161283 { 1712d39a76e7Sxw161283 gld_mac_info_t *macinfo = obj->ch_macp; 1713d39a76e7Sxw161283 if (link_status) { 1714d39a76e7Sxw161283 gld_linkstate(macinfo, GLD_LINKSTATE_UP); 1715d39a76e7Sxw161283 /* 1716d39a76e7Sxw161283 * Link states should be reported to user 1717d39a76e7Sxw161283 * whenever it changes 1718d39a76e7Sxw161283 */ 1719d39a76e7Sxw161283 cmn_err(CE_NOTE, "%s: link is up", adapter_name(obj)); 1720d39a76e7Sxw161283 } else { 1721d39a76e7Sxw161283 gld_linkstate(macinfo, GLD_LINKSTATE_DOWN); 1722d39a76e7Sxw161283 /* 1723d39a76e7Sxw161283 * Link states should be reported to user 1724d39a76e7Sxw161283 * whenever it changes 1725d39a76e7Sxw161283 */ 1726d39a76e7Sxw161283 cmn_err(CE_NOTE, "%s: link is down", adapter_name(obj)); 1727d39a76e7Sxw161283 } 1728d39a76e7Sxw161283 } 1729