diff options
Diffstat (limited to 'usr/src/uts/common/io/bge')
-rw-r--r-- | usr/src/uts/common/io/bge/bge_chip2.c | 29 | ||||
-rw-r--r-- | usr/src/uts/common/io/bge/bge_impl.h | 22 | ||||
-rw-r--r-- | usr/src/uts/common/io/bge/bge_kstats.c | 27 | ||||
-rw-r--r-- | usr/src/uts/common/io/bge/bge_main2.c | 516 | ||||
-rw-r--r-- | usr/src/uts/common/io/bge/bge_ndd.c | 73 | ||||
-rw-r--r-- | usr/src/uts/common/io/bge/bge_recv2.c | 8 |
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; |