xref: /illumos-gate/usr/src/uts/common/io/hxge/hxge_vmac.c (revision 19397407)
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_CRC_CHECK_DISABLE |
141 	    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, max_frame_length)
153 	    != 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
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
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
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 	rv = hxge_rx_vmac_init(hxgep);
220 	if (rv != HXGE_OK)
221 		return (rv);
222 
223 	rv = hpi_vmac_rx_config(handle, ENABLE, CFG_VMAC_RX_EN, 0);
224 
225 	status = (rv == HPI_SUCCESS) ? HXGE_OK : HXGE_ERROR;
226 
227 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_rx_vmac_enable"));
228 
229 	return (status);
230 }
231 
232 /* Disable RxVMAC */
233 
234 hxge_status_t
235 hxge_rx_vmac_disable(p_hxge_t hxgep)
236 {
237 	hpi_status_t	rv;
238 	hxge_status_t	status = HXGE_OK;
239 	hpi_handle_t	handle = hxgep->hpi_handle;
240 
241 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_rx_vmac_disable"));
242 
243 	rv = hpi_vmac_rx_config(handle, DISABLE, CFG_VMAC_RX_EN, 0);
244 
245 	status = (rv == HPI_SUCCESS) ? HXGE_OK : HXGE_ERROR;
246 
247 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_rx_vmac_disable"));
248 
249 	return (status);
250 }
251 
252 /* Reset TxVMAC */
253 
254 hxge_status_t
255 hxge_tx_vmac_reset(p_hxge_t hxgep)
256 {
257 	hpi_handle_t	handle = hxgep->hpi_handle;
258 
259 	(void) hpi_tx_vmac_reset(handle);
260 
261 	return (HXGE_OK);
262 }
263 
264 /* Reset RxVMAC */
265 
266 hxge_status_t
267 hxge_rx_vmac_reset(p_hxge_t hxgep)
268 {
269 	hpi_handle_t	handle = hxgep->hpi_handle;
270 
271 	(void) hpi_rx_vmac_reset(handle);
272 
273 	return (HXGE_OK);
274 }
275 
276 /*ARGSUSED*/
277 uint_t
278 hxge_vmac_intr(caddr_t arg1, caddr_t arg2)
279 {
280 	p_hxge_t	hxgep = (p_hxge_t)arg2;
281 	hpi_handle_t	handle;
282 
283 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_vmac_intr"));
284 
285 	handle = HXGE_DEV_HPI_HANDLE(hxgep);
286 
287 	hxge_save_cntrs(hxgep);
288 
289 	/* Clear the interrupt status registers */
290 	(void) hpi_vmac_clear_rx_int_stat(handle);
291 	(void) hpi_vmac_clear_tx_int_stat(handle);
292 
293 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_vmac_intr"));
294 	return (DDI_INTR_CLAIMED);
295 }
296 
297 /*
298  * Set promiscous mode
299  */
300 hxge_status_t
301 hxge_set_promisc(p_hxge_t hxgep, boolean_t on)
302 {
303 	hxge_status_t status = HXGE_OK;
304 
305 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_set_promisc: on %d", on));
306 
307 	hxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
308 
309 	RW_ENTER_WRITER(&hxgep->filter_lock);
310 	if ((status = hxge_rx_vmac_disable(hxgep)) != HXGE_OK)
311 		goto fail;
312 	if ((status = hxge_rx_vmac_enable(hxgep)) != HXGE_OK)
313 		goto fail;
314 	RW_EXIT(&hxgep->filter_lock);
315 
316 	if (on)
317 		hxgep->statsp->mac_stats.promisc = B_TRUE;
318 	else
319 		hxgep->statsp->mac_stats.promisc = B_FALSE;
320 
321 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_set_promisc"));
322 	return (HXGE_OK);
323 
324 fail:
325 	RW_EXIT(&hxgep->filter_lock);
326 
327 	HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_set_promisc: "
328 	    "Unable to set promisc (%d)", on));
329 	return (status);
330 }
331 
332 void
333 hxge_save_cntrs(p_hxge_t hxgep)
334 {
335 	p_hxge_stats_t	statsp;
336 	hpi_handle_t	handle;
337 
338 	vmac_tx_frame_cnt_t tx_frame_cnt;
339 	vmac_tx_byte_cnt_t tx_byte_cnt;
340 	vmac_rx_frame_cnt_t rx_frame_cnt;
341 	vmac_rx_byte_cnt_t rx_byte_cnt;
342 	vmac_rx_drop_fr_cnt_t rx_drop_fr_cnt;
343 	vmac_rx_drop_byte_cnt_t rx_drop_byte_cnt;
344 	vmac_rx_crc_cnt_t rx_crc_cnt;
345 	vmac_rx_pause_cnt_t rx_pause_cnt;
346 	vmac_rx_bcast_fr_cnt_t rx_bcast_fr_cnt;
347 	vmac_rx_mcast_fr_cnt_t rx_mcast_fr_cnt;
348 
349 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_save_cntrs"));
350 
351 	statsp = (p_hxge_stats_t)hxgep->statsp;
352 	handle = hxgep->hpi_handle;
353 
354 	HXGE_REG_RD64(handle, VMAC_TX_FRAME_CNT, &tx_frame_cnt.value);
355 	HXGE_REG_RD64(handle, VMAC_TX_BYTE_CNT, &tx_byte_cnt.value);
356 	HXGE_REG_RD64(handle, VMAC_RX_FRAME_CNT, &rx_frame_cnt.value);
357 	HXGE_REG_RD64(handle, VMAC_RX_BYTE_CNT, &rx_byte_cnt.value);
358 	HXGE_REG_RD64(handle, VMAC_RX_DROP_FR_CNT, &rx_drop_fr_cnt.value);
359 	HXGE_REG_RD64(handle, VMAC_RX_DROP_BYTE_CNT, &rx_drop_byte_cnt.value);
360 	HXGE_REG_RD64(handle, VMAC_RX_CRC_CNT, &rx_crc_cnt.value);
361 	HXGE_REG_RD64(handle, VMAC_RX_PAUSE_CNT, &rx_pause_cnt.value);
362 	HXGE_REG_RD64(handle, VMAC_RX_BCAST_FR_CNT, &rx_bcast_fr_cnt.value);
363 	HXGE_REG_RD64(handle, VMAC_RX_MCAST_FR_CNT, &rx_mcast_fr_cnt.value);
364 
365 	statsp->vmac_stats.tx_frame_cnt += tx_frame_cnt.bits.tx_frame_cnt;
366 	statsp->vmac_stats.tx_byte_cnt += tx_byte_cnt.bits.tx_byte_cnt;
367 	statsp->vmac_stats.rx_frame_cnt += rx_frame_cnt.bits.rx_frame_cnt;
368 	statsp->vmac_stats.rx_byte_cnt += rx_byte_cnt.bits.rx_byte_cnt;
369 	statsp->vmac_stats.rx_drop_frame_cnt +=
370 	    rx_drop_fr_cnt.bits.rx_drop_frame_cnt;
371 	statsp->vmac_stats.rx_drop_byte_cnt +=
372 	    rx_drop_byte_cnt.bits.rx_drop_byte_cnt;
373 	statsp->vmac_stats.rx_crc_cnt += rx_crc_cnt.bits.rx_crc_cnt;
374 	statsp->vmac_stats.rx_pause_cnt += rx_pause_cnt.bits.rx_pause_cnt;
375 	statsp->vmac_stats.rx_bcast_fr_cnt +=
376 	    rx_bcast_fr_cnt.bits.rx_bcast_fr_cnt;
377 	statsp->vmac_stats.rx_mcast_fr_cnt +=
378 	    rx_mcast_fr_cnt.bits.rx_mcast_fr_cnt;
379 
380 hxge_save_cntrs_exit:
381 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_save_cntrs"));
382 }
383 
384 int
385 hxge_vmac_set_framesize(p_hxge_t hxgep)
386 {
387 	int	status = 0;
388 
389 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_vmac_set_framesize"));
390 
391 	RW_ENTER_WRITER(&hxgep->filter_lock);
392 	(void) hxge_rx_vmac_disable(hxgep);
393 	(void) hxge_tx_vmac_disable(hxgep);
394 
395 	/*
396 	 * Apply the new jumbo parameter here which is contained in hxgep
397 	 * data structure (hxgep->vmac.maxframesize);
398 	 * The order of the following two calls is important.
399 	 */
400 	(void) hxge_tx_vmac_enable(hxgep);
401 	(void) hxge_rx_vmac_enable(hxgep);
402 	RW_EXIT(&hxgep->filter_lock);
403 
404 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_vmac_set_framesize"));
405 	return (status);
406 }
407