summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcc210113 <none@none>2008-04-09 18:30:42 -0700
committercc210113 <none@none>2008-04-09 18:30:42 -0700
commit9ce7e93c0e8e6d2b400f40e9c5742b1d6682611e (patch)
treeeb2f18ee756c212cfdf66bb3718fe97974d09778
parente57b9183811d515e3bbcd1a104516f0102fde114 (diff)
downloadillumos-gate-9ce7e93c0e8e6d2b400f40e9c5742b1d6682611e.tar.gz
6673650 e1000g needs to support Brussels
-rw-r--r--usr/src/uts/common/io/e1000g/README5
-rw-r--r--usr/src/uts/common/io/e1000g/e1000g_main.c954
-rw-r--r--usr/src/uts/common/io/e1000g/e1000g_ndd.c382
-rw-r--r--usr/src/uts/common/io/e1000g/e1000g_rx.c29
-rw-r--r--usr/src/uts/common/io/e1000g/e1000g_stat.c76
-rw-r--r--usr/src/uts/common/io/e1000g/e1000g_sw.h56
-rw-r--r--usr/src/uts/common/io/e1000g/e1000g_tx.c10
7 files changed, 1015 insertions, 497 deletions
diff --git a/usr/src/uts/common/io/e1000g/README b/usr/src/uts/common/io/e1000g/README
index bcd70bb376..cbf5b54883 100644
--- a/usr/src/uts/common/io/e1000g/README
+++ b/usr/src/uts/common/io/e1000g/README
@@ -566,3 +566,8 @@ Notes on packaging:
This version has the following fix:
6633239 e1000g: link flaps observed on Galaxy(X4100) systems running 64-bit kernel
+5.2.7
+======
+ This version has the following fix:
+ 6673650 e1000g needs to support Brussels
+
diff --git a/usr/src/uts/common/io/e1000g/e1000g_main.c b/usr/src/uts/common/io/e1000g/e1000g_main.c
index e4aefe2620..abc22125db 100644
--- a/usr/src/uts/common/io/e1000g/e1000g_main.c
+++ b/usr/src/uts/common/io/e1000g/e1000g_main.c
@@ -43,12 +43,13 @@
#include <sys/dlpi.h>
#include <sys/mac.h>
+#include <sys/dld.h>
#include "e1000g_sw.h"
#include "e1000g_debug.h"
-static char ident[] = "Intel PRO/1000 Ethernet 5.2.6";
+static char ident[] = "Intel PRO/1000 Ethernet 5.2.7";
static char e1000g_string[] = "Intel(R) PRO/1000 Network Connection";
-static char e1000g_version[] = "Driver Ver. 5.2.6";
+static char e1000g_version[] = "Driver Ver. 5.2.7";
/*
* Proto types for DDI entry points
@@ -81,11 +82,20 @@ static int e1000g_m_unicst_modify(void *, mac_multi_addr_t *);
static int e1000g_m_unicst_get(void *, mac_multi_addr_t *);
static int e1000g_m_multicst(void *, boolean_t, const uint8_t *);
static void e1000g_m_ioctl(void *, queue_t *, mblk_t *);
+static int e1000g_m_setprop(void *, const char *, mac_prop_id_t,
+ uint_t, const void *);
+static int e1000g_m_getprop(void *, const char *, mac_prop_id_t,
+ uint_t, void *);
+static int e1000g_set_priv_prop(struct e1000g *, const char *, uint_t,
+ const void *);
+static int e1000g_get_priv_prop(struct e1000g *, const char *, uint_t,
+ void *);
static void e1000g_init_locks(struct e1000g *);
static void e1000g_destroy_locks(struct e1000g *);
static int e1000g_identify_hardware(struct e1000g *);
static int e1000g_regs_map(struct e1000g *);
static int e1000g_set_driver_params(struct e1000g *);
+static void e1000g_set_bufsize(struct e1000g *);
static int e1000g_register_mac(struct e1000g *);
static boolean_t e1000g_rx_drain(struct e1000g *);
static boolean_t e1000g_tx_drain(struct e1000g *);
@@ -199,7 +209,8 @@ static ddi_device_acc_attr_t e1000g_regs_acc_attr = {
DDI_FLAGERR_ACC
};
-#define E1000G_M_CALLBACK_FLAGS (MC_IOCTL | MC_GETCAPAB)
+#define E1000G_M_CALLBACK_FLAGS \
+ (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP)
static mac_callbacks_t e1000g_m_callbacks = {
E1000G_M_CALLBACK_FLAGS,
@@ -212,7 +223,11 @@ static mac_callbacks_t e1000g_m_callbacks = {
e1000g_m_tx,
NULL,
e1000g_m_ioctl,
- e1000g_m_getcapab
+ e1000g_m_getcapab,
+ NULL,
+ NULL,
+ e1000g_m_setprop,
+ e1000g_m_getprop
};
/*
@@ -559,11 +574,7 @@ e1000g_register_mac(struct e1000g *Adapter)
mac->m_src_addr = hw->mac.addr;
mac->m_callbacks = &e1000g_m_callbacks;
mac->m_min_sdu = 0;
- mac->m_max_sdu =
- (hw->mac.max_frame_size > FRAME_SIZE_UPTO_8K) ?
- hw->mac.max_frame_size - 256 :
- (hw->mac.max_frame_size != ETHERMAX) ?
- hw->mac.max_frame_size - 24 : ETHERMTU;
+ mac->m_max_sdu = Adapter->default_mtu;
mac->m_margin = VLAN_TAGSZ;
err = mac_register(mac, &Adapter->mh);
@@ -663,10 +674,6 @@ e1000g_set_driver_params(struct e1000g *Adapter)
struct e1000_hw *hw;
e1000g_tx_ring_t *tx_ring;
uint32_t mem_bar, io_bar, bar64;
-#ifdef __sparc
- dev_info_t *devinfo = Adapter->dip;
- ulong_t iommu_pagesize;
-#endif
hw = &Adapter->shared;
@@ -741,10 +748,56 @@ e1000g_set_driver_params(struct e1000g *Adapter)
/* Get Jumbo Frames settings in conf file */
e1000g_get_max_frame_size(Adapter);
- hw->mac.min_frame_size =
- MINIMUM_ETHERNET_PACKET_SIZE + CRC_LENGTH;
+
+ /* Set Rx/Tx buffer size */
+ e1000g_set_bufsize(Adapter);
+
+ /* Master Latency Timer */
+ Adapter->master_latency_timer = DEFAULT_MASTER_LATENCY_TIMER;
+
+ /* copper options */
+ if (hw->media_type == e1000_media_type_copper) {
+ hw->phy.mdix = 0; /* AUTO_ALL_MODES */
+ hw->phy.disable_polarity_correction = B_FALSE;
+ hw->phy.ms_type = e1000_ms_hw_default; /* E1000_MASTER_SLAVE */
+ }
+
+ /* The initial link state should be "unknown" */
+ Adapter->link_state = LINK_STATE_UNKNOWN;
+
+ /* Initialize rx parameters */
+ Adapter->rx_intr_delay = DEFAULT_RX_INTR_DELAY;
+ Adapter->rx_intr_abs_delay = DEFAULT_RX_INTR_ABS_DELAY;
+
+ /* Initialize tx parameters */
+ Adapter->tx_intr_enable = DEFAULT_TX_INTR_ENABLE;
+ Adapter->tx_bcopy_thresh = DEFAULT_TX_BCOPY_THRESHOLD;
+ Adapter->tx_intr_delay = DEFAULT_TX_INTR_DELAY;
+ Adapter->tx_intr_abs_delay = DEFAULT_TX_INTR_ABS_DELAY;
+
+ tx_ring = Adapter->tx_ring;
+ tx_ring->frags_limit =
+ (hw->mac.max_frame_size / Adapter->tx_bcopy_thresh) + 2;
+ if (tx_ring->frags_limit > (MAX_TX_DESC_PER_PACKET >> 1))
+ tx_ring->frags_limit = (MAX_TX_DESC_PER_PACKET >> 1);
+
+ /* Initialize rx parameters */
+ Adapter->rx_bcopy_thresh = DEFAULT_RX_BCOPY_THRESHOLD;
+
+ return (DDI_SUCCESS);
+}
+
+static void
+e1000g_set_bufsize(struct e1000g *Adapter)
+{
+ struct e1000_mac_info *mac = &Adapter->shared.mac;
+ uint64_t rx_size;
+ uint64_t tx_size;
#ifdef __sparc
+ dev_info_t *devinfo = Adapter->dip;
+ ulong_t iommu_pagesize;
+
/* Get the system page size */
Adapter->sys_page_sz = ddi_ptob(devinfo, (ulong_t)1);
iommu_pagesize = dvma_pagesize(devinfo);
@@ -757,36 +810,36 @@ e1000g_set_driver_params(struct e1000g *Adapter)
Adapter->sys_page_sz = iommu_pagesize;
}
}
- Adapter->dvma_page_num = hw->mac.max_frame_size /
+ Adapter->dvma_page_num = mac->max_frame_size /
Adapter->sys_page_sz + E1000G_DEFAULT_DVMA_PAGE_NUM;
ASSERT(Adapter->dvma_page_num >= E1000G_DEFAULT_DVMA_PAGE_NUM);
#endif
- /* Set Rx/Tx buffer size */
- switch (hw->mac.max_frame_size) {
- case ETHERMAX:
- Adapter->rx_buffer_size = E1000_RX_BUFFER_SIZE_2K;
- Adapter->tx_buffer_size = E1000_TX_BUFFER_SIZE_2K;
- break;
- case FRAME_SIZE_UPTO_4K:
+ mac->min_frame_size = ETHERMIN + ETHERFCSL;
+
+ rx_size = mac->max_frame_size + E1000G_IPALIGNPRESERVEROOM;
+ if ((rx_size > FRAME_SIZE_UPTO_2K) && (rx_size <= FRAME_SIZE_UPTO_4K))
Adapter->rx_buffer_size = E1000_RX_BUFFER_SIZE_4K;
- Adapter->tx_buffer_size = E1000_TX_BUFFER_SIZE_4K;
- break;
- case FRAME_SIZE_UPTO_8K:
+ else if ((rx_size > FRAME_SIZE_UPTO_4K) &&
+ (rx_size <= FRAME_SIZE_UPTO_8K))
Adapter->rx_buffer_size = E1000_RX_BUFFER_SIZE_8K;
- Adapter->tx_buffer_size = E1000_TX_BUFFER_SIZE_8K;
- break;
- case FRAME_SIZE_UPTO_9K:
- case FRAME_SIZE_UPTO_16K:
+ else if ((rx_size > FRAME_SIZE_UPTO_8K) &&
+ (rx_size <= FRAME_SIZE_UPTO_16K))
Adapter->rx_buffer_size = E1000_RX_BUFFER_SIZE_16K;
- Adapter->tx_buffer_size = E1000_TX_BUFFER_SIZE_16K;
- break;
- default:
+ else
Adapter->rx_buffer_size = E1000_RX_BUFFER_SIZE_2K;
+
+ tx_size = mac->max_frame_size;
+ if ((tx_size > FRAME_SIZE_UPTO_2K) && (tx_size <= FRAME_SIZE_UPTO_4K))
+ Adapter->tx_buffer_size = E1000_TX_BUFFER_SIZE_4K;
+ else if ((tx_size > FRAME_SIZE_UPTO_4K) &&
+ (tx_size <= FRAME_SIZE_UPTO_8K))
+ Adapter->tx_buffer_size = E1000_TX_BUFFER_SIZE_8K;
+ else if ((tx_size > FRAME_SIZE_UPTO_8K) &&
+ (tx_size <= FRAME_SIZE_UPTO_16K))
+ Adapter->tx_buffer_size = E1000_TX_BUFFER_SIZE_16K;
+ else
Adapter->tx_buffer_size = E1000_TX_BUFFER_SIZE_2K;
- break;
- }
- Adapter->rx_buffer_size += E1000G_IPALIGNPRESERVEROOM;
#ifndef NO_82542_SUPPORT
/*
@@ -800,45 +853,11 @@ e1000g_set_driver_params(struct e1000g *Adapter)
* aligned...so all wiseman boards to have 256 byte aligned
* buffers
*/
- if (hw->mac.type < e1000_82543)
+ if (mac->type < e1000_82543)
Adapter->rx_buf_align = RECEIVE_BUFFER_ALIGN_SIZE;
else
Adapter->rx_buf_align = 1;
#endif
-
- /* Master Latency Timer */
- Adapter->master_latency_timer = DEFAULT_MASTER_LATENCY_TIMER;
-
- /* copper options */
- if (hw->media_type == e1000_media_type_copper) {
- hw->phy.mdix = 0; /* AUTO_ALL_MODES */
- hw->phy.disable_polarity_correction = B_FALSE;
- hw->phy.ms_type = e1000_ms_hw_default; /* E1000_MASTER_SLAVE */
- }
-
- /* The initial link state should be "unknown" */
- Adapter->link_state = LINK_STATE_UNKNOWN;
-
- /* Initialize rx parameters */
- Adapter->rx_intr_delay = DEFAULT_RX_INTR_DELAY;
- Adapter->rx_intr_abs_delay = DEFAULT_RX_INTR_ABS_DELAY;
-
- /* Initialize tx parameters */
- Adapter->tx_intr_enable = DEFAULT_TX_INTR_ENABLE;
- Adapter->tx_bcopy_thresh = DEFAULT_TX_BCOPY_THRESHOLD;
- Adapter->tx_intr_delay = DEFAULT_TX_INTR_DELAY;
- Adapter->tx_intr_abs_delay = DEFAULT_TX_INTR_ABS_DELAY;
-
- tx_ring = Adapter->tx_ring;
- tx_ring->frags_limit =
- (hw->mac.max_frame_size / Adapter->tx_bcopy_thresh) + 2;
- if (tx_ring->frags_limit > (MAX_TX_DESC_PER_PACKET >> 1))
- tx_ring->frags_limit = (MAX_TX_DESC_PER_PACKET >> 1);
-
- /* Initialize rx parameters */
- Adapter->rx_bcopy_thresh = DEFAULT_RX_BCOPY_THRESHOLD;
-
- return (DDI_SUCCESS);
}
/*
@@ -2571,9 +2590,635 @@ e1000g_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
return (B_TRUE);
}
+static boolean_t
+e1000g_param_locked(mac_prop_id_t pr_num)
+{
+ /*
+ * All en_* parameters are locked (read-only) while
+ * the device is in any sort of loopback mode ...
+ */
+ switch (pr_num) {
+ case DLD_PROP_EN_1000FDX_CAP:
+ case DLD_PROP_EN_1000HDX_CAP:
+ case DLD_PROP_EN_100FDX_CAP:
+ case DLD_PROP_EN_100HDX_CAP:
+ case DLD_PROP_EN_10FDX_CAP:
+ case DLD_PROP_EN_10HDX_CAP:
+ case DLD_PROP_AUTONEG:
+ case DLD_PROP_FLOWCTRL:
+ return (B_TRUE);
+ }
+ return (B_FALSE);
+}
+
+/*
+ * callback function for set/get of properties
+ */
+static int
+e1000g_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
+ uint_t pr_valsize, const void *pr_val)
+{
+ struct e1000g *Adapter = arg;
+ struct e1000_mac_info *mac = &Adapter->shared.mac;
+ struct e1000_phy_info *phy = &Adapter->shared.phy;
+ e1000g_tx_ring_t *tx_ring;
+ int err = 0;
+ link_flowctrl_t fc;
+ uint64_t cur_mtu, new_mtu;
+ uint64_t tmp = 0;
+
+ rw_enter(&Adapter->chip_lock, RW_WRITER);
+ if (Adapter->loopback_mode != E1000G_LB_NONE &&
+ e1000g_param_locked(pr_num)) {
+ /*
+ * All en_* parameters are locked (read-only)
+ * while the device is in any sort of loopback mode.
+ */
+ rw_exit(&Adapter->chip_lock);
+ return (EBUSY);
+ }
+
+ switch (pr_num) {
+ case DLD_PROP_EN_1000FDX_CAP:
+ Adapter->param_en_1000fdx = *(uint8_t *)pr_val;
+ Adapter->param_adv_1000fdx = *(uint8_t *)pr_val;
+ goto reset;
+ case DLD_PROP_EN_1000HDX_CAP:
+ Adapter->param_en_1000hdx = *(uint8_t *)pr_val;
+ Adapter->param_adv_1000hdx = *(uint8_t *)pr_val;
+ goto reset;
+ case DLD_PROP_EN_100FDX_CAP:
+ Adapter->param_en_100fdx = *(uint8_t *)pr_val;
+ Adapter->param_adv_100fdx = *(uint8_t *)pr_val;
+ goto reset;
+ case DLD_PROP_EN_100HDX_CAP:
+ Adapter->param_en_100hdx = *(uint8_t *)pr_val;
+ Adapter->param_adv_100hdx = *(uint8_t *)pr_val;
+ goto reset;
+ case DLD_PROP_EN_10FDX_CAP:
+ Adapter->param_en_10fdx = *(uint8_t *)pr_val;
+ Adapter->param_adv_10fdx = *(uint8_t *)pr_val;
+ goto reset;
+ case DLD_PROP_EN_10HDX_CAP:
+ Adapter->param_en_10hdx = *(uint8_t *)pr_val;
+ Adapter->param_adv_10hdx = *(uint8_t *)pr_val;
+ goto reset;
+ case DLD_PROP_AUTONEG:
+ Adapter->param_adv_autoneg = *(uint8_t *)pr_val;
+ goto reset;
+ case DLD_PROP_FLOWCTRL:
+ mac->fc_send_xon = B_TRUE;
+ bcopy(pr_val, &fc, sizeof (fc));
+
+ switch (fc) {
+ default:
+ err = EINVAL;
+ break;
+ case LINK_FLOWCTRL_NONE:
+ mac->fc = e1000_fc_none;
+ break;
+ case LINK_FLOWCTRL_RX:
+ mac->fc = e1000_fc_rx_pause;
+ break;
+ case LINK_FLOWCTRL_TX:
+ mac->fc = e1000_fc_tx_pause;
+ break;
+ case LINK_FLOWCTRL_BI:
+ mac->fc = e1000_fc_full;
+ break;
+ }
+reset:
+ if (err == 0) {
+ if (e1000g_reset_link(Adapter) != DDI_SUCCESS)
+ err = EINVAL;
+ }
+ break;
+ case DLD_PROP_ADV_1000FDX_CAP:
+ case DLD_PROP_ADV_1000HDX_CAP:
+ case DLD_PROP_ADV_100FDX_CAP:
+ case DLD_PROP_ADV_100HDX_CAP:
+ case DLD_PROP_ADV_10FDX_CAP:
+ case DLD_PROP_ADV_10HDX_CAP:
+ case DLD_PROP_STATUS:
+ case DLD_PROP_SPEED:
+ case DLD_PROP_DUPLEX:
+ err = ENOTSUP; /* read-only prop. Can't set this. */
+ break;
+ case DLD_PROP_DEFMTU:
+ cur_mtu = Adapter->default_mtu;
+ bcopy(pr_val, &new_mtu, sizeof (new_mtu));
+ if (new_mtu == cur_mtu) {
+ err = 0;
+ break;
+ }
+
+ tmp = new_mtu + sizeof (struct ether_vlan_header) +
+ ETHERFCSL;
+ if ((tmp < DEFAULT_FRAME_SIZE) ||
+ (tmp > MAXIMUM_FRAME_SIZE)) {
+ err = EINVAL;
+ break;
+ }
+
+ /* ich8 doed not support jumbo frames */
+ if ((mac->type == e1000_ich8lan) &&
+ (tmp > DEFAULT_FRAME_SIZE)) {
+ err = EINVAL;
+ break;
+ }
+ /* ich9 does not do jumbo frames on one phy type */
+ if ((mac->type == e1000_ich9lan) &&
+ (phy->type == e1000_phy_ife) &&
+ (tmp > DEFAULT_FRAME_SIZE)) {
+ err = EINVAL;
+ break;
+ }
+ if (Adapter->chip_state != E1000G_STOP) {
+ err = EBUSY;
+ break;
+ }
+
+ err = mac_maxsdu_update(Adapter->mh, new_mtu);
+ if (err == 0) {
+ mac->max_frame_size = tmp;
+ Adapter->default_mtu = new_mtu;
+ e1000g_set_bufsize(Adapter);
+ tx_ring = Adapter->tx_ring;
+ tx_ring->frags_limit = (mac->max_frame_size /
+ Adapter->tx_bcopy_thresh) + 2;
+ if (tx_ring->frags_limit >
+ (MAX_TX_DESC_PER_PACKET >> 1))
+ tx_ring->frags_limit =
+ (MAX_TX_DESC_PER_PACKET >> 1);
+ }
+ break;
+ case DLD_PROP_PRIVATE:
+ err = e1000g_set_priv_prop(Adapter, pr_name,
+ pr_valsize, pr_val);
+ break;
+ default:
+ err = ENOTSUP;
+ break;
+ }
+ rw_exit(&Adapter->chip_lock);
+ return (err);
+}
+
+static int
+e1000g_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
+ uint_t pr_valsize, void *pr_val)
+{
+ struct e1000g *Adapter = arg;
+ struct e1000_mac_info *mac = &Adapter->shared.mac;
+ int err = EINVAL;
+ link_flowctrl_t fc;
+ uint64_t tmp = 0;
+
+ bzero(pr_val, pr_valsize);
+ switch (pr_num) {
+ case DLD_PROP_DUPLEX:
+ if (pr_valsize >= sizeof (uint8_t)) {
+ *(uint8_t *)pr_val = Adapter->link_duplex;
+ err = 0;
+ }
+ break;
+ case DLD_PROP_SPEED:
+ if (pr_valsize >= sizeof (uint64_t)) {
+ tmp = Adapter->link_speed * 1000000ull;
+ bcopy(&tmp, pr_val, sizeof (tmp));
+ err = 0;
+ }
+ break;
+ case DLD_PROP_STATUS:
+ if (pr_valsize >= sizeof (uint8_t)) {
+ *(uint8_t *)pr_val = Adapter->link_state;
+ err = 0;
+ }
+ break;
+ case DLD_PROP_AUTONEG:
+ if (pr_valsize >= sizeof (uint8_t)) {
+ *(uint8_t *)pr_val = Adapter->param_adv_autoneg;
+ err = 0;
+ }
+ break;
+ case DLD_PROP_DEFMTU:
+ if (pr_valsize >= sizeof (uint64_t)) {
+ tmp = Adapter->default_mtu;
+ bcopy(&tmp, pr_val, sizeof (tmp));
+ err = 0;
+ }
+ break;
+ case DLD_PROP_FLOWCTRL:
+ if (pr_valsize >= sizeof (link_flowctrl_t)) {
+ switch (mac->fc) {
+ case e1000_fc_none:
+ fc = LINK_FLOWCTRL_NONE;
+ break;
+ case e1000_fc_rx_pause:
+ fc = LINK_FLOWCTRL_RX;
+ break;
+ case e1000_fc_tx_pause:
+ fc = LINK_FLOWCTRL_TX;
+ break;
+ case e1000_fc_full:
+ fc = LINK_FLOWCTRL_BI;
+ break;
+ }
+ bcopy(&fc, pr_val, sizeof (fc));
+ err = 0;
+ }
+ break;
+ case DLD_PROP_ADV_1000FDX_CAP:
+ if (pr_valsize >= sizeof (uint8_t)) {
+ *(uint8_t *)pr_val = Adapter->param_adv_1000fdx;
+ err = 0;
+ }
+ break;
+ case DLD_PROP_EN_1000FDX_CAP:
+ if (pr_valsize >= sizeof (uint8_t)) {
+ *(uint8_t *)pr_val = Adapter->param_en_1000fdx;
+ err = 0;
+ }
+ break;
+ case DLD_PROP_ADV_1000HDX_CAP:
+ if (pr_valsize >= sizeof (uint8_t)) {
+ *(uint8_t *)pr_val = Adapter->param_adv_1000hdx;
+ err = 0;
+ }
+ break;
+ case DLD_PROP_EN_1000HDX_CAP:
+ if (pr_valsize >= sizeof (uint8_t)) {
+ *(uint8_t *)pr_val = Adapter->param_en_1000hdx;
+ err = 0;
+ }
+ break;
+ case DLD_PROP_ADV_100FDX_CAP:
+ if (pr_valsize >= sizeof (uint8_t)) {
+ *(uint8_t *)pr_val = Adapter->param_adv_100fdx;
+ err = 0;
+ }
+ break;
+ case DLD_PROP_EN_100FDX_CAP:
+ if (pr_valsize >= sizeof (uint8_t)) {
+ *(uint8_t *)pr_val = Adapter->param_en_100fdx;
+ err = 0;
+ }
+ break;
+ case DLD_PROP_ADV_100HDX_CAP:
+ if (pr_valsize >= sizeof (uint8_t)) {
+ *(uint8_t *)pr_val = Adapter->param_adv_100hdx;
+ err = 0;
+ }
+ break;
+ case DLD_PROP_EN_100HDX_CAP:
+ if (pr_valsize >= sizeof (uint8_t)) {
+ *(uint8_t *)pr_val = Adapter->param_en_100hdx;
+ err = 0;
+ }
+ break;
+ case DLD_PROP_ADV_10FDX_CAP:
+ if (pr_valsize >= sizeof (uint8_t)) {
+ *(uint8_t *)pr_val = Adapter->param_adv_10fdx;
+ err = 0;
+ }
+ break;
+ case DLD_PROP_EN_10FDX_CAP:
+ if (pr_valsize >= sizeof (uint8_t)) {
+ *(uint8_t *)pr_val = Adapter->param_en_10fdx;
+ err = 0;
+ }
+ break;
+ case DLD_PROP_ADV_10HDX_CAP:
+ if (pr_valsize >= sizeof (uint8_t)) {
+ *(uint8_t *)pr_val = Adapter->param_adv_10hdx;
+ err = 0;
+ }
+ break;
+ case DLD_PROP_EN_10HDX_CAP:
+ if (pr_valsize >= sizeof (uint8_t)) {
+ *(uint8_t *)pr_val = Adapter->param_en_10hdx;
+ err = 0;
+ }
+ break;
+ case DLD_PROP_PRIVATE:
+ err = e1000g_get_priv_prop(Adapter, pr_name,
+ pr_valsize, pr_val);
+ break;
+ default:
+ err = ENOTSUP;
+ break;
+ }
+ return (err);
+}
+
+/* ARGUSED */
+static int
+e1000g_set_priv_prop(struct e1000g *Adapter, const char *pr_name,
+ uint_t pr_valsize, const void *pr_val)
+{
+ int err = 0;
+ long result;
+ e1000g_tx_ring_t *tx_ring = Adapter->tx_ring;
+ struct e1000_hw *hw = &Adapter->shared;
+
+ if (strcmp(pr_name, "_tx_bcopy_threshold") == 0) {
+ if (pr_val == NULL) {
+ err = EINVAL;
+ return (err);
+ }
+ (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
+ if (result < MIN_TX_BCOPY_THRESHOLD ||
+ result > MAX_TX_BCOPY_THRESHOLD)
+ err = EINVAL;
+ else {
+ Adapter->tx_bcopy_thresh = (uint32_t)result;
+ tx_ring->frags_limit = (hw->mac.max_frame_size /
+ Adapter->tx_bcopy_thresh) + 2;
+ if (tx_ring->frags_limit >
+ (MAX_TX_DESC_PER_PACKET >> 1))
+ tx_ring->frags_limit =
+ (MAX_TX_DESC_PER_PACKET >> 1);
+ }
+ return (err);
+ }
+ if (strcmp(pr_name, "_tx_interrupt_enable") == 0) {
+ if (pr_val == NULL) {
+ err = EINVAL;
+ return (err);
+ }
+ (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
+ if (result < 0 || result > 1)
+ err = EINVAL;
+ else {
+ Adapter->tx_intr_enable = (result == 1) ?
+ B_TRUE: B_FALSE;
+ if (Adapter->tx_intr_enable)
+ e1000g_mask_tx_interrupt(Adapter);
+ else
+ e1000g_clear_tx_interrupt(Adapter);
+ if (e1000g_check_acc_handle(
+ Adapter->osdep.reg_handle) != DDI_FM_OK)
+ ddi_fm_service_impact(Adapter->dip,
+ DDI_SERVICE_DEGRADED);
+ }
+ return (err);
+ }
+ if (strcmp(pr_name, "_tx_intr_delay") == 0) {
+ if (pr_val == NULL) {
+ err = EINVAL;
+ return (err);
+ }
+ (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
+ if (result < MIN_TX_INTR_DELAY ||
+ result > MAX_TX_INTR_DELAY)
+ err = EINVAL;
+ else {
+ Adapter->tx_intr_delay = (uint32_t)result;
+ E1000_WRITE_REG(hw, E1000_TIDV, Adapter->tx_intr_delay);
+ if (e1000g_check_acc_handle(
+ Adapter->osdep.reg_handle) != DDI_FM_OK)
+ ddi_fm_service_impact(Adapter->dip,
+ DDI_SERVICE_DEGRADED);
+ }
+ return (err);
+ }
+ if (strcmp(pr_name, "_tx_intr_abs_delay") == 0) {
+ if (pr_val == NULL) {
+ err = EINVAL;
+ return (err);
+ }
+ (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
+ if (result < MIN_TX_INTR_ABS_DELAY ||
+ result > MAX_TX_INTR_ABS_DELAY)
+ err = EINVAL;
+ else {
+ Adapter->tx_intr_abs_delay = (uint32_t)result;
+ E1000_WRITE_REG(hw, E1000_TADV,
+ Adapter->tx_intr_abs_delay);
+ if (e1000g_check_acc_handle(
+ Adapter->osdep.reg_handle) != DDI_FM_OK)
+ ddi_fm_service_impact(Adapter->dip,
+ DDI_SERVICE_DEGRADED);
+ }
+ return (err);
+ }
+ if (strcmp(pr_name, "_rx_bcopy_threshold") == 0) {
+ if (pr_val == NULL) {
+ err = EINVAL;
+ return (err);
+ }
+ (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
+ if (result < MIN_RX_BCOPY_THRESHOLD ||
+ result > MAX_RX_BCOPY_THRESHOLD)
+ err = EINVAL;
+ else
+ Adapter->rx_bcopy_thresh = (uint32_t)result;
+ return (err);
+ }
+ if (strcmp(pr_name, "_max_num_rcv_packets") == 0) {
+ if (pr_val == NULL) {
+ err = EINVAL;
+ return (err);
+ }
+ (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
+ if (result < MIN_RX_LIMIT_ON_INTR ||
+ result > MAX_RX_LIMIT_ON_INTR)
+ err = EINVAL;
+ else
+ Adapter->rx_limit_onintr = (uint32_t)result;
+ return (err);
+ }
+ if (strcmp(pr_name, "_rx_intr_delay") == 0) {
+ if (pr_val == NULL) {
+ err = EINVAL;
+ return (err);
+ }
+ (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
+ if (result < MIN_RX_INTR_DELAY ||
+ result > MAX_RX_INTR_DELAY)
+ err = EINVAL;
+ else {
+ Adapter->rx_intr_delay = (uint32_t)result;
+ E1000_WRITE_REG(hw, E1000_RDTR, Adapter->rx_intr_delay);
+ if (e1000g_check_acc_handle(
+ Adapter->osdep.reg_handle) != DDI_FM_OK)
+ ddi_fm_service_impact(Adapter->dip,
+ DDI_SERVICE_DEGRADED);
+ }
+ return (err);
+ }
+ if (strcmp(pr_name, "_rx_intr_abs_delay") == 0) {
+ if (pr_val == NULL) {
+ err = EINVAL;
+ return (err);
+ }
+ (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
+ if (result < MIN_RX_INTR_ABS_DELAY ||
+ result > MAX_RX_INTR_ABS_DELAY)
+ err = EINVAL;
+ else {
+ Adapter->rx_intr_abs_delay = (uint32_t)result;
+ E1000_WRITE_REG(hw, E1000_RADV,
+ Adapter->rx_intr_abs_delay);
+ if (e1000g_check_acc_handle(
+ Adapter->osdep.reg_handle) != DDI_FM_OK)
+ ddi_fm_service_impact(Adapter->dip,
+ DDI_SERVICE_DEGRADED);
+ }
+ return (err);
+ }
+ if (strcmp(pr_name, "_intr_throttling_rate") == 0) {
+ if (pr_val == NULL) {
+ err = EINVAL;
+ return (err);
+ }
+ (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
+ if (result < MIN_INTR_THROTTLING ||
+ result > MAX_INTR_THROTTLING)
+ err = EINVAL;
+ else {
+ if (hw->mac.type >= e1000_82540) {
+ Adapter->intr_throttling_rate =
+ (uint32_t)result;
+ E1000_WRITE_REG(hw, E1000_ITR,
+ Adapter->intr_throttling_rate);
+ if (e1000g_check_acc_handle(
+ Adapter->osdep.reg_handle) != DDI_FM_OK)
+ ddi_fm_service_impact(Adapter->dip,
+ DDI_SERVICE_DEGRADED);
+ } else
+ err = EINVAL;
+ }
+ return (err);
+ }
+ if (strcmp(pr_name, "_intr_adaptive") == 0) {
+ if (pr_val == NULL) {
+ err = EINVAL;
+ return (err);
+ }
+ (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
+ if (result < 0 || result > 1)
+ err = EINVAL;
+ else {
+ if (hw->mac.type >= e1000_82540) {
+ Adapter->intr_adaptive = (result == 1) ?
+ B_TRUE : B_FALSE;
+ } else {
+ err = EINVAL;
+ }
+ }
+ return (err);
+ }
+ if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
+ if (pr_val == NULL) {
+ err = EINVAL;
+ return (err);
+ }
+ (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
+ if (result < MIN_TX_RECYCLE_THRESHOLD ||
+ result > MAX_TX_RECYCLE_THRESHOLD)
+ err = EINVAL;
+ else
+ Adapter->tx_recycle_thresh = (uint32_t)result;
+ return (err);
+ }
+ if (strcmp(pr_name, "_tx_recycle_num") == 0) {
+ if (pr_val == NULL) {
+ err = EINVAL;
+ return (err);
+ }
+ (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
+ if (result < MIN_TX_RECYCLE_NUM ||
+ result > MAX_TX_RECYCLE_NUM)
+ err = EINVAL;
+ else
+ Adapter->tx_recycle_num = (uint32_t)result;
+ return (err);
+ }
+ return (ENOTSUP);
+}
+
+static int
+e1000g_get_priv_prop(struct e1000g *Adapter, const char *pr_name,
+ uint_t pr_valsize, void *pr_val)
+{
+ char valstr[MAXNAMELEN];
+ int err = ENOTSUP;
+ uint_t strsize;
+
+ if (strcmp(pr_name, "_tx_bcopy_threshold") == 0) {
+ (void) sprintf(valstr, "%d", Adapter->tx_bcopy_thresh);
+ err = 0;
+ goto done;
+ }
+ if (strcmp(pr_name, "_tx_interrupt_enable") == 0) {
+ (void) sprintf(valstr, "%d", Adapter->tx_intr_enable);
+ err = 0;
+ goto done;
+ }
+ if (strcmp(pr_name, "_tx_intr_delay") == 0) {
+ (void) sprintf(valstr, "%d", Adapter->tx_intr_delay);
+ err = 0;
+ goto done;
+ }
+ if (strcmp(pr_name, "_tx_intr_abs_delay") == 0) {
+ (void) sprintf(valstr, "%d", Adapter->tx_intr_abs_delay);
+ err = 0;
+ goto done;
+ }
+ if (strcmp(pr_name, "_rx_bcopy_threshold") == 0) {
+ (void) sprintf(valstr, "%d", Adapter->rx_bcopy_thresh);
+ err = 0;
+ goto done;
+ }
+ if (strcmp(pr_name, "_max_num_rcv_packets") == 0) {
+ (void) sprintf(valstr, "%d", Adapter->rx_limit_onintr);
+ err = 0;
+ goto done;
+ }
+ if (strcmp(pr_name, "_rx_intr_delay") == 0) {
+ (void) sprintf(valstr, "%d", Adapter->rx_intr_delay);
+ err = 0;
+ goto done;
+ }
+ if (strcmp(pr_name, "_rx_intr_abs_delay") == 0) {
+ (void) sprintf(valstr, "%d", Adapter->rx_intr_abs_delay);
+ err = 0;
+ goto done;
+ }
+ if (strcmp(pr_name, "_intr_throttling_rate") == 0) {
+ (void) sprintf(valstr, "%d", Adapter->intr_throttling_rate);
+ err = 0;
+ goto done;
+ }
+ if (strcmp(pr_name, "_intr_adaptive") == 0) {
+ (void) sprintf(valstr, "%d", Adapter->intr_adaptive);
+ err = 0;
+ goto done;
+ }
+ if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
+ (void) sprintf(valstr, "%d", Adapter->tx_recycle_thresh);
+ err = 0;
+ goto done;
+ }
+ if (strcmp(pr_name, "_tx_recycle_num") == 0) {
+ (void) sprintf(valstr, "%d", Adapter->tx_recycle_num);
+ err = 0;
+ goto done;
+ }
+done:
+ if (err == 0) {
+ strsize = (uint_t)strlen(valstr);
+ if (pr_valsize < strsize)
+ err = ENOBUFS;
+ else
+ (void) strlcpy(pr_val, valstr, pr_valsize);
+ }
+ return (err);
+}
+
/*
* e1000g_get_conf - get configurations set in e1000g.conf
- *
* This routine gets user-configured values out of the configuration
* file e1000g.conf.
*
@@ -2851,6 +3496,76 @@ e1000g_link_check(struct e1000g *Adapter)
return (link_changed);
}
+/*
+ * e1000g_reset_link - Using the link properties to setup the link
+ */
+int
+e1000g_reset_link(struct e1000g *Adapter)
+{
+ struct e1000_mac_info *mac;
+ struct e1000_phy_info *phy;
+ boolean_t invalid;
+
+ mac = &Adapter->shared.mac;
+ phy = &Adapter->shared.phy;
+ invalid = B_FALSE;
+
+ if (Adapter->param_adv_autoneg == 1) {
+ mac->autoneg = B_TRUE;
+ phy->autoneg_advertised = 0;
+
+ /*
+ * 1000hdx is not supported for autonegotiation
+ */
+ if (Adapter->param_adv_1000fdx == 1)
+ phy->autoneg_advertised |= ADVERTISE_1000_FULL;
+
+ if (Adapter->param_adv_100fdx == 1)
+ phy->autoneg_advertised |= ADVERTISE_100_FULL;
+
+ if (Adapter->param_adv_100hdx == 1)
+ phy->autoneg_advertised |= ADVERTISE_100_HALF;
+
+ if (Adapter->param_adv_10fdx == 1)
+ phy->autoneg_advertised |= ADVERTISE_10_FULL;
+
+ if (Adapter->param_adv_10hdx == 1)
+ phy->autoneg_advertised |= ADVERTISE_10_HALF;
+
+ if (phy->autoneg_advertised == 0)
+ invalid = B_TRUE;
+ } else {
+ mac->autoneg = B_FALSE;
+
+ /*
+ * 1000fdx and 1000hdx are not supported for forced link
+ */
+ if (Adapter->param_adv_100fdx == 1)
+ mac->forced_speed_duplex = ADVERTISE_100_FULL;
+ else if (Adapter->param_adv_100hdx == 1)
+ mac->forced_speed_duplex = ADVERTISE_100_HALF;
+ else if (Adapter->param_adv_10fdx == 1)
+ mac->forced_speed_duplex = ADVERTISE_10_FULL;
+ else if (Adapter->param_adv_10hdx == 1)
+ mac->forced_speed_duplex = ADVERTISE_10_HALF;
+ else
+ invalid = B_TRUE;
+
+ }
+
+ if (invalid) {
+ e1000g_log(Adapter, CE_WARN,
+ "Invalid link sets. Setup link to"
+ "support autonegotiation with all link capabilities.");
+ mac->autoneg = B_TRUE;
+ phy->autoneg_advertised = ADVERTISE_1000_FULL |
+ ADVERTISE_100_FULL | ADVERTISE_100_HALF |
+ ADVERTISE_10_FULL | ADVERTISE_10_HALF;
+ }
+
+ return (e1000_setup_link(&Adapter->shared));
+}
+
static void
e1000g_local_timer(void *ws)
{
@@ -3060,25 +3775,38 @@ e1000g_get_max_frame_size(struct e1000g *Adapter)
switch (max_frame) {
case 0:
- mac->max_frame_size = ETHERMAX;
+ Adapter->default_mtu = ETHERMTU;
break;
+ /*
+ * To avoid excessive memory allocation for rx buffers,
+ * the bytes of E1000G_IPALIGNPRESERVEROOM are reserved.
+ */
case 1:
- mac->max_frame_size = FRAME_SIZE_UPTO_4K;
+ Adapter->default_mtu = FRAME_SIZE_UPTO_4K -
+ sizeof (struct ether_vlan_header) - ETHERFCSL -
+ E1000G_IPALIGNPRESERVEROOM;
break;
case 2:
- mac->max_frame_size = FRAME_SIZE_UPTO_8K;
+ Adapter->default_mtu = FRAME_SIZE_UPTO_8K -
+ sizeof (struct ether_vlan_header) - ETHERFCSL -
+ E1000G_IPALIGNPRESERVEROOM;
break;
case 3:
- if (mac->type < e1000_82571)
- mac->max_frame_size = FRAME_SIZE_UPTO_16K;
+ if (mac->type >= e1000_82571)
+ Adapter->default_mtu = MAXIMUM_MTU;
else
- mac->max_frame_size = FRAME_SIZE_UPTO_9K;
+ Adapter->default_mtu = FRAME_SIZE_UPTO_16K -
+ sizeof (struct ether_vlan_header) - ETHERFCSL -
+ E1000G_IPALIGNPRESERVEROOM;
break;
default:
- mac->max_frame_size = ETHERMAX;
+ Adapter->default_mtu = ETHERMTU;
break;
} /* switch */
+ mac->max_frame_size = Adapter->default_mtu +
+ sizeof (struct ether_vlan_header) + ETHERFCSL;
+
/* ich8 does not do jumbo frames */
if (mac->type == e1000_ich8lan) {
mac->max_frame_size = ETHERMAX;
@@ -4477,6 +5205,74 @@ e1000g_get_phy_state(struct e1000g *Adapter)
e1000_read_phy_reg(hw, PHY_1000T_CTRL, &Adapter->phy_1000t_ctrl);
e1000_read_phy_reg(hw, PHY_1000T_STATUS, &Adapter->phy_1000t_status);
e1000_read_phy_reg(hw, PHY_LP_ABILITY, &Adapter->phy_lp_able);
+
+ Adapter->param_autoneg_cap =
+ (Adapter->phy_status & MII_SR_AUTONEG_CAPS) ? 1 : 0;
+ Adapter->param_pause_cap =
+ (Adapter->phy_an_adv & NWAY_AR_PAUSE) ? 1 : 0;
+ Adapter->param_asym_pause_cap =
+ (Adapter->phy_an_adv & NWAY_AR_ASM_DIR) ? 1 : 0;
+ Adapter->param_1000fdx_cap =
+ ((Adapter->phy_ext_status & IEEE_ESR_1000T_FD_CAPS) ||
+ (Adapter->phy_ext_status & IEEE_ESR_1000X_FD_CAPS)) ? 1 : 0;
+ Adapter->param_1000hdx_cap =
+ ((Adapter->phy_ext_status & IEEE_ESR_1000T_HD_CAPS) ||
+ (Adapter->phy_ext_status & IEEE_ESR_1000X_HD_CAPS)) ? 1 : 0;
+ Adapter->param_100t4_cap =
+ (Adapter->phy_status & MII_SR_100T4_CAPS) ? 1 : 0;
+ Adapter->param_100fdx_cap =
+ ((Adapter->phy_status & MII_SR_100X_FD_CAPS) ||
+ (Adapter->phy_status & MII_SR_100T2_FD_CAPS)) ? 1 : 0;
+ Adapter->param_100hdx_cap =
+ ((Adapter->phy_status & MII_SR_100X_HD_CAPS) ||
+ (Adapter->phy_status & MII_SR_100T2_HD_CAPS)) ? 1 : 0;
+ Adapter->param_10fdx_cap =
+ (Adapter->phy_status & MII_SR_10T_FD_CAPS) ? 1 : 0;
+ Adapter->param_10hdx_cap =
+ (Adapter->phy_status & MII_SR_10T_HD_CAPS) ? 1 : 0;
+
+ Adapter->param_adv_autoneg = hw->mac.autoneg;
+ Adapter->param_adv_pause =
+ (Adapter->phy_an_adv & NWAY_AR_PAUSE) ? 1 : 0;
+ Adapter->param_adv_asym_pause =
+ (Adapter->phy_an_adv & NWAY_AR_ASM_DIR) ? 1 : 0;
+ Adapter->param_adv_1000hdx =
+ (Adapter->phy_1000t_ctrl & CR_1000T_HD_CAPS) ? 1 : 0;
+ Adapter->param_adv_100t4 =
+ (Adapter->phy_an_adv & NWAY_AR_100T4_CAPS) ? 1 : 0;
+ if (Adapter->param_adv_autoneg == 1) {
+ Adapter->param_adv_1000fdx =
+ (Adapter->phy_1000t_ctrl & CR_1000T_FD_CAPS) ? 1 : 0;
+ Adapter->param_adv_100fdx =
+ (Adapter->phy_an_adv & NWAY_AR_100TX_FD_CAPS) ? 1 : 0;
+ Adapter->param_adv_100hdx =
+ (Adapter->phy_an_adv & NWAY_AR_100TX_HD_CAPS) ? 1 : 0;
+ Adapter->param_adv_10fdx =
+ (Adapter->phy_an_adv & NWAY_AR_10T_FD_CAPS) ? 1 : 0;
+ Adapter->param_adv_10hdx =
+ (Adapter->phy_an_adv & NWAY_AR_10T_HD_CAPS) ? 1 : 0;
+ }
+
+ Adapter->param_lp_autoneg =
+ (Adapter->phy_an_exp & NWAY_ER_LP_NWAY_CAPS) ? 1 : 0;
+ Adapter->param_lp_pause =
+ (Adapter->phy_lp_able & NWAY_LPAR_PAUSE) ? 1 : 0;
+ Adapter->param_lp_asym_pause =
+ (Adapter->phy_lp_able & NWAY_LPAR_ASM_DIR) ? 1 : 0;
+ Adapter->param_lp_1000fdx =
+ (Adapter->phy_1000t_status & SR_1000T_LP_FD_CAPS) ? 1 : 0;
+ Adapter->param_lp_1000hdx =
+ (Adapter->phy_1000t_status & SR_1000T_LP_HD_CAPS) ? 1 : 0;
+ Adapter->param_lp_100t4 =
+ (Adapter->phy_lp_able & NWAY_LPAR_100T4_CAPS) ? 1 : 0;
+ Adapter->param_lp_100fdx =
+ (Adapter->phy_lp_able & NWAY_LPAR_100TX_FD_CAPS) ? 1 : 0;
+ Adapter->param_lp_100hdx =
+ (Adapter->phy_lp_able & NWAY_LPAR_100TX_HD_CAPS) ? 1 : 0;
+ Adapter->param_lp_10fdx =
+ (Adapter->phy_lp_able & NWAY_LPAR_10T_FD_CAPS) ? 1 : 0;
+ Adapter->param_lp_10hdx =
+ (Adapter->phy_lp_able & NWAY_LPAR_10T_HD_CAPS) ? 1 : 0;
}
/*
diff --git a/usr/src/uts/common/io/e1000g/e1000g_ndd.c b/usr/src/uts/common/io/e1000g/e1000g_ndd.c
index 5a65eb0e8c..5964006c2b 100644
--- a/usr/src/uts/common/io/e1000g/e1000g_ndd.c
+++ b/usr/src/uts/common/io/e1000g/e1000g_ndd.c
@@ -19,7 +19,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms of the CDDLv1.
*/
@@ -33,6 +33,7 @@ static int e1000g_nd_set(queue_t *q, mblk_t *mp,
char *value, caddr_t cp, cred_t *credp);
static int e1000g_nd_get(queue_t *q, mblk_t *mp,
caddr_t cp, cred_t *credp);
+static void e1000g_nd_param_sync(struct e1000g *Adapter);
static void e1000g_nd_get_param_val(nd_param_t *ndp);
static void e1000g_nd_set_param_val(nd_param_t *ndp, uint32_t value);
@@ -99,10 +100,6 @@ static const nd_param_t nd_template[] = {
{ PARAM_LP_10FDX_CAP, 0, 1, 0, NULL, "-lp_10fdx_cap" },
{ PARAM_LP_10HDX_CAP, 0, 1, 0, NULL, "-lp_10hdx_cap" },
-/* Force Speed and Duplex */
-{ PARAM_FORCE_SPEED_DUPLEX, GDIAG_10_HALF, GDIAG_100_FULL, GDIAG_100_FULL,
- NULL, "?force_speed_duplex" },
-
/* Current operating modes */
{ PARAM_LINK_STATUS, 0, 1, 0, NULL, "-link_status" },
{ PARAM_LINK_SPEED, 0, 1000, 0, NULL, "-link_speed" },
@@ -184,6 +181,25 @@ e1000g_nd_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *credp)
return (0);
}
+/*
+ * synchronize the adv* and en* parameters.
+ *
+ * See comments in <sys/dld.h> for details of the *_en_*
+ * parameters. The usage of ndd for setting adv parameters will
+ * synchronize all the en parameters with the e1000g parameters,
+ * implicity disalbing any settings made via dladm.
+ */
+static void
+e1000g_nd_param_sync(struct e1000g *Adapter)
+{
+ Adapter->param_en_1000fdx = Adapter->param_adv_1000fdx;
+ Adapter->param_en_1000hdx = Adapter->param_adv_1000hdx;
+ Adapter->param_en_100fdx = Adapter->param_adv_100fdx;
+ Adapter->param_en_100hdx = Adapter->param_adv_100hdx;
+ Adapter->param_en_10fdx = Adapter->param_adv_10fdx;
+ Adapter->param_en_10hdx = Adapter->param_adv_10hdx;
+}
+
static int
e1000g_nd_param_load(struct e1000g *Adapter)
{
@@ -277,152 +293,6 @@ e1000g_nd_get_param_val(nd_param_t *ndp)
rw_enter(&Adapter->chip_lock, RW_READER);
switch (ndp->ndp_info) {
- /* Hardware Capabilities */
- case PARAM_AUTONEG_CAP:
- ndp->ndp_val =
- (Adapter->phy_status & MII_SR_AUTONEG_CAPS) ? 1 : 0;
- break;
- case PARAM_PAUSE_CAP:
- ndp->ndp_val =
- (Adapter->phy_an_adv & NWAY_AR_PAUSE) ? 1 : 0;
- break;
- case PARAM_ASYM_PAUSE_CAP:
- ndp->ndp_val =
- (Adapter->phy_an_adv & NWAY_AR_ASM_DIR) ? 1 : 0;
- break;
- case PARAM_1000FDX_CAP:
- ndp->ndp_val =
- ((Adapter->phy_ext_status & IEEE_ESR_1000T_FD_CAPS) ||
- (Adapter->phy_ext_status & IEEE_ESR_1000X_FD_CAPS)) ? 1 : 0;
- break;
- case PARAM_1000HDX_CAP:
- ndp->ndp_val =
- ((Adapter->phy_ext_status & IEEE_ESR_1000T_HD_CAPS) ||
- (Adapter->phy_ext_status & IEEE_ESR_1000X_HD_CAPS)) ? 1 : 0;
- break;
- case PARAM_100T4_CAP:
- ndp->ndp_val =
- (Adapter->phy_status & MII_SR_100T4_CAPS) ? 1 : 0;
- break;
- case PARAM_100FDX_CAP:
- ndp->ndp_val =
- ((Adapter->phy_status & MII_SR_100X_FD_CAPS) ||
- (Adapter->phy_status & MII_SR_100T2_FD_CAPS)) ? 1 : 0;
- break;
- case PARAM_100HDX_CAP:
- ndp->ndp_val =
- ((Adapter->phy_status & MII_SR_100X_HD_CAPS) ||
- (Adapter->phy_status & MII_SR_100T2_HD_CAPS)) ? 1 : 0;
- break;
- case PARAM_10FDX_CAP:
- ndp->ndp_val =
- (Adapter->phy_status & MII_SR_10T_FD_CAPS) ? 1 : 0;
- break;
- case PARAM_10HDX_CAP:
- ndp->ndp_val =
- (Adapter->phy_status & MII_SR_10T_HD_CAPS) ? 1 : 0;
- break;
-
- /* Auto-Negotiation Advertisement Capabilities */
- case PARAM_ADV_AUTONEG_CAP:
- ndp->ndp_val = hw->mac.autoneg;
- break;
- case PARAM_ADV_PAUSE_CAP:
- ndp->ndp_val =
- (Adapter->phy_an_adv & NWAY_AR_PAUSE) ? 1 : 0;
- break;
- case PARAM_ADV_ASYM_PAUSE_CAP:
- ndp->ndp_val =
- (Adapter->phy_an_adv & NWAY_AR_ASM_DIR) ? 1 : 0;
- break;
- case PARAM_ADV_1000FDX_CAP:
- ndp->ndp_val =
- (Adapter->phy_1000t_ctrl & CR_1000T_FD_CAPS) ? 1 : 0;
- break;
- case PARAM_ADV_1000HDX_CAP:
- ndp->ndp_val =
- (Adapter->phy_1000t_ctrl & CR_1000T_HD_CAPS) ? 1 : 0;
- break;
- case PARAM_ADV_100T4_CAP:
- ndp->ndp_val =
- (Adapter->phy_an_adv & NWAY_AR_100T4_CAPS) ? 1 : 0;
- break;
- case PARAM_ADV_100FDX_CAP:
- ndp->ndp_val =
- (Adapter->phy_an_adv & NWAY_AR_100TX_FD_CAPS) ? 1 : 0;
- break;
- case PARAM_ADV_100HDX_CAP:
- ndp->ndp_val =
- (Adapter->phy_an_adv & NWAY_AR_100TX_HD_CAPS) ? 1 : 0;
- break;
- case PARAM_ADV_10FDX_CAP:
- ndp->ndp_val =
- (Adapter->phy_an_adv & NWAY_AR_10T_FD_CAPS) ? 1 : 0;
- break;
- case PARAM_ADV_10HDX_CAP:
- ndp->ndp_val =
- (Adapter->phy_an_adv & NWAY_AR_10T_HD_CAPS) ? 1 : 0;
- break;
-
- /* Link-Partner's Advertisement Capabilities */
- case PARAM_LP_AUTONEG_CAP:
- ndp->ndp_val =
- (Adapter->phy_an_exp & NWAY_ER_LP_NWAY_CAPS) ? 1 : 0;
- break;
- case PARAM_LP_PAUSE_CAP:
- ndp->ndp_val =
- (Adapter->phy_lp_able & NWAY_LPAR_PAUSE) ? 1 : 0;
- break;
- case PARAM_LP_ASYM_PAUSE_CAP:
- ndp->ndp_val =
- (Adapter->phy_lp_able & NWAY_LPAR_ASM_DIR) ? 1 : 0;
- break;
- case PARAM_LP_1000FDX_CAP:
- ndp->ndp_val =
- (Adapter->phy_1000t_status & SR_1000T_LP_FD_CAPS) ? 1 : 0;
- break;
- case PARAM_LP_1000HDX_CAP:
- ndp->ndp_val =
- (Adapter->phy_1000t_status & SR_1000T_LP_HD_CAPS) ? 1 : 0;
- break;
- case PARAM_LP_100T4_CAP:
- ndp->ndp_val =
- (Adapter->phy_lp_able & NWAY_LPAR_100T4_CAPS) ? 1 : 0;
- break;
- case PARAM_LP_100FDX_CAP:
- ndp->ndp_val =
- (Adapter->phy_lp_able & NWAY_LPAR_100TX_FD_CAPS) ? 1 : 0;
- break;
- case PARAM_LP_100HDX_CAP:
- ndp->ndp_val =
- (Adapter->phy_lp_able & NWAY_LPAR_100TX_HD_CAPS) ? 1 : 0;
- break;
- case PARAM_LP_10FDX_CAP:
- ndp->ndp_val =
- (Adapter->phy_lp_able & NWAY_LPAR_10T_FD_CAPS) ? 1 : 0;
- break;
- case PARAM_LP_10HDX_CAP:
- ndp->ndp_val =
- (Adapter->phy_lp_able & NWAY_LPAR_10T_HD_CAPS) ? 1 : 0;
- break;
-
- /* Force Speed and Duplex Parameter */
- case PARAM_FORCE_SPEED_DUPLEX:
- switch (hw->mac.forced_speed_duplex) {
- case ADVERTISE_10_HALF:
- ndp->ndp_val = GDIAG_10_HALF;
- break;
- case ADVERTISE_10_FULL:
- ndp->ndp_val = GDIAG_10_FULL;
- break;
- case ADVERTISE_100_HALF:
- ndp->ndp_val = GDIAG_100_HALF;
- break;
- case ADVERTISE_100_FULL:
- ndp->ndp_val = GDIAG_100_FULL;
- break;
- }
- break;
/* Link States */
case PARAM_LINK_STATUS:
ndp->ndp_val = (Adapter->link_state == LINK_STATE_UP) ? 1 : 0;
@@ -489,21 +359,12 @@ e1000g_nd_set_param_val(nd_param_t *ndp, uint32_t value)
struct e1000g *Adapter;
struct e1000_hw *hw;
e1000g_tx_ring_t *tx_ring;
- uint16_t autoneg_advertised;
- uint8_t forced_speed_duplex;
- boolean_t autoneg_enable;
- boolean_t link_change;
Adapter = ndp->ndp_instance;
ASSERT(Adapter);
hw = &Adapter->shared;
tx_ring = Adapter->tx_ring;
- autoneg_advertised = 0;
- forced_speed_duplex = 0;
- autoneg_enable = B_FALSE;
- link_change = B_FALSE;
-
rw_enter(&Adapter->chip_lock, RW_WRITER);
switch (ndp->ndp_info) {
@@ -514,7 +375,7 @@ e1000g_nd_set_param_val(nd_param_t *ndp, uint32_t value)
Adapter->tx_bcopy_thresh) + 2;
if (tx_ring->frags_limit > (MAX_TX_DESC_PER_PACKET >> 1))
tx_ring->frags_limit = (MAX_TX_DESC_PER_PACKET >> 1);
- goto finished;
+ break;
case PARAM_TX_INTR_ENABLE:
ndp->ndp_val = value;
Adapter->tx_intr_enable = (value == 1) ? B_TRUE : B_FALSE;
@@ -522,7 +383,7 @@ e1000g_nd_set_param_val(nd_param_t *ndp, uint32_t value)
e1000g_mask_tx_interrupt(Adapter);
else
e1000g_clear_tx_interrupt(Adapter);
- goto finished;
+ break;
case PARAM_TX_TIDV:
ndp->ndp_val = value;
Adapter->tx_intr_delay = value;
@@ -530,219 +391,42 @@ e1000g_nd_set_param_val(nd_param_t *ndp, uint32_t value)
if (Adapter->tx_intr_delay) {
E1000_WRITE_REG(hw, E1000_TIDV, Adapter->tx_intr_delay);
}
- goto finished;
+ break;
case PARAM_TX_TADV:
ndp->ndp_val = value;
Adapter->tx_intr_abs_delay = value;
E1000_WRITE_REG(hw, E1000_TADV, Adapter->tx_intr_abs_delay);
- goto finished;
+ break;
case PARAM_RX_BCOPY_THRESHOLD:
ndp->ndp_val = value;
Adapter->rx_bcopy_thresh = value;
- goto finished;
+ break;
case PARAM_RX_PKT_ON_INTR:
ndp->ndp_val = value;
Adapter->rx_limit_onintr = value;
- goto finished;
+ break;
case PARAM_RX_RDTR:
ndp->ndp_val = value;
Adapter->rx_intr_delay = value;
E1000_WRITE_REG(hw, E1000_RDTR, value);
- goto finished;
+ break;
case PARAM_RX_RADV:
ndp->ndp_val = value;
Adapter->rx_intr_abs_delay = value;
E1000_WRITE_REG(hw, E1000_RADV, value);
- goto finished;
- default:
break;
- }
-
- /*
- * ndd params that will impact link status
- */
- if (Adapter->param_adv_1000fdx) {
- autoneg_advertised |= ADVERTISE_1000_FULL;
- }
- if (Adapter->param_adv_100fdx) {
- autoneg_advertised |= ADVERTISE_100_FULL;
- }
- if (Adapter->param_adv_100hdx) {
- autoneg_advertised |= ADVERTISE_100_HALF;
- }
- if (Adapter->param_adv_10fdx) {
- autoneg_advertised |= ADVERTISE_10_FULL;
- }
- if (Adapter->param_adv_10hdx) {
- autoneg_advertised |= ADVERTISE_10_HALF;
- }
-
- switch (Adapter->param_force_speed_duplex) {
- case GDIAG_10_HALF:
- forced_speed_duplex = ADVERTISE_10_HALF;
- break;
- case GDIAG_10_FULL:
- forced_speed_duplex = ADVERTISE_10_FULL;
- break;
- case GDIAG_100_HALF:
- forced_speed_duplex = ADVERTISE_100_HALF;
- break;
- case GDIAG_100_FULL:
- forced_speed_duplex = ADVERTISE_100_FULL;
- break;
- default:
- ASSERT(B_FALSE);
- break;
- }
-
- switch (ndp->ndp_info) {
- /* Auto-Negotiation Advertisement Capabilities */
case PARAM_ADV_AUTONEG_CAP:
- if (value != ndp->ndp_val) {
- autoneg_enable = (value == 1) ? B_TRUE : B_FALSE;
- link_change = B_TRUE;
- }
- break;
case PARAM_ADV_1000FDX_CAP:
- if (value != ndp->ndp_val) {
- if (Adapter->param_adv_autoneg == 0) {
- e1000g_log(Adapter, CE_WARN,
- "ndd set: adv_1000fdx requires "
- "adv_autoneg_cap enabled");
- goto finished;
- }
- autoneg_enable = B_TRUE;
- link_change = B_TRUE;
- if (value == 1) {
- autoneg_advertised |= ADVERTISE_1000_FULL;
- } else {
- autoneg_advertised &= ~ADVERTISE_1000_FULL;
- }
- }
- break;
case PARAM_ADV_100FDX_CAP:
- if (value != ndp->ndp_val) {
- if (Adapter->param_adv_autoneg == 0) {
- e1000g_log(Adapter, CE_WARN,
- "ndd set: adv_100fdx requires "
- "adv_autoneg_cap enabled");
- goto finished;
- }
- autoneg_enable = B_TRUE;
- link_change = B_TRUE;
- if (value == 1) {
- autoneg_advertised |= ADVERTISE_100_FULL;
- } else {
- autoneg_advertised &= ~ADVERTISE_100_FULL;
- }
- }
- break;
case PARAM_ADV_100HDX_CAP:
- if (value != ndp->ndp_val) {
- if (Adapter->param_adv_autoneg == 0) {
- e1000g_log(Adapter, CE_WARN,
- "ndd set: adv_100hdx requires "
- "adv_autoneg_cap enabled");
- goto finished;
- }
- autoneg_enable = B_TRUE;
- link_change = B_TRUE;
- if (value == 1) {
- autoneg_advertised |= ADVERTISE_100_HALF;
- } else {
- autoneg_advertised &= ~ADVERTISE_100_HALF;
- }
- }
- break;
case PARAM_ADV_10FDX_CAP:
- if (value != ndp->ndp_val) {
- if (Adapter->param_adv_autoneg == 0) {
- e1000g_log(Adapter, CE_WARN,
- "ndd set: adv_10fdx requires "
- "adv_autoneg_cap enabled");
- goto finished;
- }
- autoneg_enable = B_TRUE;
- link_change = B_TRUE;
- if (value == 1) {
- autoneg_advertised |= ADVERTISE_10_FULL;
- } else {
- autoneg_advertised &= ~ADVERTISE_10_FULL;
- }
- }
- break;
case PARAM_ADV_10HDX_CAP:
- if (value != ndp->ndp_val) {
- if (Adapter->param_adv_autoneg == 0) {
- e1000g_log(Adapter, CE_WARN,
- "ndd set: adv_10hdx requires "
- "adv_autoneg_cap enabled");
- goto finished;
- }
- autoneg_enable = B_TRUE;
- link_change = B_TRUE;
- if (value == 1) {
- autoneg_advertised |= ADVERTISE_10_HALF;
- } else {
- autoneg_advertised &= ~ADVERTISE_10_HALF;
- }
- }
- break;
- case PARAM_FORCE_SPEED_DUPLEX:
- if (value != ndp->ndp_val) {
- if (Adapter->param_adv_autoneg == 1) {
- e1000g_log(Adapter, CE_WARN,
- "ndd set: force_speed_duplex requires "
- "adv_autoneg_cap disabled");
- goto finished;
- }
- autoneg_enable = B_FALSE;
- link_change = B_TRUE;
- switch (value) {
- case GDIAG_10_HALF:
- forced_speed_duplex = ADVERTISE_10_HALF;
- break;
- case GDIAG_10_FULL:
- forced_speed_duplex = ADVERTISE_10_FULL;
- break;
- case GDIAG_100_HALF:
- forced_speed_duplex = ADVERTISE_100_HALF;
- break;
- case GDIAG_100_FULL:
- forced_speed_duplex = ADVERTISE_100_FULL;
- break;
- default:
- ASSERT(B_FALSE);
- break;
- }
- }
+ ndp->ndp_val = value;
+ (void) e1000g_reset_link(Adapter);
break;
default:
- goto finished;
- }
-
- if (link_change) {
- if (autoneg_enable) {
- if (autoneg_advertised == 0) {
- e1000g_log(Adapter, CE_WARN,
- "ndd set: there must be at least one "
- "advertised capability enabled");
- goto finished;
- }
-
- hw->mac.autoneg = B_TRUE;
- hw->phy.autoneg_advertised = autoneg_advertised;
- } else {
- hw->mac.autoneg = B_FALSE;
- hw->mac.forced_speed_duplex = forced_speed_duplex;
- }
-
- ndp->ndp_val = value;
-
- e1000_setup_link(hw);
+ break;
}
-
-finished:
rw_exit(&Adapter->chip_lock);
if (e1000g_check_acc_handle(Adapter->osdep.reg_handle) != DDI_FM_OK)
@@ -766,6 +450,8 @@ e1000g_nd_init(struct e1000g *Adapter)
if (e1000g_nd_param_load(Adapter) != DDI_SUCCESS)
return (DDI_FAILURE);
+ e1000g_nd_param_sync(Adapter);
+
return (DDI_SUCCESS);
}
@@ -817,6 +503,8 @@ e1000g_nd_ioctl(struct e1000g *Adapter, queue_t *wq,
ok = nd_getset(wq, Adapter->nd_data, mp);
+ e1000g_nd_param_sync(Adapter);
+
if (!ok)
return (IOC_INVAL);
diff --git a/usr/src/uts/common/io/e1000g/e1000g_rx.c b/usr/src/uts/common/io/e1000g/e1000g_rx.c
index 7ca3b70376..0cfa0453ca 100644
--- a/usr/src/uts/common/io/e1000g/e1000g_rx.c
+++ b/usr/src/uts/common/io/e1000g/e1000g_rx.c
@@ -337,24 +337,17 @@ e1000g_rx_setup(struct e1000g *Adapter)
if (Adapter->strip_crc)
reg_val |= E1000_RCTL_SECRC; /* Strip Ethernet CRC */
- switch (hw->mac.max_frame_size) {
- case ETHERMAX:
- reg_val |= E1000_RCTL_SZ_2048;
- break;
- case FRAME_SIZE_UPTO_4K:
+ if ((hw->mac.max_frame_size > FRAME_SIZE_UPTO_2K) &&
+ (hw->mac.max_frame_size <= FRAME_SIZE_UPTO_4K))
reg_val |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX;
- break;
- case FRAME_SIZE_UPTO_8K:
+ else if ((hw->mac.max_frame_size > FRAME_SIZE_UPTO_4K) &&
+ (hw->mac.max_frame_size <= FRAME_SIZE_UPTO_8K))
reg_val |= E1000_RCTL_SZ_8192 | E1000_RCTL_BSEX;
- break;
- case FRAME_SIZE_UPTO_9K:
- case FRAME_SIZE_UPTO_16K:
+ else if ((hw->mac.max_frame_size > FRAME_SIZE_UPTO_8K) &&
+ (hw->mac.max_frame_size <= FRAME_SIZE_UPTO_16K))
reg_val |= E1000_RCTL_SZ_16384 | E1000_RCTL_BSEX;
- break;
- default:
+ else
reg_val |= E1000_RCTL_SZ_2048;
- break;
- }
if (e1000_tbi_sbp_enabled_82543(hw))
reg_val |= E1000_RCTL_SBP;
@@ -562,8 +555,8 @@ e1000g_receive(struct e1000g *Adapter)
* we need to strip it before sending it up to the stack.
*/
if (end_of_packet && !Adapter->strip_crc) {
- if (length > CRC_LENGTH) {
- length -= CRC_LENGTH;
+ if (length > ETHERFCSL) {
+ length -= ETHERFCSL;
} else {
/*
* If the fragment is smaller than the CRC,
@@ -572,9 +565,9 @@ e1000g_receive(struct e1000g *Adapter)
*/
ASSERT(rx_ring->rx_mblk_tail != NULL);
rx_ring->rx_mblk_tail->b_wptr -=
- CRC_LENGTH - length;
+ ETHERFCSL - length;
rx_ring->rx_mblk_len -=
- CRC_LENGTH - length;
+ ETHERFCSL - length;
QUEUE_POP_HEAD(&rx_ring->recv_list);
diff --git a/usr/src/uts/common/io/e1000g/e1000g_stat.c b/usr/src/uts/common/io/e1000g/e1000g_stat.c
index 83b2002d4a..2844d001e8 100644
--- a/usr/src/uts/common/io/e1000g/e1000g_stat.c
+++ b/usr/src/uts/common/io/e1000g/e1000g_stat.c
@@ -539,75 +539,71 @@ e1000g_m_stat(void *arg, uint_t stat, uint64_t *val)
break;
case ETHER_STAT_CAP_1000FDX:
- *val = ((Adapter->phy_ext_status & IEEE_ESR_1000T_FD_CAPS) ||
- (Adapter->phy_ext_status & IEEE_ESR_1000X_FD_CAPS)) ? 1 : 0;
+ *val = Adapter->param_1000fdx_cap;
break;
case ETHER_STAT_CAP_1000HDX:
- *val = ((Adapter->phy_ext_status & IEEE_ESR_1000T_HD_CAPS) ||
- (Adapter->phy_ext_status & IEEE_ESR_1000X_HD_CAPS)) ? 1 : 0;
+ *val = Adapter->param_1000hdx_cap;
break;
case ETHER_STAT_CAP_100FDX:
- *val = ((Adapter->phy_status & MII_SR_100X_FD_CAPS) ||
- (Adapter->phy_status & MII_SR_100T2_FD_CAPS)) ? 1 : 0;
+ *val = Adapter->param_100fdx_cap;
break;
case ETHER_STAT_CAP_100HDX:
- *val = ((Adapter->phy_status & MII_SR_100X_HD_CAPS) ||
- (Adapter->phy_status & MII_SR_100T2_HD_CAPS)) ? 1 : 0;
+ *val = Adapter->param_100hdx_cap;
break;
case ETHER_STAT_CAP_10FDX:
- *val = (Adapter->phy_status & MII_SR_10T_FD_CAPS) ? 1 : 0;
+ *val = Adapter->param_10fdx_cap;
break;
case ETHER_STAT_CAP_10HDX:
- *val = (Adapter->phy_status & MII_SR_10T_HD_CAPS) ? 1 : 0;
+ *val = Adapter->param_10hdx_cap;
break;
case ETHER_STAT_CAP_ASMPAUSE:
- *val = (Adapter->phy_an_adv & NWAY_AR_ASM_DIR) ? 1 : 0;
+ *val = Adapter->param_asym_pause_cap;
break;
case ETHER_STAT_CAP_PAUSE:
- *val = (Adapter->phy_an_adv & NWAY_AR_PAUSE) ? 1 : 0;
+ *val = Adapter->param_pause_cap;
break;
case ETHER_STAT_CAP_AUTONEG:
- *val = (Adapter->phy_status & MII_SR_AUTONEG_CAPS) ? 1 : 0;
+ *val = Adapter->param_autoneg_cap;
break;
case ETHER_STAT_ADV_CAP_1000FDX:
- *val = (Adapter->phy_1000t_ctrl & CR_1000T_FD_CAPS) ? 1 : 0;
+ *val = Adapter->param_adv_1000fdx;
break;
case ETHER_STAT_ADV_CAP_1000HDX:
- *val = (Adapter->phy_1000t_ctrl & CR_1000T_HD_CAPS) ? 1 : 0;
+ *val = Adapter->param_adv_1000hdx;
break;
case ETHER_STAT_ADV_CAP_100FDX:
- *val = (Adapter->phy_an_adv & NWAY_AR_100TX_FD_CAPS) ? 1 : 0;
+ *val = Adapter->param_adv_100fdx;
break;
case ETHER_STAT_ADV_CAP_100HDX:
- *val = (Adapter->phy_an_adv & NWAY_AR_100TX_HD_CAPS) ? 1 : 0;
+ *val = Adapter->param_adv_100hdx;
break;
case ETHER_STAT_ADV_CAP_10FDX:
- *val = (Adapter->phy_an_adv & NWAY_AR_10T_FD_CAPS) ? 1 : 0;
+ *val = Adapter->param_adv_10fdx;
break;
case ETHER_STAT_ADV_CAP_10HDX:
- *val = (Adapter->phy_an_adv & NWAY_AR_10T_HD_CAPS) ? 1 : 0;
+ *val = Adapter->param_adv_10hdx;
break;
case ETHER_STAT_ADV_CAP_ASMPAUSE:
- *val = (Adapter->phy_an_adv & NWAY_AR_ASM_DIR) ? 1 : 0;
+ *val = Adapter->param_adv_asym_pause;
break;
case ETHER_STAT_ADV_CAP_PAUSE:
- *val = (Adapter->phy_an_adv & NWAY_AR_PAUSE) ? 1 : 0;
+ *val = Adapter->param_adv_pause;
break;
case ETHER_STAT_ADV_CAP_AUTONEG:
@@ -615,53 +611,51 @@ e1000g_m_stat(void *arg, uint_t stat, uint64_t *val)
break;
case ETHER_STAT_LP_CAP_1000FDX:
- *val =
- (Adapter->phy_1000t_status & SR_1000T_LP_FD_CAPS) ? 1 : 0;
+ *val = Adapter->param_lp_1000fdx;
break;
case ETHER_STAT_LP_CAP_1000HDX:
- *val =
- (Adapter->phy_1000t_status & SR_1000T_LP_HD_CAPS) ? 1 : 0;
+ *val = Adapter->param_lp_1000hdx;
break;
case ETHER_STAT_LP_CAP_100FDX:
- *val = (Adapter->phy_lp_able & NWAY_LPAR_100TX_FD_CAPS) ? 1 : 0;
+ *val = Adapter->param_lp_100fdx;
break;
case ETHER_STAT_LP_CAP_100HDX:
- *val = (Adapter->phy_lp_able & NWAY_LPAR_100TX_HD_CAPS) ? 1 : 0;
+ *val = Adapter->param_lp_100hdx;
break;
case ETHER_STAT_LP_CAP_10FDX:
- *val = (Adapter->phy_lp_able & NWAY_LPAR_10T_FD_CAPS) ? 1 : 0;
+ *val = Adapter->param_lp_10fdx;
break;
case ETHER_STAT_LP_CAP_10HDX:
- *val = (Adapter->phy_lp_able & NWAY_LPAR_10T_HD_CAPS) ? 1 : 0;
+ *val = Adapter->param_lp_10hdx;
break;
case ETHER_STAT_LP_CAP_ASMPAUSE:
- *val = (Adapter->phy_lp_able & NWAY_LPAR_ASM_DIR) ? 1 : 0;
+ *val = Adapter->param_lp_asym_pause;
break;
case ETHER_STAT_LP_CAP_PAUSE:
- *val = (Adapter->phy_lp_able & NWAY_LPAR_PAUSE) ? 1 : 0;
+ *val = Adapter->param_lp_pause;
break;
case ETHER_STAT_LP_CAP_AUTONEG:
- *val = (Adapter->phy_an_exp & NWAY_ER_LP_NWAY_CAPS) ? 1 : 0;
+ *val = Adapter->param_lp_autoneg;
break;
case ETHER_STAT_LINK_ASMPAUSE:
- *val = (Adapter->phy_an_adv & NWAY_AR_ASM_DIR) ? 1 : 0;
+ *val = Adapter->param_asym_pause_cap;
break;
case ETHER_STAT_LINK_PAUSE:
- *val = (Adapter->phy_an_adv & NWAY_AR_PAUSE) ? 1 : 0;
+ *val = Adapter->param_pause_cap;
break;
case ETHER_STAT_LINK_AUTONEG:
- *val = (Adapter->phy_ctrl & MII_CR_AUTO_NEG_EN) ? 1 : 0;
+ *val = hw->mac.autoneg;
break;
case ETHER_STAT_LINK_DUPLEX:
@@ -669,6 +663,18 @@ e1000g_m_stat(void *arg, uint_t stat, uint64_t *val)
LINK_DUPLEX_FULL : LINK_DUPLEX_HALF;
break;
+ case ETHER_STAT_CAP_100T4:
+ *val = Adapter->param_100t4_cap;
+ break;
+
+ case ETHER_STAT_ADV_CAP_100T4:
+ *val = Adapter->param_adv_100t4;
+ break;
+
+ case ETHER_STAT_LP_CAP_100T4:
+ *val = Adapter->param_lp_100t4;
+ break;
+
default:
rw_exit(&Adapter->chip_lock);
return (ENOTSUP);
diff --git a/usr/src/uts/common/io/e1000g/e1000g_sw.h b/usr/src/uts/common/io/e1000g/e1000g_sw.h
index ba7f1f4a6f..3bc2d988c1 100644
--- a/usr/src/uts/common/io/e1000g/e1000g_sw.h
+++ b/usr/src/uts/common/io/e1000g/e1000g_sw.h
@@ -122,7 +122,7 @@ extern "C" {
#define MIN_TX_INTR_ABS_DELAY 0
#define MIN_INTR_THROTTLING 0
#define MIN_RX_BCOPY_THRESHOLD 0
-#define MIN_TX_BCOPY_THRESHOLD MINIMUM_ETHERNET_PACKET_SIZE
+#define MIN_TX_BCOPY_THRESHOLD ETHERMIN
#define MIN_TX_RECYCLE_THRESHOLD 0
#define MIN_TX_RECYCLE_NUM MAX_TX_DESC_PER_PACKET
@@ -255,15 +255,13 @@ extern "C" {
#define FRAME_SIZE_UPTO_16K 16384
#define FRAME_SIZE_UPTO_9K 9234
-/* The sizes (in bytes) of a ethernet packet */
-#define MAXIMUM_ETHERNET_FRAME_SIZE 1518 /* With FCS */
-#define MINIMUM_ETHERNET_FRAME_SIZE 64 /* With FCS */
-#define ETHERNET_FCS_SIZE 4
-#define MAXIMUM_ETHERNET_PACKET_SIZE \
- (MAXIMUM_ETHERNET_FRAME_SIZE - ETHERNET_FCS_SIZE)
-#define MINIMUM_ETHERNET_PACKET_SIZE \
- (MINIMUM_ETHERNET_FRAME_SIZE - ETHERNET_FCS_SIZE)
-#define CRC_LENGTH ETHERNET_FCS_SIZE
+#define MAXIMUM_MTU 9000
+#define DEFAULT_MTU ETHERMTU
+
+#define DEFAULT_FRAME_SIZE \
+ (DEFAULT_MTU + sizeof (struct ether_vlan_header) + ETHERFCSL)
+#define MAXIMUM_FRAME_SIZE \
+ (MAXIMUM_MTU + sizeof (struct ether_vlan_header) + ETHERFCSL)
/* Defines for Tx stall check */
#define E1000G_STALL_WATCHDOG_COUNT 8
@@ -404,16 +402,38 @@ extern "C" {
/*
* Shorthand for the NDD parameters
*/
+#define param_autoneg_cap nd_params[PARAM_AUTONEG_CAP].ndp_val
+#define param_pause_cap nd_params[PARAM_PAUSE_CAP].ndp_val
+#define param_asym_pause_cap nd_params[PARAM_ASYM_PAUSE_CAP].ndp_val
+#define param_1000fdx_cap nd_params[PARAM_1000FDX_CAP].ndp_val
+#define param_1000hdx_cap nd_params[PARAM_1000HDX_CAP].ndp_val
+#define param_100t4_cap nd_params[PARAM_100T4_CAP].ndp_val
+#define param_100fdx_cap nd_params[PARAM_100FDX_CAP].ndp_val
+#define param_100hdx_cap nd_params[PARAM_100HDX_CAP].ndp_val
+#define param_10fdx_cap nd_params[PARAM_10FDX_CAP].ndp_val
+#define param_10hdx_cap nd_params[PARAM_10HDX_CAP].ndp_val
+
#define param_adv_autoneg nd_params[PARAM_ADV_AUTONEG_CAP].ndp_val
#define param_adv_pause nd_params[PARAM_ADV_PAUSE_CAP].ndp_val
#define param_adv_asym_pause nd_params[PARAM_ADV_ASYM_PAUSE_CAP].ndp_val
#define param_adv_1000fdx nd_params[PARAM_ADV_1000FDX_CAP].ndp_val
#define param_adv_1000hdx nd_params[PARAM_ADV_1000HDX_CAP].ndp_val
+#define param_adv_100t4 nd_params[PARAM_ADV_100T4_CAP].ndp_val
#define param_adv_100fdx nd_params[PARAM_ADV_100FDX_CAP].ndp_val
#define param_adv_100hdx nd_params[PARAM_ADV_100HDX_CAP].ndp_val
#define param_adv_10fdx nd_params[PARAM_ADV_10FDX_CAP].ndp_val
#define param_adv_10hdx nd_params[PARAM_ADV_10HDX_CAP].ndp_val
-#define param_force_speed_duplex nd_params[PARAM_FORCE_SPEED_DUPLEX].ndp_val
+
+#define param_lp_autoneg nd_params[PARAM_LP_AUTONEG_CAP].ndp_val
+#define param_lp_pause nd_params[PARAM_LP_PAUSE_CAP].ndp_val
+#define param_lp_asym_pause nd_params[PARAM_LP_ASYM_PAUSE_CAP].ndp_val
+#define param_lp_1000fdx nd_params[PARAM_LP_1000FDX_CAP].ndp_val
+#define param_lp_1000hdx nd_params[PARAM_LP_1000HDX_CAP].ndp_val
+#define param_lp_100t4 nd_params[PARAM_LP_100T4_CAP].ndp_val
+#define param_lp_100fdx nd_params[PARAM_LP_100FDX_CAP].ndp_val
+#define param_lp_100hdx nd_params[PARAM_LP_100HDX_CAP].ndp_val
+#define param_lp_10fdx nd_params[PARAM_LP_10FDX_CAP].ndp_val
+#define param_lp_10hdx nd_params[PARAM_LP_10HDX_CAP].ndp_val
#ifdef E1000G_DEBUG
/*
@@ -508,8 +528,6 @@ enum {
PARAM_LP_10FDX_CAP,
PARAM_LP_10HDX_CAP,
- PARAM_FORCE_SPEED_DUPLEX,
-
PARAM_LINK_STATUS,
PARAM_LINK_SPEED,
PARAM_LINK_DUPLEX,
@@ -910,6 +928,8 @@ typedef struct e1000g {
uint32_t rx_intr_abs_delay;
uint32_t intr_throttling_rate;
+ uint32_t default_mtu;
+
boolean_t watchdog_timer_enabled;
boolean_t watchdog_timer_started;
timeout_id_t watchdog_tid;
@@ -991,6 +1011,14 @@ typedef struct e1000g {
* FMA capabilities
*/
int fm_capabilities;
+
+ uint32_t param_en_1000fdx:1,
+ param_en_1000hdx:1,
+ param_en_100fdx:1,
+ param_en_100hdx:1,
+ param_en_10fdx:1,
+ param_en_10hdx:1,
+ param_pad_to_32:26;
} e1000g_t;
@@ -1035,6 +1063,8 @@ int e1000g_check_dma_handle(ddi_dma_handle_t handle);
void e1000g_fm_ereport(struct e1000g *Adapter, char *detail);
void e1000g_set_fma_flags(struct e1000g *Adapter, int acc_flag, int dma_flag);
+int e1000g_reset_link(struct e1000g *Adapter);
+
#pragma inline(e1000_rar_set)
/*
diff --git a/usr/src/uts/common/io/e1000g/e1000g_tx.c b/usr/src/uts/common/io/e1000g/e1000g_tx.c
index 10fb13aefd..757bc093d1 100644
--- a/usr/src/uts/common/io/e1000g/e1000g_tx.c
+++ b/usr/src/uts/common/io/e1000g/e1000g_tx.c
@@ -179,7 +179,7 @@ e1000g_send(struct e1000g *Adapter, mblk_t *mp)
}
/* Make sure packet is less than the max frame size */
- if (msg_size > hw->mac.max_frame_size + VLAN_TAGSZ) {
+ if (msg_size > hw->mac.max_frame_size - ETHERFCSL) {
/*
* For the over size packet, we'll just drop it.
* So we return B_TRUE here.
@@ -224,7 +224,7 @@ e1000g_send(struct e1000g *Adapter, mblk_t *mp)
* If the message size is less than the minimum ethernet packet size,
* we'll use bcopy to send it, and padd it to 60 bytes later.
*/
- if (msg_size < MINIMUM_ETHERNET_PACKET_SIZE) {
+ if (msg_size < ETHERMIN) {
E1000G_DEBUG_STAT(tx_ring->stat_under_size);
force_bcopy |= FORCE_BCOPY_UNDER_SIZE;
}
@@ -1001,11 +1001,11 @@ e1000g_tx_copy(e1000g_tx_ring_t *tx_ring, p_tx_sw_packet_t packet,
* for CRC.
*/
if (force_bcopy & FORCE_BCOPY_UNDER_SIZE) {
- ASSERT(tx_buf->len < MINIMUM_ETHERNET_PACKET_SIZE);
+ ASSERT(tx_buf->len < ETHERMIN);
bzero(tx_buf->address + tx_buf->len,
- MINIMUM_ETHERNET_PACKET_SIZE - tx_buf->len);
- tx_buf->len = MINIMUM_ETHERNET_PACKET_SIZE;
+ ETHERMIN - tx_buf->len);
+ tx_buf->len = ETHERMIN;
}
#ifdef __sparc