diff options
author | gs150176 <none@none> | 2006-08-13 17:35:34 -0700 |
---|---|---|
committer | gs150176 <none@none> | 2006-08-13 17:35:34 -0700 |
commit | aa81749390e332985277568edab1ee6132326b42 (patch) | |
tree | e52ff6d41848a2cab963b2aa15c4c4e9b9714a69 /usr/src | |
parent | 4cb70d33a0347eb8a72054ff37d58fb4b7fb185f (diff) | |
download | illumos-gate-aa81749390e332985277568edab1ee6132326b42.tar.gz |
6396777 RealTek 10/100BaseT ethernet support
6431573 rge need support RTL8111(B)/RTL8168(B) pcie chipset
Diffstat (limited to 'usr/src')
-rwxr-xr-x | usr/src/pkgdefs/SUNWrge/postinstall | 9 | ||||
-rw-r--r-- | usr/src/pkgdefs/SUNWrtls/postinstall | 4 | ||||
-rwxr-xr-x | usr/src/uts/common/io/rge/rge.h | 65 | ||||
-rwxr-xr-x | usr/src/uts/common/io/rge/rge_chip.c | 296 | ||||
-rwxr-xr-x | usr/src/uts/common/io/rge/rge_hw.h | 52 | ||||
-rwxr-xr-x | usr/src/uts/common/io/rge/rge_main.c | 663 | ||||
-rwxr-xr-x | usr/src/uts/common/io/rge/rge_ndd.c | 10 | ||||
-rwxr-xr-x | usr/src/uts/common/io/rge/rge_rxtx.c | 267 |
8 files changed, 831 insertions, 535 deletions
diff --git a/usr/src/pkgdefs/SUNWrge/postinstall b/usr/src/pkgdefs/SUNWrge/postinstall index 903e518a02..b1c1aa90fa 100755 --- a/usr/src/pkgdefs/SUNWrge/postinstall +++ b/usr/src/pkgdefs/SUNWrge/postinstall @@ -3,9 +3,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -21,7 +20,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -128,4 +127,4 @@ check_add_drv() } -check_add_drv -i '"pci10ec,8169" "pci10ec,8110"' -b "$BASEDIR" rge +check_add_drv -i '"pci10ec,8169" "pci10ec,8110" "pci10ec,8168" "pci10ec,8111"' -b "$BASEDIR" rge diff --git a/usr/src/pkgdefs/SUNWrtls/postinstall b/usr/src/pkgdefs/SUNWrtls/postinstall index 4604b51c73..e7546f053d 100644 --- a/usr/src/pkgdefs/SUNWrtls/postinstall +++ b/usr/src/pkgdefs/SUNWrtls/postinstall @@ -1,6 +1,6 @@ #!/sbin/sh # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -107,4 +107,4 @@ check_add_drv() } -check_add_drv -i '"pci10ec,8139"' -b "$BASEDIR" rtls +check_add_drv -i '"pci10ec,8139" "pci1186,1301" "pci1113,1211"' -b "$BASEDIR" rtls diff --git a/usr/src/uts/common/io/rge/rge.h b/usr/src/uts/common/io/rge/rge.h index 7f5f4c29c6..9d7f3fc3b7 100755 --- a/usr/src/uts/common/io/rge/rge.h +++ b/usr/src/uts/common/io/rge/rge.h @@ -51,7 +51,6 @@ extern "C" { #include <sys/conf.h> #include <netinet/ip6.h> - #include <inet/common.h> #include <inet/ip.h> #include <inet/mi.h> @@ -67,20 +66,15 @@ extern "C" { /* * Reconfiguring the network devices requires the net_config privilege - * in Solaris 10+. Prior to this, root privilege is required. In order - * that the driver binary can run on both S10+ and earlier versions, we - * make the decisiion as to which to use at runtime. These declarations - * allow for either (or both) to exist ... + * in Solaris 10+. */ extern int secpolicy_net_config(const cred_t *, boolean_t); -extern int drv_priv(cred_t *); -#pragma weak secpolicy_net_config -#pragma weak drv_priv #include <sys/netlb.h> /* originally from cassini */ #include <sys/miiregs.h> /* by fjlite out of intel */ #include "rge_hw.h" + /* * Name of the driver */ @@ -163,7 +157,6 @@ typedef struct { #define PHY_RESET_LOOP 1000 #define STATS_DUMP_LOOP 1000 #define RXBUFF_FREE_LOOP 1000 -#define RGE_SPLIT 128 #define RGE_RX_INT_TIME 128 #define RGE_RX_INT_PKTS 8 @@ -214,7 +207,6 @@ enum { PARAM_LINK_DUPLEX, PARAM_LOOP_MODE, - PARAM_DEFAULT_MTU, PARAM_COUNT }; @@ -229,7 +221,8 @@ enum rge_chip_state { }; enum rge_mac_state { - RGE_MAC_STOPPED = 0, + RGE_MAC_ATTACH = 0, + RGE_MAC_STOPPED, RGE_MAC_STARTED, RGE_MAC_UNATTACH }; @@ -263,13 +256,6 @@ enum { RGE_KSTAT_COUNT }; -enum { - IS_IPV4_PKT = 1, - IS_UDP_PKT, - IS_TCP_PKT, - UNKNOWN_PKT -}; - /* * Basic data types, for clarity in distinguishing 'numbers' * used for different purposes ... @@ -362,6 +348,7 @@ typedef struct { uint8_t revision; /* revision-id */ uint8_t clsize; /* cache-line-size */ uint8_t latency; /* latency-timer */ + boolean_t is_pcie; uint32_t mac_ver; uint32_t phy_ver; uint32_t rxconfig; @@ -377,7 +364,6 @@ typedef struct rge_stats { uint32_t in_short; uint32_t no_rcvbuf; /* ifInDiscards */ uint32_t intr; /* interrupt count */ - uint32_t recycle_err; uint16_t chip_reset; uint16_t phy_reset; } rge_stats_t; @@ -392,13 +378,23 @@ typedef struct rge { ddi_acc_handle_t io_handle; /* DDI I/O handle */ caddr_t io_regs; /* mapped registers */ cyclic_id_t cyclic_id; /* cyclic callback */ - ddi_softintr_t resched_id; /* reschedule callback */ - ddi_softintr_t factotum_id; /* factotum callback */ - ddi_iblock_cookie_t iblk; + ddi_softint_handle_t resched_hdl; /* reschedule callback */ + ddi_softint_handle_t factotum_hdl; /* factotum callback */ + uint_t soft_pri; + ddi_intr_handle_t *htable; /* For array of interrupts */ + int intr_type; /* What type of interrupt */ + int intr_rqst; /* # of request intrs count */ + int intr_cnt; /* # of intrs count returned */ + uint_t intr_pri; /* Interrupt priority */ + int intr_cap; /* Interrupt capabilities */ + boolean_t msi_enable; + uint32_t ethmax_size; + uint32_t default_mtu; uint32_t rxbuf_size; uint32_t txbuf_size; - + uint32_t chip_flags; + uint32_t head_room; char ifname[8]; /* "rge0" ... "rge999" */ int32_t instance; uint32_t progress; /* attach tracking */ @@ -413,9 +409,6 @@ typedef struct rge { */ dma_area_t dma_area_rxdesc; dma_area_t dma_area_txdesc; - dma_area_t dma_area_rxbuf[RGE_SPLIT]; - dma_area_t dma_area_freebuf[RGE_SPLIT]; - dma_area_t dma_area_txbuf[RGE_SPLIT]; dma_area_t dma_area_stats; /* describes hardware statistics area */ @@ -424,7 +417,7 @@ typedef struct rge { /* used for multicast/promisc mode set */ char mcast_refs[RGE_MCAST_BUF_SIZE]; - uint32_t mcast_hash[2]; + uint8_t mcast_hash[RGE_MCAST_NUM]; boolean_t promisc; /* promisc state flag */ /* used for recv */ @@ -433,9 +426,7 @@ typedef struct rge { boolean_t rx_bcopy; uint32_t rx_next; /* current rx bd index */ sw_rbd_t *sw_rbds; - dma_buf_t *sw_rbuf; - sw_rbd_t *free_rbds; - dma_buf_t *sw_freebuf; + sw_rbd_t *free_srbds; uint32_t rf_next; /* current free buf index */ uint32_t rc_next; /* current recycle buf index */ uint32_t rx_free; /* number of rx free buf */ @@ -511,13 +502,18 @@ typedef struct rge { #define PROGRESS_FACTOTUM 0x0020 /* factotum softint registered */ #define PROGRESS_INTR 0X0040 /* h/w interrupt registered */ /* and mutexen initialised */ -#define PROGRESS_HWINT 0x0080 /* rx/buf/tx ring initialised */ +#define PROGRESS_INIT 0x0080 /* rx/buf/tx ring initialised */ #define PROGRESS_PHY 0x0100 /* PHY initialised */ #define PROGRESS_NDD 0x1000 /* NDD parameters set up */ #define PROGRESS_KSTATS 0x2000 /* kstats created */ #define PROGRESS_READY 0x8000 /* ready for work */ /* + * Special chip flags + */ +#define CHIP_FLAG_FORCE_BCOPY 0x10000000 + +/* * Shorthand for the NDD parameters */ #define param_adv_autoneg nd_params[PARAM_ADV_AUTONEG_CAP].ndp_val @@ -535,7 +531,6 @@ typedef struct rge { #define param_link_duplex nd_params[PARAM_LINK_DUPLEX].ndp_val #define param_loop_mode nd_params[PARAM_LOOP_MODE].ndp_val -#define param_default_mtu nd_params[PARAM_DEFAULT_MTU].ndp_val /* * Sync a DMA area described by a dma_area_t @@ -723,8 +718,8 @@ void rge_chip_sync(rge_t *rgep, enum rge_sync_op todo); void rge_chip_blank(void *arg, time_t ticks, uint_t count); void rge_tx_trigger(rge_t *rgep); void rge_hw_stats_dump(rge_t *rgep); -uint_t rge_intr(caddr_t arg); -uint_t rge_chip_factotum(caddr_t arg); +uint_t rge_intr(caddr_t arg1, caddr_t arg2); +uint_t rge_chip_factotum(caddr_t arg1, caddr_t arg2); void rge_chip_cyclic(void *arg); enum ioc_reply rge_chip_ioctl(rge_t *rgep, queue_t *wq, mblk_t *mp, struct iocblk *iocp); @@ -764,7 +759,7 @@ void rge_nd_cleanup(rge_t *rgep); void rge_rx_recycle(caddr_t arg); void rge_receive(rge_t *rgep); mblk_t *rge_m_tx(void *arg, mblk_t *mp); -uint_t rge_reschedule(caddr_t arg); +uint_t rge_reschedule(caddr_t arg1, caddr_t arg2); #ifdef __cplusplus } diff --git a/usr/src/uts/common/io/rge/rge_chip.c b/usr/src/uts/common/io/rge/rge_chip.c index 5942f1df8a..88779388e4 100755 --- a/usr/src/uts/common/io/rge/rge_chip.c +++ b/usr/src/uts/common/io/rge/rge_chip.c @@ -258,7 +258,7 @@ rge_mii_get16(rge_t *rgep, uintptr_t mii) drv_usecwait(100); val32 = rge_reg_get32(rgep, PHY_ACCESS_REG); if (val32 & PHY_ACCESS_WR_FLAG) - return (val32 & 0xffff); + return ((uint16_t)(val32 & 0xffff)); } RGE_REPORT((rgep, "rge_mii_get16(0x%x) fail, val = %x", mii, val32)); @@ -293,6 +293,34 @@ rge_mii_put16(rge_t *rgep, uintptr_t mii, uint16_t data) mii, data)); } +void rge_ephy_put16(rge_t *rgep, uintptr_t emii, uint16_t data); +#pragma no_inline(rge_ephy_put16) + +void +rge_ephy_put16(rge_t *rgep, uintptr_t emii, uint16_t data) +{ + uint32_t regval; + uint32_t val32; + uint32_t i; + + regval = (emii & EPHY_REG_MASK) << EPHY_REG_SHIFT; + regval |= data & EPHY_DATA_MASK; + regval |= EPHY_ACCESS_WR_FLAG; + rge_reg_put32(rgep, EPHY_ACCESS_REG, regval); + + /* + * Waiting for PHY writing OK + */ + for (i = 0; i < PHY_RESET_LOOP; i++) { + drv_usecwait(100); + val32 = rge_reg_get32(rgep, EPHY_ACCESS_REG); + if (!(val32 & EPHY_ACCESS_WR_FLAG)) + return; + } + RGE_REPORT((rgep, "rge_ephy_put16(0x%lx, 0x%x) fail", + emii, data)); +} + /* * Atomically shift a 32-bit word left, returning * the value it had *before* the shift was applied @@ -574,6 +602,8 @@ rge_phy_update(rge_t *rgep) /* * Chipset limitation: need set other capabilities to true */ + if (rgep->chipid.is_pcie) + adv_1000hdx = B_TRUE; adv_100fdx = B_TRUE; adv_100hdx = B_TRUE; adv_10fdx = B_TRUE; @@ -610,8 +640,8 @@ rge_phy_update(rge_t *rgep) rgep->phys_write_time = gethrtime(); rge_phy_init(rgep); rge_mii_put16(rgep, MII_AN_ADVERT, anar); - rge_mii_put16(rgep, MII_CONTROL, control); rge_mii_put16(rgep, MII_1000BASE_T_CONTROL, gigctrl); + rge_mii_put16(rgep, MII_CONTROL, control); RGE_DEBUG(("rge_phy_update: anar <- 0x%x", anar)); RGE_DEBUG(("rge_phy_update: control <- 0x%x", control)); @@ -624,84 +654,91 @@ void rge_phy_init(rge_t *rgep); void rge_phy_init(rge_t *rgep) { - uint16_t val16; - rgep->phy_mii_addr = 1; /* * Below phy config steps are copied from the Programming Guide * (there's no detail comments for these steps.) */ - if ((rgep->chipid.mac_ver == MAC_VER_SD || - rgep->chipid.mac_ver == MAC_VER_SE) && - (rgep->chipid.phy_ver == PHY_VER_S)) { - rge_mii_put16(rgep, PHY_1F_REG, 1); + switch (rgep->chipid.mac_ver) { + case MAC_VER_8169S_D: + case MAC_VER_8169S_E : + rge_mii_put16(rgep, PHY_1F_REG, 0x0001); rge_mii_put16(rgep, PHY_15_REG, 0x1000); rge_mii_put16(rgep, PHY_18_REG, 0x65c7); - val16 = rge_mii_get16(rgep, PHY_ANAR_REG); - rge_mii_put16(rgep, PHY_ANAR_REG, val16 & (~ANAR_ASY_PAUSE)); - val16 = rge_mii_get16(rgep, PHY_ANAR_REG); - rge_mii_put16(rgep, PHY_ANAR_REG, val16 & 0x0fff); + rge_mii_put16(rgep, PHY_ANAR_REG, 0x0000); rge_mii_put16(rgep, PHY_ID_REG_2, 0x00a1); rge_mii_put16(rgep, PHY_ID_REG_1, 0x0008); rge_mii_put16(rgep, PHY_BMSR_REG, 0x1020); rge_mii_put16(rgep, PHY_BMCR_REG, 0x1000); - val16 = rge_mii_get16(rgep, PHY_ANAR_REG); - rge_mii_put16(rgep, PHY_ANAR_REG, val16 | ANAR_ASY_PAUSE); - val16 = rge_mii_get16(rgep, PHY_ANAR_REG); - rge_mii_put16(rgep, PHY_ANAR_REG, val16 & (~ANAR_ASY_PAUSE)); - val16 = rge_mii_get16(rgep, PHY_ANAR_REG); - rge_mii_put16(rgep, PHY_ANAR_REG, (val16 & 0x0fff) | 0x7000); + rge_mii_put16(rgep, PHY_ANAR_REG, 0x0800); + rge_mii_put16(rgep, PHY_ANAR_REG, 0x0000); + rge_mii_put16(rgep, PHY_ANAR_REG, 0x7000); rge_mii_put16(rgep, PHY_ID_REG_2, 0xff41); rge_mii_put16(rgep, PHY_ID_REG_1, 0xde60); rge_mii_put16(rgep, PHY_BMSR_REG, 0x0140); rge_mii_put16(rgep, PHY_BMCR_REG, 0x0077); - val16 = rge_mii_get16(rgep, PHY_ANAR_REG); - rge_mii_put16(rgep, PHY_ANAR_REG, val16 | ANAR_ASY_PAUSE); - val16 = rge_mii_get16(rgep, PHY_ANAR_REG); - rge_mii_put16(rgep, PHY_ANAR_REG, val16 & (~ANAR_ASY_PAUSE)); - val16 = rge_mii_get16(rgep, PHY_ANAR_REG); - rge_mii_put16(rgep, PHY_ANAR_REG, (val16 & 0x0fff) | 0xa000); + rge_mii_put16(rgep, PHY_ANAR_REG, 0x7800); + rge_mii_put16(rgep, PHY_ANAR_REG, 0x7000); + rge_mii_put16(rgep, PHY_ANAR_REG, 0xa000); rge_mii_put16(rgep, PHY_ID_REG_2, 0xdf01); rge_mii_put16(rgep, PHY_ID_REG_1, 0xdf20); rge_mii_put16(rgep, PHY_BMSR_REG, 0xff95); rge_mii_put16(rgep, PHY_BMCR_REG, 0xfa00); - val16 = rge_mii_get16(rgep, PHY_ANAR_REG); - rge_mii_put16(rgep, PHY_ANAR_REG, val16 | ANAR_ASY_PAUSE); - val16 = rge_mii_get16(rgep, PHY_ANAR_REG); - rge_mii_put16(rgep, PHY_ANAR_REG, val16 & (~ANAR_ASY_PAUSE)); - val16 = rge_mii_get16(rgep, PHY_ANAR_REG); - rge_mii_put16(rgep, PHY_ANAR_REG, (val16 & 0x0fff) | 0xb000); + rge_mii_put16(rgep, PHY_ANAR_REG, 0xa800); + rge_mii_put16(rgep, PHY_ANAR_REG, 0xa000); + rge_mii_put16(rgep, PHY_ANAR_REG, 0xb000); rge_mii_put16(rgep, PHY_ID_REG_2, 0xff41); rge_mii_put16(rgep, PHY_ID_REG_1, 0xde20); rge_mii_put16(rgep, PHY_BMSR_REG, 0x0140); rge_mii_put16(rgep, PHY_BMCR_REG, 0x00bb); - val16 = rge_mii_get16(rgep, PHY_ANAR_REG); - rge_mii_put16(rgep, PHY_ANAR_REG, val16 | ANAR_ASY_PAUSE); - val16 = rge_mii_get16(rgep, PHY_ANAR_REG); - rge_mii_put16(rgep, PHY_ANAR_REG, val16 & (~ANAR_ASY_PAUSE)); - val16 = rge_mii_get16(rgep, PHY_ANAR_REG); - rge_mii_put16(rgep, PHY_ANAR_REG, (val16 & 0x0fff) | 0xf000); + rge_mii_put16(rgep, PHY_ANAR_REG, 0xb800); + rge_mii_put16(rgep, PHY_ANAR_REG, 0xb000); + rge_mii_put16(rgep, PHY_ANAR_REG, 0xf000); rge_mii_put16(rgep, PHY_ID_REG_2, 0xdf01); rge_mii_put16(rgep, PHY_ID_REG_1, 0xdf20); rge_mii_put16(rgep, PHY_BMSR_REG, 0xff95); rge_mii_put16(rgep, PHY_BMCR_REG, 0xbf00); - val16 = rge_mii_get16(rgep, PHY_ANAR_REG); - rge_mii_put16(rgep, PHY_ANAR_REG, val16 | ANAR_ASY_PAUSE); - val16 = rge_mii_get16(rgep, PHY_ANAR_REG); - rge_mii_put16(rgep, PHY_ANAR_REG, val16 & (~ANAR_ASY_PAUSE)); + rge_mii_put16(rgep, PHY_ANAR_REG, 0xf800); + rge_mii_put16(rgep, PHY_ANAR_REG, 0xf000); + rge_mii_put16(rgep, PHY_ANAR_REG, 0x0000); rge_mii_put16(rgep, PHY_1F_REG, 0x0000); rge_mii_put16(rgep, PHY_0B_REG, 0x0000); - } + break; - if (rgep->chipid.mac_ver == MAC_VER_SB) { + case MAC_VER_8169SB: rge_mii_put16(rgep, PHY_1F_REG, 0x0001); - rge_mii_put16(rgep, PHY_1B_REG, 0x841e); - rge_mii_put16(rgep, PHY_0E_REG, 0x7bfb); + rge_mii_put16(rgep, PHY_1B_REG, 0xD41E); + rge_mii_put16(rgep, PHY_0E_REG, 0x7bff); rge_mii_put16(rgep, PHY_GBCR_REG, GBCR_DEFAULT); rge_mii_put16(rgep, PHY_1F_REG, 0x0002); rge_mii_put16(rgep, PHY_BMSR_REG, 0x90D0); rge_mii_put16(rgep, PHY_1F_REG, 0x0000); + break; + + case MAC_VER_8168: + rge_mii_put16(rgep, PHY_1F_REG, 0x0001); + rge_mii_put16(rgep, PHY_ANER_REG, 0x00aa); + rge_mii_put16(rgep, PHY_ANNPTR_REG, 0x3173); + rge_mii_put16(rgep, PHY_ANNPRR_REG, 0x08fc); + rge_mii_put16(rgep, PHY_GBCR_REG, 0xe2d0); + rge_mii_put16(rgep, PHY_0B_REG, 0x941a); + rge_mii_put16(rgep, PHY_18_REG, 0x65fe); + rge_mii_put16(rgep, PHY_1C_REG, 0x1e02); + rge_mii_put16(rgep, PHY_1F_REG, 0x0002); + rge_mii_put16(rgep, PHY_ANNPTR_REG, 0x103e); + rge_mii_put16(rgep, PHY_1F_REG, 0x0000); + break; + + case MAC_VER_8168B_B: + case MAC_VER_8168B_C: + rge_mii_put16(rgep, PHY_1F_REG, 0x0001); + rge_mii_put16(rgep, PHY_0B_REG, 0x94b0); + rge_mii_put16(rgep, PHY_1B_REG, 0xc416); + rge_mii_put16(rgep, PHY_1F_REG, 0x0003); + rge_mii_put16(rgep, PHY_12_REG, 0x6096); + rge_mii_put16(rgep, PHY_1F_REG, 0x0000); + break; } } @@ -715,15 +752,60 @@ rge_chip_ident(rge_t *rgep) uint32_t val32; uint16_t val16; + /* + * Read and record MAC version + */ val32 = rge_reg_get32(rgep, TX_CONFIG_REG); val32 &= HW_VERSION_ID_0 | HW_VERSION_ID_1; chip->mac_ver = val32; + switch (chip->mac_ver) { + case MAC_VER_8168: + case MAC_VER_8168B_B: + case MAC_VER_8168B_C: + chip->is_pcie = B_TRUE; + break; + + default: + chip->is_pcie = B_FALSE; + break; + } + /* + * Read and record PHY version + */ val16 = rge_mii_get16(rgep, PHY_ID_REG_2); val16 &= PHY_VER_MASK; chip->phy_ver = val16; - if (rgep->param_default_mtu > ETHERMTU) { + /* set pci latency timer */ + if (chip->mac_ver == MAC_VER_8169 || + chip->mac_ver == MAC_VER_8169S_D) + pci_config_put8(rgep->cfg_handle, PCI_CONF_LATENCY_TIMER, 0x40); + + /* + * PCIE chipset require the Rx buffer start address must be + * 8-byte alignment and the Rx buffer size must be multiple of 8. + * We'll just use bcopy in receive procedure for the PCIE chipset. + */ + if (chip->is_pcie) { + rgep->chip_flags |= CHIP_FLAG_FORCE_BCOPY; + if (rgep->default_mtu > ETHERMTU) { + rge_notice(rgep, "Jumbo packets not supported " + "for this PCIE chipset"); + rgep->default_mtu = ETHERMTU; + } + } + if (rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY) + rgep->head_room = 0; + else + rgep->head_room = RGE_HEADROOM; + + /* + * Initialize other variables. + */ + if (rgep->default_mtu < ETHERMTU || rgep->default_mtu > RGE_JUMBO_MTU) + rgep->default_mtu = ETHERMTU; + if (rgep->default_mtu > ETHERMTU) { rgep->rxbuf_size = RGE_BUFF_SIZE_JUMBO; rgep->txbuf_size = RGE_BUFF_SIZE_JUMBO; rgep->ethmax_size = RGE_JUMBO_SIZE; @@ -732,16 +814,11 @@ rge_chip_ident(rge_t *rgep) rgep->txbuf_size = RGE_BUFF_SIZE_STD; rgep->ethmax_size = ETHERMAX; } - chip->rxconfig = RX_CONFIG_DEFAULT; chip->txconfig = TX_CONFIG_DEFAULT; RGE_TRACE(("%s: MAC version = %x, PHY version = %x", rgep->ifname, chip->mac_ver, chip->phy_ver)); - - /* set pci latency timer */ - if (chip->mac_ver == MAC_VER_NS || chip->mac_ver == MAC_VER_SD) - pci_config_put8(rgep->cfg_handle, PCI_CONF_LATENCY_TIMER, 0x40); } /* @@ -810,8 +887,8 @@ rge_chip_reset(rge_t *rgep) /* * Disable interrupt */ - rge_reg_clr16(rgep, INT_MASK_REG, INT_MASK_ALL); rgep->int_mask = INT_MASK_NONE; + rge_reg_put16(rgep, INT_MASK_REG, rgep->int_mask); /* * Clear pended interrupt @@ -845,6 +922,31 @@ void rge_chip_init(rge_t *rgep) { uint32_t val32; + uint32_t val16; + uint32_t *hashp; + chip_id_t *chip = &rgep->chipid; + + if (chip->is_pcie) { + /* + * Increase the threshold voltage of RX sensitivity + */ + if (chip->mac_ver != MAC_VER_8168) + rge_ephy_put16(rgep, 0x01, 0x1bd3); + + val16 = rge_reg_get8(rgep, PHY_STATUS_REG); + val16 = 0x12<<8 | val16; + rge_reg_put16(rgep, PHY_STATUS_REG, val16); + rge_reg_put32(rgep, RT_CSI_DATA_REG, 0x00021c01); + rge_reg_put32(rgep, RT_CSI_ACCESS_REG, 0x8000f088); + rge_reg_put32(rgep, RT_CSI_DATA_REG, 0x00004000); + rge_reg_put32(rgep, RT_CSI_ACCESS_REG, 0x8000f0b0); + rge_reg_put32(rgep, RT_CSI_ACCESS_REG, 0x0000f068); + val32 = rge_reg_get32(rgep, RT_CSI_DATA_REG); + val32 |= 0x7000; + val32 &= 0xffff5fff; + rge_reg_put32(rgep, RT_CSI_DATA_REG, val32); + rge_reg_put32(rgep, RT_CSI_ACCESS_REG, 0x8000f068); + } /* * Config MII register @@ -857,23 +959,20 @@ rge_chip_init(rge_t *rgep) * Then for vlan support, we must enable receive vlan de-tagging. * Otherwise, there'll be checksum error. */ - rge_reg_set16(rgep, CPLUS_COMMAND_REG, RX_CKSM_OFFLOAD | RX_VLAN_DETAG); - - /* - * Suggested setting from Realtek - */ - if (rgep->chipid.mac_ver == MAC_VER_SD) { - rge_reg_set16(rgep, CPLUS_COMMAND_REG, - CPLUS_BIT14 | MUL_PCI_RW_ENABLE); + val16 = rge_reg_get16(rgep, CPLUS_COMMAND_REG); + val16 |= RX_CKSM_OFFLOAD | RX_VLAN_DETAG; + if (chip->mac_ver == MAC_VER_8169S_D) { + val16 |= CPLUS_BIT14 | MUL_PCI_RW_ENABLE; rge_reg_put8(rgep, RESV_82_REG, 0x01); } - rge_reg_clr16(rgep, CPLUS_COMMAND_REG, 0x03); + rge_reg_put16(rgep, CPLUS_COMMAND_REG, val16 & (~0x03)); /* * Start transmit/receive before set tx/rx configuration register */ - rge_reg_set8(rgep, RT_COMMAND_REG, - RT_COMMAND_RX_ENABLE | RT_COMMAND_TX_ENABLE); + if (!chip->is_pcie) + rge_reg_set8(rgep, RT_COMMAND_REG, + RT_COMMAND_RX_ENABLE | RT_COMMAND_TX_ENABLE); /* * Set dump tally counter register @@ -893,7 +992,7 @@ rge_chip_init(rge_t *rgep) /* * Set Tx/Rx maximum packet size */ - if (rgep->param_default_mtu > ETHERMTU) { + if (rgep->default_mtu > ETHERMTU) { rge_reg_put8(rgep, TX_MAX_PKTSIZE_REG, TX_PKTSIZE_JUMBO); rge_reg_put16(rgep, RX_MAX_PKTSIZE_REG, RX_PKTSIZE_JUMBO); } else { @@ -908,19 +1007,14 @@ rge_chip_init(rge_t *rgep) val32 &= RX_CONFIG_REG_RESV; if (rgep->promisc) val32 |= RX_ACCEPT_ALL_PKT; - rge_reg_put32(rgep, RX_CONFIG_REG, val32 | rgep->chipid.rxconfig); + rge_reg_put32(rgep, RX_CONFIG_REG, val32 | chip->rxconfig); /* * Set transmit configuration register */ val32 = rge_reg_get32(rgep, TX_CONFIG_REG); val32 &= TX_CONFIG_REG_RESV; - rge_reg_put32(rgep, TX_CONFIG_REG, val32 | rgep->chipid.txconfig); - - /* - * Initialize PHY registers - */ - rge_phy_init(rgep); + rge_reg_put32(rgep, TX_CONFIG_REG, val32 | chip->txconfig); /* * Set Tx/Rx descriptor register @@ -950,14 +1044,9 @@ rge_chip_init(rge_t *rgep) /* * Set multicast register */ - rge_reg_put32(rgep, MULTICAST_0_REG, rgep->mcast_hash[0]); - rge_reg_put32(rgep, MULTICAST_4_REG, rgep->mcast_hash[1]); - - /* - * Mask and clear all Interrupt - */ - rge_reg_put16(rgep, INT_MASK_REG, INT_MASK_NONE); - rge_reg_put16(rgep, INT_STATUS_REG, INT_MASK_ALL); + hashp = (uint32_t *)rgep->mcast_hash; + rge_reg_put32(rgep, MULTICAST_0_REG, hashp[0]); + rge_reg_put32(rgep, MULTICAST_4_REG, hashp[1]); /* * Msic register setting: @@ -995,8 +1084,8 @@ rge_chip_start(rge_t *rgep) /* * Enable interrupt */ - rge_reg_set16(rgep, INT_MASK_REG, RGE_INT_MASK); rgep->int_mask = RGE_INT_MASK; + rge_reg_put16(rgep, INT_MASK_REG, rgep->int_mask); /* * All done! @@ -1016,8 +1105,8 @@ rge_chip_stop(rge_t *rgep, boolean_t fault) /* * Disable interrupt */ - rge_reg_put16(rgep, INT_MASK_REG, INT_MASK_NONE); rgep->int_mask = INT_MASK_NONE; + rge_reg_put16(rgep, INT_MASK_REG, rgep->int_mask); /* * Clear pended interrupt @@ -1126,9 +1215,9 @@ rge_set_multi_addr(rge_t *rgep) { uint32_t *hashp; - hashp = rgep->mcast_hash; - rge_reg_put32(rgep, MULTICAST_0_REG, hashp[0]); - rge_reg_put32(rgep, MULTICAST_4_REG, hashp[1]); + hashp = (uint32_t *)rgep->mcast_hash; + rge_reg_put32(rgep, MULTICAST_0_REG, RGE_BSWAP_32(hashp[0])); + rge_reg_put32(rgep, MULTICAST_4_REG, RGE_BSWAP_32(hashp[1])); rge_reg_set8(rgep, RT_COMMAND_REG, RT_COMMAND_RX_ENABLE | RT_COMMAND_TX_ENABLE); } @@ -1237,24 +1326,25 @@ rge_wake_factotum(rge_t *rgep) { if (rgep->factotum_flag == 0) { rgep->factotum_flag = 1; - ddi_trigger_softintr(rgep->factotum_id); + (void) ddi_intr_trigger_softint(rgep->factotum_hdl, NULL); } } /* * rge_intr() -- handle chip interrupts */ -uint_t rge_intr(caddr_t arg); +uint_t rge_intr(caddr_t arg1, caddr_t arg2); #pragma no_inline(rge_intr) uint_t -rge_intr(caddr_t arg) +rge_intr(caddr_t arg1, caddr_t arg2) { - rge_t *rgep = (rge_t *)arg; + rge_t *rgep = (rge_t *)arg1; uint16_t int_status; - mutex_enter(rgep->genlock); + _NOTE(ARGUNUSED(arg2)) + mutex_enter(rgep->genlock); /* * Was this interrupt caused by our device... */ @@ -1264,12 +1354,14 @@ rge_intr(caddr_t arg) return (DDI_INTR_UNCLAIMED); /* indicate it wasn't our interrupt */ } - rgep->stats.intr++; /* * Clear interrupt + * For PCIE chipset, we need disable interrupt first. */ + if (rgep->chipid.is_pcie) + rge_reg_put16(rgep, INT_MASK_REG, INT_MASK_NONE); rge_reg_put16(rgep, INT_STATUS_REG, int_status); /* @@ -1278,16 +1370,21 @@ rge_intr(caddr_t arg) if (int_status & LINK_CHANGE_INT) { rge_chip_cyclic(rgep); } + mutex_exit(rgep->genlock); /* * Receive interrupt */ - if (int_status & RGE_RX_OVERFLOW_INT) - rgep->stats.overflow++; - if (rgep->rge_chip_state == RGE_CHIP_RUNNING) + if (int_status & RGE_RX_INT) rge_receive(rgep); + /* + * Re-enable interrupt for PCIE chipset + */ + if (rgep->chipid.is_pcie) + rge_reg_put16(rgep, INT_MASK_REG, rgep->int_mask); + return (DDI_INTR_CLAIMED); /* indicate it was our interrupt */ } @@ -1387,6 +1484,8 @@ rge_factotum_stall_check(rge_t *rgep) * All of which should ensure that we don't get into a state * where packets are left pending indefinitely! */ + if (rgep->resched_needed) + (void) ddi_intr_trigger_softint(rgep->resched_hdl, NULL); dogval = rge_atomic_shl32(&rgep->watchdog, 1); if (dogval < rge_watchdog_count) return (B_FALSE); @@ -1403,18 +1502,19 @@ rge_factotum_stall_check(rge_t *rgep) * reset & restart the chip after an error * check the link status whenever necessary */ -uint_t rge_chip_factotum(caddr_t arg); +uint_t rge_chip_factotum(caddr_t arg1, caddr_t arg2); #pragma no_inline(rge_chip_factotum) uint_t -rge_chip_factotum(caddr_t arg) +rge_chip_factotum(caddr_t arg1, caddr_t arg2) { rge_t *rgep; uint_t result; boolean_t error; boolean_t linkchg; - rgep = (rge_t *)arg; + rgep = (rge_t *)arg1; + _NOTE(ARGUNUSED(arg2)) if (rgep->factotum_flag == 0) return (DDI_INTR_UNCLAIMED); @@ -1851,15 +1951,9 @@ rge_pp_ioctl(rge_t *rgep, int cmd, mblk_t *mp, struct iocblk *iocp) case RGE_PP_SPACE_TXDESC: areap = &rgep->dma_area_txdesc; break; - case RGE_PP_SPACE_TXBUFF: - areap = &rgep->dma_area_txbuf[0]; - break; case RGE_PP_SPACE_RXDESC: areap = &rgep->dma_area_rxdesc; break; - case RGE_PP_SPACE_RXBUFF: - areap = &rgep->dma_area_rxbuf[0]; - break; case RGE_PP_SPACE_STATISTICS: areap = &rgep->dma_area_stats; break; diff --git a/usr/src/uts/common/io/rge/rge_hw.h b/usr/src/uts/common/io/rge/rge_hw.h index 39d2b461a1..08f77b023a 100755 --- a/usr/src/uts/common/io/rge/rge_hw.h +++ b/usr/src/uts/common/io/rge/rge_hw.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -47,6 +46,8 @@ extern "C" { #define VENDOR_ID_REALTECK 0x10EC #define DEVICE_ID_8169 0x8169 #define DEVICE_ID_8110 0x8110 +#define DEVICE_ID_8168 0x8168 +#define DEVICE_ID_8111 0x8111 #define RGE_REGISTER_MAX 0x0100 @@ -77,6 +78,7 @@ extern "C" { #define MULTICAST_5_REG 0x000d #define MULTICAST_6_REG 0x000e #define MULTICAST_7_REG 0x000f +#define RGE_MCAST_NUM 8 /* total 8 registers: MAR0 - MAR7 */ /* * Dump Tally Counter Command register @@ -131,9 +133,8 @@ extern "C" { #define INT_REG_RESV 0x3e00 #define INT_MASK_ALL 0xffff #define INT_MASK_NONE 0x0000 -#define RGE_RX_OVERFLOW_INT (NO_RXDESC_INT | RX_FIFO_OVERFLOW_INT) #define RGE_RX_INT (RX_OK_INT | RX_ERR_INT | \ - RGE_RX_OVERFLOW_INT) + NO_RXDESC_INT) #define RGE_INT_MASK (RGE_RX_INT | LINK_CHANGE_INT) /* @@ -158,10 +159,13 @@ extern "C" { #define TX_DMA_BURST_32B 0x00000100 #define TX_DMA_BURST_16B 0x00000000 -#define MAC_VER_NS 0x00000000 -#define MAC_VER_SD 0x00800000 -#define MAC_VER_SE 0x04000000 -#define MAC_VER_SB 0x10000000 +#define MAC_VER_8169 0x00000000 +#define MAC_VER_8169S_D 0x00800000 +#define MAC_VER_8169S_E 0x04000000 +#define MAC_VER_8169SB 0x10000000 +#define MAC_VER_8168 0x20000000 +#define MAC_VER_8168B_B 0x30000000 +#define MAC_VER_8168B_C 0x38000000 #define TX_CONFIG_DEFAULT (TX_INTERFRAME_GAP_802_3 | \ TX_DMA_BURST_1024B) @@ -253,6 +257,16 @@ extern "C" { #define PHY_REG_SHIFT 16 /* + * CSI data register (for PCIE chipset) + */ +#define RT_CSI_DATA_REG 0x0064 + +/* + * CSI access register (for PCIE chipset) + */ +#define RT_CSI_ACCESS_REG 0x0068 + +/* * PHY status register */ #define PHY_STATUS_REG 0x006c @@ -271,6 +285,17 @@ extern "C" { #define RGE_SPEED_UNKNOWN 0 /* + * EPHY access register (for PCIE chipset) + */ +#define EPHY_ACCESS_REG 0x0080 +#define EPHY_ACCESS_WR_FLAG 0x80000000 +#define EPHY_ACCESS_REG_BITS 0x001f0000 +#define EPHY_ACCESS_DATA_BITS 0x0000ffff +#define EPHY_DATA_MASK 0xffff +#define EPHY_REG_MASK 0x1f +#define EPHY_REG_SHIFT 16 + +/* * Receive packet maximum size register * -- the maximum rx size supported is (16K - 1) bytes */ @@ -415,11 +440,13 @@ extern "C" { #define PHY_GBESR_REG 0x0f #define PHY_1F_REG 0x1f +#define PHY_1C_REG 0x1c #define PHY_1B_REG 0x1b -#define PHY_15_REG 0x15 #define PHY_18_REG 0x18 -#define PHY_0B_REG 0x0b +#define PHY_15_REG 0x15 +#define PHY_12_REG 0x12 #define PHY_0E_REG 0x0e +#define PHY_0B_REG 0x0b /* * MII (PHY) registers, beyond those already defined in <sys/miiregs.h> @@ -519,6 +546,7 @@ extern "C" { #define RGE_BUFF_SIZE_STD 1536 /* 1536 bytes */ #define RGE_BUFF_SIZE_JUMBO 7168 /* maximum 7K */ #define RGE_JUMBO_SIZE 7014 +#define RGE_JUMBO_MTU 7000 #define RGE_STATS_DUMP_SIZE 64 typedef struct rge_bd { diff --git a/usr/src/uts/common/io/rge/rge_main.c b/usr/src/uts/common/io/rge/rge_main.c index 329f54fb61..4faa3a4389 100755 --- a/usr/src/uts/common/io/rge/rge_main.c +++ b/usr/src/uts/common/io/rge/rge_main.c @@ -31,7 +31,7 @@ * This is the string displayed by modinfo, etc. * Make sure you keep the version ID up to date! */ -static char rge_ident[] = "Realtek Gigabit Ethernet Driver v%I%"; +static char rge_ident[] = "Realtek 1Gb Ethernet v%I%"; /* * Used for buffers allocated by ddi_dma_mem_alloc() @@ -102,7 +102,9 @@ static ddi_device_acc_attr_t rge_buf_accattr = { /* * Property names */ -static char debug_propname[] = "rge-debug-flags"; +static char debug_propname[] = "rge_debug_flags"; +static char mtu_propname[] = "default_mtu"; +static char msi_propname[] = "msi_enable"; static int rge_m_start(void *); static void rge_m_stop(void *); @@ -234,16 +236,11 @@ rge_slice_chunk(dma_area_t *slice, dma_area_t *chunk, chunk->cookie.dmac_size -= totsize; } - static int rge_alloc_bufs(rge_t *rgep) { size_t txdescsize; size_t rxdescsize; - size_t txbuffsize; - size_t rxbuffsize; - size_t freebuffsize; - int split; int err; /* @@ -285,54 +282,6 @@ rge_alloc_bufs(rge_t *rgep) if (err != DDI_SUCCESS) return (DDI_FAILURE); - /* - * Allocate memory & handle for Tx buffers - */ - txbuffsize = RGE_SEND_SLOTS * rgep->txbuf_size; - ASSERT((txbuffsize % RGE_SPLIT) == 0); - for (split = 0; split < RGE_SPLIT; ++split) { - err = rge_alloc_dma_mem(rgep, - txbuffsize/RGE_SPLIT, - &dma_attr_buf, - &rge_buf_accattr, - DDI_DMA_WRITE | DDI_DMA_STREAMING, - &rgep->dma_area_txbuf[split]); - if (err != DDI_SUCCESS) - return (DDI_FAILURE); - } - - /* - * Allocate memory & handle for Rx buffers - */ - rxbuffsize = RGE_RECV_SLOTS * rgep->rxbuf_size; - ASSERT((rxbuffsize % RGE_SPLIT) == 0); - for (split = 0; split < RGE_SPLIT; ++split) { - err = rge_alloc_dma_mem(rgep, - rxbuffsize/RGE_SPLIT, - &dma_attr_buf, - &rge_buf_accattr, - DDI_DMA_READ | DDI_DMA_STREAMING, - &rgep->dma_area_rxbuf[split]); - if (err != DDI_SUCCESS) - return (DDI_FAILURE); - } - - /* - * Allocate memory & handle for free Rx buffers - */ - freebuffsize = RGE_BUF_SLOTS * rgep->rxbuf_size; - ASSERT((freebuffsize % RGE_SPLIT) == 0); - for (split = 0; split < RGE_SPLIT; ++split) { - err = rge_alloc_dma_mem(rgep, - freebuffsize/RGE_SPLIT, - &dma_attr_buf, - &rge_buf_accattr, - DDI_DMA_READ | DDI_DMA_STREAMING, - &rgep->dma_area_freebuf[split]); - if (err != DDI_SUCCESS) - return (DDI_FAILURE); - } - return (DDI_SUCCESS); } @@ -343,16 +292,9 @@ rge_alloc_bufs(rge_t *rgep) static void rge_free_bufs(rge_t *rgep) { - int i; - rge_free_dma_mem(&rgep->dma_area_stats); rge_free_dma_mem(&rgep->dma_area_txdesc); rge_free_dma_mem(&rgep->dma_area_rxdesc); - for (i = 0; i < RGE_SPLIT; i++) { - rge_free_dma_mem(&rgep->dma_area_txbuf[i]); - rge_free_dma_mem(&rgep->dma_area_rxbuf[i]); - rge_free_dma_mem(&rgep->dma_area_freebuf[i]); - } } /* @@ -413,11 +355,11 @@ rge_reinit_recv_ring(rge_t *rgep) for (slot = 0; slot < RGE_RECV_SLOTS; slot++) { pbuf = &srbdp->rx_buf->pbuf; bdp->host_buf_addr = - RGE_BSWAP_32(pbuf->cookie.dmac_laddress + RGE_HEADROOM); + RGE_BSWAP_32(pbuf->cookie.dmac_laddress + rgep->head_room); bdp->host_buf_addr_hi = RGE_BSWAP_32(pbuf->cookie.dmac_laddress >> 32); bdp->flags_len = RGE_BSWAP_32(BD_FLAG_HW_OWN | - (rgep->rxbuf_size - RGE_HEADROOM)); + (rgep->rxbuf_size - rgep->head_room)); /* last BD in Tx ring */ if (slot == (RGE_RECV_SLOTS - 1)) bdp->flags_len |= RGE_BSWAP_32(BD_FLAG_EOR); @@ -432,11 +374,14 @@ rge_reinit_recv_ring(rge_t *rgep) static void rge_reinit_buf_ring(rge_t *rgep) { + + if (rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY) + return; + /* - * re-init free buffer ring + * If all the up-sending buffers haven't been returned to driver, + * use bcopy() only in rx process. */ - rgep->rc_next = 0; - rgep->rf_next = 0; if (rgep->rx_free != RGE_BUF_SLOTS) rgep->rx_bcopy = B_TRUE; } @@ -450,14 +395,88 @@ rge_reinit_rings(rge_t *rgep) } static void +rge_fini_send_ring(rge_t *rgep) +{ + sw_sbd_t *ssbdp; + uint32_t slot; + + ssbdp = rgep->sw_sbds; + for (slot = 0; slot < RGE_SEND_SLOTS; ++slot) { + rge_free_dma_mem(&ssbdp->pbuf); + ssbdp++; + } + + kmem_free(rgep->sw_sbds, RGE_SEND_SLOTS * sizeof (sw_sbd_t)); + rgep->sw_sbds = NULL; +} + +static void +rge_fini_recv_ring(rge_t *rgep) +{ + sw_rbd_t *srbdp; + uint32_t slot; + + srbdp = rgep->sw_rbds; + for (slot = 0; slot < RGE_RECV_SLOTS; ++srbdp, ++slot) { + if (srbdp->rx_buf) { + if (srbdp->rx_buf->mp != NULL) { + freemsg(srbdp->rx_buf->mp); + srbdp->rx_buf->mp = NULL; + } + rge_free_dma_mem(&srbdp->rx_buf->pbuf); + kmem_free(srbdp->rx_buf, sizeof (dma_buf_t)); + srbdp->rx_buf = NULL; + } + } + + kmem_free(rgep->sw_rbds, RGE_RECV_SLOTS * sizeof (sw_rbd_t)); + rgep->sw_rbds = NULL; +} + +static void +rge_fini_buf_ring(rge_t *rgep) +{ + sw_rbd_t *srbdp; + uint32_t slot; + + if (rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY) + return; + + ASSERT(rgep->rx_free == RGE_BUF_SLOTS); + + srbdp = rgep->free_srbds; + for (slot = 0; slot < RGE_BUF_SLOTS; ++srbdp, ++slot) { + if (srbdp->rx_buf != NULL) { + if (srbdp->rx_buf->mp != NULL) { + freemsg(srbdp->rx_buf->mp); + srbdp->rx_buf->mp = NULL; + } + rge_free_dma_mem(&srbdp->rx_buf->pbuf); + kmem_free(srbdp->rx_buf, sizeof (dma_buf_t)); + srbdp->rx_buf = NULL; + } + } + + kmem_free(rgep->free_srbds, RGE_BUF_SLOTS * sizeof (sw_rbd_t)); + rgep->free_srbds = NULL; +} + +static void +rge_fini_rings(rge_t *rgep) +{ + rge_fini_send_ring(rgep); + rge_fini_recv_ring(rgep); + rge_fini_buf_ring(rgep); +} + +static int rge_init_send_ring(rge_t *rgep) { uint32_t slot; - uint32_t split; - rge_bd_t *bdp; sw_sbd_t *ssbdp; - dma_area_t buf_chunk; dma_area_t *pbuf; + dma_area_t desc; + int err; /* * Allocate the array of s/w Tx Buffer Descriptors @@ -468,55 +487,49 @@ rge_init_send_ring(rge_t *rgep) /* * Init send ring */ - rgep->tx_next = 0; - rgep->tc_next = 0; - rgep->tc_tail = 0; - rgep->tx_flow = 0; - rgep->tx_free = RGE_SEND_SLOTS; rgep->tx_desc = rgep->dma_area_txdesc; DMA_ZERO(rgep->tx_desc); - bdp = rgep->tx_desc.mem_va; - rgep->tx_ring = bdp; - for (split = 0; split < RGE_SPLIT; split++) { - buf_chunk = rgep->dma_area_txbuf[split]; - for (slot = 0; slot < RGE_SEND_SLOTS/RGE_SPLIT; slot++) { - rge_slice_chunk(&ssbdp->desc, &rgep->dma_area_txdesc, - 1, sizeof (rge_bd_t)); - pbuf = &ssbdp->pbuf; - rge_slice_chunk(pbuf, &buf_chunk, 1, rgep->txbuf_size); - bdp->host_buf_addr = - RGE_BSWAP_32(pbuf->cookie.dmac_laddress); - bdp->host_buf_addr_hi = - RGE_BSWAP_32(pbuf->cookie.dmac_laddress >> 32); - /* last BD in Tx ring */ - if (split == (RGE_SPLIT - 1) && - slot == (RGE_SEND_SLOTS/RGE_SPLIT -1)) - bdp->flags_len |= RGE_BSWAP_32(BD_FLAG_EOR); - ssbdp++; - bdp++; + rgep->tx_ring = rgep->tx_desc.mem_va; + + desc = rgep->tx_desc; + for (slot = 0; slot < RGE_SEND_SLOTS; slot++) { + rge_slice_chunk(&ssbdp->desc, &desc, 1, sizeof (rge_bd_t)); + + /* + * Allocate memory & handle for Tx buffers + */ + pbuf = &ssbdp->pbuf; + err = rge_alloc_dma_mem(rgep, rgep->txbuf_size, + &dma_attr_buf, &rge_buf_accattr, + DDI_DMA_WRITE | DDI_DMA_STREAMING, pbuf); + if (err != DDI_SUCCESS) { + rge_error(rgep, + "rge_init_send_ring: alloc tx buffer failed"); + rge_fini_send_ring(rgep); + return (DDI_FAILURE); } + ssbdp++; } + ASSERT(desc.alength == 0); + DMA_SYNC(rgep->tx_desc, DDI_DMA_SYNC_FORDEV); + return (DDI_SUCCESS); } static int rge_init_recv_ring(rge_t *rgep) { uint32_t slot; - uint32_t split; - rge_bd_t *bdp; sw_rbd_t *srbdp; dma_buf_t *rx_buf; - dma_area_t buf_chunk; dma_area_t *pbuf; + int err; /* * Allocate the array of s/w Rx Buffer Descriptors */ srbdp = kmem_zalloc(RGE_RECV_SLOTS*sizeof (*srbdp), KM_SLEEP); - rx_buf = kmem_zalloc(RGE_RECV_SLOTS*sizeof (*rx_buf), KM_SLEEP); rgep->sw_rbds = srbdp; - rgep->sw_rbuf = rx_buf; /* * Init receive ring @@ -524,41 +537,42 @@ rge_init_recv_ring(rge_t *rgep) rgep->rx_next = 0; rgep->rx_desc = rgep->dma_area_rxdesc; DMA_ZERO(rgep->rx_desc); - bdp = rgep->rx_desc.mem_va; - rgep->rx_ring = bdp; - for (split = 0; split < RGE_SPLIT; split++) { - buf_chunk = rgep->dma_area_rxbuf[split]; - for (slot = 0; slot < RGE_RECV_SLOTS/RGE_SPLIT; slot++) { - srbdp->rx_buf = rx_buf; - pbuf = &rx_buf->pbuf; - rge_slice_chunk(pbuf, &buf_chunk, 1, rgep->rxbuf_size); - pbuf->alength -= RGE_HEADROOM; - pbuf->offset += RGE_HEADROOM; + rgep->rx_ring = rgep->rx_desc.mem_va; + + for (slot = 0; slot < RGE_RECV_SLOTS; slot++) { + srbdp->rx_buf = rx_buf = + kmem_zalloc(sizeof (dma_buf_t), KM_SLEEP); + + /* + * Allocate memory & handle for Rx buffers + */ + pbuf = &rx_buf->pbuf; + err = rge_alloc_dma_mem(rgep, rgep->rxbuf_size, + &dma_attr_buf, &rge_buf_accattr, + DDI_DMA_READ | DDI_DMA_STREAMING, pbuf); + if (err != DDI_SUCCESS) { + rge_fini_recv_ring(rgep); + rge_error(rgep, + "rge_init_recv_ring: alloc rx buffer failed"); + return (DDI_FAILURE); + } + + pbuf->alength -= rgep->head_room; + pbuf->offset += rgep->head_room; + if (!(rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY)) { rx_buf->rx_recycle.free_func = rge_rx_recycle; rx_buf->rx_recycle.free_arg = (caddr_t)rx_buf; rx_buf->private = (caddr_t)rgep; rx_buf->mp = desballoc(DMA_VPTR(rx_buf->pbuf), rgep->rxbuf_size, 0, &rx_buf->rx_recycle); if (rx_buf->mp == NULL) { + rge_fini_recv_ring(rgep); rge_problem(rgep, "rge_init_recv_ring: desballoc() failed"); return (DDI_FAILURE); } - - bdp->host_buf_addr = RGE_BSWAP_32(RGE_HEADROOM + - pbuf->cookie.dmac_laddress); - bdp->host_buf_addr_hi = - RGE_BSWAP_32(pbuf->cookie.dmac_laddress >> 32); - bdp->flags_len = RGE_BSWAP_32(BD_FLAG_HW_OWN | - (rgep->rxbuf_size - RGE_HEADROOM)); - /* last BD in Rx ring */ - if (split == (RGE_SPLIT - 1) && - slot == (RGE_RECV_SLOTS/RGE_SPLIT -1)) - bdp->flags_len |= RGE_BSWAP_32(BD_FLAG_EOR); - srbdp++; - bdp++; - rx_buf++; } + srbdp++; } DMA_SYNC(rgep->rx_desc, DDI_DMA_SYNC_FORDEV); return (DDI_SUCCESS); @@ -568,19 +582,21 @@ static int rge_init_buf_ring(rge_t *rgep) { uint32_t slot; - uint32_t split; - sw_rbd_t *free_rbdp; + sw_rbd_t *free_srbdp; dma_buf_t *rx_buf; - dma_area_t buf_chunk; dma_area_t *pbuf; + int err; + + if (rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY) { + rgep->rx_bcopy = B_TRUE; + return (DDI_SUCCESS); + } /* * Allocate the array of s/w free Buffer Descriptors */ - free_rbdp = kmem_zalloc(RGE_BUF_SLOTS*sizeof (*free_rbdp), KM_SLEEP); - rx_buf = kmem_zalloc(RGE_BUF_SLOTS*sizeof (*rx_buf), KM_SLEEP); - rgep->free_rbds = free_rbdp; - rgep->sw_freebuf = rx_buf; + free_srbdp = kmem_zalloc(RGE_BUF_SLOTS*sizeof (*free_srbdp), KM_SLEEP); + rgep->free_srbds = free_srbdp; /* * Init free buffer ring @@ -589,27 +605,37 @@ rge_init_buf_ring(rge_t *rgep) rgep->rf_next = 0; rgep->rx_bcopy = B_FALSE; rgep->rx_free = RGE_BUF_SLOTS; - for (split = 0; split < RGE_SPLIT; split++) { - buf_chunk = rgep->dma_area_freebuf[split]; - for (slot = 0; slot < RGE_BUF_SLOTS/RGE_SPLIT; slot++) { - free_rbdp->rx_buf = rx_buf; - pbuf = &rx_buf->pbuf; - rge_slice_chunk(pbuf, &buf_chunk, 1, rgep->rxbuf_size); - pbuf->alength -= RGE_HEADROOM; - pbuf->offset += RGE_HEADROOM; - rx_buf->rx_recycle.free_func = rge_rx_recycle; - rx_buf->rx_recycle.free_arg = (caddr_t)rx_buf; - rx_buf->private = (caddr_t)rgep; - rx_buf->mp = desballoc(DMA_VPTR(rx_buf->pbuf), - rgep->rxbuf_size, 0, &rx_buf->rx_recycle); - if (rx_buf->mp == NULL) { - rge_problem(rgep, - "rge_init_buf_ring: desballoc() failed"); - return (DDI_FAILURE); - } - free_rbdp++; - rx_buf++; + for (slot = 0; slot < RGE_BUF_SLOTS; slot++) { + free_srbdp->rx_buf = rx_buf = + kmem_zalloc(sizeof (dma_buf_t), KM_SLEEP); + + /* + * Allocate memory & handle for free Rx buffers + */ + pbuf = &rx_buf->pbuf; + err = rge_alloc_dma_mem(rgep, rgep->rxbuf_size, + &dma_attr_buf, &rge_buf_accattr, + DDI_DMA_READ | DDI_DMA_STREAMING, pbuf); + if (err != DDI_SUCCESS) { + rge_fini_buf_ring(rgep); + rge_error(rgep, + "rge_init_buf_ring: alloc rx free buffer failed"); + return (DDI_FAILURE); + } + pbuf->alength -= rgep->head_room; + pbuf->offset += rgep->head_room; + rx_buf->rx_recycle.free_func = rge_rx_recycle; + rx_buf->rx_recycle.free_arg = (caddr_t)rx_buf; + rx_buf->private = (caddr_t)rgep; + rx_buf->mp = desballoc(DMA_VPTR(rx_buf->pbuf), + rgep->rxbuf_size, 0, &rx_buf->rx_recycle); + if (rx_buf->mp == NULL) { + rge_fini_buf_ring(rgep); + rge_problem(rgep, + "rge_init_buf_ring: desballoc() failed"); + return (DDI_FAILURE); } + free_srbdp++; } return (DDI_SUCCESS); } @@ -619,48 +645,24 @@ rge_init_rings(rge_t *rgep) { int err; - rge_init_send_ring(rgep); - err = rge_init_recv_ring(rgep); - err = rge_init_buf_ring(rgep); - return (err); -} - -static void -rge_fini_send_ring(rge_t *rgep) -{ - kmem_free(rgep->sw_sbds, RGE_SEND_SLOTS * sizeof (sw_sbd_t)); -} - -static void -rge_fini_recv_ring(rge_t *rgep) -{ - dma_buf_t *rx_buf = rgep->sw_rbuf; - uint32_t slot; - - for (slot = 0; slot < RGE_RECV_SLOTS; slot++, rx_buf++) - freemsg(rx_buf->mp); - kmem_free(rgep->sw_rbuf, RGE_RECV_SLOTS * sizeof (dma_buf_t)); - kmem_free(rgep->sw_rbds, RGE_RECV_SLOTS * sizeof (sw_rbd_t)); -} + err = rge_init_send_ring(rgep); + if (err != DDI_SUCCESS) + return (DDI_FAILURE); -static void -rge_fini_buf_ring(rge_t *rgep) -{ - dma_buf_t *rx_buf = rgep->sw_freebuf; - uint32_t slot; + err = rge_init_recv_ring(rgep); + if (err != DDI_SUCCESS) { + rge_fini_send_ring(rgep); + return (DDI_FAILURE); + } - for (slot = 0; slot < RGE_BUF_SLOTS; slot++, rx_buf++) - freemsg(rx_buf->mp); - kmem_free(rgep->sw_freebuf, RGE_BUF_SLOTS * sizeof (dma_buf_t)); - kmem_free(rgep->free_rbds, RGE_BUF_SLOTS * sizeof (sw_rbd_t)); -} + err = rge_init_buf_ring(rgep); + if (err != DDI_SUCCESS) { + rge_fini_send_ring(rgep); + rge_fini_recv_ring(rgep); + return (DDI_FAILURE); + } -static void -rge_fini_rings(rge_t *rgep) -{ - rge_fini_send_ring(rgep); - rge_fini_recv_ring(rgep); - rge_fini_buf_ring(rgep); + return (DDI_SUCCESS); } /* @@ -759,7 +761,8 @@ rge_restart(rge_t *rgep) rgep->stats.chip_reset++; if (rgep->rge_mac_state == RGE_MAC_STARTED) { rge_start(rgep); - ddi_trigger_softintr(rgep->resched_id); + rgep->resched_needed = B_TRUE; + (void) ddi_intr_trigger_softint(rgep->resched_hdl, NULL); } } @@ -859,7 +862,7 @@ rge_m_unicst(void *arg, const uint8_t *macaddr) static uint32_t rge_hash_index(const uint8_t *mca) { - uint32_t crc = (ulong_t)RGE_HASH_CRC; + uint32_t crc = (uint32_t)RGE_HASH_CRC; uint32_t const POLY = RGE_HASH_POLY; uint32_t msb; int bytes; @@ -872,14 +875,13 @@ rge_hash_index(const uint8_t *mca) for (bit = 0; bit < 8; bit++) { msb = crc >> 31; crc <<= 1; - if (msb ^ (currentbyte & 1)) { + if (msb ^ (currentbyte & 1)) crc ^= POLY; - crc |= 0x00000001; - } currentbyte >>= 1; } } index = crc >> 26; + /* the index value is between 0 and 63(0x3f) */ return (index); } @@ -893,26 +895,39 @@ rge_m_multicst(void *arg, boolean_t add, const uint8_t *mca) rge_t *rgep = arg; /* private device info */ struct ether_addr *addr; uint32_t index; - uint32_t *hashp; + uint32_t reg; + uint8_t *hashp; mutex_enter(rgep->genlock); hashp = rgep->mcast_hash; addr = (struct ether_addr *)mca; + /* + * Calculate the Multicast address hash index value + * Normally, the position of MAR0-MAR7 is + * MAR0: offset 0x08, ..., MAR7: offset 0x0F. + * + * For pcie chipset, the position of MAR0-MAR7 is + * different from others: + * MAR0: offset 0x0F, ..., MAR7: offset 0x08. + */ index = rge_hash_index(addr->ether_addr_octet); - /* index value is between 0 and 63 */ + if (rgep->chipid.is_pcie) + reg = (~(index / RGE_MCAST_NUM)) & 0x7; + else + reg = index / RGE_MCAST_NUM; if (add) { if (rgep->mcast_refs[index]++) { mutex_exit(rgep->genlock); return (0); } - hashp[index/32] |= 1<< (index % 32); + hashp[reg] |= 1 << (index % RGE_MCAST_NUM); } else { if (--rgep->mcast_refs[index]) { mutex_exit(rgep->genlock); return (0); } - hashp[index/32] &= ~(1<< (index % 32)); + hashp[reg] &= ~ (1 << (index % RGE_MCAST_NUM)); } /* @@ -1107,13 +1122,9 @@ rge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) if (need_privilege) { /* - * Check for specific net_config privilege on Solaris 10+. - * Otherwise just check for root access ... + * Check for specific net_config privilege */ - if (secpolicy_net_config != NULL) - err = secpolicy_net_config(iocp->ioc_cr, B_FALSE); - else - err = drv_priv(iocp->ioc_cr); + err = secpolicy_net_config(iocp->ioc_cr, B_FALSE); if (err != 0) { miocnak(wq, mp, 0, err); return; @@ -1252,6 +1263,146 @@ rge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) } /* + * ============ Init MSI/Fixed Interrupt routines ============== + */ + +/* + * rge_add_intrs: + * + * Register FIXED or MSI interrupts. + */ +static int +rge_add_intrs(rge_t *rgep, int intr_type) +{ + dev_info_t *dip = rgep->devinfo; + int avail; + int actual; + int intr_size; + int count; + int i, j; + int ret; + + /* Get number of interrupts */ + ret = ddi_intr_get_nintrs(dip, intr_type, &count); + if ((ret != DDI_SUCCESS) || (count == 0)) { + rge_error(rgep, "ddi_intr_get_nintrs() failure, ret: %d, " + "count: %d", ret, count); + return (DDI_FAILURE); + } + + /* Get number of available interrupts */ + ret = ddi_intr_get_navail(dip, intr_type, &avail); + if ((ret != DDI_SUCCESS) || (avail == 0)) { + rge_error(rgep, "ddi_intr_get_navail() failure, " + "ret: %d, avail: %d\n", ret, avail); + return (DDI_FAILURE); + } + + /* Allocate an array of interrupt handles */ + intr_size = count * sizeof (ddi_intr_handle_t); + rgep->htable = kmem_alloc(intr_size, KM_SLEEP); + rgep->intr_rqst = count; + + /* Call ddi_intr_alloc() */ + ret = ddi_intr_alloc(dip, rgep->htable, intr_type, 0, + count, &actual, DDI_INTR_ALLOC_NORMAL); + if (ret != DDI_SUCCESS || actual == 0) { + rge_error(rgep, "ddi_intr_alloc() failed %d\n", ret); + kmem_free(rgep->htable, intr_size); + return (DDI_FAILURE); + } + if (actual < count) { + rge_log(rgep, "ddi_intr_alloc() Requested: %d, Received: %d\n", + count, actual); + } + rgep->intr_cnt = actual; + + /* + * Get priority for first msi, assume remaining are all the same + */ + if ((ret = ddi_intr_get_pri(rgep->htable[0], &rgep->intr_pri)) != + DDI_SUCCESS) { + rge_error(rgep, "ddi_intr_get_pri() failed %d\n", ret); + /* Free already allocated intr */ + for (i = 0; i < actual; i++) { + (void) ddi_intr_free(rgep->htable[i]); + } + kmem_free(rgep->htable, intr_size); + return (DDI_FAILURE); + } + + /* Test for high level mutex */ + if (rgep->intr_pri >= ddi_intr_get_hilevel_pri()) { + rge_error(rgep, "rge_add_intrs:" + "Hi level interrupt not supported"); + for (i = 0; i < actual; i++) + (void) ddi_intr_free(rgep->htable[i]); + kmem_free(rgep->htable, intr_size); + return (DDI_FAILURE); + } + + /* Call ddi_intr_add_handler() */ + for (i = 0; i < actual; i++) { + if ((ret = ddi_intr_add_handler(rgep->htable[i], rge_intr, + (caddr_t)rgep, (caddr_t)(uintptr_t)i)) != DDI_SUCCESS) { + rge_error(rgep, "ddi_intr_add_handler() " + "failed %d\n", ret); + /* Remove already added intr */ + for (j = 0; j < i; j++) + (void) ddi_intr_remove_handler(rgep->htable[j]); + /* Free already allocated intr */ + for (i = 0; i < actual; i++) { + (void) ddi_intr_free(rgep->htable[i]); + } + kmem_free(rgep->htable, intr_size); + return (DDI_FAILURE); + } + } + + if ((ret = ddi_intr_get_cap(rgep->htable[0], &rgep->intr_cap)) + != DDI_SUCCESS) { + rge_error(rgep, "ddi_intr_get_cap() failed %d\n", ret); + for (i = 0; i < actual; i++) { + (void) ddi_intr_remove_handler(rgep->htable[i]); + (void) ddi_intr_free(rgep->htable[i]); + } + kmem_free(rgep->htable, intr_size); + return (DDI_FAILURE); + } + + return (DDI_SUCCESS); +} + +/* + * rge_rem_intrs: + * + * Unregister FIXED or MSI interrupts + */ +static void +rge_rem_intrs(rge_t *rgep) +{ + int i; + + /* Disable all interrupts */ + if (rgep->intr_cap & DDI_INTR_FLAG_BLOCK) { + /* Call ddi_intr_block_disable() */ + (void) ddi_intr_block_disable(rgep->htable, rgep->intr_cnt); + } else { + for (i = 0; i < rgep->intr_cnt; i++) { + (void) ddi_intr_disable(rgep->htable[i]); + } + } + + /* Call ddi_intr_remove_handler() */ + for (i = 0; i < rgep->intr_cnt; i++) { + (void) ddi_intr_remove_handler(rgep->htable[i]); + (void) ddi_intr_free(rgep->htable[i]); + } + + kmem_free(rgep->htable, rgep->intr_rqst * sizeof (ddi_intr_handle_t)); +} + +/* * ========== Per-instance setup/teardown code ========== */ @@ -1283,12 +1434,15 @@ rge_unattach(rge_t *rgep) if (rgep->progress & PROGRESS_PHY) (void) rge_phy_reset(rgep); - if (rgep->progress & PROGRESS_INTR) { + if (rgep->progress & PROGRESS_INIT) { mutex_enter(rgep->genlock); (void) rge_chip_reset(rgep); mutex_exit(rgep->genlock); - ddi_remove_intr(rgep->devinfo, 0, rgep->iblk); rge_fini_rings(rgep); + } + + if (rgep->progress & PROGRESS_INTR) { + rge_rem_intrs(rgep); mutex_destroy(rgep->rc_lock); mutex_destroy(rgep->rx_lock); mutex_destroy(rgep->tc_lock); @@ -1298,10 +1452,10 @@ rge_unattach(rge_t *rgep) } if (rgep->progress & PROGRESS_FACTOTUM) - ddi_remove_softintr(rgep->factotum_id); + (void) ddi_intr_remove_softint(rgep->factotum_hdl); if (rgep->progress & PROGRESS_RESCHED) - ddi_remove_softintr(rgep->resched_id); + (void) ddi_intr_remove_softint(rgep->resched_hdl); rge_free_bufs(rgep); @@ -1371,8 +1525,10 @@ rge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) chip_id_t *cidp; cyc_handler_t cychand; cyc_time_t cyctime; + int intr_types; caddr_t regs; int instance; + int i; int err; /* @@ -1407,8 +1563,13 @@ rge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) /* * Initialize more fields in RGE private data */ + rgep->rge_mac_state = RGE_MAC_ATTACH; rgep->debug = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, DDI_PROP_DONTPASS, debug_propname, rge_debug); + rgep->default_mtu = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, + DDI_PROP_DONTPASS, mtu_propname, ETHERMTU); + rgep->msi_enable = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, + DDI_PROP_DONTPASS, msi_propname, B_TRUE); (void) snprintf(rgep->ifname, sizeof (rgep->ifname), "%s%d", RGE_DRIVER_NAME, instance); @@ -1487,37 +1648,70 @@ rge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) * state, just in case we aren't getting link status change * interrupts ... */ - err = ddi_add_softintr(devinfo, DDI_SOFTINT_LOW, &rgep->resched_id, - NULL, NULL, rge_reschedule, (caddr_t)rgep); + err = ddi_intr_add_softint(devinfo, &rgep->resched_hdl, + DDI_INTR_SOFTPRI_MIN, rge_reschedule, (caddr_t)rgep); if (err != DDI_SUCCESS) { - rge_problem(rgep, "ddi_add_softintr() failed"); + rge_problem(rgep, "ddi_intr_add_softint() failed"); goto attach_fail; } rgep->progress |= PROGRESS_RESCHED; - err = ddi_add_softintr(devinfo, DDI_SOFTINT_LOW, &rgep->factotum_id, - NULL, NULL, rge_chip_factotum, (caddr_t)rgep); + err = ddi_intr_add_softint(devinfo, &rgep->factotum_hdl, + DDI_INTR_SOFTPRI_MIN, rge_chip_factotum, (caddr_t)rgep); if (err != DDI_SUCCESS) { - rge_problem(rgep, "ddi_add_softintr() failed"); + rge_problem(rgep, "ddi_intr_add_softint() failed"); goto attach_fail; } rgep->progress |= PROGRESS_FACTOTUM; /* + * Get supported interrupt types + */ + if (ddi_intr_get_supported_types(devinfo, &intr_types) + != DDI_SUCCESS) { + rge_error(rgep, "ddi_intr_get_supported_types failed\n"); + goto attach_fail; + } + + /* * Add the h/w interrupt handler and initialise mutexes */ - err = ddi_add_intr(devinfo, 0, &rgep->iblk, NULL, - rge_intr, (caddr_t)rgep); - if (err != DDI_SUCCESS) { - rge_problem(rgep, "ddi_add_intr() failed"); + if ((intr_types & DDI_INTR_TYPE_MSI) && rgep->msi_enable) { + if (rge_add_intrs(rgep, DDI_INTR_TYPE_MSI) != DDI_SUCCESS) { + rge_error(rgep, "MSI registration failed, " + "trying FIXED interrupt type\n"); + } else { + rge_log(rgep, "Using MSI interrupt type\n"); + rgep->intr_type = DDI_INTR_TYPE_MSI; + rgep->progress |= PROGRESS_INTR; + } + } + if (!(rgep->progress & PROGRESS_INTR) && + (intr_types & DDI_INTR_TYPE_FIXED)) { + if (rge_add_intrs(rgep, DDI_INTR_TYPE_FIXED) != DDI_SUCCESS) { + rge_error(rgep, "FIXED interrupt " + "registration failed\n"); + goto attach_fail; + } + rge_log(rgep, "Using FIXED interrupt type\n"); + rgep->intr_type = DDI_INTR_TYPE_FIXED; + rgep->progress |= PROGRESS_INTR; + } + if (!(rgep->progress & PROGRESS_INTR)) { + rge_error(rgep, "No interrupts registered\n"); goto attach_fail; } - mutex_init(rgep->genlock, NULL, MUTEX_DRIVER, rgep->iblk); - rw_init(rgep->errlock, NULL, RW_DRIVER, rgep->iblk); - mutex_init(rgep->tx_lock, NULL, MUTEX_DRIVER, rgep->iblk); - mutex_init(rgep->tc_lock, NULL, MUTEX_DRIVER, rgep->iblk); - mutex_init(rgep->rx_lock, NULL, MUTEX_DRIVER, rgep->iblk); - mutex_init(rgep->rc_lock, NULL, MUTEX_DRIVER, rgep->iblk); - rgep->progress |= PROGRESS_INTR; + mutex_init(rgep->genlock, NULL, MUTEX_DRIVER, + DDI_INTR_PRI(rgep->intr_pri)); + rw_init(rgep->errlock, NULL, RW_DRIVER, + DDI_INTR_PRI(rgep->intr_pri)); + mutex_init(rgep->tx_lock, NULL, MUTEX_DRIVER, + DDI_INTR_PRI(rgep->intr_pri)); + mutex_init(rgep->tc_lock, NULL, MUTEX_DRIVER, + DDI_INTR_PRI(rgep->intr_pri)); + mutex_init(rgep->rx_lock, NULL, MUTEX_DRIVER, + DDI_INTR_PRI(rgep->intr_pri)); + mutex_init(rgep->rc_lock, NULL, MUTEX_DRIVER, + DDI_INTR_PRI(rgep->intr_pri)); /* * Initialize rings @@ -1527,6 +1721,20 @@ rge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) rge_problem(rgep, "rge_init_rings() failed"); goto attach_fail; } + rgep->progress |= PROGRESS_INIT; + + /* + * Now that mutex locks are initialized, enable interrupts. + */ + if (rgep->intr_cap & DDI_INTR_FLAG_BLOCK) { + /* Call ddi_intr_block_enable() for MSI interrupts */ + (void) ddi_intr_block_enable(rgep->htable, rgep->intr_cnt); + } else { + /* Call ddi_intr_enable for MSI or FIXED interrupts */ + for (i = 0; i < rgep->intr_cnt; i++) { + (void) ddi_intr_enable(rgep->htable[i]); + } + } /* * Initialise link state variables @@ -1565,7 +1773,7 @@ rge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) macp->m_src_addr = rgep->netaddr; macp->m_callbacks = &rge_m_callbacks; macp->m_min_sdu = 0; - macp->m_max_sdu = rgep->param_default_mtu; + macp->m_max_sdu = rgep->default_mtu; /* * Finally, we're ready to register ourselves with the MAC layer @@ -1636,7 +1844,8 @@ rge_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) * If there is any posted buffer, the driver should reject to be * detached. Need notice upper layer to release them. */ - if (rgep->rx_free != RGE_BUF_SLOTS) + if (!(rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY) && + rgep->rx_free != RGE_BUF_SLOTS) return (DDI_FAILURE); /* diff --git a/usr/src/uts/common/io/rge/rge_ndd.c b/usr/src/uts/common/io/rge/rge_ndd.c index 836b71f003..29206ddabb 100755 --- a/usr/src/uts/common/io/rge/rge_ndd.c +++ b/usr/src/uts/common/io/rge/rge_ndd.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -95,9 +94,6 @@ static const nd_param_t nd_template[] = { /* Loopback status */ { PARAM_LOOP_MODE, 0, 2, 0, "-loop_mode" }, -/* Jumbo support */ -{ PARAM_DEFAULT_MTU, 0, 7000, 1500, "+default_mtu" }, - /* Terminator */ { PARAM_COUNT, 0, 0, 0, NULL } }; diff --git a/usr/src/uts/common/io/rge/rge_rxtx.c b/usr/src/uts/common/io/rge/rge_rxtx.c index 376f831dd9..561800271d 100755 --- a/usr/src/uts/common/io/rge/rge_rxtx.c +++ b/usr/src/uts/common/io/rge/rge_rxtx.c @@ -79,25 +79,25 @@ rge_atomic_renounce(uint32_t *count_p, uint32_t n) * Callback code invoked from STREAMs when the recv data buffer is free * for recycling. */ - void rge_rx_recycle(caddr_t arg) { rge_t *rgep; dma_buf_t *rx_buf; - sw_rbd_t *free_rbdp; + sw_rbd_t *free_srbdp; uint32_t slot_recy; rx_buf = (dma_buf_t *)arg; rgep = (rge_t *)rx_buf->private; /* - * If rge_unattach() is called, this callback function will also - * be called when we try to free the mp in rge_fini_rings(). - * In such situation, we needn't do below desballoc(), otherwise, + * In rge_unattach() and rge_attach(), this callback function will + * also be called to free mp in rge_fini_rings() and rge_init_rings(). + * In such situation, we shouldn't do below desballoc(), otherwise, * there'll be memory leak. */ - if (rgep->rge_mac_state == RGE_MAC_UNATTACH) + if (rgep->rge_mac_state == RGE_MAC_UNATTACH || + rgep->rge_mac_state == RGE_MAC_ATTACH) return; /* @@ -112,22 +112,16 @@ rge_rx_recycle(caddr_t arg) } mutex_enter(rgep->rc_lock); slot_recy = rgep->rc_next; - free_rbdp = &rgep->free_rbds[slot_recy]; - if (free_rbdp->rx_buf == NULL) { - free_rbdp->rx_buf = rx_buf; - rgep->rc_next = NEXT(slot_recy, RGE_BUF_SLOTS); - rge_atomic_renounce(&rgep->rx_free, 1); - if (rgep->rx_bcopy && rgep->rx_free == RGE_BUF_SLOTS) - rgep->rx_bcopy = B_FALSE; - ASSERT(rgep->rx_free <= RGE_BUF_SLOTS); - } else { - /* - * This situation shouldn't happen - */ - rge_problem(rgep, "rge_rx_recycle: buffer %d recycle error", - slot_recy); - rgep->stats.recycle_err++; - } + free_srbdp = &rgep->free_srbds[slot_recy]; + + ASSERT(free_srbdp->rx_buf == NULL); + free_srbdp->rx_buf = rx_buf; + rgep->rc_next = NEXT(slot_recy, RGE_BUF_SLOTS); + rge_atomic_renounce(&rgep->rx_free, 1); + if (rgep->rx_bcopy && rgep->rx_free == RGE_BUF_SLOTS) + rgep->rx_bcopy = B_FALSE; + ASSERT(rgep->rx_free <= RGE_BUF_SLOTS); + mutex_exit(rgep->rc_lock); } @@ -145,11 +139,11 @@ rge_rx_refill(rge_t *rgep, uint32_t slot) srbdp = &rgep->sw_rbds[slot]; hw_rbd_p = &rgep->rx_ring[slot]; free_slot = rgep->rf_next; - free_buf = rgep->free_rbds[free_slot].rx_buf; + free_buf = rgep->free_srbds[free_slot].rx_buf; if (free_buf != NULL) { srbdp->rx_buf = free_buf; - rgep->free_rbds[free_slot].rx_buf = NULL; - hw_rbd_p->host_buf_addr = RGE_BSWAP_32(RGE_HEADROOM + + rgep->free_srbds[free_slot].rx_buf = NULL; + hw_rbd_p->host_buf_addr = RGE_BSWAP_32(rgep->head_room + + free_buf->pbuf.cookie.dmac_laddress); hw_rbd_p->host_buf_addr_hi = RGE_BSWAP_32(free_buf->pbuf.cookie.dmac_laddress >> 32); @@ -188,7 +182,6 @@ rge_receive_packet(rge_t *rgep, uint32_t slot) hw_rbd_p = &rgep->rx_ring[slot]; srbdp = &rgep->sw_rbds[slot]; - packet_len = RGE_BSWAP_32(hw_rbd_p->flags_len) & RBD_LEN_MASK; /* * Read receive status @@ -222,16 +215,20 @@ rge_receive_packet(rge_t *rgep, uint32_t slot) /* * Handle size error packet */ - minsize = ETHERMIN - VLAN_TAGSZ + ETHERFCSL; - maxsize = rgep->ethmax_size + ETHERFCSL; - + packet_len = RGE_BSWAP_32(hw_rbd_p->flags_len) & RBD_LEN_MASK; + packet_len -= ETHERFCSL; + minsize = ETHERMIN; + pflags = RGE_BSWAP_32(hw_rbd_p->vlan_tag); + if (pflags & RBD_VLAN_PKT) + minsize -= VLAN_TAGSZ; + maxsize = rgep->ethmax_size; if (packet_len < minsize || packet_len > maxsize) { RGE_DEBUG(("rge_receive_packet: len err = %d", packet_len)); return (NULL); } DMA_SYNC(srbdp->rx_buf->pbuf, DDI_DMA_SYNC_FORKERNEL); - if (packet_len <= RGE_RECV_COPY_SIZE || rgep->rx_bcopy || + if (rgep->rx_bcopy || packet_len <= RGE_RECV_COPY_SIZE || !rge_atomic_reserve(&rgep->rx_free, 1)) { /* * Allocate buffer to receive this good packet @@ -248,12 +245,12 @@ rge_receive_packet(rge_t *rgep, uint32_t slot) */ rx_ptr = DMA_VPTR(srbdp->rx_buf->pbuf); mp->b_rptr = dp = mp->b_rptr + RGE_HEADROOM; - bcopy(rx_ptr + RGE_HEADROOM, dp, packet_len); - mp->b_wptr = dp + packet_len - ETHERFCSL; + bcopy(rx_ptr + rgep->head_room, dp, packet_len); + mp->b_wptr = dp + packet_len; } else { mp = srbdp->rx_buf->mp; - mp->b_rptr += RGE_HEADROOM; - mp->b_wptr = mp->b_rptr + packet_len - ETHERFCSL; + mp->b_rptr += rgep->head_room; + mp->b_wptr = mp->b_rptr + packet_len; mp->b_next = mp->b_cont = NULL; /* * Refill the current receive bd buffer @@ -267,7 +264,6 @@ rge_receive_packet(rge_t *rgep, uint32_t slot) /* * VLAN packet ? */ - pflags = RGE_BSWAP_32(hw_rbd_p->vlan_tag); if (pflags & RBD_VLAN_PKT) vtag = pflags & RBD_VLAN_TAG; if (vtag) { @@ -282,6 +278,7 @@ rge_receive_packet(rge_t *rgep, uint32_t slot) ehp = (struct ether_vlan_header *)mp->b_rptr; ehp->ether_tpid = htons(VLAN_TPID); ehp->ether_tci = htons(vtag); + rgep->stats.rbytes += VLAN_TAGSZ; } /* @@ -345,7 +342,7 @@ rge_receive_ring(rge_t *rgep) * Clear RBD flags */ hw_rbd_p->flags_len = - RGE_BSWAP_32(rgep->rxbuf_size - RGE_HEADROOM); + RGE_BSWAP_32(rgep->rxbuf_size - rgep->head_room); HW_RBD_INIT(hw_rbd_p, slot); slot = NEXT(slot, RGE_RECV_SLOTS); hw_rbd_p = &rgep->rx_ring[slot]; @@ -428,12 +425,11 @@ rge_send_recycle(rge_t *rgep) uint32_t tc_head; uint32_t n; - if (rgep->tx_free == RGE_SEND_SLOTS) - return; - mutex_enter(rgep->tc_lock); tc_head = rgep->tc_next; tc_tail = rgep->tc_tail; + if (tc_head == tc_tail) + goto resched; do { tc_tail = LAST(tc_tail, RGE_SEND_SLOTS); @@ -442,8 +438,9 @@ rge_send_recycle(rge_t *rgep) if (hw_sbd_p->flags_len & RGE_BSWAP_32(BD_FLAG_HW_OWN)) { /* - * Bump the watchdog counter, thus guaranteeing - * that it's nonzero (watchdog activated). + * Recyled nothing: bump the watchdog counter, + * thus guaranteeing that it's nonzero + * (watchdog activated). */ rgep->watchdog += 1; mutex_exit(rgep->tc_lock); @@ -453,28 +450,34 @@ rge_send_recycle(rge_t *rgep) } } while (hw_sbd_p->flags_len & RGE_BSWAP_32(BD_FLAG_HW_OWN)); + /* + * Recyled something :-) + */ rgep->tc_next = NEXT(tc_tail, RGE_SEND_SLOTS); n = rgep->tc_next - tc_head; if (rgep->tc_next < tc_head) n += RGE_SEND_SLOTS; rge_atomic_renounce(&rgep->tx_free, n); rgep->watchdog = 0; - mutex_exit(rgep->tc_lock); + ASSERT(rgep->tx_free <= RGE_SEND_SLOTS); - if (rgep->resched_needed) { - rgep->resched_needed = 0; - ddi_trigger_softintr(rgep->resched_id); +resched: + mutex_exit(rgep->tc_lock); + if (rgep->resched_needed && + rgep->rge_mac_state == RGE_MAC_STARTED) { + rgep->resched_needed = B_FALSE; + mac_tx_update(rgep->mh); } } /* * Send a message by copying it into a preallocated (and premapped) buffer */ -static void rge_send_copy(rge_t *rgep, mblk_t *mp, uint16_t tci, uchar_t proto); +static void rge_send_copy(rge_t *rgep, mblk_t *mp, uint16_t tci); #pragma inline(rge_send_copy) static void -rge_send_copy(rge_t *rgep, mblk_t *mp, uint16_t tci, uchar_t proto) +rge_send_copy(rge_t *rgep, mblk_t *mp, uint16_t tci) { rge_bd_t *hw_sbd_p; sw_sbd_t *ssbdp; @@ -484,6 +487,8 @@ rge_send_copy(rge_t *rgep, mblk_t *mp, uint16_t tci, uchar_t proto) size_t totlen; size_t mblen; uint32_t pflags; + struct ether_header *ethhdr; + struct ip *ip_hdr; /* * IMPORTANT: @@ -510,14 +515,34 @@ rge_send_copy(rge_t *rgep, mblk_t *mp, uint16_t tci, uchar_t proto) * splitting the message across multiple buffers either. */ txb = DMA_VPTR(ssbdp->pbuf); - for (totlen = 0, bp = mp; bp != NULL; bp = bp->b_cont) { + totlen = 0; + bp = mp; + if (tci != 0) { + /* + * Do not copy the vlan tag + */ + bcopy(bp->b_rptr, txb, 2 * ETHERADDRL); + txb += 2 * ETHERADDRL; + totlen += 2 * ETHERADDRL; + mblen = bp->b_wptr - bp->b_rptr; + ASSERT(mblen >= 2 * ETHERADDRL + VLAN_TAGSZ); + mblen -= 2 * ETHERADDRL + VLAN_TAGSZ; + if ((totlen += mblen) <= rgep->ethmax_size) { + bcopy(bp->b_rptr + 2 * ETHERADDRL + VLAN_TAGSZ, + txb, mblen); + txb += mblen; + } + bp = bp->b_cont; + rgep->stats.obytes += VLAN_TAGSZ; + } + for (; bp != NULL; bp = bp->b_cont) { mblen = bp->b_wptr - bp->b_rptr; if ((totlen += mblen) <= rgep->ethmax_size) { bcopy(bp->b_rptr, txb, mblen); txb += mblen; } } - rgep->stats.obytes += totlen + ETHERFCSL; + rgep->stats.obytes += totlen; /* * We'e reached the end of the chain; and we should have @@ -528,11 +553,10 @@ rge_send_copy(rge_t *rgep, mblk_t *mp, uint16_t tci, uchar_t proto) DMA_SYNC(ssbdp->pbuf, DDI_DMA_SYNC_FORDEV); /* - * Update the hardware send buffer descriptor; then we're done - * and return. The message can be freed right away in rge_send(), - * as we've already copied the contents ... + * Update the hardware send buffer descriptor flags */ hw_sbd_p = &rgep->tx_ring[slot]; + ASSERT(hw_sbd_p == ssbdp->desc.mem_va); hw_sbd_p->flags_len = RGE_BSWAP_32(totlen & SBD_LEN_MASK); if (tci != 0) { tci = TCI_OS2CHIP(tci); @@ -542,121 +566,78 @@ rge_send_copy(rge_t *rgep, mblk_t *mp, uint16_t tci, uchar_t proto) hw_sbd_p->vlan_tag = 0; } + /* + * h/w checksum offload flags + */ hcksum_retrieve(mp, NULL, NULL, NULL, NULL, NULL, NULL, &pflags); if (pflags & HCK_FULLCKSUM) { - switch (proto) { - case IS_UDP_PKT: - hw_sbd_p->flags_len |= RGE_BSWAP_32(SBD_FLAG_UDP_CKSUM); - proto = IS_IPV4_PKT; - break; - case IS_TCP_PKT: - hw_sbd_p->flags_len |= RGE_BSWAP_32(SBD_FLAG_TCP_CKSUM); - proto = IS_IPV4_PKT; - break; - default: - break; + ASSERT(totlen >= sizeof (struct ether_header) + + sizeof (struct ip)); + ethhdr = (struct ether_header *)(DMA_VPTR(ssbdp->pbuf)); + /* + * Is the packet an IP(v4) packet? + */ + if (ntohs(ethhdr->ether_type) == ETHERTYPE_IP) { + ip_hdr = (struct ip *) + ((uint8_t *)DMA_VPTR(ssbdp->pbuf) + + sizeof (struct ether_header)); + if (ip_hdr->ip_p == IPPROTO_TCP) + hw_sbd_p->flags_len |= + RGE_BSWAP_32(SBD_FLAG_TCP_CKSUM); + else if (ip_hdr->ip_p == IPPROTO_UDP) + hw_sbd_p->flags_len |= + RGE_BSWAP_32(SBD_FLAG_UDP_CKSUM); } } - if ((pflags & HCK_IPV4_HDRCKSUM) && (proto == IS_IPV4_PKT)) + if (pflags & HCK_IPV4_HDRCKSUM) hw_sbd_p->flags_len |= RGE_BSWAP_32(SBD_FLAG_IP_CKSUM); HW_SBD_SET(hw_sbd_p, slot); + + /* + * We're done. + * The message can be freed right away, as we've already + * copied the contents ... + */ + freemsg(mp); } static boolean_t rge_send(rge_t *rgep, mblk_t *mp) { struct ether_vlan_header *ehp; - boolean_t need_strip = B_FALSE; - uint16_t tci = 0; - uchar_t proto = UNKNOWN_PKT; - struct ether_header *ethhdr; - struct ip *ip_hdr; + uint16_t tci; ASSERT(mp->b_next == NULL); /* - * Determine if the packet is VLAN tagged. - */ - ASSERT(MBLKL(mp) >= sizeof (struct ether_header)); - ehp = (struct ether_vlan_header *)mp->b_rptr; - - if (ehp->ether_tpid == htons(VLAN_TPID)) { - if (MBLKL(mp) < sizeof (struct ether_vlan_header)) { - uint32_t pflags; - - /* - * Need to preserve checksum flags across pullup. - */ - hcksum_retrieve(mp, NULL, NULL, NULL, NULL, NULL, - NULL, &pflags); - - if (!pullupmsg(mp, - sizeof (struct ether_vlan_header))) { - RGE_DEBUG(("rge_send: pullup failure")); - rgep->resched_needed = B_TRUE; - return (B_FALSE); - } - - (void) hcksum_assoc(mp, NULL, NULL, NULL, NULL, NULL, - NULL, pflags, KM_NOSLEEP); - } - - ehp = (struct ether_vlan_header *)mp->b_rptr; - need_strip = B_TRUE; - } - - /* * Try to reserve a place in the transmit ring. */ if (!rge_atomic_reserve(&rgep->tx_free, 1)) { RGE_DEBUG(("rge_send: no free slots")); rgep->stats.defer++; rgep->resched_needed = B_TRUE; - rge_send_recycle(rgep); + (void) ddi_intr_trigger_softint(rgep->resched_hdl, NULL); return (B_FALSE); } /* + * Determine if the packet is VLAN tagged. + */ + ASSERT(MBLKL(mp) >= sizeof (struct ether_header)); + tci = 0; + ehp = (struct ether_vlan_header *)mp->b_rptr; + if (ehp->ether_tpid == htons(VLAN_TPID)) + tci = ntohs(ehp->ether_tci); + + /* * We've reserved a place :-) * These ASSERTions check that our invariants still hold: * there must still be at least one free place * there must be at least one place NOT free (ours!) */ ASSERT(rgep->tx_free < RGE_SEND_SLOTS); - - /* - * Now that we know that there is space to transmit the packet - * strip any VLAN tag that is present. - */ - if (need_strip) { - tci = ntohs(ehp->ether_tci); - (void) memmove(mp->b_rptr + VLAN_TAGSZ, mp->b_rptr, - 2 * ETHERADDRL); - mp->b_rptr += VLAN_TAGSZ; - } - - /* - * Check the packet protocol type for according h/w checksum offload - */ - if (MBLKL(mp) >= sizeof (struct ether_header) + - sizeof (struct ip)) { - ethhdr = (struct ether_header *)(mp->b_rptr); - /* - * Is the packet an IP(v4) packet? - */ - if (ntohs(ethhdr->ether_type) == ETHERTYPE_IP) { - proto = IS_IPV4_PKT; - ip_hdr = (struct ip *)(mp->b_rptr + - sizeof (struct ether_header)); - if (ip_hdr->ip_p == IPPROTO_TCP) - proto = IS_TCP_PKT; - else if (ip_hdr->ip_p == IPPROTO_UDP) - proto = IS_UDP_PKT; - } - } - - rge_send_copy(rgep, mp, tci, proto); + rge_send_copy(rgep, mp, tci); /* * Trigger chip h/w transmit ... @@ -665,32 +646,26 @@ rge_send(rge_t *rgep, mblk_t *mp) if (--rgep->tx_flow == 0) { DMA_SYNC(rgep->tx_desc, DDI_DMA_SYNC_FORDEV); rge_tx_trigger(rgep); - if (rgep->tx_free < RGE_SEND_SLOTS/32) + if (rgep->tx_free < RGE_SEND_SLOTS/2) rge_send_recycle(rgep); rgep->tc_tail = rgep->tx_next; } mutex_exit(rgep->tx_lock); - freemsg(mp); return (B_TRUE); } uint_t -rge_reschedule(caddr_t arg) +rge_reschedule(caddr_t arg1, caddr_t arg2) { rge_t *rgep; - uint_t rslt; - rgep = (rge_t *)arg; - rslt = DDI_INTR_UNCLAIMED; + rgep = (rge_t *)arg1; + _NOTE(ARGUNUSED(arg2)) - if (rgep->rge_mac_state == RGE_MAC_STARTED && rgep->resched_needed) { - mac_tx_update(rgep->mh); - rgep->resched_needed = B_FALSE; - rslt = DDI_INTR_CLAIMED; - } + rge_send_recycle(rgep); - return (rslt); + return (DDI_INTR_CLAIMED); } /* |