1*eef4f27bSRobert Mustacchi /*
2*eef4f27bSRobert Mustacchi * Copyright 2014-2017 Cavium, Inc.
3*eef4f27bSRobert Mustacchi * The contents of this file are subject to the terms of the Common Development
4*eef4f27bSRobert Mustacchi * and Distribution License, v.1, (the "License").
5*eef4f27bSRobert Mustacchi *
6*eef4f27bSRobert Mustacchi * You may not use this file except in compliance with the License.
7*eef4f27bSRobert Mustacchi *
8*eef4f27bSRobert Mustacchi * You can obtain a copy of the License at available
9*eef4f27bSRobert Mustacchi * at http://opensource.org/licenses/CDDL-1.0
10*eef4f27bSRobert Mustacchi *
11*eef4f27bSRobert Mustacchi * See the License for the specific language governing permissions and
12*eef4f27bSRobert Mustacchi * limitations under the License.
13*eef4f27bSRobert Mustacchi */
14*eef4f27bSRobert Mustacchi
15*eef4f27bSRobert Mustacchi /*
16*eef4f27bSRobert Mustacchi * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
17*eef4f27bSRobert Mustacchi * Copyright (c) 2019, Joyent, Inc.
18*eef4f27bSRobert Mustacchi */
19*eef4f27bSRobert Mustacchi
20*eef4f27bSRobert Mustacchi #include "bnxtmr.h"
21*eef4f27bSRobert Mustacchi #include "bnxrcv.h"
22*eef4f27bSRobert Mustacchi #include "bnxgld.h"
23*eef4f27bSRobert Mustacchi
24*eef4f27bSRobert Mustacchi
25*eef4f27bSRobert Mustacchi /* 1.5 seconds */
26*eef4f27bSRobert Mustacchi #define BNX_LINK_CHECK_INTERVAL 10
27*eef4f27bSRobert Mustacchi
28*eef4f27bSRobert Mustacchi /* Approximately every second. */
29*eef4f27bSRobert Mustacchi #define BNX_LINK_CHECK_INTERVAL2 7
30*eef4f27bSRobert Mustacchi
31*eef4f27bSRobert Mustacchi /* 500 msecs */
32*eef4f27bSRobert Mustacchi #define BNX_TIMER_INTERVAL 500000
33*eef4f27bSRobert Mustacchi
34*eef4f27bSRobert Mustacchi
35*eef4f27bSRobert Mustacchi typedef struct _bnx_fw_t {
36*eef4f27bSRobert Mustacchi u32_t shmemaddr;
37*eef4f27bSRobert Mustacchi u32_t length;
38*eef4f27bSRobert Mustacchi u32_t nvramaddr;
39*eef4f27bSRobert Mustacchi } bnx_fw_t;
40*eef4f27bSRobert Mustacchi
41*eef4f27bSRobert Mustacchi static void
bnx_link_check(lm_device_t * const lmdevice)42*eef4f27bSRobert Mustacchi bnx_link_check(lm_device_t *const lmdevice)
43*eef4f27bSRobert Mustacchi {
44*eef4f27bSRobert Mustacchi if (lmdevice->vars.link_status == LM_STATUS_LINK_ACTIVE) {
45*eef4f27bSRobert Mustacchi /*
46*eef4f27bSRobert Mustacchi * If we have link and we are in the fallback (1gb forced),
47*eef4f27bSRobert Mustacchi * mode, we need to see if our link partner is sending us
48*eef4f27bSRobert Mustacchi * configs. If this is the case, we'll switch back to autoneg.
49*eef4f27bSRobert Mustacchi */
50*eef4f27bSRobert Mustacchi if (lmdevice->vars.serdes_fallback_status) {
51*eef4f27bSRobert Mustacchi u32_t intr_exp_status;
52*eef4f27bSRobert Mustacchi
53*eef4f27bSRobert Mustacchi (void) lm_mwrite(lmdevice, lmdevice->params.phy_addr,
54*eef4f27bSRobert Mustacchi 0x17, 0x0f01);
55*eef4f27bSRobert Mustacchi (void) lm_mread(lmdevice, lmdevice->params.phy_addr,
56*eef4f27bSRobert Mustacchi 0x15, &intr_exp_status);
57*eef4f27bSRobert Mustacchi (void) lm_mread(lmdevice, lmdevice->params.phy_addr,
58*eef4f27bSRobert Mustacchi 0x15, &intr_exp_status);
59*eef4f27bSRobert Mustacchi
60*eef4f27bSRobert Mustacchi if (intr_exp_status & 0x20) {
61*eef4f27bSRobert Mustacchi (void) lm_mwrite(lmdevice,
62*eef4f27bSRobert Mustacchi lmdevice->params.phy_addr,
63*eef4f27bSRobert Mustacchi PHY_CTRL_REG, PHY_CTRL_AUTO_NEG_ENABLE |
64*eef4f27bSRobert Mustacchi PHY_CTRL_RESTART_AUTO_NEG);
65*eef4f27bSRobert Mustacchi }
66*eef4f27bSRobert Mustacchi }
67*eef4f27bSRobert Mustacchi } else {
68*eef4f27bSRobert Mustacchi lm_service_phy_int(lmdevice, TRUE);
69*eef4f27bSRobert Mustacchi }
70*eef4f27bSRobert Mustacchi }
71*eef4f27bSRobert Mustacchi
72*eef4f27bSRobert Mustacchi static void
bnx_link_check2(lm_device_t * const lmdevice)73*eef4f27bSRobert Mustacchi bnx_link_check2(lm_device_t *const lmdevice)
74*eef4f27bSRobert Mustacchi {
75*eef4f27bSRobert Mustacchi if (lmdevice->vars.link_status == LM_STATUS_LINK_ACTIVE) {
76*eef4f27bSRobert Mustacchi u32_t val;
77*eef4f27bSRobert Mustacchi u32_t phy_addr;
78*eef4f27bSRobert Mustacchi
79*eef4f27bSRobert Mustacchi phy_addr = lmdevice->params.phy_addr;
80*eef4f27bSRobert Mustacchi
81*eef4f27bSRobert Mustacchi /* Is the link really up? */
82*eef4f27bSRobert Mustacchi (void) lm_mwrite(lmdevice, phy_addr, 0x1c, 0x6800);
83*eef4f27bSRobert Mustacchi (void) lm_mread(lmdevice, phy_addr, 0x1c, &val);
84*eef4f27bSRobert Mustacchi (void) lm_mread(lmdevice, phy_addr, 0x1c, &val);
85*eef4f27bSRobert Mustacchi
86*eef4f27bSRobert Mustacchi if (val & 2) {
87*eef4f27bSRobert Mustacchi /* Nope. Force the link down. */
88*eef4f27bSRobert Mustacchi (void) lm_mwrite(lmdevice, phy_addr, 0x17, 0x0f03);
89*eef4f27bSRobert Mustacchi (void) lm_mread(lmdevice, phy_addr, 0x15, &val);
90*eef4f27bSRobert Mustacchi (void) lm_mwrite(lmdevice, phy_addr, 0x15,
91*eef4f27bSRobert Mustacchi val & 0xff0f);
92*eef4f27bSRobert Mustacchi
93*eef4f27bSRobert Mustacchi lmdevice->vars.bcm5706s_tx_drv_cur = (u16_t)val;
94*eef4f27bSRobert Mustacchi }
95*eef4f27bSRobert Mustacchi }
96*eef4f27bSRobert Mustacchi }
97*eef4f27bSRobert Mustacchi
98*eef4f27bSRobert Mustacchi
99*eef4f27bSRobert Mustacchi
100*eef4f27bSRobert Mustacchi /*
101*eef4f27bSRobert Mustacchi * Name: bnx_timer
102*eef4f27bSRobert Mustacchi *
103*eef4f27bSRobert Mustacchi * Input: ptr to device structure
104*eef4f27bSRobert Mustacchi *
105*eef4f27bSRobert Mustacchi * Return: None
106*eef4f27bSRobert Mustacchi *
107*eef4f27bSRobert Mustacchi * Description: bnx_timer is the periodic timer callback funtion.
108*eef4f27bSRobert Mustacchi */
109*eef4f27bSRobert Mustacchi static void
bnx_timer(void * arg)110*eef4f27bSRobert Mustacchi bnx_timer(void *arg)
111*eef4f27bSRobert Mustacchi {
112*eef4f27bSRobert Mustacchi lm_device_t *lmdevice;
113*eef4f27bSRobert Mustacchi um_device_t *umdevice;
114*eef4f27bSRobert Mustacchi
115*eef4f27bSRobert Mustacchi umdevice = (um_device_t *)arg;
116*eef4f27bSRobert Mustacchi lmdevice = &(umdevice->lm_dev);
117*eef4f27bSRobert Mustacchi
118*eef4f27bSRobert Mustacchi mutex_enter(&umdevice->tmr_mutex);
119*eef4f27bSRobert Mustacchi
120*eef4f27bSRobert Mustacchi if (umdevice->timer_enabled != B_TRUE) {
121*eef4f27bSRobert Mustacchi goto done;
122*eef4f27bSRobert Mustacchi }
123*eef4f27bSRobert Mustacchi
124*eef4f27bSRobert Mustacchi um_send_driver_pulse(umdevice);
125*eef4f27bSRobert Mustacchi
126*eef4f27bSRobert Mustacchi /*
127*eef4f27bSRobert Mustacchi * Take this opportunity to replenish any unused Rx Bds. Don't
128*eef4f27bSRobert Mustacchi * wait around for the rcv_mutex though. We share the
129*eef4f27bSRobert Mustacchi * responsibility of replenishing the rx buffers with the ISR.
130*eef4f27bSRobert Mustacchi */
131*eef4f27bSRobert Mustacchi if (mutex_tryenter(&umdevice->os_param.rcv_mutex)) {
132*eef4f27bSRobert Mustacchi /* This function does an implicit *_fill(). */
133*eef4f27bSRobert Mustacchi bnx_rxpkts_post(umdevice);
134*eef4f27bSRobert Mustacchi
135*eef4f27bSRobert Mustacchi mutex_exit(&umdevice->os_param.rcv_mutex);
136*eef4f27bSRobert Mustacchi }
137*eef4f27bSRobert Mustacchi
138*eef4f27bSRobert Mustacchi if (umdevice->timer_link_check_interval2) {
139*eef4f27bSRobert Mustacchi /*
140*eef4f27bSRobert Mustacchi * If enabled, check to see if the serdes
141*eef4f27bSRobert Mustacchi * PHY can fallback to a forced mode.
142*eef4f27bSRobert Mustacchi */
143*eef4f27bSRobert Mustacchi if (umdevice->timer_link_check_interval) {
144*eef4f27bSRobert Mustacchi if (umdevice->timer_link_check_counter) {
145*eef4f27bSRobert Mustacchi if (umdevice->timer_link_check_counter == 1) {
146*eef4f27bSRobert Mustacchi mutex_enter(
147*eef4f27bSRobert Mustacchi &umdevice->os_param.phy_mutex);
148*eef4f27bSRobert Mustacchi bnx_link_check(lmdevice);
149*eef4f27bSRobert Mustacchi mutex_exit(
150*eef4f27bSRobert Mustacchi &umdevice->os_param.phy_mutex);
151*eef4f27bSRobert Mustacchi }
152*eef4f27bSRobert Mustacchi umdevice->timer_link_check_counter--;
153*eef4f27bSRobert Mustacchi }
154*eef4f27bSRobert Mustacchi }
155*eef4f27bSRobert Mustacchi
156*eef4f27bSRobert Mustacchi umdevice->timer_link_check_counter2--;
157*eef4f27bSRobert Mustacchi if (umdevice->timer_link_check_counter2 == 0) {
158*eef4f27bSRobert Mustacchi mutex_enter(&umdevice->os_param.phy_mutex);
159*eef4f27bSRobert Mustacchi bnx_link_check2(lmdevice);
160*eef4f27bSRobert Mustacchi mutex_exit(&umdevice->os_param.phy_mutex);
161*eef4f27bSRobert Mustacchi
162*eef4f27bSRobert Mustacchi umdevice->timer_link_check_counter2 =
163*eef4f27bSRobert Mustacchi umdevice->timer_link_check_interval2;
164*eef4f27bSRobert Mustacchi }
165*eef4f27bSRobert Mustacchi }
166*eef4f27bSRobert Mustacchi
167*eef4f27bSRobert Mustacchi FLUSHPOSTEDWRITES(lmdevice);
168*eef4f27bSRobert Mustacchi
169*eef4f27bSRobert Mustacchi umdevice->tmrtid = timeout(bnx_timer, (void *)umdevice,
170*eef4f27bSRobert Mustacchi drv_usectohz(BNX_TIMER_INTERVAL));
171*eef4f27bSRobert Mustacchi
172*eef4f27bSRobert Mustacchi done:
173*eef4f27bSRobert Mustacchi mutex_exit(&umdevice->tmr_mutex);
174*eef4f27bSRobert Mustacchi }
175*eef4f27bSRobert Mustacchi
176*eef4f27bSRobert Mustacchi void
bnx_timer_start(um_device_t * const umdevice)177*eef4f27bSRobert Mustacchi bnx_timer_start(um_device_t *const umdevice)
178*eef4f27bSRobert Mustacchi {
179*eef4f27bSRobert Mustacchi lm_device_t *lmdevice;
180*eef4f27bSRobert Mustacchi
181*eef4f27bSRobert Mustacchi lmdevice = &(umdevice->lm_dev);
182*eef4f27bSRobert Mustacchi
183*eef4f27bSRobert Mustacchi umdevice->timer_enabled = B_TRUE;
184*eef4f27bSRobert Mustacchi
185*eef4f27bSRobert Mustacchi if (CHIP_NUM(lmdevice) == CHIP_NUM_5706 &&
186*eef4f27bSRobert Mustacchi umdevice->dev_var.isfiber == B_TRUE) {
187*eef4f27bSRobert Mustacchi if (lmdevice->vars.serdes_fallback_select !=
188*eef4f27bSRobert Mustacchi SERDES_FALLBACK_NONE) {
189*eef4f27bSRobert Mustacchi umdevice->timer_link_check_interval =
190*eef4f27bSRobert Mustacchi BNX_LINK_CHECK_INTERVAL;
191*eef4f27bSRobert Mustacchi } else {
192*eef4f27bSRobert Mustacchi umdevice->timer_link_check_interval = 0;
193*eef4f27bSRobert Mustacchi }
194*eef4f27bSRobert Mustacchi
195*eef4f27bSRobert Mustacchi umdevice->timer_link_check_interval2 = BNX_LINK_CHECK_INTERVAL2;
196*eef4f27bSRobert Mustacchi umdevice->timer_link_check_counter2 =
197*eef4f27bSRobert Mustacchi umdevice->timer_link_check_interval2;
198*eef4f27bSRobert Mustacchi } else {
199*eef4f27bSRobert Mustacchi umdevice->timer_link_check_interval2 = 0;
200*eef4f27bSRobert Mustacchi }
201*eef4f27bSRobert Mustacchi
202*eef4f27bSRobert Mustacchi umdevice->tmrtid = timeout(bnx_timer, (void *)umdevice,
203*eef4f27bSRobert Mustacchi drv_usectohz(BNX_TIMER_INTERVAL));
204*eef4f27bSRobert Mustacchi }
205*eef4f27bSRobert Mustacchi
206*eef4f27bSRobert Mustacchi
207*eef4f27bSRobert Mustacchi void
bnx_timer_stop(um_device_t * const umdevice)208*eef4f27bSRobert Mustacchi bnx_timer_stop(um_device_t *const umdevice)
209*eef4f27bSRobert Mustacchi {
210*eef4f27bSRobert Mustacchi mutex_enter(&umdevice->tmr_mutex);
211*eef4f27bSRobert Mustacchi umdevice->timer_enabled = B_FALSE;
212*eef4f27bSRobert Mustacchi mutex_exit(&umdevice->tmr_mutex);
213*eef4f27bSRobert Mustacchi
214*eef4f27bSRobert Mustacchi (void) untimeout(umdevice->tmrtid);
215*eef4f27bSRobert Mustacchi umdevice->tmrtid = 0;
216*eef4f27bSRobert Mustacchi }
217*eef4f27bSRobert Mustacchi
218*eef4f27bSRobert Mustacchi
219*eef4f27bSRobert Mustacchi
220*eef4f27bSRobert Mustacchi /*
221*eef4f27bSRobert Mustacchi * Name: bnx_link_timer_restart
222*eef4f27bSRobert Mustacchi *
223*eef4f27bSRobert Mustacchi * Input: ptr to device structure
224*eef4f27bSRobert Mustacchi *
225*eef4f27bSRobert Mustacchi * Return: None
226*eef4f27bSRobert Mustacchi *
227*eef4f27bSRobert Mustacchi * Description: This function restarts the link poll timer
228*eef4f27bSRobert Mustacchi *
229*eef4f27bSRobert Mustacchi */
230*eef4f27bSRobert Mustacchi void
bnx_link_timer_restart(um_device_t * const umdevice)231*eef4f27bSRobert Mustacchi bnx_link_timer_restart(um_device_t *const umdevice)
232*eef4f27bSRobert Mustacchi {
233*eef4f27bSRobert Mustacchi /* FIXME -- Make timer_link_check_counter atomic */
234*eef4f27bSRobert Mustacchi umdevice->timer_link_check_counter =
235*eef4f27bSRobert Mustacchi umdevice->timer_link_check_interval;
236*eef4f27bSRobert Mustacchi }
237*eef4f27bSRobert Mustacchi
238*eef4f27bSRobert Mustacchi
239*eef4f27bSRobert Mustacchi
240*eef4f27bSRobert Mustacchi void
bnx_timer_init(um_device_t * const umdevice)241*eef4f27bSRobert Mustacchi bnx_timer_init(um_device_t *const umdevice)
242*eef4f27bSRobert Mustacchi {
243*eef4f27bSRobert Mustacchi mutex_init(&umdevice->tmr_mutex, NULL, MUTEX_DRIVER,
244*eef4f27bSRobert Mustacchi DDI_INTR_PRI(umdevice->intrPriority));
245*eef4f27bSRobert Mustacchi }
246*eef4f27bSRobert Mustacchi
247*eef4f27bSRobert Mustacchi
248*eef4f27bSRobert Mustacchi
249*eef4f27bSRobert Mustacchi void
bnx_timer_fini(um_device_t * const umdevice)250*eef4f27bSRobert Mustacchi bnx_timer_fini(um_device_t *const umdevice)
251*eef4f27bSRobert Mustacchi {
252*eef4f27bSRobert Mustacchi mutex_destroy(&umdevice->tmr_mutex);
253*eef4f27bSRobert Mustacchi }
254