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