xref: /illumos-gate/usr/src/uts/common/io/hxge/hxge_vmac.c (revision 85bb5f1d)
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  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <hxge_impl.h>
29 #include <hxge_vmac.h>
30 
31 hxge_status_t hxge_vmac_init(p_hxge_t hxgep);
32 hxge_status_t hxge_tx_vmac_init(p_hxge_t hxgep);
33 hxge_status_t hxge_rx_vmac_init(p_hxge_t hxgep);
34 hxge_status_t hxge_tx_vmac_enable(p_hxge_t hxgep);
35 hxge_status_t hxge_tx_vmac_disable(p_hxge_t hxgep);
36 hxge_status_t hxge_rx_vmac_enable(p_hxge_t hxgep);
37 hxge_status_t hxge_rx_vmac_disable(p_hxge_t hxgep);
38 hxge_status_t hxge_tx_vmac_reset(p_hxge_t hxgep);
39 hxge_status_t hxge_rx_vmac_reset(p_hxge_t hxgep);
40 uint_t hxge_vmac_intr(caddr_t arg1, caddr_t arg2);
41 hxge_status_t hxge_set_promisc(p_hxge_t hxgep, boolean_t on);
42 
43 extern boolean_t hxge_jumbo_enable;
44 
45 hxge_status_t
46 hxge_link_init(p_hxge_t hxgep)
47 {
48 	p_hxge_stats_t		statsp;
49 
50 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_link_init>"));
51 
52 	statsp = hxgep->statsp;
53 
54 	statsp->mac_stats.cap_10gfdx = 1;
55 	statsp->mac_stats.lp_cap_10gfdx = 1;
56 
57 	/*
58 	 * The driver doesn't control the link.
59 	 * It is always 10Gb full duplex.
60 	 */
61 	statsp->mac_stats.link_duplex = 2;
62 	statsp->mac_stats.link_speed = 10000;
63 
64 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_link_init"));
65 	return (HXGE_OK);
66 }
67 
68 hxge_status_t
69 hxge_vmac_init(p_hxge_t hxgep)
70 {
71 	hxge_status_t status = HXGE_OK;
72 
73 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_vmac_init:"));
74 
75 	if ((status = hxge_tx_vmac_reset(hxgep)) != HXGE_OK)
76 		goto fail;
77 
78 	if ((status = hxge_rx_vmac_reset(hxgep)) != HXGE_OK)
79 		goto fail;
80 
81 	if ((status = hxge_tx_vmac_enable(hxgep)) != HXGE_OK)
82 		goto fail;
83 
84 	if ((status = hxge_rx_vmac_enable(hxgep)) != HXGE_OK)
85 		goto fail;
86 
87 	/* Clear the interrupt status registers */
88 	(void) hpi_vmac_clear_rx_int_stat(hxgep->hpi_handle);
89 	(void) hpi_vmac_clear_tx_int_stat(hxgep->hpi_handle);
90 
91 	/*
92 	 * Take the masks off the overflow counters. Interrupt the system when
93 	 * any counts overflow. Don't interrupt the system for each frame.
94 	 * The current counts are retrieved when the "kstat" command is used.
95 	 */
96 	(void) hpi_pfc_set_rx_int_stat_mask(hxgep->hpi_handle, 0, 1);
97 	(void) hpi_pfc_set_tx_int_stat_mask(hxgep->hpi_handle, 0, 1);
98 
99 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_vmac_init:"));
100 
101 	return (HXGE_OK);
102 fail:
103 	HXGE_DEBUG_MSG((hxgep, MAC_CTL,
104 	    "hxge_vmac_init: failed to initialize VMAC>"));
105 
106 	return (status);
107 }
108 
109 
110 /* Initialize the TxVMAC sub-block */
111 
112 hxge_status_t
113 hxge_tx_vmac_init(p_hxge_t hxgep)
114 {
115 	uint64_t	config;
116 	hpi_handle_t	handle = hxgep->hpi_handle;
117 
118 	/* Set Max and Min Frame Size */
119 
120 	hxgep->vmac.is_jumbo = B_FALSE;
121 	if (hxge_jumbo_enable)
122 		hxgep->vmac.is_jumbo = B_TRUE;
123 
124 	if (hxgep->param_arr[param_accept_jumbo].value ||
125 	    hxgep->vmac.is_jumbo == B_TRUE)
126 		hxgep->vmac.maxframesize = TX_JUMBO_MTU;
127 	else
128 		hxgep->vmac.maxframesize = STD_FRAME_SIZE + TX_PKT_HEADER_SIZE;
129 	hxgep->vmac.minframesize = 64;
130 
131 	/* CFG_VMAC_TX_EN is done separately */
132 	config = CFG_VMAC_TX_CRC_INSERT | CFG_VMAC_TX_PAD;
133 
134 	if (hpi_vmac_tx_config(handle, INIT, config,
135 	    hxgep->vmac.maxframesize) != HPI_SUCCESS)
136 		return (HXGE_ERROR);
137 
138 	hxgep->vmac.tx_config = config;
139 
140 	return (HXGE_OK);
141 }
142 
143 /* Initialize the RxVMAC sub-block */
144 
145 hxge_status_t
146 hxge_rx_vmac_init(p_hxge_t hxgep)
147 {
148 	uint64_t	xconfig;
149 	hpi_handle_t	handle = hxgep->hpi_handle;
150 	uint16_t	max_frame_length = hxgep->vmac.maxframesize;
151 
152 	/*
153 	 * NOTE: CFG_VMAC_RX_ENABLE is done separately. Do not enable
154 	 * strip CRC.  Bug ID 11451 -- enable strip CRC will cause
155 	 * rejection on minimum sized packets.
156 	 */
157 	xconfig = CFG_VMAC_RX_CRC_CHECK_DISABLE |
158 	    CFG_VMAC_RX_PASS_FLOW_CTRL_FR;
159 
160 	if (hxgep->filter.all_phys_cnt != 0)
161 		xconfig |= CFG_VMAC_RX_PROMISCUOUS_MODE;
162 
163 	if (hxgep->filter.all_multicast_cnt != 0)
164 		xconfig |= CFG_VMAC_RX_PROMIXCUOUS_GROUP;
165 
166 	if (hxgep->statsp->port_stats.lb_mode != hxge_lb_normal)
167 		xconfig |= CFG_VMAC_RX_LOOP_BACK;
168 
169 	if (hpi_vmac_rx_config(handle, INIT, xconfig, max_frame_length)
170 	    != HPI_SUCCESS)
171 		return (HXGE_ERROR);
172 
173 	hxgep->vmac.rx_config = xconfig;
174 
175 	return (HXGE_OK);
176 }
177 
178 /* Enable TxVMAC */
179 
180 hxge_status_t
181 hxge_tx_vmac_enable(p_hxge_t hxgep)
182 {
183 	hpi_status_t	rv;
184 	hxge_status_t	status = HXGE_OK;
185 	hpi_handle_t	handle = hxgep->hpi_handle;
186 
187 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_tx_vmac_enable"));
188 
189 	rv = hxge_tx_vmac_init(hxgep);
190 	if (rv != HXGE_OK)
191 		return (rv);
192 
193 	/* Based on speed */
194 	hxgep->msg_min = ETHERMIN;
195 
196 	rv = hpi_vmac_tx_config(handle, ENABLE, CFG_VMAC_TX_EN, 0);
197 
198 	status = (rv == HPI_SUCCESS) ? HXGE_OK : HXGE_ERROR;
199 
200 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_tx_vmac_enable"));
201 
202 	return (status);
203 }
204 
205 /* Disable TxVMAC */
206 
207 hxge_status_t
208 hxge_tx_vmac_disable(p_hxge_t hxgep)
209 {
210 	hpi_status_t	rv;
211 	hxge_status_t	status = HXGE_OK;
212 	hpi_handle_t	handle = hxgep->hpi_handle;
213 
214 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_tx_vmac_disable"));
215 
216 	rv = hpi_vmac_tx_config(handle, DISABLE, CFG_VMAC_TX_EN, 0);
217 
218 	status = (rv == HPI_SUCCESS) ? HXGE_OK : HXGE_ERROR;
219 
220 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_tx_vmac_disable"));
221 
222 	return (status);
223 }
224 
225 /* Enable RxVMAC */
226 
227 hxge_status_t
228 hxge_rx_vmac_enable(p_hxge_t hxgep)
229 {
230 	hpi_status_t	rv;
231 	hxge_status_t	status = HXGE_OK;
232 	hpi_handle_t	handle = hxgep->hpi_handle;
233 
234 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_rx_vmac_enable"));
235 
236 	rv = hxge_rx_vmac_init(hxgep);
237 	if (rv != HXGE_OK)
238 		return (rv);
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 
246 	return (status);
247 }
248 
249 /* Disable RxVMAC */
250 
251 hxge_status_t
252 hxge_rx_vmac_disable(p_hxge_t hxgep)
253 {
254 	hpi_status_t	rv;
255 	hxge_status_t	status = HXGE_OK;
256 	hpi_handle_t	handle = hxgep->hpi_handle;
257 
258 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_rx_vmac_disable"));
259 
260 	rv = hpi_vmac_rx_config(handle, DISABLE, CFG_VMAC_RX_EN, 0);
261 
262 	status = (rv == HPI_SUCCESS) ? HXGE_OK : HXGE_ERROR;
263 
264 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_rx_vmac_disable"));
265 
266 	return (status);
267 }
268 
269 /* Reset TxVMAC */
270 
271 hxge_status_t
272 hxge_tx_vmac_reset(p_hxge_t hxgep)
273 {
274 	hpi_handle_t	handle = hxgep->hpi_handle;
275 
276 	(void) hpi_tx_vmac_reset(handle);
277 
278 	return (HXGE_OK);
279 }
280 
281 /* Reset RxVMAC */
282 
283 hxge_status_t
284 hxge_rx_vmac_reset(p_hxge_t hxgep)
285 {
286 	hpi_handle_t	handle = hxgep->hpi_handle;
287 
288 	(void) hpi_rx_vmac_reset(handle);
289 
290 	return (HXGE_OK);
291 }
292 
293 /*ARGSUSED*/
294 uint_t
295 hxge_vmac_intr(caddr_t arg1, caddr_t arg2)
296 {
297 	p_hxge_t	hxgep = (p_hxge_t)arg2;
298 	hpi_handle_t	handle;
299 
300 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_vmac_intr"));
301 
302 	handle = HXGE_DEV_HPI_HANDLE(hxgep);
303 
304 	hxge_save_cntrs(hxgep);
305 
306 	/* Clear the interrupt status registers */
307 	(void) hpi_vmac_clear_rx_int_stat(handle);
308 	(void) hpi_vmac_clear_tx_int_stat(handle);
309 
310 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_vmac_intr"));
311 	return (DDI_INTR_CLAIMED);
312 }
313 
314 /*
315  * Set promiscous mode
316  */
317 hxge_status_t
318 hxge_set_promisc(p_hxge_t hxgep, boolean_t on)
319 {
320 	hxge_status_t status = HXGE_OK;
321 
322 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_set_promisc: on %d", on));
323 
324 	hxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
325 
326 	RW_ENTER_WRITER(&hxgep->filter_lock);
327 	if ((status = hxge_rx_vmac_disable(hxgep)) != HXGE_OK)
328 		goto fail;
329 	if ((status = hxge_rx_vmac_enable(hxgep)) != HXGE_OK)
330 		goto fail;
331 	RW_EXIT(&hxgep->filter_lock);
332 
333 	if (on)
334 		hxgep->statsp->mac_stats.promisc = B_TRUE;
335 	else
336 		hxgep->statsp->mac_stats.promisc = B_FALSE;
337 
338 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_set_promisc"));
339 	return (HXGE_OK);
340 
341 fail:
342 	RW_EXIT(&hxgep->filter_lock);
343 
344 	HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_set_promisc: "
345 	    "Unable to set promisc (%d)", on));
346 	return (status);
347 }
348 
349 void
350 hxge_save_cntrs(p_hxge_t hxgep)
351 {
352 	p_hxge_stats_t	statsp;
353 	hpi_handle_t	handle;
354 
355 	vmac_tx_frame_cnt_t tx_frame_cnt;
356 	vmac_tx_byte_cnt_t tx_byte_cnt;
357 	vmac_rx_frame_cnt_t rx_frame_cnt;
358 	vmac_rx_byte_cnt_t rx_byte_cnt;
359 	vmac_rx_drop_fr_cnt_t rx_drop_fr_cnt;
360 	vmac_rx_drop_byte_cnt_t rx_drop_byte_cnt;
361 	vmac_rx_crc_cnt_t rx_crc_cnt;
362 	vmac_rx_pause_cnt_t rx_pause_cnt;
363 	vmac_rx_bcast_fr_cnt_t rx_bcast_fr_cnt;
364 	vmac_rx_mcast_fr_cnt_t rx_mcast_fr_cnt;
365 
366 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_save_cntrs"));
367 
368 	statsp = (p_hxge_stats_t)hxgep->statsp;
369 	handle = hxgep->hpi_handle;
370 
371 	HXGE_REG_RD64(handle, VMAC_TX_FRAME_CNT, &tx_frame_cnt.value);
372 	HXGE_REG_RD64(handle, VMAC_TX_BYTE_CNT, &tx_byte_cnt.value);
373 	HXGE_REG_RD64(handle, VMAC_RX_FRAME_CNT, &rx_frame_cnt.value);
374 	HXGE_REG_RD64(handle, VMAC_RX_BYTE_CNT, &rx_byte_cnt.value);
375 	HXGE_REG_RD64(handle, VMAC_RX_DROP_FR_CNT, &rx_drop_fr_cnt.value);
376 	HXGE_REG_RD64(handle, VMAC_RX_DROP_BYTE_CNT, &rx_drop_byte_cnt.value);
377 	HXGE_REG_RD64(handle, VMAC_RX_CRC_CNT, &rx_crc_cnt.value);
378 	HXGE_REG_RD64(handle, VMAC_RX_PAUSE_CNT, &rx_pause_cnt.value);
379 	HXGE_REG_RD64(handle, VMAC_RX_BCAST_FR_CNT, &rx_bcast_fr_cnt.value);
380 	HXGE_REG_RD64(handle, VMAC_RX_MCAST_FR_CNT, &rx_mcast_fr_cnt.value);
381 
382 	statsp->vmac_stats.tx_frame_cnt += tx_frame_cnt.bits.tx_frame_cnt;
383 	statsp->vmac_stats.tx_byte_cnt += tx_byte_cnt.bits.tx_byte_cnt;
384 	statsp->vmac_stats.rx_frame_cnt += rx_frame_cnt.bits.rx_frame_cnt;
385 	statsp->vmac_stats.rx_byte_cnt += rx_byte_cnt.bits.rx_byte_cnt;
386 	statsp->vmac_stats.rx_drop_frame_cnt +=
387 	    rx_drop_fr_cnt.bits.rx_drop_frame_cnt;
388 	statsp->vmac_stats.rx_drop_byte_cnt +=
389 	    rx_drop_byte_cnt.bits.rx_drop_byte_cnt;
390 	statsp->vmac_stats.rx_crc_cnt += rx_crc_cnt.bits.rx_crc_cnt;
391 	statsp->vmac_stats.rx_pause_cnt += rx_pause_cnt.bits.rx_pause_cnt;
392 	statsp->vmac_stats.rx_bcast_fr_cnt +=
393 	    rx_bcast_fr_cnt.bits.rx_bcast_fr_cnt;
394 	statsp->vmac_stats.rx_mcast_fr_cnt +=
395 	    rx_mcast_fr_cnt.bits.rx_mcast_fr_cnt;
396 
397 hxge_save_cntrs_exit:
398 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_save_cntrs"));
399 }
400