diff options
author | cc210113 <none@none> | 2008-04-09 18:30:42 -0700 |
---|---|---|
committer | cc210113 <none@none> | 2008-04-09 18:30:42 -0700 |
commit | 9ce7e93c0e8e6d2b400f40e9c5742b1d6682611e (patch) | |
tree | eb2f18ee756c212cfdf66bb3718fe97974d09778 | |
parent | e57b9183811d515e3bbcd1a104516f0102fde114 (diff) | |
download | illumos-gate-9ce7e93c0e8e6d2b400f40e9c5742b1d6682611e.tar.gz |
6673650 e1000g needs to support Brussels
-rw-r--r-- | usr/src/uts/common/io/e1000g/README | 5 | ||||
-rw-r--r-- | usr/src/uts/common/io/e1000g/e1000g_main.c | 954 | ||||
-rw-r--r-- | usr/src/uts/common/io/e1000g/e1000g_ndd.c | 382 | ||||
-rw-r--r-- | usr/src/uts/common/io/e1000g/e1000g_rx.c | 29 | ||||
-rw-r--r-- | usr/src/uts/common/io/e1000g/e1000g_stat.c | 76 | ||||
-rw-r--r-- | usr/src/uts/common/io/e1000g/e1000g_sw.h | 56 | ||||
-rw-r--r-- | usr/src/uts/common/io/e1000g/e1000g_tx.c | 10 |
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 |