1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008-2013 Solarflare Communications Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/ddi.h> 29 #include <sys/sunddi.h> 30 #include <sys/gld.h> 31 #include <sys/stream.h> 32 #include <sys/strsun.h> 33 #include <sys/strsubr.h> 34 #include <sys/dlpi.h> 35 #include <sys/pattr.h> 36 #include <sys/ksynch.h> 37 #include <sys/spl.h> 38 39 #include <inet/nd.h> 40 #include <inet/mi.h> 41 42 #include "sfxge.h" 43 44 #ifdef _USE_GLD_V2 45 46 void 47 sfxge_gld_link_update(sfxge_t *sp) 48 { 49 sfxge_mac_t *smp = &(sp->s_mac); 50 int32_t link; 51 52 switch (smp->sm_link_mode) { 53 case EFX_LINK_UNKNOWN: 54 link = GLD_LINKSTATE_UNKNOWN; 55 break; 56 case EFX_LINK_DOWN: 57 link = GLD_LINKSTATE_DOWN; 58 break; 59 default: 60 link = GLD_LINKSTATE_UP; 61 } 62 63 gld_linkstate(sp->s_gmip, link); 64 } 65 66 void 67 sfxge_gld_mtu_update(sfxge_t *sp) 68 { 69 } 70 71 void 72 sfxge_gld_rx_post(sfxge_t *sp, unsigned int index, mblk_t *mp) 73 { 74 mblk_t **mpp; 75 76 _NOTE(ARGUNUSED(index)) 77 78 mutex_enter(&(sp->s_rx_lock)); 79 *(sp->s_mpp) = mp; 80 81 mpp = ∓ 82 while ((mp = *mpp) != NULL) 83 mpp = &(mp->b_next); 84 85 sp->s_mpp = mpp; 86 mutex_exit(&(sp->s_rx_lock)); 87 } 88 89 void 90 sfxge_gld_rx_push(sfxge_t *sp) 91 { 92 mblk_t *mp; 93 94 mutex_enter(&(sp->s_rx_lock)); 95 mp = sp->s_mp; 96 sp->s_mp = NULL; 97 sp->s_mpp = &(sp->s_mp); 98 mutex_exit(&(sp->s_rx_lock)); 99 100 while (mp != NULL) { 101 mblk_t *next; 102 103 next = mp->b_next; 104 mp->b_next = NULL; 105 106 /* The stack behaves badly with multi-fragment messages */ 107 if (mp->b_cont != NULL) { 108 uint16_t flags = DB_CKSUMFLAGS(mp); 109 110 (void) pullupmsg(mp, -1); 111 112 DB_CKSUMFLAGS(mp) = flags; 113 } 114 115 gld_recv(sp->s_gmip, mp); 116 117 mp = next; 118 } 119 } 120 121 static int 122 sfxge_gld_get_stats(gld_mac_info_t *gmip, struct gld_stats *gsp) 123 { 124 sfxge_t *sp = (sfxge_t *)(gmip->gldm_private); 125 unsigned int speed; 126 sfxge_link_duplex_t duplex; 127 uint64_t val; 128 129 sfxge_mac_stat_get(sp, EFX_MAC_TX_ERRORS, &val); 130 gsp->glds_errxmt = (uint32_t)val; 131 132 sfxge_mac_stat_get(sp, EFX_MAC_RX_ERRORS, &val); 133 gsp->glds_errrcv = (uint32_t)val; 134 135 sfxge_mac_stat_get(sp, EFX_MAC_RX_FCS_ERRORS, &val); 136 gsp->glds_crc = (uint32_t)val; 137 138 sfxge_mac_stat_get(sp, EFX_MAC_RX_DROP_EVENTS, &val); 139 gsp->glds_norcvbuf = (uint32_t)val; 140 141 sfxge_mac_link_speed_get(sp, &speed); 142 gsp->glds_speed = (uint64_t)speed * 1000000ull; 143 144 sfxge_mac_link_duplex_get(sp, &duplex); 145 146 switch (duplex) { 147 case SFXGE_LINK_DUPLEX_UNKNOWN: 148 gsp->glds_duplex = GLD_DUPLEX_UNKNOWN; 149 break; 150 151 case SFXGE_LINK_DUPLEX_HALF: 152 gsp->glds_duplex = GLD_DUPLEX_HALF; 153 break; 154 155 case SFXGE_LINK_DUPLEX_FULL: 156 gsp->glds_duplex = GLD_DUPLEX_FULL; 157 break; 158 159 default: 160 ASSERT(B_FALSE); 161 break; 162 } 163 164 return (GLD_SUCCESS); 165 } 166 167 static int 168 sfxge_gld_reset(gld_mac_info_t *gmip) 169 { 170 /* 171 * The driver already has hardware resets at appropriate times 172 * This is only ever called before gld_start() 173 */ 174 return (GLD_SUCCESS); 175 } 176 177 static int 178 sfxge_gld_start(gld_mac_info_t *gmip) 179 { 180 sfxge_t *sp = (sfxge_t *)(gmip->gldm_private); 181 int rc; 182 183 mutex_enter(&(sp->s_rx_lock)); 184 sp->s_mpp = &(sp->s_mp); 185 mutex_exit(&(sp->s_rx_lock)); 186 187 if ((rc = sfxge_start(sp, B_FALSE)) != 0) 188 goto fail1; 189 190 return (GLD_SUCCESS); 191 192 fail1: 193 DTRACE_PROBE1(fail1, int, rc); 194 195 mutex_enter(&(sp->s_rx_lock)); 196 ASSERT3P(sp->s_mp, ==, NULL); 197 sp->s_mpp = NULL; 198 mutex_exit(&(sp->s_rx_lock)); 199 200 return (GLD_FAILURE); 201 } 202 203 static int 204 sfxge_gld_stop(gld_mac_info_t *gmip) 205 { 206 sfxge_t *sp = (sfxge_t *)(gmip->gldm_private); 207 208 sfxge_stop(sp); 209 210 mutex_enter(&(sp->s_rx_lock)); 211 ASSERT3P(sp->s_mp, ==, NULL); 212 sp->s_mpp = NULL; 213 mutex_exit(&(sp->s_rx_lock)); 214 215 return (GLD_SUCCESS); 216 } 217 218 static int 219 sfxge_gld_set_promiscuous(gld_mac_info_t *gmip, int flags) 220 { 221 sfxge_t *sp = (sfxge_t *)(gmip->gldm_private); 222 int rc; 223 224 switch (flags) { 225 case GLD_MAC_PROMISC_NONE: 226 if ((rc = sfxge_mac_promisc_set(sp, SFXGE_PROMISC_OFF)) != 0) 227 goto fail1; 228 break; 229 case GLD_MAC_PROMISC_MULTI: 230 if ((rc = sfxge_mac_promisc_set(sp, SFXGE_PROMISC_ALL_MULTI)) 231 != 0) 232 goto fail2; 233 break; 234 default: 235 if ((rc = sfxge_mac_promisc_set(sp, SFXGE_PROMISC_ALL_PHYS)) 236 != 0) 237 goto fail3; 238 break; 239 } 240 241 return (GLD_SUCCESS); 242 243 fail3: 244 DTRACE_PROBE(fail3); 245 fail2: 246 DTRACE_PROBE(fail2); 247 fail1: 248 DTRACE_PROBE1(fail1, int, rc); 249 return (GLD_FAILURE); 250 } 251 252 static int 253 sfxge_gld_set_multicast(gld_mac_info_t *gmip, unsigned char *addr, int flag) 254 { 255 sfxge_t *sp = (sfxge_t *)(gmip->gldm_private); 256 int rc; 257 258 switch (flag) { 259 case GLD_MULTI_ENABLE: 260 if ((rc = sfxge_mac_multicst_add(sp, addr)) != 0) 261 goto fail1; 262 break; 263 case GLD_MULTI_DISABLE: 264 if ((rc = sfxge_mac_multicst_remove(sp, addr)) != 0) 265 goto fail2; 266 break; 267 default: 268 ASSERT(B_FALSE); 269 break; 270 } 271 272 return (GLD_SUCCESS); 273 274 fail2: 275 DTRACE_PROBE(fail2); 276 fail1: 277 DTRACE_PROBE1(fail1, int, rc); 278 return (GLD_FAILURE); 279 } 280 281 static int 282 sfxge_gld_set_mac_addr(gld_mac_info_t *gmip, unsigned char *addr) 283 { 284 sfxge_t *sp = (sfxge_t *)(gmip->gldm_private); 285 int rc; 286 287 if ((rc = sfxge_mac_unicst_set(sp, addr)) != 0) 288 goto fail1; 289 290 return (GLD_SUCCESS); 291 292 fail1: 293 DTRACE_PROBE1(fail1, int, rc); 294 295 return (GLD_BADARG); 296 } 297 298 int 299 sfxge_gld_send(gld_mac_info_t *gmip, mblk_t *mp) 300 { 301 sfxge_t *sp = (sfxge_t *)(gmip->gldm_private); 302 303 (void) sfxge_tx_packet_add(sp, mp); 304 305 /* 306 * This gives no TX backpressure, which can cause unbounded TX DPL 307 * size. See bug 18984. This feature is implemented for GLDv3 308 */ 309 return (GLD_SUCCESS); 310 } 311 312 int 313 sfxge_gld_ioctl(gld_mac_info_t *gmip, queue_t *wq, mblk_t *mp) 314 { 315 sfxge_t *sp = (sfxge_t *)(gmip->gldm_private); 316 struct iocblk *iocp; 317 318 iocp = (struct iocblk *)mp->b_rptr; 319 320 switch (iocp->ioc_cmd) { 321 case ND_GET: 322 case ND_SET: 323 if (!nd_getset(wq, sp->s_ndh, mp)) 324 miocnak(wq, mp, 0, EINVAL); 325 else 326 qreply(wq, mp); 327 break; 328 329 default: 330 sfxge_ioctl(sp, wq, mp); 331 break; 332 } 333 334 return (GLD_SUCCESS); 335 } 336 337 338 int 339 sfxge_gld_register(sfxge_t *sp) 340 { 341 gld_mac_info_t *gmip; 342 unsigned int pri; 343 int rc; 344 345 mutex_init(&(sp->s_rx_lock), NULL, MUTEX_DRIVER, 346 DDI_INTR_PRI(sp->s_intr.si_intr_pri)); 347 348 if ((rc = sfxge_gld_nd_register(sp)) != 0) 349 goto fail1; 350 351 gmip = gld_mac_alloc(sp->s_dip); 352 353 gmip->gldm_private = (caddr_t)sp; 354 355 gmip->gldm_reset = sfxge_gld_reset; 356 gmip->gldm_start = sfxge_gld_start; 357 gmip->gldm_stop = sfxge_gld_stop; 358 gmip->gldm_set_mac_addr = sfxge_gld_set_mac_addr; 359 gmip->gldm_set_multicast = sfxge_gld_set_multicast; 360 gmip->gldm_set_promiscuous = sfxge_gld_set_promiscuous; 361 gmip->gldm_send = sfxge_gld_send; 362 gmip->gldm_get_stats = sfxge_gld_get_stats; 363 gmip->gldm_ioctl = sfxge_gld_ioctl; 364 365 gmip->gldm_ident = (char *)sfxge_ident; 366 gmip->gldm_type = DL_ETHER; 367 gmip->gldm_minpkt = 0; 368 gmip->gldm_maxpkt = sp->s_mtu; 369 gmip->gldm_addrlen = ETHERADDRL; 370 gmip->gldm_saplen = -2; 371 gmip->gldm_broadcast_addr = sfxge_brdcst; 372 373 gmip->gldm_vendor_addr = kmem_alloc(ETHERADDRL, KM_SLEEP); 374 375 if ((rc = sfxge_mac_unicst_get(sp, SFXGE_UNICST_BIA, 376 gmip->gldm_vendor_addr)) != 0) 377 goto fail2; 378 379 gmip->gldm_devinfo = sp->s_dip; 380 gmip->gldm_ppa = ddi_get_instance(sp->s_dip); 381 382 gmip->gldm_cookie = spltoipl(0); 383 384 gmip->gldm_capabilities = 385 GLD_CAP_LINKSTATE | 386 GLD_CAP_CKSUM_IPHDR | 387 GLD_CAP_CKSUM_FULL_V4 | 388 GLD_CAP_ZEROCOPY; 389 390 if ((rc = gld_register(sp->s_dip, (char *)ddi_driver_name(sp->s_dip), 391 gmip)) != 0) 392 goto fail3; 393 394 sp->s_gmip = gmip; 395 return (0); 396 397 fail3: 398 DTRACE_PROBE(fail3); 399 fail2: 400 DTRACE_PROBE(fail2); 401 402 kmem_free(gmip->gldm_vendor_addr, ETHERADDRL); 403 gld_mac_free(gmip); 404 405 sfxge_gld_nd_unregister(sp); 406 407 fail1: 408 DTRACE_PROBE1(fail1, int, rc); 409 mutex_destroy(&(sp->s_rx_lock)); 410 411 return (rc); 412 } 413 414 int 415 sfxge_gld_unregister(sfxge_t *sp) 416 { 417 gld_mac_info_t *gmip = sp->s_gmip; 418 int rc; 419 420 if ((rc = gld_unregister(gmip)) != 0) 421 goto fail1; 422 423 sp->s_gmip = NULL; 424 425 kmem_free(gmip->gldm_vendor_addr, ETHERADDRL); 426 gld_mac_free(gmip); 427 428 sfxge_gld_nd_unregister(sp); 429 430 mutex_destroy(&(sp->s_rx_lock)); 431 432 return (0); 433 434 fail1: 435 DTRACE_PROBE1(fail1, int, rc); 436 437 return (rc); 438 } 439 #endif /* _USE_GLD_V2 */