summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/io/bge
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/io/bge')
-rw-r--r--usr/src/uts/common/io/bge/bge_chip2.c29
-rw-r--r--usr/src/uts/common/io/bge/bge_impl.h22
-rw-r--r--usr/src/uts/common/io/bge/bge_kstats.c27
-rw-r--r--usr/src/uts/common/io/bge/bge_main2.c516
-rw-r--r--usr/src/uts/common/io/bge/bge_ndd.c73
-rw-r--r--usr/src/uts/common/io/bge/bge_recv2.c8
6 files changed, 578 insertions, 97 deletions
diff --git a/usr/src/uts/common/io/bge/bge_chip2.c b/usr/src/uts/common/io/bge/bge_chip2.c
index 1f29ac14a9..f4a46a15da 100644
--- a/usr/src/uts/common/io/bge/bge_chip2.c
+++ b/usr/src/uts/common/io/bge/bge_chip2.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -1934,8 +1934,6 @@ bge_chip_id_init(bge_t *bgep)
int err;
uint_t i;
- ASSERT(bgep->bge_chip_state == BGE_CHIP_INITIAL);
-
sys_ok = dev_ok = B_FALSE;
cidp = &bgep->chipid;
@@ -1963,6 +1961,8 @@ bge_chip_id_init(bge_t *bgep)
cidp->mbuf_lo_water_rdma = bge_mbuf_lo_water_rdma;
cidp->mbuf_lo_water_rmac = bge_mbuf_lo_water_rmac;
cidp->mbuf_hi_water = bge_mbuf_hi_water;
+ cidp->rx_ticks_norm = bge_rx_ticks_norm;
+ cidp->rx_count_norm = bge_rx_count_norm;
if (cidp->rx_rings == 0 || cidp->rx_rings > BGE_RECV_RINGS_MAX)
cidp->rx_rings = BGE_RECV_RINGS_DEFAULT;
@@ -2649,10 +2649,10 @@ bge_chip_enable_engine(bge_t *bgep, bge_regno_t regno, uint32_t morebits)
* Reprogram the Ethernet, Transmit, and Receive MAC
* modes to match the param_* variables
*/
-static void bge_sync_mac_modes(bge_t *bgep);
+void bge_sync_mac_modes(bge_t *bgep);
#pragma no_inline(bge_sync_mac_modes)
-static void
+void
bge_sync_mac_modes(bge_t *bgep)
{
uint32_t macmode;
@@ -2741,7 +2741,7 @@ bge_chip_sync(bge_t *bgep)
int retval = DDI_SUCCESS;
BGE_TRACE(("bge_chip_sync($%p)",
- (void *)bgep));
+ (void *)bgep));
ASSERT(mutex_owned(bgep->genlock));
@@ -2945,7 +2945,9 @@ bge_chip_stop(bge_t *bgep, boolean_t fault)
if (fault) {
if (bgep->bge_chip_state != BGE_CHIP_FAULT) {
bgep->bge_chip_state = BGE_CHIP_FAULT;
- ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_LOST);
+ if (!bgep->manual_reset)
+ ddi_fm_service_impact(bgep->devinfo,
+ DDI_SERVICE_LOST);
if (bgep->bge_dma_error) {
/*
* need to free buffers in case the fault was
@@ -3926,10 +3928,10 @@ bge_status_sync(bge_t *bgep, uint64_t bits, uint64_t *flags)
return (retval);
}
-static void bge_wake_factotum(bge_t *bgep);
+void bge_wake_factotum(bge_t *bgep);
#pragma inline(bge_wake_factotum)
-static void
+void
bge_wake_factotum(bge_t *bgep)
{
mutex_enter(bgep->softintrlock);
@@ -4464,8 +4466,10 @@ bge_chip_factotum(caddr_t arg)
bgep->asf_status = ASF_STAT_RUN;
}
#endif
- ddi_fm_service_impact(bgep->devinfo,
- DDI_SERVICE_RESTORED);
+ if (!bgep->manual_reset) {
+ ddi_fm_service_impact(bgep->devinfo,
+ DDI_SERVICE_RESTORED);
+ }
}
}
break;
@@ -4507,6 +4511,9 @@ bge_chip_factotum(caddr_t arg)
*/
if (linkchg)
mac_link_update(bgep->mh, bgep->link_state);
+ if (bgep->manual_reset) {
+ bgep->manual_reset = B_FALSE;
+ }
return (result);
}
diff --git a/usr/src/uts/common/io/bge/bge_impl.h b/usr/src/uts/common/io/bge/bge_impl.h
index 8b2bbaebc7..2da4240765 100644
--- a/usr/src/uts/common/io/bge/bge_impl.h
+++ b/usr/src/uts/common/io/bge/bge_impl.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -63,6 +63,7 @@ extern "C" {
#include <sys/pattr.h>
#include <sys/disp.h>
+#include <sys/cmn_err.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
@@ -616,6 +617,9 @@ typedef struct {
uint64_t hw_mac_addr; /* from chip register */
bge_mac_addr_t vendor_addr; /* transform of same */
boolean_t msi_enabled; /* default to true */
+
+ uint32_t rx_ticks_norm;
+ uint32_t rx_count_norm;
} chip_id_t;
#define CHIP_FLAG_SUPPORTED 0x80
@@ -696,7 +700,6 @@ enum {
PARAM_LINK_RX_PAUSE,
PARAM_LINK_TX_PAUSE,
- PARAM_LOOP_MODE,
PARAM_MSI_CNT,
PARAM_DRAIN_MAX,
@@ -916,6 +919,7 @@ typedef struct bge {
boolean_t send_hw_tcp_csum;
boolean_t recv_hw_tcp_csum;
boolean_t promisc;
+ boolean_t manual_reset;
/*
* Miscellaneous operating variables (not synchronised)
@@ -960,6 +964,17 @@ typedef struct bge {
uint32_t asf_status;
timeout_id_t asf_timeout_id;
#endif
+ uint32_t param_en_pause:1,
+ param_en_asym_pause:1,
+ param_en_1000hdx:1,
+ param_en_1000fdx:1,
+ param_en_100fdx:1,
+ param_en_100hdx:1,
+ param_en_10fdx:1,
+ param_en_10hdx:1,
+ param_pad_to_32:24;
+
+ uint32_t param_loop_mode;
} bge_t;
/*
@@ -1009,7 +1024,6 @@ typedef struct bge {
#define param_link_rx_pause nd_params[PARAM_LINK_RX_PAUSE].ndp_val
#define param_link_tx_pause nd_params[PARAM_LINK_TX_PAUSE].ndp_val
-#define param_loop_mode nd_params[PARAM_LOOP_MODE].ndp_val
#define param_msi_cnt nd_params[PARAM_MSI_CNT].ndp_val
#define param_drain_max nd_params[PARAM_DRAIN_MAX].ndp_val
@@ -1220,6 +1234,7 @@ void bge_chip_cyclic(void *arg);
enum ioc_reply bge_chip_ioctl(bge_t *bgep, queue_t *wq, mblk_t *mp,
struct iocblk *iocp);
uint_t bge_intr(caddr_t arg1, caddr_t arg2);
+void bge_sync_mac_modes(bge_t *);
extern uint32_t bge_rx_ticks_norm;
extern uint32_t bge_tx_ticks_norm;
extern uint32_t bge_rx_count_norm;
@@ -1260,6 +1275,7 @@ int bge_alloc_bufs(bge_t *bgep);
void bge_free_bufs(bge_t *bgep);
void bge_intr_enable(bge_t *bgep);
void bge_intr_disable(bge_t *bgep);
+int bge_reprogram(bge_t *);
/* bge_phys.c */
int bge_phys_init(bge_t *bgep);
diff --git a/usr/src/uts/common/io/bge/bge_kstats.c b/usr/src/uts/common/io/bge/bge_kstats.c
index 98141d92ce..32af1a2b13 100644
--- a/usr/src/uts/common/io/bge/bge_kstats.c
+++ b/usr/src/uts/common/io/bge/bge_kstats.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -600,31 +600,6 @@ bge_setup_named_kstat(bge_t *bgep, int instance, char *name,
return (ksp);
}
-/*
- * Create kstats corresponding to NDD parameters
- */
-static kstat_t *
-bge_setup_params_kstat(bge_t *bgep, int instance, char *name,
- int (*update)(kstat_t *, int))
-{
- kstat_t *ksp;
- kstat_named_t *knp;
- int i;
-
- ksp = kstat_create(BGE_DRIVER_NAME, instance, name, "net",
- KSTAT_TYPE_NAMED, PARAM_COUNT, KSTAT_FLAG_PERSISTENT);
- if (ksp != NULL) {
- ksp->ks_private = bgep;
- ksp->ks_update = update;
- for (knp = ksp->ks_data, i = 0; i < PARAM_COUNT; ++knp, ++i)
- kstat_named_init(knp, bgep->nd_params[i].ndp_name+1,
- KSTAT_DATA_UINT64);
- kstat_install(ksp);
- }
-
- return (ksp);
-}
-
void
bge_init_kstats(bge_t *bgep, int instance)
{
diff --git a/usr/src/uts/common/io/bge/bge_main2.c b/usr/src/uts/common/io/bge/bge_main2.c
index f80a750652..7a13f85e50 100644
--- a/usr/src/uts/common/io/bge/bge_main2.c
+++ b/usr/src/uts/common/io/bge/bge_main2.c
@@ -28,6 +28,7 @@
#include "bge_impl.h"
#include <sys/sdt.h>
+#include <sys/dld.h>
/*
* This is the string displayed by modinfo, etc.
@@ -127,8 +128,17 @@ static int bge_m_unicst_add(void *, mac_multi_addr_t *);
static int bge_m_unicst_remove(void *, mac_addr_slot_t);
static int bge_m_unicst_modify(void *, mac_multi_addr_t *);
static int bge_m_unicst_get(void *, mac_multi_addr_t *);
-
-#define BGE_M_CALLBACK_FLAGS (MC_RESOURCES | MC_IOCTL | MC_GETCAPAB)
+static int bge_m_setprop(void *, const char *, mac_prop_id_t,
+ uint_t, const void *);
+static int bge_m_getprop(void *, const char *, mac_prop_id_t,
+ uint_t, void *);
+static int bge_set_priv_prop(bge_t *, const char *, uint_t,
+ const void *);
+static int bge_get_priv_prop(bge_t *, const char *, uint_t,
+ void *);
+
+#define BGE_M_CALLBACK_FLAGS\
+ (MC_RESOURCES | MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP)
static mac_callbacks_t bge_m_callbacks = {
BGE_M_CALLBACK_FLAGS,
@@ -141,7 +151,11 @@ static mac_callbacks_t bge_m_callbacks = {
bge_m_tx,
bge_m_resources,
bge_m_ioctl,
- bge_m_getcapab
+ bge_m_getcapab,
+ NULL,
+ NULL,
+ bge_m_setprop,
+ bge_m_getprop
};
/*
@@ -834,6 +848,439 @@ bge_m_unicst_get(void *arg, mac_multi_addr_t *maddr)
return (0);
}
+extern void bge_wake_factotum(bge_t *);
+
+static boolean_t
+bge_param_locked(mac_prop_id_t pr_num)
+{
+ /*
+ * All adv_* parameters are locked (read-only) while
+ * the device is in any sort of loopback mode ...
+ */
+ switch (pr_num) {
+ case DLD_PROP_ADV_1000FDX_CAP:
+ case DLD_PROP_EN_1000FDX_CAP:
+ case DLD_PROP_ADV_1000HDX_CAP:
+ case DLD_PROP_EN_1000HDX_CAP:
+ case DLD_PROP_ADV_100FDX_CAP:
+ case DLD_PROP_EN_100FDX_CAP:
+ case DLD_PROP_ADV_100HDX_CAP:
+ case DLD_PROP_EN_100HDX_CAP:
+ case DLD_PROP_ADV_10FDX_CAP:
+ case DLD_PROP_EN_10FDX_CAP:
+ case DLD_PROP_ADV_10HDX_CAP:
+ case DLD_PROP_EN_10HDX_CAP:
+ case DLD_PROP_AUTONEG:
+ case DLD_PROP_FLOWCTRL:
+ return (B_TRUE);
+ }
+ return (B_FALSE);
+}
+/*
+ * callback functions for set/get of properties
+ */
+static int
+bge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
+ uint_t pr_valsize, const void *pr_val)
+{
+ bge_t *bgep = barg;
+ int err = 0;
+ uint64_t cur_mtu, new_mtu;
+ uint_t maxsdu;
+ link_flowctrl_t fl;
+
+ mutex_enter(bgep->genlock);
+ if (bgep->param_loop_mode != BGE_LOOP_NONE &&
+ bge_param_locked(pr_num)) {
+ /*
+ * All adv_* parameters are locked (read-only)
+ * while the device is in any sort of loopback mode.
+ */
+ mutex_exit(bgep->genlock);
+ return (EBUSY);
+ }
+ switch (pr_num) {
+ case DLD_PROP_EN_1000FDX_CAP:
+ bgep->param_en_1000fdx = *(uint8_t *)pr_val;
+ bgep->param_adv_1000fdx = *(uint8_t *)pr_val;
+ goto reprogram;
+ case DLD_PROP_EN_1000HDX_CAP:
+ bgep->param_en_1000hdx = *(uint8_t *)pr_val;
+ bgep->param_adv_1000hdx = *(uint8_t *)pr_val;
+ goto reprogram;
+ case DLD_PROP_EN_100FDX_CAP:
+ bgep->param_en_100fdx = *(uint8_t *)pr_val;
+ bgep->param_adv_100fdx = *(uint8_t *)pr_val;
+ goto reprogram;
+ case DLD_PROP_EN_100HDX_CAP:
+ bgep->param_en_100hdx = *(uint8_t *)pr_val;
+ bgep->param_adv_100hdx = *(uint8_t *)pr_val;
+ goto reprogram;
+ case DLD_PROP_EN_10FDX_CAP:
+ bgep->param_en_10fdx = *(uint8_t *)pr_val;
+ bgep->param_adv_10fdx = *(uint8_t *)pr_val;
+ goto reprogram;
+ case DLD_PROP_EN_10HDX_CAP:
+ bgep->param_en_10hdx = *(uint8_t *)pr_val;
+ bgep->param_adv_10hdx = *(uint8_t *)pr_val;
+reprogram:
+ if (err == 0 && bge_reprogram(bgep) == IOC_INVAL)
+ 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 = EINVAL; /* read-only prop. Can't set this */
+ break;
+ case DLD_PROP_AUTONEG:
+ bgep->param_adv_autoneg = *(uint8_t *)pr_val;
+ if (bge_reprogram(bgep) == IOC_INVAL)
+ err = EINVAL;
+ break;
+ case DLD_PROP_DEFMTU:
+ cur_mtu = bgep->chipid.default_mtu;
+ bcopy(pr_val, &new_mtu, sizeof (new_mtu));
+ if (new_mtu == cur_mtu) {
+ err = 0;
+ break;
+ }
+ if (new_mtu < BGE_DEFAULT_MTU ||
+ new_mtu > BGE_MAXIMUM_MTU) {
+ err = EINVAL;
+ break;
+ }
+ if ((new_mtu > BGE_DEFAULT_MTU) &&
+ (bgep->chipid.flags & CHIP_FLAG_NO_JUMBO)) {
+ err = EINVAL;
+ break;
+ }
+ if (bgep->bge_mac_state == BGE_MAC_STARTED) {
+ err = EBUSY;
+ break;
+ }
+ bgep->chipid.default_mtu = new_mtu;
+ if (bge_chip_id_init(bgep)) {
+ err = EINVAL;
+ break;
+ }
+ maxsdu = bgep->chipid.ethmax_size -
+ sizeof (struct ether_header);
+ err = mac_maxsdu_update(bgep->mh, maxsdu);
+ if (err == 0) {
+ bgep->bge_dma_error = B_TRUE;
+ bgep->manual_reset = B_TRUE;
+ bge_chip_stop(bgep, B_TRUE);
+ bge_wake_factotum(bgep);
+ err = 0;
+ }
+ break;
+ case DLD_PROP_FLOWCTRL:
+ bcopy(pr_val, &fl, sizeof (fl));
+ switch (fl) {
+ default:
+ err = EINVAL;
+ break;
+ case LINK_FLOWCTRL_NONE:
+ bgep->param_adv_pause = 0;
+ bgep->param_adv_asym_pause = 0;
+
+ bgep->param_link_rx_pause = B_FALSE;
+ bgep->param_link_tx_pause = B_FALSE;
+ break;
+ case LINK_FLOWCTRL_RX:
+ if (!((bgep->param_lp_pause == 0) &&
+ (bgep->param_lp_asym_pause == 1))) {
+ err = EINVAL;
+ break;
+ }
+ bgep->param_adv_pause = 1;
+ bgep->param_adv_asym_pause = 1;
+
+ bgep->param_link_rx_pause = B_TRUE;
+ bgep->param_link_tx_pause = B_FALSE;
+ break;
+ case LINK_FLOWCTRL_TX:
+ if (!((bgep->param_lp_pause == 1) &&
+ (bgep->param_lp_asym_pause == 1))) {
+ err = EINVAL;
+ break;
+ }
+ bgep->param_adv_pause = 0;
+ bgep->param_adv_asym_pause = 1;
+
+ bgep->param_link_rx_pause = B_FALSE;
+ bgep->param_link_tx_pause = B_TRUE;
+ break;
+ case LINK_FLOWCTRL_BI:
+ if (bgep->param_lp_pause != 1) {
+ err = EINVAL;
+ break;
+ }
+ bgep->param_adv_pause = 1;
+
+ bgep->param_link_rx_pause = B_TRUE;
+ bgep->param_link_tx_pause = B_TRUE;
+ break;
+ }
+
+ if (err == 0) {
+ if (bge_reprogram(bgep) == IOC_INVAL)
+ err = EINVAL;
+ }
+
+ break;
+ default:
+ err = bge_set_priv_prop(bgep, pr_name, pr_valsize,
+ pr_val);
+ break;
+ }
+ mutex_exit(bgep->genlock);
+ return (err);
+}
+static int
+bge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
+ uint_t pr_valsize, void *pr_val)
+{
+ bge_t *bgep = barg;
+ int err = 0;
+ link_flowctrl_t fl;
+
+ bzero(pr_val, pr_valsize);
+ switch (pr_num) {
+ case DLD_PROP_DUPLEX:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_link_duplex;
+ break;
+ case DLD_PROP_SPEED:
+ if (pr_valsize < sizeof (uint_t))
+ return (EINVAL);
+ bcopy(&(bgep->param_link_speed), pr_val,
+ sizeof (bgep->param_link_speed));
+ break;
+ case DLD_PROP_STATUS:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_link_up;
+ break;
+ case DLD_PROP_AUTONEG:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_adv_autoneg;
+ break;
+ case DLD_PROP_DEFMTU: {
+ uint64_t tmp = 0;
+
+ if (pr_valsize < sizeof (uint64_t))
+ return (EINVAL);
+ tmp = bgep->chipid.default_mtu;
+ bcopy(&tmp, pr_val, sizeof (tmp));
+ break;
+ }
+ case DLD_PROP_FLOWCTRL:
+ if (pr_valsize < sizeof (link_flowctrl_t))
+ return (EINVAL);
+ if (bgep->param_link_rx_pause &&
+ !bgep->param_link_tx_pause)
+ fl = LINK_FLOWCTRL_RX;
+
+ if (!bgep->param_link_rx_pause &&
+ !bgep->param_link_tx_pause)
+ fl = LINK_FLOWCTRL_NONE;
+
+ if (!bgep->param_link_rx_pause &&
+ bgep->param_link_tx_pause)
+ fl = LINK_FLOWCTRL_TX;
+
+ if (bgep->param_link_rx_pause &&
+ bgep->param_link_tx_pause)
+ fl = LINK_FLOWCTRL_BI;
+ bcopy(&fl, pr_val, sizeof (fl));
+ break;
+ case DLD_PROP_ADV_1000FDX_CAP:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_adv_1000fdx;
+ break;
+ case DLD_PROP_EN_1000FDX_CAP:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_en_1000fdx;
+ break;
+ case DLD_PROP_ADV_1000HDX_CAP:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_adv_1000hdx;
+ break;
+ case DLD_PROP_EN_1000HDX_CAP:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_en_1000hdx;
+ break;
+ case DLD_PROP_ADV_100FDX_CAP:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_adv_100fdx;
+ break;
+ case DLD_PROP_EN_100FDX_CAP:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_en_100fdx;
+ break;
+ case DLD_PROP_ADV_100HDX_CAP:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_adv_100hdx;
+ break;
+ case DLD_PROP_EN_100HDX_CAP:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_en_100hdx;
+ break;
+ case DLD_PROP_ADV_10FDX_CAP:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_adv_10fdx;
+ break;
+ case DLD_PROP_EN_10FDX_CAP:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_en_10fdx;
+ break;
+ case DLD_PROP_ADV_10HDX_CAP:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_adv_10hdx;
+ break;
+ case DLD_PROP_EN_10HDX_CAP:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_en_10hdx;
+ break;
+ default:
+ err = bge_get_priv_prop(bgep, pr_name, pr_valsize,
+ pr_val);
+ return (err);
+ }
+ return (0);
+}
+
+/* ARGSUSED */
+static int
+bge_set_priv_prop(bge_t *bgep, const char *pr_name, uint_t pr_valsize,
+ const void *pr_val)
+{
+ int err = 0;
+ long result;
+
+ if (strcmp(pr_name, "_drain_max") == 0) {
+
+ /*
+ * on the Tx side, we need to update the h/w register for
+ * real packet transmission per packet. The drain_max parameter
+ * is used to reduce the register access. This parameter
+ * controls the max number of packets that we will hold before
+ * updating the bge h/w to trigger h/w transmit. The bge
+ * chipset usually has a max of 512 Tx descriptors, thus
+ * the upper bound on drain_max is 512.
+ */
+ if (pr_val == NULL) {
+ err = EINVAL;
+ return (err);
+ }
+ (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
+ if (result > 512 || result < 1)
+ err = EINVAL;
+ else {
+ bgep->param_drain_max = (uint32_t)result;
+ if (bge_reprogram(bgep) == IOC_INVAL)
+ err = EINVAL;
+ }
+ return (err);
+ }
+ if (strcmp(pr_name, "_msi_cnt") == 0) {
+
+ if (pr_val == NULL) {
+ err = EINVAL;
+ return (err);
+ }
+ (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
+ if (result > 7 || result < 0)
+ err = EINVAL;
+ else {
+ bgep->param_msi_cnt = (uint32_t)result;
+ if (bge_reprogram(bgep) == IOC_INVAL)
+ err = EINVAL;
+ }
+ return (err);
+ }
+ if (strcmp(pr_name, "_intr_coalesce_blank_time") == 0) {
+ if (ddi_strtol(pr_val, (char **)NULL, 0, &result) != 0) {
+ return (EINVAL);
+ }
+
+ bgep->chipid.rx_ticks_norm = result;
+ return (0);
+ }
+
+ if (strcmp(pr_name, "_intr_coalesce_pkt_cnt") == 0) {
+ if (ddi_strtol(pr_val, (char **)NULL, 0, &result) != 0)
+ return (EINVAL);
+
+ bgep->chipid.rx_count_norm = result;
+ return (0);
+ }
+ return (EINVAL);
+}
+
+static int
+bge_get_priv_prop(bge_t *bge, const char *pr_name, uint_t pr_valsize,
+ void *pr_val)
+{
+ char valstr[MAXNAMELEN];
+ int err = EINVAL;
+ uint_t strsize;
+
+
+ if (strcmp(pr_name, "_drain_max") == 0) {
+ (void) sprintf(valstr, "%d", bge->param_drain_max);
+ err = 0;
+ goto done;
+ }
+ if (strcmp(pr_name, "_msi_cnt") == 0) {
+ (void) sprintf(valstr, "%d", bge->param_msi_cnt);
+ err = 0;
+ goto done;
+ }
+
+ if (strcmp(pr_name, "_intr_coalesce_blank_time") == 0) {
+ (void) sprintf(valstr, "%d", bge->chipid.rx_ticks_norm);
+ err = 0;
+ goto done;
+ }
+
+ if (strcmp(pr_name, "_intr_coalesce_pkt_cnt") == 0) {
+ (void) sprintf(valstr, "%d", bge->chipid.rx_count_norm);
+ err = 0;
+ goto done;
+ }
+
+done:
+ strsize = (uint_t)strlen(valstr);
+ if (pr_valsize < strsize) {
+ err = ENOBUFS;
+ } else {
+ (void) strlcpy(pr_val, valstr, pr_valsize);
+ }
+ return (err);
+}
+
/*
* Compute the index of the required bit in the multicast hash map.
* This must mirror the way the hardware actually does it!
@@ -1262,22 +1709,8 @@ bge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
switch (status) {
case IOC_RESTART_REPLY:
case IOC_RESTART_ACK:
- if (bge_phys_update(bgep) != DDI_SUCCESS) {
- ddi_fm_service_impact(bgep->devinfo,
- DDI_SERVICE_DEGRADED);
- status = IOC_INVAL;
- }
-#ifdef BGE_IPMI_ASF
- if (bge_chip_sync(bgep, B_TRUE) == DDI_FAILURE) {
-#else
- if (bge_chip_sync(bgep) == DDI_FAILURE) {
-#endif
- ddi_fm_service_impact(bgep->devinfo,
- DDI_SERVICE_DEGRADED);
+ if (bge_reprogram(bgep) == IOC_INVAL)
status = IOC_INVAL;
- }
- if (bgep->intr_type == DDI_INTR_TYPE_MSI)
- bge_chip_msi_trig(bgep);
break;
}
@@ -1331,15 +1764,13 @@ bge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
}
static void
-bge_m_resources(void *arg)
+bge_resources_add(bge_t *bgep, time_t time, uint_t pkt_cnt)
{
- bge_t *bgep = arg;
+
recv_ring_t *rrp;
mac_rx_fifo_t mrf;
int ring;
- mutex_enter(bgep->genlock);
-
/*
* Register Rx rings as resources and save mac
* resource id for future reference
@@ -1347,15 +1778,25 @@ bge_m_resources(void *arg)
mrf.mrf_type = MAC_RX_FIFO;
mrf.mrf_blank = bge_chip_blank;
mrf.mrf_arg = (void *)bgep;
- mrf.mrf_normal_blank_time = bge_rx_ticks_norm;
- mrf.mrf_normal_pkt_count = bge_rx_count_norm;
+ mrf.mrf_normal_blank_time = time;
+ mrf.mrf_normal_pkt_count = pkt_cnt;
for (ring = 0; ring < bgep->chipid.rx_rings; ring++) {
rrp = &bgep->recv[ring];
rrp->handle = mac_resource_add(bgep->mh,
(mac_resource_t *)&mrf);
}
+}
+static void
+bge_m_resources(void *arg)
+{
+ bge_t *bgep = arg;
+
+ mutex_enter(bgep->genlock);
+
+ bge_resources_add(bgep, bgep->chipid.rx_ticks_norm,
+ bgep->chipid.rx_count_norm);
mutex_exit(bgep->genlock);
}
@@ -2520,6 +2961,9 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
ddi_set_driver_private(devinfo, bgep);
bgep->bge_guard = BGE_GUARD;
bgep->devinfo = devinfo;
+ bgep->param_drain_max = 64;
+ bgep->param_msi_cnt = 0;
+ bgep->param_loop_mode = 0;
/*
* Initialize more fields in BGE private data
@@ -3241,3 +3685,27 @@ bge_intr_disable(bge_t *bgep)
}
}
}
+
+int
+bge_reprogram(bge_t *bgep)
+{
+ int status = 0;
+
+ ASSERT(mutex_owned(bgep->genlock));
+
+ if (bge_phys_update(bgep) != DDI_SUCCESS) {
+ ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_DEGRADED);
+ status = IOC_INVAL;
+ }
+#ifdef BGE_IPMI_ASF
+ if (bge_chip_sync(bgep, B_TRUE) == DDI_FAILURE) {
+#else
+ if (bge_chip_sync(bgep) == DDI_FAILURE) {
+#endif
+ ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_DEGRADED);
+ status = IOC_INVAL;
+ }
+ if (bgep->intr_type == DDI_INTR_TYPE_MSI)
+ bge_chip_msi_trig(bgep);
+ return (status);
+}
diff --git a/usr/src/uts/common/io/bge/bge_ndd.c b/usr/src/uts/common/io/bge/bge_ndd.c
index ca993b64f7..280f3b6bcb 100644
--- a/usr/src/uts/common/io/bge/bge_ndd.c
+++ b/usr/src/uts/common/io/bge/bge_ndd.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -30,7 +30,6 @@
#define BGE_DBG BGE_DBG_NDD /* debug flag for this code */
-
/*
* Property names
*/
@@ -112,15 +111,6 @@ static const nd_param_t nd_template[] = {
{ PARAM_LINK_RX_PAUSE, 0, 1, 0, "-link_rx_pause" },
{ PARAM_LINK_TX_PAUSE, 0, 1, 0, "-link_tx_pause" },
-/* Loopback status */
-{ PARAM_LOOP_MODE, 0, 5, 0, "-loop_mode" },
-
-/* MSI count */
-{ PARAM_MSI_CNT, 0, 7, 0, "+msi_cnt" },
-
-/* Performance tuning */
-{ PARAM_DRAIN_MAX, 1, 512, 64, "+drain_max" },
-
/* Terminator */
{ PARAM_COUNT, 0, 0, 0, NULL }
};
@@ -146,6 +136,27 @@ bge_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
}
/*
+ * 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 bge parameters,
+ * implicitly disabling any settings made via dladm.
+ */
+static void
+bge_param_sync(bge_t *bgep)
+{
+ bgep->param_en_pause = bgep->param_adv_pause;
+ bgep->param_en_asym_pause = bgep->param_adv_asym_pause;
+ bgep->param_en_1000fdx = bgep->param_adv_1000fdx;
+ bgep->param_en_1000hdx = bgep->param_adv_1000hdx;
+ bgep->param_en_100fdx = bgep->param_adv_100fdx;
+ bgep->param_en_100hdx = bgep->param_adv_100hdx;
+ bgep->param_en_10fdx = bgep->param_adv_10fdx;
+ bgep->param_en_10hdx = bgep->param_adv_10hdx;
+}
+
+/*
* Validates the request to set a BGE parameter to a specific value.
* If the request is OK, the parameter is set. Also the <info> field
* is incremented to show that the parameter was touched, even though
@@ -251,7 +262,7 @@ bge_param_register(bge_t *bgep)
nd_fail:
BGE_DEBUG(("bge_param_register: FAILED at index %d [info %d]",
- tmplp-nd_template, tmplp->ndp_info));
+ tmplp-nd_template, tmplp->ndp_info));
nd_free(nddpp);
return (DDI_FAILURE);
}
@@ -280,8 +291,8 @@ bge_nd_init(bge_t *bgep)
*/
if (BGE_PROP_EXISTS(bgep->devinfo, supported_net)) {
if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, bgep->devinfo,
- DDI_PROP_DONTPASS, supported_net,
- &options, &noptions) == DDI_PROP_SUCCESS) {
+ DDI_PROP_DONTPASS, supported_net,
+ &options, &noptions) == DDI_PROP_SUCCESS) {
bgep->param_adv_autoneg = 0;
bgep->param_adv_1000fdx = 0;
@@ -342,7 +353,7 @@ bge_nd_init(bge_t *bgep)
speed = BGE_PROP_GET_INT(dip, transfer_speed_propname);
bge_log(bgep, "%s property is %d",
- transfer_speed_propname, speed);
+ transfer_speed_propname, speed);
switch (speed) {
case 1000:
@@ -401,9 +412,9 @@ bge_nd_init(bge_t *bgep)
speed = BGE_PROP_GET_INT(dip, speed_propname);
duplex = BGE_PROP_GET_INT(dip, duplex_propname);
bge_log(bgep, "%s property is %d",
- speed_propname, speed);
+ speed_propname, speed);
bge_log(bgep, "%s property is %d",
- duplex_propname, duplex);
+ duplex_propname, duplex);
switch (speed) {
case 1000:
@@ -446,15 +457,17 @@ bge_nd_init(bge_t *bgep)
}
BGE_DEBUG(("bge_nd_init: autoneg %d"
- "pause %d asym_pause %d "
- "1000fdx %d 1000hdx %d "
- "100fdx %d 100hdx %d "
- "10fdx %d 10hdx %d ",
- bgep->param_adv_autoneg,
- bgep->param_adv_pause, bgep->param_adv_asym_pause,
- bgep->param_adv_1000fdx, bgep->param_adv_1000hdx,
- bgep->param_adv_100fdx, bgep->param_adv_100hdx,
- bgep->param_adv_10fdx, bgep->param_adv_10hdx));
+ "pause %d asym_pause %d "
+ "1000fdx %d 1000hdx %d "
+ "100fdx %d 100hdx %d "
+ "10fdx %d 10hdx %d ",
+ bgep->param_adv_autoneg,
+ bgep->param_adv_pause, bgep->param_adv_asym_pause,
+ bgep->param_adv_1000fdx, bgep->param_adv_1000hdx,
+ bgep->param_adv_100fdx, bgep->param_adv_100hdx,
+ bgep->param_adv_10fdx, bgep->param_adv_10hdx));
+
+ bge_param_sync(bgep);
return (0);
}
@@ -468,7 +481,7 @@ bge_nd_ioctl(bge_t *bgep, queue_t *wq, mblk_t *mp, struct iocblk *iocp)
int cmd;
BGE_TRACE(("bge_nd_ioctl($%p, $%p, $%p, $%p)",
- (void *)bgep, (void *)wq, (void *)mp, (void *)iocp));
+ (void *)bgep, (void *)wq, (void *)mp, (void *)iocp));
ASSERT(mutex_owned(bgep->genlock));
@@ -513,6 +526,8 @@ bge_nd_ioctl(bge_t *bgep, queue_t *wq, mblk_t *mp, struct iocblk *iocp)
info = ndp->ndp_info;
ok = nd_getset(wq, bgep->nd_data_p, mp);
+ bge_param_sync(bgep);
+
/*
* If nd_getset() returns B_FALSE, the command was
* not valid (e.g. unknown name), so we just tell
@@ -526,8 +541,8 @@ bge_nd_ioctl(bge_t *bgep, queue_t *wq, mblk_t *mp, struct iocblk *iocp)
* So, we also drop out in that case ...
*/
BGE_DEBUG(("bge_nd_ioctl: set %s err %d autoneg %d info %d/%d",
- ok ? "OK" : "FAIL", iocp->ioc_error,
- ndp->ndp_val, info, ndp->ndp_info));
+ ok ? "OK" : "FAIL", iocp->ioc_error,
+ ndp->ndp_val, info, ndp->ndp_info));
if (!ok)
return (IOC_INVAL);
if (iocp->ioc_error)
diff --git a/usr/src/uts/common/io/bge/bge_recv2.c b/usr/src/uts/common/io/bge/bge_recv2.c
index 78a5913ae2..06282b461b 100644
--- a/usr/src/uts/common/io/bge/bge_recv2.c
+++ b/usr/src/uts/common/io/bge/bge_recv2.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -211,8 +211,8 @@ bge_receive_packet(bge_t *bgep, bge_rbd_t *hw_rbd_p)
ehp->ether_tpid = ntohs(ETHERTYPE_VLAN);
ehp->ether_tci = ntohs(hw_rbd.vlan_tci);
bcopy(((uchar_t *)(DMA_VPTR(srbdp->pbuf))) + 2 * ETHERADDRL,
- dp + 2 * ETHERADDRL + VLAN_TAGSZ,
- len - 2 * ETHERADDRL);
+ dp + 2 * ETHERADDRL + VLAN_TAGSZ,
+ len - 2 * ETHERADDRL);
} else {
#endif
mp->b_rptr = dp = mp->b_rptr + BGE_HEADROOM;
@@ -312,7 +312,7 @@ bge_receive_ring(bge_t *bgep, recv_ring_t *rrp)
slot = rrp->rx_next;
while ((slot != *rrp->prod_index_p) && /* Note: volatile */
- (recv_cnt < BGE_MAXPKT_RCVED)) {
+ (recv_cnt < BGE_MAXPKT_RCVED)) {
if ((mp = bge_receive_packet(bgep, &hw_rbd_p[slot])) != NULL) {
*tail = mp;
tail = &mp->b_next;