xref: /illumos-gate/usr/src/uts/common/io/bnx/bnxhwi.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 "bnx.h"
21*eef4f27bSRobert Mustacchi #include "bnx_mm.h"
22*eef4f27bSRobert Mustacchi #include "bnxsnd.h"
23*eef4f27bSRobert Mustacchi #include "bnxrcv.h"
24*eef4f27bSRobert Mustacchi #include "bnxint.h"
25*eef4f27bSRobert Mustacchi #include "bnxtmr.h"
26*eef4f27bSRobert Mustacchi #include "bnxcfg.h"
27*eef4f27bSRobert Mustacchi 
28*eef4f27bSRobert Mustacchi void
bnx_update_phy(um_device_t * const umdevice)29*eef4f27bSRobert Mustacchi bnx_update_phy(um_device_t * const umdevice)
30*eef4f27bSRobert Mustacchi {
31*eef4f27bSRobert Mustacchi 	lm_status_t lmstatus;
32*eef4f27bSRobert Mustacchi 	lm_device_t *lmdevice;
33*eef4f27bSRobert Mustacchi 
34*eef4f27bSRobert Mustacchi 	lmdevice = &(umdevice->lm_dev);
35*eef4f27bSRobert Mustacchi 
36*eef4f27bSRobert Mustacchi 	/* Map 'ndd' parameters to LM struct. */
37*eef4f27bSRobert Mustacchi 	bnx_cfg_map_phy(umdevice);
38*eef4f27bSRobert Mustacchi 
39*eef4f27bSRobert Mustacchi 	mutex_enter(&umdevice->os_param.phy_mutex);
40*eef4f27bSRobert Mustacchi 
41*eef4f27bSRobert Mustacchi 	/* Reset, re-program and bring-up phy. */
42*eef4f27bSRobert Mustacchi 	lmstatus = lm_init_phy(lmdevice, lmdevice->params.req_medium,
43*eef4f27bSRobert Mustacchi 	    lmdevice->params.flow_ctrl_cap, lmdevice->params.selective_autoneg,
44*eef4f27bSRobert Mustacchi 	    lmdevice->params.wire_speed, 0);
45*eef4f27bSRobert Mustacchi 	if (lmstatus != LM_STATUS_SUCCESS) {
46*eef4f27bSRobert Mustacchi 		cmn_err(CE_WARN, "%s: Failed to configure the PHY.",
47*eef4f27bSRobert Mustacchi 		    umdevice->dev_name);
48*eef4f27bSRobert Mustacchi 	}
49*eef4f27bSRobert Mustacchi 
50*eef4f27bSRobert Mustacchi 	lm_service_phy_int(lmdevice, TRUE);
51*eef4f27bSRobert Mustacchi 
52*eef4f27bSRobert Mustacchi 	mutex_exit(&umdevice->os_param.phy_mutex);
53*eef4f27bSRobert Mustacchi }
54*eef4f27bSRobert Mustacchi 
55*eef4f27bSRobert Mustacchi ddi_dma_handle_t *
bnx_find_dma_hdl(um_device_t * const umdevice,const void * const virtaddr)56*eef4f27bSRobert Mustacchi bnx_find_dma_hdl(um_device_t *const umdevice, const void *const virtaddr)
57*eef4f27bSRobert Mustacchi {
58*eef4f27bSRobert Mustacchi 	int i;
59*eef4f27bSRobert Mustacchi 	ddi_dma_handle_t *dmahdl;
60*eef4f27bSRobert Mustacchi 
61*eef4f27bSRobert Mustacchi 	dmahdl = NULL;
62*eef4f27bSRobert Mustacchi 	for (i = 0; i < umdevice->os_param.dma_handles_used; i++) {
63*eef4f27bSRobert Mustacchi 		if (umdevice->os_param.dma_virt[i] == virtaddr) {
64*eef4f27bSRobert Mustacchi 			dmahdl = &(umdevice->os_param.dma_handle[i]);
65*eef4f27bSRobert Mustacchi 		}
66*eef4f27bSRobert Mustacchi 	}
67*eef4f27bSRobert Mustacchi 
68*eef4f27bSRobert Mustacchi 	return (dmahdl);
69*eef4f27bSRobert Mustacchi }
70*eef4f27bSRobert Mustacchi 
71*eef4f27bSRobert Mustacchi static void
bnx_free_lmmem(um_device_t * const umdevice)72*eef4f27bSRobert Mustacchi bnx_free_lmmem(um_device_t * const umdevice)
73*eef4f27bSRobert Mustacchi {
74*eef4f27bSRobert Mustacchi 	int i;
75*eef4f27bSRobert Mustacchi 	bnx_memreq_t *memreq;
76*eef4f27bSRobert Mustacchi 	ddi_dma_handle_t *dma_handle;
77*eef4f27bSRobert Mustacchi 	ddi_acc_handle_t *acc_handle;
78*eef4f27bSRobert Mustacchi 
79*eef4f27bSRobert Mustacchi 	if (umdevice->os_param.dma_handles_used != 0) {
80*eef4f27bSRobert Mustacchi 		i = umdevice->os_param.dma_handles_used - 1;
81*eef4f27bSRobert Mustacchi 
82*eef4f27bSRobert Mustacchi 		dma_handle = &(umdevice->os_param.dma_handle[i]);
83*eef4f27bSRobert Mustacchi 		acc_handle = &(umdevice->os_param.dma_acc_handle[i]);
84*eef4f27bSRobert Mustacchi 
85*eef4f27bSRobert Mustacchi 		/* Free all shared memory. */
86*eef4f27bSRobert Mustacchi 		for (; i >= 0; i--) {
87*eef4f27bSRobert Mustacchi 			(void) ddi_dma_unbind_handle(*dma_handle);
88*eef4f27bSRobert Mustacchi 
89*eef4f27bSRobert Mustacchi 			ddi_dma_mem_free(acc_handle);
90*eef4f27bSRobert Mustacchi 
91*eef4f27bSRobert Mustacchi 			ddi_dma_free_handle(dma_handle);
92*eef4f27bSRobert Mustacchi 
93*eef4f27bSRobert Mustacchi 			dma_handle--;
94*eef4f27bSRobert Mustacchi 			acc_handle--;
95*eef4f27bSRobert Mustacchi 		}
96*eef4f27bSRobert Mustacchi 
97*eef4f27bSRobert Mustacchi 		umdevice->os_param.dma_handles_used = 0;
98*eef4f27bSRobert Mustacchi 	}
99*eef4f27bSRobert Mustacchi 
100*eef4f27bSRobert Mustacchi 	if (umdevice->memcnt != 0) {
101*eef4f27bSRobert Mustacchi 		/* Free all local memory. */
102*eef4f27bSRobert Mustacchi 		for (i = umdevice->memcnt - 1; i >= 0; i--) {
103*eef4f27bSRobert Mustacchi 			memreq = &umdevice->memreq[i];
104*eef4f27bSRobert Mustacchi 
105*eef4f27bSRobert Mustacchi 			kmem_free(memreq->addr, memreq->size);
106*eef4f27bSRobert Mustacchi 
107*eef4f27bSRobert Mustacchi 			memreq->addr = NULL;
108*eef4f27bSRobert Mustacchi 			memreq->size = 0;
109*eef4f27bSRobert Mustacchi 		}
110*eef4f27bSRobert Mustacchi 
111*eef4f27bSRobert Mustacchi 		umdevice->memcnt = 0;
112*eef4f27bSRobert Mustacchi 	}
113*eef4f27bSRobert Mustacchi }
114*eef4f27bSRobert Mustacchi 
115*eef4f27bSRobert Mustacchi int
bnx_hdwr_init(um_device_t * const umdevice)116*eef4f27bSRobert Mustacchi bnx_hdwr_init(um_device_t *const umdevice)
117*eef4f27bSRobert Mustacchi {
118*eef4f27bSRobert Mustacchi 	lm_status_t lmstatus;
119*eef4f27bSRobert Mustacchi 	lm_device_t *lmdevice;
120*eef4f27bSRobert Mustacchi 
121*eef4f27bSRobert Mustacchi 	lmdevice = &(umdevice->lm_dev);
122*eef4f27bSRobert Mustacchi 
123*eef4f27bSRobert Mustacchi 	lmstatus = lm_get_dev_info(lmdevice);
124*eef4f27bSRobert Mustacchi 	if (lmstatus != LM_STATUS_SUCCESS) {
125*eef4f27bSRobert Mustacchi 		cmn_err(CE_WARN, "%s: Failed to get device information.\n",
126*eef4f27bSRobert Mustacchi 		    umdevice->dev_name);
127*eef4f27bSRobert Mustacchi 		return (-1);
128*eef4f27bSRobert Mustacchi 	}
129*eef4f27bSRobert Mustacchi 
130*eef4f27bSRobert Mustacchi 	/*
131*eef4f27bSRobert Mustacchi 	 * Initialize the adapter resource.  Mainly allocating memory needed
132*eef4f27bSRobert Mustacchi 	 * by the driver, such as packet descriptors, shared memory, etc.
133*eef4f27bSRobert Mustacchi 	 */
134*eef4f27bSRobert Mustacchi 	lmstatus = lm_init_resc(lmdevice);
135*eef4f27bSRobert Mustacchi 	if (lmstatus != LM_STATUS_SUCCESS) {
136*eef4f27bSRobert Mustacchi 		cmn_err(CE_WARN, "%s: Failed to allocate device resources.\n",
137*eef4f27bSRobert Mustacchi 		    umdevice->dev_name);
138*eef4f27bSRobert Mustacchi 		goto error1;
139*eef4f27bSRobert Mustacchi 	}
140*eef4f27bSRobert Mustacchi 
141*eef4f27bSRobert Mustacchi 	if (bnx_txpkts_init(umdevice)) {
142*eef4f27bSRobert Mustacchi 		goto error1;
143*eef4f27bSRobert Mustacchi 	}
144*eef4f27bSRobert Mustacchi 
145*eef4f27bSRobert Mustacchi 	if (bnx_rxpkts_init(umdevice)) {
146*eef4f27bSRobert Mustacchi 		goto error2;
147*eef4f27bSRobert Mustacchi 	}
148*eef4f27bSRobert Mustacchi 
149*eef4f27bSRobert Mustacchi 	/* Find	the DMA handle associated with the status block memory. */
150*eef4f27bSRobert Mustacchi 	umdevice->os_param.status_block_dma_hdl = bnx_find_dma_hdl(umdevice,
151*eef4f27bSRobert Mustacchi 	    (void *)(umdevice->lm_dev.vars.status_virt));
152*eef4f27bSRobert Mustacchi 
153*eef4f27bSRobert Mustacchi 	/* Reset the local interrupt event index. */
154*eef4f27bSRobert Mustacchi 	umdevice->dev_var.processed_status_idx = 0;
155*eef4f27bSRobert Mustacchi 
156*eef4f27bSRobert Mustacchi 	/* Initialize the receive mask to a sane default. */
157*eef4f27bSRobert Mustacchi 	umdevice->dev_var.rx_filter_mask = LM_RX_MASK_ACCEPT_UNICAST |
158*eef4f27bSRobert Mustacchi 	    LM_RX_MASK_ACCEPT_BROADCAST;
159*eef4f27bSRobert Mustacchi 
160*eef4f27bSRobert Mustacchi 	return (0);
161*eef4f27bSRobert Mustacchi 
162*eef4f27bSRobert Mustacchi error2:
163*eef4f27bSRobert Mustacchi 	bnx_txpkts_fini(umdevice);
164*eef4f27bSRobert Mustacchi 
165*eef4f27bSRobert Mustacchi error1:
166*eef4f27bSRobert Mustacchi 	bnx_free_lmmem(umdevice);
167*eef4f27bSRobert Mustacchi 
168*eef4f27bSRobert Mustacchi 	return (-1);
169*eef4f27bSRobert Mustacchi }
170*eef4f27bSRobert Mustacchi 
171*eef4f27bSRobert Mustacchi int
bnx_hdwr_acquire(um_device_t * const umdevice)172*eef4f27bSRobert Mustacchi bnx_hdwr_acquire(um_device_t *const umdevice)
173*eef4f27bSRobert Mustacchi {
174*eef4f27bSRobert Mustacchi 	lm_status_t lmstatus;
175*eef4f27bSRobert Mustacchi 	lm_device_t *lmdevice;
176*eef4f27bSRobert Mustacchi 
177*eef4f27bSRobert Mustacchi 	lmdevice = &(umdevice->lm_dev);
178*eef4f27bSRobert Mustacchi 
179*eef4f27bSRobert Mustacchi 	/* Reset the configuration to the hardware default. */
180*eef4f27bSRobert Mustacchi 	bnx_cfg_reset(umdevice);
181*eef4f27bSRobert Mustacchi 
182*eef4f27bSRobert Mustacchi 	/*
183*eef4f27bSRobert Mustacchi 	 * A call to lm_reset() implicitly means we are relieving the firmware
184*eef4f27bSRobert Mustacchi 	 * of it's responsibility to maintain the device.  The driver assumes
185*eef4f27bSRobert Mustacchi 	 * control.  The LM vars.medium field normally gets set with a call to
186*eef4f27bSRobert Mustacchi 	 * lm_init_phy(), but this function cannot be called before we assume
187*eef4f27bSRobert Mustacchi 	 * control of the device.  If we did, we run the risk of contending
188*eef4f27bSRobert Mustacchi 	 * with the firmware for PHY accesses.  Do the next best thing.
189*eef4f27bSRobert Mustacchi 	 */
190*eef4f27bSRobert Mustacchi 	lmdevice->vars.medium = lm_get_medium(lmdevice);
191*eef4f27bSRobert Mustacchi 
192*eef4f27bSRobert Mustacchi 	/* Map 'ndd' parameters to LM struct. */
193*eef4f27bSRobert Mustacchi 	bnx_cfg_map_phy(umdevice);
194*eef4f27bSRobert Mustacchi 
195*eef4f27bSRobert Mustacchi 	/* Bring the chip under driver control. */
196*eef4f27bSRobert Mustacchi 	lmstatus = lm_reset(lmdevice, LM_REASON_DRIVER_RESET);
197*eef4f27bSRobert Mustacchi 	if (lmstatus != LM_STATUS_SUCCESS) {
198*eef4f27bSRobert Mustacchi 		cmn_err(CE_WARN, "%s: Failed to reset chip.\n",
199*eef4f27bSRobert Mustacchi 		    umdevice->dev_name);
200*eef4f27bSRobert Mustacchi 		return (-1);
201*eef4f27bSRobert Mustacchi 	}
202*eef4f27bSRobert Mustacchi 
203*eef4f27bSRobert Mustacchi 	/* Configure the PHY to the requested settings. */
204*eef4f27bSRobert Mustacchi 	lmstatus = lm_init_phy(lmdevice, lmdevice->params.req_medium,
205*eef4f27bSRobert Mustacchi 	    lmdevice->params.flow_ctrl_cap, lmdevice->params.selective_autoneg,
206*eef4f27bSRobert Mustacchi 	    lmdevice->params.wire_speed, 0);
207*eef4f27bSRobert Mustacchi 	if (lmstatus != LM_STATUS_SUCCESS) {
208*eef4f27bSRobert Mustacchi 		cmn_err(CE_WARN, "%s: Failed to initialize the PHY.",
209*eef4f27bSRobert Mustacchi 		    umdevice->dev_name);
210*eef4f27bSRobert Mustacchi 	}
211*eef4f27bSRobert Mustacchi 
212*eef4f27bSRobert Mustacchi 	lm_service_phy_int(lmdevice, FALSE); /* force a phy status update */
213*eef4f27bSRobert Mustacchi 
214*eef4f27bSRobert Mustacchi 	umdevice->dev_var.indLink = lmdevice->vars.link_status;
215*eef4f27bSRobert Mustacchi 	umdevice->dev_var.indMedium = lmdevice->vars.medium;
216*eef4f27bSRobert Mustacchi 
217*eef4f27bSRobert Mustacchi 	/*
218*eef4f27bSRobert Mustacchi 	 * Need to clear TX PATCH scratch register at offset 0x420
219*eef4f27bSRobert Mustacchi 	 * to instruct chip to do full TCP checksum calculations.
220*eef4f27bSRobert Mustacchi 	 */
221*eef4f27bSRobert Mustacchi 	REG_WR_IND(lmdevice, (OFFSETOF(reg_space_t, tpat.tpat_scratch[0]) +
222*eef4f27bSRobert Mustacchi 	    0x420), 0);
223*eef4f27bSRobert Mustacchi 
224*eef4f27bSRobert Mustacchi 	FLUSHPOSTEDWRITES(lmdevice);
225*eef4f27bSRobert Mustacchi 
226*eef4f27bSRobert Mustacchi 	umdevice->recv_discards = 0;
227*eef4f27bSRobert Mustacchi 
228*eef4f27bSRobert Mustacchi 	/* Make sure the rx statistics counters are reset. */
229*eef4f27bSRobert Mustacchi 	bzero(&(lmdevice->rx_info.stats), sizeof (lm_rx_stats_t));
230*eef4f27bSRobert Mustacchi 
231*eef4f27bSRobert Mustacchi 	/* Post rx buffers to the chip. */
232*eef4f27bSRobert Mustacchi 	(void) lm_post_buffers(lmdevice, 0, NULL);
233*eef4f27bSRobert Mustacchi 
234*eef4f27bSRobert Mustacchi 	/* Allow the hardware to accept rx traffic. */
235*eef4f27bSRobert Mustacchi 	(void) lm_set_rx_mask(lmdevice, RX_FILTER_USER_IDX0,
236*eef4f27bSRobert Mustacchi 	    umdevice->dev_var.rx_filter_mask);
237*eef4f27bSRobert Mustacchi 
238*eef4f27bSRobert Mustacchi 	FLUSHPOSTEDWRITES(lmdevice);
239*eef4f27bSRobert Mustacchi 
240*eef4f27bSRobert Mustacchi 	/* Enable interrupts. */
241*eef4f27bSRobert Mustacchi 	bnx_intr_enable(umdevice);
242*eef4f27bSRobert Mustacchi 
243*eef4f27bSRobert Mustacchi 	/* Start the periodic timer. */
244*eef4f27bSRobert Mustacchi 	bnx_timer_start(umdevice);
245*eef4f27bSRobert Mustacchi 
246*eef4f27bSRobert Mustacchi 	return (0);
247*eef4f27bSRobert Mustacchi }
248*eef4f27bSRobert Mustacchi 
249*eef4f27bSRobert Mustacchi void
bnx_hdwr_release(um_device_t * const umdevice)250*eef4f27bSRobert Mustacchi bnx_hdwr_release(um_device_t *const umdevice)
251*eef4f27bSRobert Mustacchi {
252*eef4f27bSRobert Mustacchi 	int reason;
253*eef4f27bSRobert Mustacchi 	lm_device_t *lmdevice;
254*eef4f27bSRobert Mustacchi 
255*eef4f27bSRobert Mustacchi 	lmdevice = &(umdevice->lm_dev);
256*eef4f27bSRobert Mustacchi 
257*eef4f27bSRobert Mustacchi 	/* Stop the periodic timer. */
258*eef4f27bSRobert Mustacchi 	bnx_timer_stop(umdevice);
259*eef4f27bSRobert Mustacchi 
260*eef4f27bSRobert Mustacchi 	/* Disable interrupts. */
261*eef4f27bSRobert Mustacchi 	bnx_intr_disable(umdevice);
262*eef4f27bSRobert Mustacchi 
263*eef4f27bSRobert Mustacchi 	/*
264*eef4f27bSRobert Mustacchi 	 * In Solaris when RX traffic is accepted, the system might generate
265*eef4f27bSRobert Mustacchi 	 * and attempt to send some TX packets (from within gld_recv() !).
266*eef4f27bSRobert Mustacchi 	 * Claiming any TX locks before this point would create a deadlock.
267*eef4f27bSRobert Mustacchi 	 * The ISR would be waiting for a lock acquired here that would never
268*eef4f27bSRobert Mustacchi 	 * be freed, since we in-turn would be waiting for the ISR to finish
269*eef4f27bSRobert Mustacchi 	 * here.  Consequently, we acquire the TX lock as soon as we know that
270*eef4f27bSRobert Mustacchi 	 * no TX traffic is a result of RX traffic.
271*eef4f27bSRobert Mustacchi 	 */
272*eef4f27bSRobert Mustacchi 	rw_enter(&umdevice->os_param.gld_snd_mutex, RW_WRITER);
273*eef4f27bSRobert Mustacchi 
274*eef4f27bSRobert Mustacchi 	/* Set RX mask to stop receiving any further packets */
275*eef4f27bSRobert Mustacchi 	(void) lm_set_rx_mask(lmdevice, RX_FILTER_USER_IDX0,
276*eef4f27bSRobert Mustacchi 	    LM_RX_MASK_ACCEPT_NONE);
277*eef4f27bSRobert Mustacchi 
278*eef4f27bSRobert Mustacchi 	FLUSHPOSTEDWRITES(lmdevice);
279*eef4f27bSRobert Mustacchi 
280*eef4f27bSRobert Mustacchi 	if (umdevice->dev_var.fw_ver < FW_VER_WITH_UNLOAD_POWER_DOWN) {
281*eef4f27bSRobert Mustacchi 		reason = LM_REASON_DRIVER_SHUTDOWN;
282*eef4f27bSRobert Mustacchi 	} else {
283*eef4f27bSRobert Mustacchi 		reason = LM_REASON_DRIVER_UNLOAD_POWER_DOWN;
284*eef4f27bSRobert Mustacchi 	}
285*eef4f27bSRobert Mustacchi 
286*eef4f27bSRobert Mustacchi 	lm_chip_reset(lmdevice, reason);
287*eef4f27bSRobert Mustacchi 
288*eef4f27bSRobert Mustacchi 	FLUSHPOSTEDWRITES(lmdevice);
289*eef4f27bSRobert Mustacchi 
290*eef4f27bSRobert Mustacchi 	/* Reclaim all tx buffers submitted to the hardware. */
291*eef4f27bSRobert Mustacchi 	bnx_txpkts_flush(umdevice);
292*eef4f27bSRobert Mustacchi 
293*eef4f27bSRobert Mustacchi 	/* Reclaim all rx buffers submitted to the hardware. */
294*eef4f27bSRobert Mustacchi 	bnx_rxpkts_recycle(umdevice);
295*eef4f27bSRobert Mustacchi 
296*eef4f27bSRobert Mustacchi 	rw_exit(&umdevice->os_param.gld_snd_mutex);
297*eef4f27bSRobert Mustacchi }
298*eef4f27bSRobert Mustacchi 
299*eef4f27bSRobert Mustacchi void
bnx_hdwr_fini(um_device_t * const umdevice)300*eef4f27bSRobert Mustacchi bnx_hdwr_fini(um_device_t *const umdevice)
301*eef4f27bSRobert Mustacchi {
302*eef4f27bSRobert Mustacchi 	bnx_rxpkts_fini(umdevice);
303*eef4f27bSRobert Mustacchi 
304*eef4f27bSRobert Mustacchi 	bnx_txpkts_fini(umdevice);
305*eef4f27bSRobert Mustacchi 
306*eef4f27bSRobert Mustacchi 	bnx_free_lmmem(umdevice);
307*eef4f27bSRobert Mustacchi }
308*eef4f27bSRobert Mustacchi 
309*eef4f27bSRobert Mustacchi static u32_t
compute_crc32(const u8_t * const buf,u32_t buf_size)310*eef4f27bSRobert Mustacchi compute_crc32(const u8_t *const buf, u32_t buf_size)
311*eef4f27bSRobert Mustacchi {
312*eef4f27bSRobert Mustacchi 	u32_t reg;
313*eef4f27bSRobert Mustacchi 	u32_t tmp;
314*eef4f27bSRobert Mustacchi 	u32_t j;
315*eef4f27bSRobert Mustacchi 	u32_t k;
316*eef4f27bSRobert Mustacchi 
317*eef4f27bSRobert Mustacchi 	reg = 0xffffffff;
318*eef4f27bSRobert Mustacchi 
319*eef4f27bSRobert Mustacchi 	for (j = 0; j < buf_size; j++) {
320*eef4f27bSRobert Mustacchi 		reg ^= buf[j];
321*eef4f27bSRobert Mustacchi 
322*eef4f27bSRobert Mustacchi 		for (k = 0; k < 8; k++) {
323*eef4f27bSRobert Mustacchi 			tmp = reg & 0x01;
324*eef4f27bSRobert Mustacchi 
325*eef4f27bSRobert Mustacchi 			reg >>= 1;
326*eef4f27bSRobert Mustacchi 
327*eef4f27bSRobert Mustacchi 			if (tmp) {
328*eef4f27bSRobert Mustacchi 				reg ^= 0xedb88320;
329*eef4f27bSRobert Mustacchi 			}
330*eef4f27bSRobert Mustacchi 		}
331*eef4f27bSRobert Mustacchi 	}
332*eef4f27bSRobert Mustacchi 
333*eef4f27bSRobert Mustacchi 	return (~reg);
334*eef4f27bSRobert Mustacchi }
335*eef4f27bSRobert Mustacchi 
336*eef4f27bSRobert Mustacchi int
bnx_find_mchash_collision(lm_mc_table_t * mc_table,const uint8_t * const mc_addr)337*eef4f27bSRobert Mustacchi bnx_find_mchash_collision(lm_mc_table_t *mc_table, const uint8_t *const mc_addr)
338*eef4f27bSRobert Mustacchi {
339*eef4f27bSRobert Mustacchi 	u32_t cur_bit_pos;
340*eef4f27bSRobert Mustacchi 	u32_t tgt_bit_pos;
341*eef4f27bSRobert Mustacchi 	u32_t idx;
342*eef4f27bSRobert Mustacchi 	u32_t crc32;
343*eef4f27bSRobert Mustacchi 
344*eef4f27bSRobert Mustacchi 	crc32 = compute_crc32(mc_addr, ETHERNET_ADDRESS_SIZE);
345*eef4f27bSRobert Mustacchi 
346*eef4f27bSRobert Mustacchi 	tgt_bit_pos = ~crc32 & 0xff;
347*eef4f27bSRobert Mustacchi 
348*eef4f27bSRobert Mustacchi 	for (idx = 0; idx < mc_table->entry_cnt; idx++) {
349*eef4f27bSRobert Mustacchi 		crc32 = compute_crc32(mc_table->addr_arr[idx].mc_addr,
350*eef4f27bSRobert Mustacchi 		    ETHERNET_ADDRESS_SIZE);
351*eef4f27bSRobert Mustacchi 
352*eef4f27bSRobert Mustacchi 		/*
353*eef4f27bSRobert Mustacchi 		 * The most significant 7 bits of the CRC32 (no inversion),
354*eef4f27bSRobert Mustacchi 		 * are used to index into one of the possible 128 bit positions.
355*eef4f27bSRobert Mustacchi 		 */
356*eef4f27bSRobert Mustacchi 		cur_bit_pos = ~crc32 & 0xff;
357*eef4f27bSRobert Mustacchi 
358*eef4f27bSRobert Mustacchi 		if (tgt_bit_pos == cur_bit_pos) {
359*eef4f27bSRobert Mustacchi 			return (idx);
360*eef4f27bSRobert Mustacchi 		}
361*eef4f27bSRobert Mustacchi 	}
362*eef4f27bSRobert Mustacchi 
363*eef4f27bSRobert Mustacchi 	return (-1);
364*eef4f27bSRobert Mustacchi }
365*eef4f27bSRobert Mustacchi 
366*eef4f27bSRobert Mustacchi 
367*eef4f27bSRobert Mustacchi 
368*eef4f27bSRobert Mustacchi /*
369*eef4f27bSRobert Mustacchi  * Name:	um_send_driver_pulse
370*eef4f27bSRobert Mustacchi  *
371*eef4f27bSRobert Mustacchi  * Input:       ptr to driver structure
372*eef4f27bSRobert Mustacchi  *
373*eef4f27bSRobert Mustacchi  * Return:      none
374*eef4f27bSRobert Mustacchi  *
375*eef4f27bSRobert Mustacchi  * Description: um_send_driver_pulse routine sends heartbeat pulse to firmware.
376*eef4f27bSRobert Mustacchi  */
377*eef4f27bSRobert Mustacchi void
um_send_driver_pulse(um_device_t * const umdevice)378*eef4f27bSRobert Mustacchi um_send_driver_pulse(um_device_t *const umdevice)
379*eef4f27bSRobert Mustacchi {
380*eef4f27bSRobert Mustacchi 	u32_t msg_code;
381*eef4f27bSRobert Mustacchi 	u32_t offset;
382*eef4f27bSRobert Mustacchi 	lm_device_t *lmdevice;
383*eef4f27bSRobert Mustacchi 
384*eef4f27bSRobert Mustacchi 	lmdevice = &(umdevice->lm_dev);
385*eef4f27bSRobert Mustacchi 
386*eef4f27bSRobert Mustacchi 	offset = lmdevice->hw_info.shmem_base;
387*eef4f27bSRobert Mustacchi 	offset += OFFSETOF(shmem_region_t, drv_fw_mb.drv_pulse_mb);
388*eef4f27bSRobert Mustacchi 
389*eef4f27bSRobert Mustacchi 	mutex_enter(&umdevice->os_param.ind_mutex);
390*eef4f27bSRobert Mustacchi 
391*eef4f27bSRobert Mustacchi 	lmdevice->vars.drv_pulse_wr_seq++;
392*eef4f27bSRobert Mustacchi 
393*eef4f27bSRobert Mustacchi 	msg_code = lmdevice->vars.drv_pulse_wr_seq & DRV_PULSE_SEQ_MASK;
394*eef4f27bSRobert Mustacchi 
395*eef4f27bSRobert Mustacchi 	mutex_exit(&umdevice->os_param.ind_mutex);
396*eef4f27bSRobert Mustacchi 
397*eef4f27bSRobert Mustacchi 	if (lmdevice->params.test_mode & TEST_MODE_DRIVER_PULSE_ALWAYS_ALIVE) {
398*eef4f27bSRobert Mustacchi 		msg_code |= DRV_PULSE_ALWAYS_ALIVE;
399*eef4f27bSRobert Mustacchi 	}
400*eef4f27bSRobert Mustacchi 
401*eef4f27bSRobert Mustacchi 	REG_WR_IND(lmdevice, offset, msg_code);
402*eef4f27bSRobert Mustacchi }
403