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