xref: /illumos-gate/usr/src/uts/common/io/hxge/hxge_vmac.c (revision f043ebed)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <hxge_impl.h>
28 #include <hxge_vmac.h>
29 
30 hxge_status_t hxge_vmac_init(p_hxge_t hxgep);
31 hxge_status_t hxge_tx_vmac_init(p_hxge_t hxgep);
32 hxge_status_t hxge_rx_vmac_init(p_hxge_t hxgep);
33 hxge_status_t hxge_tx_vmac_enable(p_hxge_t hxgep);
34 hxge_status_t hxge_tx_vmac_disable(p_hxge_t hxgep);
35 hxge_status_t hxge_rx_vmac_enable(p_hxge_t hxgep);
36 hxge_status_t hxge_rx_vmac_disable(p_hxge_t hxgep);
37 hxge_status_t hxge_tx_vmac_reset(p_hxge_t hxgep);
38 hxge_status_t hxge_rx_vmac_reset(p_hxge_t hxgep);
39 uint_t hxge_vmac_intr(caddr_t arg1, caddr_t arg2);
40 hxge_status_t hxge_set_promisc(p_hxge_t hxgep, boolean_t on);
41 
42 hxge_status_t
hxge_link_init(p_hxge_t hxgep)43 hxge_link_init(p_hxge_t hxgep)
44 {
45 	p_hxge_stats_t		statsp;
46 
47 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_link_init>"));
48 
49 	statsp = hxgep->statsp;
50 
51 	statsp->mac_stats.cap_10gfdx = 1;
52 	statsp->mac_stats.lp_cap_10gfdx = 1;
53 
54 	/*
55 	 * The driver doesn't control the link.
56 	 * It is always 10Gb full duplex.
57 	 */
58 	statsp->mac_stats.link_duplex = 2;
59 	statsp->mac_stats.link_speed = 10000;
60 
61 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_link_init"));
62 	return (HXGE_OK);
63 }
64 
65 hxge_status_t
hxge_vmac_init(p_hxge_t hxgep)66 hxge_vmac_init(p_hxge_t hxgep)
67 {
68 	hxge_status_t status = HXGE_OK;
69 
70 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_vmac_init:"));
71 
72 	if ((status = hxge_tx_vmac_reset(hxgep)) != HXGE_OK)
73 		goto fail;
74 
75 	if ((status = hxge_rx_vmac_reset(hxgep)) != HXGE_OK)
76 		goto fail;
77 
78 	if ((status = hxge_tx_vmac_enable(hxgep)) != HXGE_OK)
79 		goto fail;
80 
81 	if ((status = hxge_rx_vmac_enable(hxgep)) != HXGE_OK)
82 		goto fail;
83 
84 	/* Clear the interrupt status registers */
85 	(void) hpi_vmac_clear_rx_int_stat(hxgep->hpi_handle);
86 	(void) hpi_vmac_clear_tx_int_stat(hxgep->hpi_handle);
87 
88 	/*
89 	 * Take the masks off the overflow counters. Interrupt the system when
90 	 * any counts overflow. Don't interrupt the system for each frame.
91 	 * The current counts are retrieved when the "kstat" command is used.
92 	 */
93 	(void) hpi_pfc_set_rx_int_stat_mask(hxgep->hpi_handle, 0, 1);
94 	(void) hpi_pfc_set_tx_int_stat_mask(hxgep->hpi_handle, 0, 1);
95 
96 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_vmac_init:"));
97 
98 	return (HXGE_OK);
99 fail:
100 	HXGE_DEBUG_MSG((hxgep, MAC_CTL,
101 	    "hxge_vmac_init: failed to initialize VMAC>"));
102 
103 	return (status);
104 }
105 
106 
107 /* Initialize the TxVMAC sub-block */
108 
109 hxge_status_t
hxge_tx_vmac_init(p_hxge_t hxgep)110 hxge_tx_vmac_init(p_hxge_t hxgep)
111 {
112 	uint64_t	config;
113 	hpi_handle_t	handle = hxgep->hpi_handle;
114 
115 	/* CFG_VMAC_TX_EN is done separately */
116 	config = CFG_VMAC_TX_CRC_INSERT | CFG_VMAC_TX_PAD;
117 
118 	if (hpi_vmac_tx_config(handle, INIT, config,
119 	    hxgep->vmac.maxframesize) != HPI_SUCCESS)
120 		return (HXGE_ERROR);
121 
122 	hxgep->vmac.tx_config = config;
123 
124 	return (HXGE_OK);
125 }
126 
127 /* Initialize the RxVMAC sub-block */
128 
129 hxge_status_t
hxge_rx_vmac_init(p_hxge_t hxgep)130 hxge_rx_vmac_init(p_hxge_t hxgep)
131 {
132 	uint64_t	xconfig;
133 	hpi_handle_t	handle = hxgep->hpi_handle;
134 	uint16_t	max_frame_length = hxgep->vmac.maxframesize;
135 
136 	/*
137 	 * NOTE: CFG_VMAC_RX_ENABLE is done separately. Do not enable
138 	 * strip CRC.  Bug ID 11451 -- enable strip CRC will cause
139 	 * rejection on minimum sized packets.
140 	 */
141 	xconfig = CFG_VMAC_RX_PASS_FLOW_CTRL_FR;
142 
143 	if (hxgep->filter.all_phys_cnt != 0)
144 		xconfig |= CFG_VMAC_RX_PROMISCUOUS_MODE;
145 
146 	if (hxgep->filter.all_multicast_cnt != 0)
147 		xconfig |= CFG_VMAC_RX_PROMIXCUOUS_GROUP;
148 
149 	if (hxgep->statsp->port_stats.lb_mode != hxge_lb_normal)
150 		xconfig |= CFG_VMAC_RX_LOOP_BACK;
151 
152 	if (hpi_vmac_rx_config(handle, INIT, xconfig,
153 	    max_frame_length) != HPI_SUCCESS)
154 		return (HXGE_ERROR);
155 
156 	hxgep->vmac.rx_config = xconfig;
157 
158 	return (HXGE_OK);
159 }
160 
161 /* Enable TxVMAC */
162 
163 hxge_status_t
hxge_tx_vmac_enable(p_hxge_t hxgep)164 hxge_tx_vmac_enable(p_hxge_t hxgep)
165 {
166 	hpi_status_t	rv;
167 	hxge_status_t	status = HXGE_OK;
168 	hpi_handle_t	handle = hxgep->hpi_handle;
169 
170 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_tx_vmac_enable"));
171 
172 	rv = hxge_tx_vmac_init(hxgep);
173 	if (rv != HXGE_OK)
174 		return (rv);
175 
176 	/* Based on speed */
177 	hxgep->msg_min = ETHERMIN;
178 
179 	rv = hpi_vmac_tx_config(handle, ENABLE, CFG_VMAC_TX_EN, 0);
180 
181 	status = (rv == HPI_SUCCESS) ? HXGE_OK : HXGE_ERROR;
182 
183 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_tx_vmac_enable"));
184 
185 	return (status);
186 }
187 
188 /* Disable TxVMAC */
189 
190 hxge_status_t
hxge_tx_vmac_disable(p_hxge_t hxgep)191 hxge_tx_vmac_disable(p_hxge_t hxgep)
192 {
193 	hpi_status_t	rv;
194 	hxge_status_t	status = HXGE_OK;
195 	hpi_handle_t	handle = hxgep->hpi_handle;
196 
197 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_tx_vmac_disable"));
198 
199 	rv = hpi_vmac_tx_config(handle, DISABLE, CFG_VMAC_TX_EN, 0);
200 
201 	status = (rv == HPI_SUCCESS) ? HXGE_OK : HXGE_ERROR;
202 
203 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_tx_vmac_disable"));
204 
205 	return (status);
206 }
207 
208 /* Enable RxVMAC */
209 
210 hxge_status_t
hxge_rx_vmac_enable(p_hxge_t hxgep)211 hxge_rx_vmac_enable(p_hxge_t hxgep)
212 {
213 	hpi_status_t	rv;
214 	hxge_status_t	status = HXGE_OK;
215 	hpi_handle_t	handle = hxgep->hpi_handle;
216 
217 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_rx_vmac_enable"));
218 
219 	/*
220 	 * Because of hardware bug document with CR6770577, need
221 	 * reprogram max framesize when enabling/disabling RX
222 	 * vmac.  Max framesize is programed here in
223 	 * hxge_rx_vmac_init().
224 	 */
225 	rv = hpi_vmac_rx_set_framesize(HXGE_DEV_HPI_HANDLE(hxgep),
226 	    (uint16_t)hxgep->vmac.maxframesize);
227 	if (rv != HPI_SUCCESS) {
228 		HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_rx_vmac_enable"));
229 		return (HXGE_ERROR);
230 	}
231 
232 	/*
233 	 * Wait for a period of time.
234 	 */
235 	HXGE_DELAY(10);
236 
237 	/*
238 	 * Enable the vmac.
239 	 */
240 	rv = hpi_vmac_rx_config(handle, ENABLE, CFG_VMAC_RX_EN, 0);
241 
242 	status = (rv == HPI_SUCCESS) ? HXGE_OK : HXGE_ERROR;
243 
244 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_rx_vmac_enable"));
245 	return (status);
246 }
247 
248 /* Disable RxVMAC */
249 
250 hxge_status_t
hxge_rx_vmac_disable(p_hxge_t hxgep)251 hxge_rx_vmac_disable(p_hxge_t hxgep)
252 {
253 	hpi_status_t	rv;
254 	hxge_status_t	status = HXGE_OK;
255 	hpi_handle_t	handle = hxgep->hpi_handle;
256 
257 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_rx_vmac_disable"));
258 
259 	/*
260 	 * Because of hardware bug document with CR6770577, need
261 	 * reprogram max framesize when enabling/disabling RX
262 	 * vmac.  Max framesize is programed here in
263 	 * hxge_rx_vmac_init().
264 	 */
265 	(void) hpi_vmac_rx_set_framesize(HXGE_DEV_HPI_HANDLE(hxgep),
266 	    (uint16_t)0);
267 
268 	/*
269 	 * Wait for 10us before doing disable.
270 	 */
271 	HXGE_DELAY(10);
272 
273 	rv = hpi_vmac_rx_config(handle, DISABLE, CFG_VMAC_RX_EN, 0);
274 
275 	status = (rv == HPI_SUCCESS) ? HXGE_OK : HXGE_ERROR;
276 
277 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_rx_vmac_disable"));
278 	return (status);
279 }
280 
281 /* Reset TxVMAC */
282 
283 hxge_status_t
hxge_tx_vmac_reset(p_hxge_t hxgep)284 hxge_tx_vmac_reset(p_hxge_t hxgep)
285 {
286 	hpi_handle_t	handle = hxgep->hpi_handle;
287 
288 	(void) hpi_tx_vmac_reset(handle);
289 
290 	return (HXGE_OK);
291 }
292 
293 /* Reset RxVMAC */
294 
295 hxge_status_t
hxge_rx_vmac_reset(p_hxge_t hxgep)296 hxge_rx_vmac_reset(p_hxge_t hxgep)
297 {
298 	hpi_handle_t	handle = hxgep->hpi_handle;
299 
300 	(void) hpi_vmac_rx_set_framesize(HXGE_DEV_HPI_HANDLE(hxgep),
301 	    (uint16_t)0);
302 
303 	/*
304 	 * Wait for 10us  before doing reset.
305 	 */
306 	HXGE_DELAY(10);
307 
308 	(void) hpi_rx_vmac_reset(handle);
309 
310 	return (HXGE_OK);
311 }
312 
313 /*ARGSUSED*/
314 uint_t
hxge_vmac_intr(caddr_t arg1,caddr_t arg2)315 hxge_vmac_intr(caddr_t arg1, caddr_t arg2)
316 {
317 	p_hxge_t	hxgep = (p_hxge_t)arg2;
318 	hpi_handle_t	handle;
319 
320 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_vmac_intr"));
321 
322 	handle = HXGE_DEV_HPI_HANDLE(hxgep);
323 
324 	hxge_save_cntrs(hxgep);
325 
326 	/* Clear the interrupt status registers */
327 	(void) hpi_vmac_clear_rx_int_stat(handle);
328 	(void) hpi_vmac_clear_tx_int_stat(handle);
329 
330 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_vmac_intr"));
331 	return (DDI_INTR_CLAIMED);
332 }
333 
334 /*
335  * Set promiscous mode
336  */
337 hxge_status_t
hxge_set_promisc(p_hxge_t hxgep,boolean_t on)338 hxge_set_promisc(p_hxge_t hxgep, boolean_t on)
339 {
340 	hxge_status_t status = HXGE_OK;
341 
342 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_set_promisc: on %d", on));
343 
344 	hxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
345 
346 	RW_ENTER_WRITER(&hxgep->filter_lock);
347 	if ((status = hxge_rx_vmac_disable(hxgep)) != HXGE_OK)
348 		goto fail;
349 	if ((status = hxge_rx_vmac_enable(hxgep)) != HXGE_OK)
350 		goto fail;
351 	RW_EXIT(&hxgep->filter_lock);
352 
353 	if (on)
354 		hxgep->statsp->mac_stats.promisc = B_TRUE;
355 	else
356 		hxgep->statsp->mac_stats.promisc = B_FALSE;
357 
358 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_set_promisc"));
359 	return (HXGE_OK);
360 
361 fail:
362 	RW_EXIT(&hxgep->filter_lock);
363 
364 	HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_set_promisc: "
365 	    "Unable to set promisc (%d)", on));
366 	return (status);
367 }
368 
369 void
hxge_save_cntrs(p_hxge_t hxgep)370 hxge_save_cntrs(p_hxge_t hxgep)
371 {
372 	p_hxge_stats_t	statsp;
373 	hpi_handle_t	handle;
374 
375 	vmac_tx_frame_cnt_t tx_frame_cnt;
376 	vmac_tx_byte_cnt_t tx_byte_cnt;
377 	vmac_rx_frame_cnt_t rx_frame_cnt;
378 	vmac_rx_byte_cnt_t rx_byte_cnt;
379 	vmac_rx_drop_fr_cnt_t rx_drop_fr_cnt;
380 	vmac_rx_drop_byte_cnt_t rx_drop_byte_cnt;
381 	vmac_rx_crc_cnt_t rx_crc_cnt;
382 	vmac_rx_pause_cnt_t rx_pause_cnt;
383 	vmac_rx_bcast_fr_cnt_t rx_bcast_fr_cnt;
384 	vmac_rx_mcast_fr_cnt_t rx_mcast_fr_cnt;
385 
386 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_save_cntrs"));
387 
388 	statsp = (p_hxge_stats_t)hxgep->statsp;
389 	handle = hxgep->hpi_handle;
390 
391 	HXGE_REG_RD64(handle, VMAC_TX_FRAME_CNT, &tx_frame_cnt.value);
392 	HXGE_REG_RD64(handle, VMAC_TX_BYTE_CNT, &tx_byte_cnt.value);
393 	HXGE_REG_RD64(handle, VMAC_RX_FRAME_CNT, &rx_frame_cnt.value);
394 	HXGE_REG_RD64(handle, VMAC_RX_BYTE_CNT, &rx_byte_cnt.value);
395 	HXGE_REG_RD64(handle, VMAC_RX_DROP_FR_CNT, &rx_drop_fr_cnt.value);
396 	HXGE_REG_RD64(handle, VMAC_RX_DROP_BYTE_CNT, &rx_drop_byte_cnt.value);
397 	HXGE_REG_RD64(handle, VMAC_RX_CRC_CNT, &rx_crc_cnt.value);
398 	HXGE_REG_RD64(handle, VMAC_RX_PAUSE_CNT, &rx_pause_cnt.value);
399 	HXGE_REG_RD64(handle, VMAC_RX_BCAST_FR_CNT, &rx_bcast_fr_cnt.value);
400 	HXGE_REG_RD64(handle, VMAC_RX_MCAST_FR_CNT, &rx_mcast_fr_cnt.value);
401 
402 	statsp->vmac_stats.tx_frame_cnt += tx_frame_cnt.bits.tx_frame_cnt;
403 	statsp->vmac_stats.tx_byte_cnt += tx_byte_cnt.bits.tx_byte_cnt;
404 	statsp->vmac_stats.rx_frame_cnt += rx_frame_cnt.bits.rx_frame_cnt;
405 	statsp->vmac_stats.rx_byte_cnt += rx_byte_cnt.bits.rx_byte_cnt;
406 	statsp->vmac_stats.rx_drop_frame_cnt +=
407 	    rx_drop_fr_cnt.bits.rx_drop_frame_cnt;
408 	statsp->vmac_stats.rx_drop_byte_cnt +=
409 	    rx_drop_byte_cnt.bits.rx_drop_byte_cnt;
410 	statsp->vmac_stats.rx_crc_cnt += rx_crc_cnt.bits.rx_crc_cnt;
411 	statsp->vmac_stats.rx_pause_cnt += rx_pause_cnt.bits.rx_pause_cnt;
412 	statsp->vmac_stats.rx_bcast_fr_cnt +=
413 	    rx_bcast_fr_cnt.bits.rx_bcast_fr_cnt;
414 	statsp->vmac_stats.rx_mcast_fr_cnt +=
415 	    rx_mcast_fr_cnt.bits.rx_mcast_fr_cnt;
416 
417 hxge_save_cntrs_exit:
418 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_save_cntrs"));
419 }
420 
421 int
hxge_vmac_set_framesize(p_hxge_t hxgep)422 hxge_vmac_set_framesize(p_hxge_t hxgep)
423 {
424 	int	status = 0;
425 
426 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_vmac_set_framesize"));
427 
428 	RW_ENTER_WRITER(&hxgep->filter_lock);
429 	(void) hxge_rx_vmac_disable(hxgep);
430 	(void) hxge_tx_vmac_disable(hxgep);
431 
432 	/*
433 	 * Apply the new jumbo parameter here which is contained in hxgep
434 	 * data structure (hxgep->vmac.maxframesize);
435 	 * The order of the following two calls is important.
436 	 */
437 	(void) hxge_tx_vmac_enable(hxgep);
438 	(void) hxge_rx_vmac_enable(hxgep);
439 	RW_EXIT(&hxgep->filter_lock);
440 
441 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_vmac_set_framesize"));
442 	return (status);
443 }
444