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 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include "rge.h" 29 30 #define U32TOPTR(x) ((void *)(uintptr_t)(uint32_t)(x)) 31 #define PTRTOU32(x) ((uint32_t)(uintptr_t)(void *)(x)) 32 33 /* 34 * ========== RX side routines ========== 35 */ 36 37 #define RGE_DBG RGE_DBG_RECV /* debug flag for this code */ 38 39 static uint32_t rge_atomic_reserve(uint32_t *count_p, uint32_t n); 40 #pragma inline(rge_atomic_reserve) 41 42 static uint32_t 43 rge_atomic_reserve(uint32_t *count_p, uint32_t n) 44 { 45 uint32_t oldval; 46 uint32_t newval; 47 48 /* ATOMICALLY */ 49 do { 50 oldval = *count_p; 51 newval = oldval - n; 52 if (oldval <= n) 53 return (0); /* no resources left */ 54 } while (cas32(count_p, oldval, newval) != oldval); 55 56 return (newval); 57 } 58 59 /* 60 * Atomically increment a counter 61 */ 62 static void rge_atomic_renounce(uint32_t *count_p, uint32_t n); 63 #pragma inline(rge_atomic_renounce) 64 65 static void 66 rge_atomic_renounce(uint32_t *count_p, uint32_t n) 67 { 68 uint32_t oldval; 69 uint32_t newval; 70 71 /* ATOMICALLY */ 72 do { 73 oldval = *count_p; 74 newval = oldval + n; 75 } while (cas32(count_p, oldval, newval) != oldval); 76 } 77 78 /* 79 * Callback code invoked from STREAMs when the recv data buffer is free 80 * for recycling. 81 */ 82 void 83 rge_rx_recycle(caddr_t arg) 84 { 85 rge_t *rgep; 86 dma_buf_t *rx_buf; 87 sw_rbd_t *free_srbdp; 88 uint32_t slot_recy; 89 90 rx_buf = (dma_buf_t *)arg; 91 rgep = (rge_t *)rx_buf->private; 92 93 /* 94 * In rge_unattach() and rge_attach(), this callback function will 95 * also be called to free mp in rge_fini_rings() and rge_init_rings(). 96 * In such situation, we shouldn't do below desballoc(), otherwise, 97 * there'll be memory leak. 98 */ 99 if (rgep->rge_mac_state == RGE_MAC_UNATTACH || 100 rgep->rge_mac_state == RGE_MAC_ATTACH) 101 return; 102 103 /* 104 * Recycle the data buffer again 105 * and fill them in free ring 106 */ 107 rx_buf->mp = desballoc(DMA_VPTR(rx_buf->pbuf), 108 rgep->rxbuf_size, 0, &rx_buf->rx_recycle); 109 if (rx_buf->mp == NULL) { 110 rge_problem(rgep, "rge_rx_recycle: desballoc() failed"); 111 return; 112 } 113 mutex_enter(rgep->rc_lock); 114 slot_recy = rgep->rc_next; 115 free_srbdp = &rgep->free_srbds[slot_recy]; 116 117 ASSERT(free_srbdp->rx_buf == NULL); 118 free_srbdp->rx_buf = rx_buf; 119 rgep->rc_next = NEXT(slot_recy, RGE_BUF_SLOTS); 120 rge_atomic_renounce(&rgep->rx_free, 1); 121 if (rgep->rx_bcopy && rgep->rx_free == RGE_BUF_SLOTS) 122 rgep->rx_bcopy = B_FALSE; 123 ASSERT(rgep->rx_free <= RGE_BUF_SLOTS); 124 125 mutex_exit(rgep->rc_lock); 126 } 127 128 static int rge_rx_refill(rge_t *rgep, uint32_t slot); 129 #pragma inline(rge_rx_refill) 130 131 static int 132 rge_rx_refill(rge_t *rgep, uint32_t slot) 133 { 134 dma_buf_t *free_buf; 135 rge_bd_t *hw_rbd_p; 136 sw_rbd_t *srbdp; 137 uint32_t free_slot; 138 139 srbdp = &rgep->sw_rbds[slot]; 140 hw_rbd_p = &rgep->rx_ring[slot]; 141 free_slot = rgep->rf_next; 142 free_buf = rgep->free_srbds[free_slot].rx_buf; 143 if (free_buf != NULL) { 144 srbdp->rx_buf = free_buf; 145 rgep->free_srbds[free_slot].rx_buf = NULL; 146 hw_rbd_p->host_buf_addr = RGE_BSWAP_32(rgep->head_room + 147 + free_buf->pbuf.cookie.dmac_laddress); 148 hw_rbd_p->host_buf_addr_hi = 149 RGE_BSWAP_32(free_buf->pbuf.cookie.dmac_laddress >> 32); 150 rgep->rf_next = NEXT(free_slot, RGE_BUF_SLOTS); 151 return (1); 152 } else { 153 /* 154 * This situation shouldn't happen 155 */ 156 rge_problem(rgep, "rge_rx_refill: free buffer %d is NULL", 157 free_slot); 158 rgep->rx_bcopy = B_TRUE; 159 return (0); 160 } 161 } 162 163 static mblk_t *rge_receive_packet(rge_t *rgep, uint32_t slot); 164 #pragma inline(rge_receive_packet) 165 166 static mblk_t * 167 rge_receive_packet(rge_t *rgep, uint32_t slot) 168 { 169 rge_bd_t *hw_rbd_p; 170 sw_rbd_t *srbdp; 171 uchar_t *dp; 172 mblk_t *mp; 173 uint8_t *rx_ptr; 174 uint32_t rx_status; 175 uint_t packet_len; 176 uint_t minsize; 177 uint_t maxsize; 178 uint32_t proto; 179 uint32_t pflags; 180 struct ether_vlan_header *ehp; 181 uint16_t vtag = 0; 182 183 hw_rbd_p = &rgep->rx_ring[slot]; 184 srbdp = &rgep->sw_rbds[slot]; 185 186 /* 187 * Read receive status 188 */ 189 rx_status = RGE_BSWAP_32(hw_rbd_p->flags_len) & RBD_FLAGS_MASK; 190 191 /* 192 * Handle error packet 193 */ 194 if (!(rx_status & BD_FLAG_PKT_END)) { 195 RGE_DEBUG(("rge_receive_packet: not a complete packat")); 196 return (NULL); 197 } 198 if (rx_status & RBD_FLAG_ERROR) { 199 if (rx_status & RBD_FLAG_CRC_ERR) 200 rgep->stats.crc_err++; 201 if (rx_status & RBD_FLAG_RUNT) 202 rgep->stats.in_short++; 203 /* 204 * Set chip_error flag to reset chip: 205 * (suggested in Realtek programming guide.) 206 */ 207 RGE_DEBUG(("rge_receive_packet: error packet, status = %x", 208 rx_status)); 209 mutex_enter(rgep->genlock); 210 rgep->rge_chip_state = RGE_CHIP_ERROR; 211 mutex_exit(rgep->genlock); 212 return (NULL); 213 } 214 215 /* 216 * Handle size error packet 217 */ 218 packet_len = RGE_BSWAP_32(hw_rbd_p->flags_len) & RBD_LEN_MASK; 219 packet_len -= ETHERFCSL; 220 minsize = ETHERMIN; 221 pflags = RGE_BSWAP_32(hw_rbd_p->vlan_tag); 222 if (pflags & RBD_VLAN_PKT) 223 minsize -= VLAN_TAGSZ; 224 maxsize = rgep->ethmax_size; 225 if (packet_len < minsize || packet_len > maxsize) { 226 RGE_DEBUG(("rge_receive_packet: len err = %d", packet_len)); 227 return (NULL); 228 } 229 230 DMA_SYNC(srbdp->rx_buf->pbuf, DDI_DMA_SYNC_FORKERNEL); 231 if (rgep->rx_bcopy || packet_len <= RGE_RECV_COPY_SIZE || 232 !rge_atomic_reserve(&rgep->rx_free, 1)) { 233 /* 234 * Allocate buffer to receive this good packet 235 */ 236 mp = allocb(packet_len + RGE_HEADROOM, 0); 237 if (mp == NULL) { 238 RGE_DEBUG(("rge_receive_packet: allocate buffer fail")); 239 rgep->stats.no_rcvbuf++; 240 return (NULL); 241 } 242 243 /* 244 * Copy the data found into the new cluster 245 */ 246 rx_ptr = DMA_VPTR(srbdp->rx_buf->pbuf); 247 mp->b_rptr = dp = mp->b_rptr + RGE_HEADROOM; 248 bcopy(rx_ptr + rgep->head_room, dp, packet_len); 249 mp->b_wptr = dp + packet_len; 250 } else { 251 mp = srbdp->rx_buf->mp; 252 mp->b_rptr += rgep->head_room; 253 mp->b_wptr = mp->b_rptr + packet_len; 254 mp->b_next = mp->b_cont = NULL; 255 /* 256 * Refill the current receive bd buffer 257 * if fails, will just keep the mp. 258 */ 259 if (!rge_rx_refill(rgep, slot)) 260 return (NULL); 261 } 262 rgep->stats.rbytes += packet_len; 263 264 /* 265 * VLAN packet ? 266 */ 267 if (pflags & RBD_VLAN_PKT) 268 vtag = pflags & RBD_VLAN_TAG; 269 if (vtag) { 270 vtag = TCI_CHIP2OS(vtag); 271 /* 272 * As h/w strips the VLAN tag from incoming packet, we need 273 * insert VLAN tag into this packet before send up here. 274 */ 275 (void) memmove(mp->b_rptr - VLAN_TAGSZ, mp->b_rptr, 276 2 * ETHERADDRL); 277 mp->b_rptr -= VLAN_TAGSZ; 278 ehp = (struct ether_vlan_header *)mp->b_rptr; 279 ehp->ether_tpid = htons(ETHERTYPE_VLAN); 280 ehp->ether_tci = htons(vtag); 281 rgep->stats.rbytes += VLAN_TAGSZ; 282 } 283 284 /* 285 * Check h/w checksum offload status 286 */ 287 pflags = 0; 288 proto = rx_status & RBD_FLAG_PROTOCOL; 289 if ((proto == RBD_FLAG_TCP && !(rx_status & RBD_TCP_CKSUM_ERR)) || 290 (proto == RBD_FLAG_UDP && !(rx_status & RBD_UDP_CKSUM_ERR))) 291 pflags |= HCK_FULLCKSUM | HCK_FULLCKSUM_OK; 292 if (proto != RBD_FLAG_NONE_IP && !(rx_status & RBD_IP_CKSUM_ERR)) 293 pflags |= HCK_IPV4_HDRCKSUM; 294 if (pflags != 0) { 295 (void) hcksum_assoc(mp, NULL, NULL, 0, 0, 0, 0, pflags, 0); 296 } 297 298 return (mp); 299 } 300 301 /* 302 * Accept the packets received in rx ring. 303 * 304 * Returns a chain of mblks containing the received data, to be 305 * passed up to mac_rx(). 306 * The routine returns only when a complete scan has been performed 307 * without finding any packets to receive. 308 * This function must SET the OWN bit of BD to indicate the packets 309 * it has accepted from the ring. 310 */ 311 static mblk_t *rge_receive_ring(rge_t *rgep); 312 #pragma inline(rge_receive_ring) 313 314 static mblk_t * 315 rge_receive_ring(rge_t *rgep) 316 { 317 rge_bd_t *hw_rbd_p; 318 mblk_t *head; 319 mblk_t **tail; 320 mblk_t *mp; 321 uint32_t slot; 322 323 ASSERT(mutex_owned(rgep->rx_lock)); 324 325 /* 326 * Sync (all) the receive ring descriptors 327 * before accepting the packets they describe 328 */ 329 DMA_SYNC(rgep->rx_desc, DDI_DMA_SYNC_FORKERNEL); 330 slot = rgep->rx_next; 331 hw_rbd_p = &rgep->rx_ring[slot]; 332 head = NULL; 333 tail = &head; 334 335 while (!(hw_rbd_p->flags_len & RGE_BSWAP_32(BD_FLAG_HW_OWN))) { 336 if ((mp = rge_receive_packet(rgep, slot)) != NULL) { 337 *tail = mp; 338 tail = &mp->b_next; 339 } 340 341 /* 342 * Clear RBD flags 343 */ 344 hw_rbd_p->flags_len = 345 RGE_BSWAP_32(rgep->rxbuf_size - rgep->head_room); 346 HW_RBD_INIT(hw_rbd_p, slot); 347 slot = NEXT(slot, RGE_RECV_SLOTS); 348 hw_rbd_p = &rgep->rx_ring[slot]; 349 } 350 351 rgep->rx_next = slot; 352 return (head); 353 } 354 355 /* 356 * Receive all ready packets. 357 */ 358 void rge_receive(rge_t *rgep); 359 #pragma no_inline(rge_receive) 360 361 void 362 rge_receive(rge_t *rgep) 363 { 364 mblk_t *mp; 365 366 mutex_enter(rgep->rx_lock); 367 mp = rge_receive_ring(rgep); 368 mutex_exit(rgep->rx_lock); 369 370 if (mp != NULL) 371 mac_rx(rgep->mh, rgep->handle, mp); 372 } 373 374 375 #undef RGE_DBG 376 #define RGE_DBG RGE_DBG_SEND /* debug flag for this code */ 377 378 379 /* 380 * ========== Send-side recycle routines ========== 381 */ 382 static uint32_t rge_send_claim(rge_t *rgep); 383 #pragma inline(rge_send_claim) 384 385 static uint32_t 386 rge_send_claim(rge_t *rgep) 387 { 388 uint32_t slot; 389 uint32_t next; 390 391 mutex_enter(rgep->tx_lock); 392 slot = rgep->tx_next; 393 next = NEXT(slot, RGE_SEND_SLOTS); 394 rgep->tx_next = next; 395 rgep->tx_flow++; 396 mutex_exit(rgep->tx_lock); 397 398 /* 399 * We check that our invariants still hold: 400 * + the slot and next indexes are in range 401 * + the slot must not be the last one (i.e. the *next* 402 * index must not match the next-recycle index), 'cos 403 * there must always be at least one free slot in a ring 404 */ 405 ASSERT(slot < RGE_SEND_SLOTS); 406 ASSERT(next < RGE_SEND_SLOTS); 407 ASSERT(next != rgep->tc_next); 408 409 return (slot); 410 } 411 412 /* 413 * We don't want to call this function every time after a successful 414 * h/w transmit done in ISR. Instead, we call this function in the 415 * rge_send() when there're few or no free tx BDs remained. 416 */ 417 static void rge_send_recycle(rge_t *rgep); 418 #pragma inline(rge_send_recycle) 419 420 static void 421 rge_send_recycle(rge_t *rgep) 422 { 423 rge_bd_t *hw_sbd_p; 424 uint32_t tc_tail; 425 uint32_t tc_head; 426 uint32_t n; 427 428 mutex_enter(rgep->tc_lock); 429 tc_head = rgep->tc_next; 430 tc_tail = rgep->tc_tail; 431 if (tc_head == tc_tail) 432 goto resched; 433 434 do { 435 tc_tail = LAST(tc_tail, RGE_SEND_SLOTS); 436 hw_sbd_p = &rgep->tx_ring[tc_tail]; 437 if (tc_tail == tc_head) { 438 if (hw_sbd_p->flags_len & 439 RGE_BSWAP_32(BD_FLAG_HW_OWN)) { 440 /* 441 * Recyled nothing: bump the watchdog counter, 442 * thus guaranteeing that it's nonzero 443 * (watchdog activated). 444 */ 445 rgep->watchdog += 1; 446 mutex_exit(rgep->tc_lock); 447 return; 448 } 449 break; 450 } 451 } while (hw_sbd_p->flags_len & RGE_BSWAP_32(BD_FLAG_HW_OWN)); 452 453 /* 454 * Recyled something :-) 455 */ 456 rgep->tc_next = NEXT(tc_tail, RGE_SEND_SLOTS); 457 n = rgep->tc_next - tc_head; 458 if (rgep->tc_next < tc_head) 459 n += RGE_SEND_SLOTS; 460 rge_atomic_renounce(&rgep->tx_free, n); 461 rgep->watchdog = 0; 462 ASSERT(rgep->tx_free <= RGE_SEND_SLOTS); 463 464 resched: 465 mutex_exit(rgep->tc_lock); 466 if (rgep->resched_needed && 467 rgep->rge_mac_state == RGE_MAC_STARTED) { 468 rgep->resched_needed = B_FALSE; 469 mac_tx_update(rgep->mh); 470 } 471 } 472 473 /* 474 * Send a message by copying it into a preallocated (and premapped) buffer 475 */ 476 static void rge_send_copy(rge_t *rgep, mblk_t *mp, uint16_t tci); 477 #pragma inline(rge_send_copy) 478 479 static void 480 rge_send_copy(rge_t *rgep, mblk_t *mp, uint16_t tci) 481 { 482 rge_bd_t *hw_sbd_p; 483 sw_sbd_t *ssbdp; 484 mblk_t *bp; 485 char *txb; 486 uint32_t slot; 487 size_t totlen; 488 size_t mblen; 489 uint32_t pflags; 490 struct ether_header *ethhdr; 491 struct ip *ip_hdr; 492 493 /* 494 * IMPORTANT: 495 * Up to the point where it claims a place, a send_msg() 496 * routine can indicate failure by returning B_FALSE. Once it's 497 * claimed a place, it mustn't fail. 498 * 499 * In this version, there's no setup to be done here, and there's 500 * nothing that can fail, so we can go straight to claiming our 501 * already-reserved place on the train. 502 * 503 * This is the point of no return! 504 */ 505 slot = rge_send_claim(rgep); 506 ssbdp = &rgep->sw_sbds[slot]; 507 508 /* 509 * Copy the data into a pre-mapped buffer, which avoids the 510 * overhead (and complication) of mapping/unmapping STREAMS 511 * buffers and keeping hold of them until the DMA has completed. 512 * 513 * Because all buffers are the same size, and larger than the 514 * longest single valid message, we don't have to bother about 515 * splitting the message across multiple buffers either. 516 */ 517 txb = DMA_VPTR(ssbdp->pbuf); 518 totlen = 0; 519 bp = mp; 520 if (tci != 0) { 521 /* 522 * Do not copy the vlan tag 523 */ 524 bcopy(bp->b_rptr, txb, 2 * ETHERADDRL); 525 txb += 2 * ETHERADDRL; 526 totlen += 2 * ETHERADDRL; 527 mblen = bp->b_wptr - bp->b_rptr; 528 ASSERT(mblen >= 2 * ETHERADDRL + VLAN_TAGSZ); 529 mblen -= 2 * ETHERADDRL + VLAN_TAGSZ; 530 if ((totlen += mblen) <= rgep->ethmax_size) { 531 bcopy(bp->b_rptr + 2 * ETHERADDRL + VLAN_TAGSZ, 532 txb, mblen); 533 txb += mblen; 534 } 535 bp = bp->b_cont; 536 rgep->stats.obytes += VLAN_TAGSZ; 537 } 538 for (; bp != NULL; bp = bp->b_cont) { 539 mblen = bp->b_wptr - bp->b_rptr; 540 if ((totlen += mblen) <= rgep->ethmax_size) { 541 bcopy(bp->b_rptr, txb, mblen); 542 txb += mblen; 543 } 544 } 545 rgep->stats.obytes += totlen; 546 547 /* 548 * We'e reached the end of the chain; and we should have 549 * collected no more than ETHERMAX bytes into our buffer. 550 */ 551 ASSERT(bp == NULL); 552 ASSERT(totlen <= rgep->ethmax_size); 553 DMA_SYNC(ssbdp->pbuf, DDI_DMA_SYNC_FORDEV); 554 555 /* 556 * Update the hardware send buffer descriptor flags 557 */ 558 hw_sbd_p = &rgep->tx_ring[slot]; 559 ASSERT(hw_sbd_p == ssbdp->desc.mem_va); 560 hw_sbd_p->flags_len = RGE_BSWAP_32(totlen & SBD_LEN_MASK); 561 if (tci != 0) { 562 tci = TCI_OS2CHIP(tci); 563 hw_sbd_p->vlan_tag = RGE_BSWAP_32(tci); 564 hw_sbd_p->vlan_tag |= RGE_BSWAP_32(SBD_VLAN_PKT); 565 } else { 566 hw_sbd_p->vlan_tag = 0; 567 } 568 569 /* 570 * h/w checksum offload flags 571 */ 572 hcksum_retrieve(mp, NULL, NULL, NULL, NULL, NULL, NULL, &pflags); 573 if (pflags & HCK_FULLCKSUM) { 574 ASSERT(totlen >= sizeof (struct ether_header) + 575 sizeof (struct ip)); 576 ethhdr = (struct ether_header *)(DMA_VPTR(ssbdp->pbuf)); 577 /* 578 * Is the packet an IP(v4) packet? 579 */ 580 if (ntohs(ethhdr->ether_type) == ETHERTYPE_IP) { 581 ip_hdr = (struct ip *) 582 ((uint8_t *)DMA_VPTR(ssbdp->pbuf) + 583 sizeof (struct ether_header)); 584 if (ip_hdr->ip_p == IPPROTO_TCP) 585 hw_sbd_p->flags_len |= 586 RGE_BSWAP_32(SBD_FLAG_TCP_CKSUM); 587 else if (ip_hdr->ip_p == IPPROTO_UDP) 588 hw_sbd_p->flags_len |= 589 RGE_BSWAP_32(SBD_FLAG_UDP_CKSUM); 590 } 591 } 592 if (pflags & HCK_IPV4_HDRCKSUM) 593 hw_sbd_p->flags_len |= RGE_BSWAP_32(SBD_FLAG_IP_CKSUM); 594 595 HW_SBD_SET(hw_sbd_p, slot); 596 597 /* 598 * We're done. 599 * The message can be freed right away, as we've already 600 * copied the contents ... 601 */ 602 freemsg(mp); 603 } 604 605 static boolean_t 606 rge_send(rge_t *rgep, mblk_t *mp) 607 { 608 struct ether_vlan_header *ehp; 609 uint16_t tci; 610 611 ASSERT(mp->b_next == NULL); 612 613 /* 614 * Try to reserve a place in the transmit ring. 615 */ 616 if (!rge_atomic_reserve(&rgep->tx_free, 1)) { 617 RGE_DEBUG(("rge_send: no free slots")); 618 rgep->stats.defer++; 619 rgep->resched_needed = B_TRUE; 620 (void) ddi_intr_trigger_softint(rgep->resched_hdl, NULL); 621 return (B_FALSE); 622 } 623 624 /* 625 * Determine if the packet is VLAN tagged. 626 */ 627 ASSERT(MBLKL(mp) >= sizeof (struct ether_header)); 628 tci = 0; 629 ehp = (struct ether_vlan_header *)mp->b_rptr; 630 if (ehp->ether_tpid == htons(ETHERTYPE_VLAN)) 631 tci = ntohs(ehp->ether_tci); 632 633 /* 634 * We've reserved a place :-) 635 * These ASSERTions check that our invariants still hold: 636 * there must still be at least one free place 637 * there must be at least one place NOT free (ours!) 638 */ 639 ASSERT(rgep->tx_free < RGE_SEND_SLOTS); 640 rge_send_copy(rgep, mp, tci); 641 642 /* 643 * Trigger chip h/w transmit ... 644 */ 645 mutex_enter(rgep->tx_lock); 646 if (--rgep->tx_flow == 0) { 647 DMA_SYNC(rgep->tx_desc, DDI_DMA_SYNC_FORDEV); 648 rge_tx_trigger(rgep); 649 if (rgep->tx_free < RGE_SEND_SLOTS/2) 650 rge_send_recycle(rgep); 651 rgep->tc_tail = rgep->tx_next; 652 } 653 mutex_exit(rgep->tx_lock); 654 655 return (B_TRUE); 656 } 657 658 uint_t 659 rge_reschedule(caddr_t arg1, caddr_t arg2) 660 { 661 rge_t *rgep; 662 663 rgep = (rge_t *)arg1; 664 _NOTE(ARGUNUSED(arg2)) 665 666 rge_send_recycle(rgep); 667 668 return (DDI_INTR_CLAIMED); 669 } 670 671 /* 672 * rge_m_tx() - send a chain of packets 673 */ 674 mblk_t * 675 rge_m_tx(void *arg, mblk_t *mp) 676 { 677 rge_t *rgep = arg; /* private device info */ 678 mblk_t *next; 679 680 ASSERT(mp != NULL); 681 ASSERT(rgep->rge_mac_state == RGE_MAC_STARTED); 682 683 if (rgep->rge_chip_state != RGE_CHIP_RUNNING) { 684 RGE_DEBUG(("rge_m_tx: chip not running")); 685 return (mp); 686 } 687 688 rw_enter(rgep->errlock, RW_READER); 689 while (mp != NULL) { 690 next = mp->b_next; 691 mp->b_next = NULL; 692 693 if (!rge_send(rgep, mp)) { 694 mp->b_next = next; 695 break; 696 } 697 698 mp = next; 699 } 700 rw_exit(rgep->errlock); 701 702 return (mp); 703 } 704