summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/io/bnx/bnxtmr.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/io/bnx/bnxtmr.c')
-rw-r--r--usr/src/uts/common/io/bnx/bnxtmr.c253
1 files changed, 253 insertions, 0 deletions
diff --git a/usr/src/uts/common/io/bnx/bnxtmr.c b/usr/src/uts/common/io/bnx/bnxtmr.c
new file mode 100644
index 0000000000..1a5d142d84
--- /dev/null
+++ b/usr/src/uts/common/io/bnx/bnxtmr.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2014-2017 Cavium, Inc.
+ * The contents of this file are subject to the terms of the Common Development
+ * and Distribution License, v.1, (the "License").
+ *
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the License at available
+ * at http://opensource.org/licenses/CDDL-1.0
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Joyent, Inc.
+ */
+
+#include "bnxtmr.h"
+#include "bnxrcv.h"
+#include "bnxgld.h"
+
+
+/* 1.5 seconds */
+#define BNX_LINK_CHECK_INTERVAL 10
+
+/* Approximately every second. */
+#define BNX_LINK_CHECK_INTERVAL2 7
+
+/* 500 msecs */
+#define BNX_TIMER_INTERVAL 500000
+
+
+typedef struct _bnx_fw_t {
+ u32_t shmemaddr;
+ u32_t length;
+ u32_t nvramaddr;
+} bnx_fw_t;
+
+static void
+bnx_link_check(lm_device_t *const lmdevice)
+{
+ if (lmdevice->vars.link_status == LM_STATUS_LINK_ACTIVE) {
+ /*
+ * If we have link and we are in the fallback (1gb forced),
+ * mode, we need to see if our link partner is sending us
+ * configs. If this is the case, we'll switch back to autoneg.
+ */
+ if (lmdevice->vars.serdes_fallback_status) {
+ u32_t intr_exp_status;
+
+ (void) lm_mwrite(lmdevice, lmdevice->params.phy_addr,
+ 0x17, 0x0f01);
+ (void) lm_mread(lmdevice, lmdevice->params.phy_addr,
+ 0x15, &intr_exp_status);
+ (void) lm_mread(lmdevice, lmdevice->params.phy_addr,
+ 0x15, &intr_exp_status);
+
+ if (intr_exp_status & 0x20) {
+ (void) lm_mwrite(lmdevice,
+ lmdevice->params.phy_addr,
+ PHY_CTRL_REG, PHY_CTRL_AUTO_NEG_ENABLE |
+ PHY_CTRL_RESTART_AUTO_NEG);
+ }
+ }
+ } else {
+ lm_service_phy_int(lmdevice, TRUE);
+ }
+}
+
+static void
+bnx_link_check2(lm_device_t *const lmdevice)
+{
+ if (lmdevice->vars.link_status == LM_STATUS_LINK_ACTIVE) {
+ u32_t val;
+ u32_t phy_addr;
+
+ phy_addr = lmdevice->params.phy_addr;
+
+ /* Is the link really up? */
+ (void) lm_mwrite(lmdevice, phy_addr, 0x1c, 0x6800);
+ (void) lm_mread(lmdevice, phy_addr, 0x1c, &val);
+ (void) lm_mread(lmdevice, phy_addr, 0x1c, &val);
+
+ if (val & 2) {
+ /* Nope. Force the link down. */
+ (void) lm_mwrite(lmdevice, phy_addr, 0x17, 0x0f03);
+ (void) lm_mread(lmdevice, phy_addr, 0x15, &val);
+ (void) lm_mwrite(lmdevice, phy_addr, 0x15,
+ val & 0xff0f);
+
+ lmdevice->vars.bcm5706s_tx_drv_cur = (u16_t)val;
+ }
+ }
+}
+
+
+
+/*
+ * Name: bnx_timer
+ *
+ * Input: ptr to device structure
+ *
+ * Return: None
+ *
+ * Description: bnx_timer is the periodic timer callback funtion.
+ */
+static void
+bnx_timer(void *arg)
+{
+ lm_device_t *lmdevice;
+ um_device_t *umdevice;
+
+ umdevice = (um_device_t *)arg;
+ lmdevice = &(umdevice->lm_dev);
+
+ mutex_enter(&umdevice->tmr_mutex);
+
+ if (umdevice->timer_enabled != B_TRUE) {
+ goto done;
+ }
+
+ um_send_driver_pulse(umdevice);
+
+ /*
+ * Take this opportunity to replenish any unused Rx Bds. Don't
+ * wait around for the rcv_mutex though. We share the
+ * responsibility of replenishing the rx buffers with the ISR.
+ */
+ if (mutex_tryenter(&umdevice->os_param.rcv_mutex)) {
+ /* This function does an implicit *_fill(). */
+ bnx_rxpkts_post(umdevice);
+
+ mutex_exit(&umdevice->os_param.rcv_mutex);
+ }
+
+ if (umdevice->timer_link_check_interval2) {
+ /*
+ * If enabled, check to see if the serdes
+ * PHY can fallback to a forced mode.
+ */
+ if (umdevice->timer_link_check_interval) {
+ if (umdevice->timer_link_check_counter) {
+ if (umdevice->timer_link_check_counter == 1) {
+ mutex_enter(
+ &umdevice->os_param.phy_mutex);
+ bnx_link_check(lmdevice);
+ mutex_exit(
+ &umdevice->os_param.phy_mutex);
+ }
+ umdevice->timer_link_check_counter--;
+ }
+ }
+
+ umdevice->timer_link_check_counter2--;
+ if (umdevice->timer_link_check_counter2 == 0) {
+ mutex_enter(&umdevice->os_param.phy_mutex);
+ bnx_link_check2(lmdevice);
+ mutex_exit(&umdevice->os_param.phy_mutex);
+
+ umdevice->timer_link_check_counter2 =
+ umdevice->timer_link_check_interval2;
+ }
+ }
+
+ FLUSHPOSTEDWRITES(lmdevice);
+
+ umdevice->tmrtid = timeout(bnx_timer, (void *)umdevice,
+ drv_usectohz(BNX_TIMER_INTERVAL));
+
+done:
+ mutex_exit(&umdevice->tmr_mutex);
+}
+
+void
+bnx_timer_start(um_device_t *const umdevice)
+{
+ lm_device_t *lmdevice;
+
+ lmdevice = &(umdevice->lm_dev);
+
+ umdevice->timer_enabled = B_TRUE;
+
+ if (CHIP_NUM(lmdevice) == CHIP_NUM_5706 &&
+ umdevice->dev_var.isfiber == B_TRUE) {
+ if (lmdevice->vars.serdes_fallback_select !=
+ SERDES_FALLBACK_NONE) {
+ umdevice->timer_link_check_interval =
+ BNX_LINK_CHECK_INTERVAL;
+ } else {
+ umdevice->timer_link_check_interval = 0;
+ }
+
+ umdevice->timer_link_check_interval2 = BNX_LINK_CHECK_INTERVAL2;
+ umdevice->timer_link_check_counter2 =
+ umdevice->timer_link_check_interval2;
+ } else {
+ umdevice->timer_link_check_interval2 = 0;
+ }
+
+ umdevice->tmrtid = timeout(bnx_timer, (void *)umdevice,
+ drv_usectohz(BNX_TIMER_INTERVAL));
+}
+
+
+void
+bnx_timer_stop(um_device_t *const umdevice)
+{
+ mutex_enter(&umdevice->tmr_mutex);
+ umdevice->timer_enabled = B_FALSE;
+ mutex_exit(&umdevice->tmr_mutex);
+
+ (void) untimeout(umdevice->tmrtid);
+ umdevice->tmrtid = 0;
+}
+
+
+
+/*
+ * Name: bnx_link_timer_restart
+ *
+ * Input: ptr to device structure
+ *
+ * Return: None
+ *
+ * Description: This function restarts the link poll timer
+ *
+ */
+void
+bnx_link_timer_restart(um_device_t *const umdevice)
+{
+ /* FIXME -- Make timer_link_check_counter atomic */
+ umdevice->timer_link_check_counter =
+ umdevice->timer_link_check_interval;
+}
+
+
+
+void
+bnx_timer_init(um_device_t *const umdevice)
+{
+ mutex_init(&umdevice->tmr_mutex, NULL, MUTEX_DRIVER,
+ DDI_INTR_PRI(umdevice->intrPriority));
+}
+
+
+
+void
+bnx_timer_fini(um_device_t *const umdevice)
+{
+ mutex_destroy(&umdevice->tmr_mutex);
+}