summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorgs150176 <none@none>2006-08-13 17:35:34 -0700
committergs150176 <none@none>2006-08-13 17:35:34 -0700
commitaa81749390e332985277568edab1ee6132326b42 (patch)
treee52ff6d41848a2cab963b2aa15c4c4e9b9714a69 /usr/src
parent4cb70d33a0347eb8a72054ff37d58fb4b7fb185f (diff)
downloadillumos-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-xusr/src/pkgdefs/SUNWrge/postinstall9
-rw-r--r--usr/src/pkgdefs/SUNWrtls/postinstall4
-rwxr-xr-xusr/src/uts/common/io/rge/rge.h65
-rwxr-xr-xusr/src/uts/common/io/rge/rge_chip.c296
-rwxr-xr-xusr/src/uts/common/io/rge/rge_hw.h52
-rwxr-xr-xusr/src/uts/common/io/rge/rge_main.c663
-rwxr-xr-xusr/src/uts/common/io/rge/rge_ndd.c10
-rwxr-xr-xusr/src/uts/common/io/rge/rge_rxtx.c267
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);
}
/*