xref: /illumos-gate/usr/src/uts/common/io/bnx/bnxtmr.c (revision eef4f27b)
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