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 2008-2013 Solarflare Communications Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <sys/types.h>
28 #include <sys/ddi.h>
29 #include <sys/sunddi.h>
30 #include <sys/gld.h>
31
32 #include <inet/nd.h>
33 #include <inet/mi.h>
34
35 #include "sfxge.h"
36
37
38 typedef enum sfxge_prop_e {
39 SFXGE_RX_COALESCE_MODE = 0,
40 SFXGE_RX_SCALE_COUNT,
41 SFXGE_FCNTL_RESPOND,
42 SFXGE_FCNTL_GENERATE,
43 SFXGE_INTR_MODERATION,
44 SFXGE_ADV_AUTONEG,
45 SFXGE_ADV_10GFDX,
46 SFXGE_ADV_1000FDX,
47 SFXGE_ADV_1000HDX,
48 SFXGE_ADV_100FDX,
49 SFXGE_ADV_100HDX,
50 SFXGE_ADV_10FDX,
51 SFXGE_ADV_10HDX,
52 SFXGE_ADV_PAUSE,
53 SFXGE_ADV_ASM_PAUSE,
54 SFXGE_LP_AUTONEG,
55 SFXGE_LP_10GFDX,
56 SFXGE_LP_1000FDX,
57 SFXGE_LP_1000HDX,
58 SFXGE_LP_100FDX,
59 SFXGE_LP_100HDX,
60 SFXGE_LP_10FDX,
61 SFXGE_LP_10HDX,
62 SFXGE_LP_PAUSE,
63 SFXGE_LP_ASM_PAUSE,
64 SFXGE_CAP_AUTONEG,
65 SFXGE_CAP_10GFDX,
66 SFXGE_CAP_1000FDX,
67 SFXGE_CAP_1000HDX,
68 SFXGE_CAP_100FDX,
69 SFXGE_CAP_100HDX,
70 SFXGE_CAP_10FDX,
71 SFXGE_CAP_10HDX,
72 SFXGE_CAP_PAUSE,
73 SFXGE_CAP_ASM_PAUSE,
74 SFXGE_NPROPS
75 } sfxge_prop_t;
76
77
78 static int
79 sfxge_gld_nd_get(sfxge_t *sp, unsigned int id, uint32_t *valp)
80 {
81 efx_nic_t *enp = sp->s_enp;
82 unsigned int nprops;
83 int rc;
84
85 nprops = efx_nic_cfg_get(enp)->enc_phy_nprops;
86
87 if (sp->s_mac.sm_state != SFXGE_MAC_STARTED) {
88 rc = ENODEV;
89 goto fail1;
90 }
91
92 ASSERT3U(id, <, nprops + SFXGE_NPROPS);
93
94 if (id < nprops) {
95 if ((rc = efx_phy_prop_get(enp, id, 0, valp)) != 0)
96 goto fail2;
97 } else {
98 id -= nprops;
99
100 switch (id) {
101 case SFXGE_RX_COALESCE_MODE: {
102 sfxge_rx_coalesce_mode_t mode;
103
104 sfxge_rx_coalesce_mode_get(sp, &mode);
105
106 *valp = mode;
107 break;
108 }
109 case SFXGE_RX_SCALE_COUNT: {
110 unsigned int count;
111
112 if (sfxge_rx_scale_count_get(sp, &count) != 0)
113 count = 0;
114
115 *valp = count;
116 break;
117 }
118 case SFXGE_FCNTL_RESPOND: {
119 unsigned int fcntl;
120
121 sfxge_mac_fcntl_get(sp, &fcntl);
122
123 *valp = (fcntl & EFX_FCNTL_RESPOND) ? 1 : 0;
124 break;
125 }
126 case SFXGE_FCNTL_GENERATE: {
127 unsigned int fcntl;
128
129 sfxge_mac_fcntl_get(sp, &fcntl);
130
131 *valp = (fcntl & EFX_FCNTL_GENERATE) ? 1 : 0;
132 break;
133 }
134 case SFXGE_INTR_MODERATION: {
135 unsigned int us;
136
137 sfxge_ev_moderation_get(sp, &us);
138
139 *valp = (long)us;
140 break;
141 }
142 case SFXGE_ADV_AUTONEG: {
143 uint32_t mask;
144
145 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
146
147 *valp = (mask & (1 << EFX_PHY_CAP_AN)) ? 1 : 0;
148 break;
149 }
150 case SFXGE_ADV_10GFDX: {
151 uint32_t mask;
152
153 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
154
155 *valp = (mask & (1 << EFX_PHY_CAP_10000FDX)) ? 1 : 0;
156 break;
157 }
158 case SFXGE_ADV_1000FDX: {
159 uint32_t mask;
160
161 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
162
163 *valp = (mask & (1 << EFX_PHY_CAP_1000FDX)) ? 1 : 0;
164 break;
165 }
166 case SFXGE_ADV_1000HDX: {
167 uint32_t mask;
168
169 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
170
171 *valp = (mask & (1 << EFX_PHY_CAP_1000HDX)) ? 1 : 0;
172 break;
173 }
174 case SFXGE_ADV_100FDX: {
175 uint32_t mask;
176
177 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
178
179 *valp = (mask & (1 << EFX_PHY_CAP_100FDX)) ? 1 : 0;
180 break;
181 }
182 case SFXGE_ADV_100HDX: {
183 uint32_t mask;
184
185 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
186
187 *valp = (mask & (1 << EFX_PHY_CAP_100HDX)) ? 1 : 0;
188 break;
189 }
190 case SFXGE_ADV_10FDX: {
191 uint32_t mask;
192
193 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
194
195 *valp = (mask & (1 << EFX_PHY_CAP_10FDX)) ? 1 : 0;
196 break;
197 }
198 case SFXGE_ADV_10HDX: {
199 uint32_t mask;
200
201 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
202
203 *valp = (mask & (1 << EFX_PHY_CAP_10HDX)) ? 1 : 0;
204 break;
205 }
206 case SFXGE_ADV_PAUSE: {
207 uint32_t mask;
208
209 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
210
211 *valp = (mask & (1 << EFX_PHY_CAP_PAUSE)) ? 1 : 0;
212 break;
213 }
214 case SFXGE_ADV_ASM_PAUSE: {
215 uint32_t mask;
216
217 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
218
219 *valp = (mask & (1 << EFX_PHY_CAP_ASYM)) ? 1 : 0;
220 break;
221 }
222 case SFXGE_LP_AUTONEG: {
223 uint32_t mask;
224
225 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
226
227 *valp = (mask & (1 << EFX_PHY_CAP_AN)) ? 1 : 0;
228 break;
229 }
230 case SFXGE_LP_10GFDX: {
231 uint32_t mask;
232
233 efx_phy_lp_cap_get(enp, &mask);
234
235 *valp = (mask & (1 << EFX_PHY_CAP_10000FDX)) ? 1 : 0;
236 break;
237 }
238 case SFXGE_LP_1000FDX: {
239 uint32_t mask;
240
241 efx_phy_lp_cap_get(enp, &mask);
242
243 *valp = (mask & (1 << EFX_PHY_CAP_1000FDX)) ? 1 : 0;
244 break;
245 }
246 case SFXGE_LP_1000HDX: {
247 uint32_t mask;
248
249 efx_phy_lp_cap_get(enp, &mask);
250
251 *valp = (mask & (1 << EFX_PHY_CAP_1000HDX)) ? 1 : 0;
252 break;
253 }
254 case SFXGE_LP_100FDX: {
255 uint32_t mask;
256
257 efx_phy_lp_cap_get(enp, &mask);
258
259 *valp = (mask & (1 << EFX_PHY_CAP_100FDX)) ? 1 : 0;
260 break;
261 }
262 case SFXGE_LP_100HDX: {
263 uint32_t mask;
264
265 efx_phy_lp_cap_get(enp, &mask);
266
267 *valp = (mask & (1 << EFX_PHY_CAP_100HDX)) ? 1 : 0;
268 break;
269 }
270 case SFXGE_LP_10FDX: {
271 uint32_t mask;
272
273 efx_phy_lp_cap_get(enp, &mask);
274
275 *valp = (mask & (1 << EFX_PHY_CAP_10FDX)) ? 1 : 0;
276 break;
277 }
278 case SFXGE_LP_10HDX: {
279 uint32_t mask;
280
281 efx_phy_lp_cap_get(enp, &mask);
282
283 *valp = (mask & (1 << EFX_PHY_CAP_10HDX)) ? 1 : 0;
284 break;
285 }
286 case SFXGE_LP_PAUSE: {
287 uint32_t mask;
288
289 efx_phy_lp_cap_get(enp, &mask);
290
291 *valp = (mask & (1 << EFX_PHY_CAP_PAUSE)) ? 1 : 0;
292 break;
293 }
294 case SFXGE_LP_ASM_PAUSE: {
295 uint32_t mask;
296
297 efx_phy_lp_cap_get(enp, &mask);
298
299 *valp = (mask & (1 << EFX_PHY_CAP_ASYM)) ? 1 : 0;
300 break;
301 }
302 case SFXGE_CAP_AUTONEG: {
303 uint32_t mask;
304
305 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask);
306
307 *valp = (mask & (1 << EFX_PHY_CAP_AN)) ? 1 : 0;
308 break;
309 }
310 case SFXGE_CAP_10GFDX: {
311 uint32_t mask;
312
313 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask);
314
315 *valp = (mask & (1 << EFX_PHY_CAP_10000FDX)) ? 1 : 0;
316 break;
317 }
318 case SFXGE_CAP_1000FDX: {
319 uint32_t mask;
320
321 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask);
322
323 *valp = (mask & (1 << EFX_PHY_CAP_1000FDX)) ? 1 : 0;
324 break;
325 }
326 case SFXGE_CAP_1000HDX: {
327 uint32_t mask;
328
329 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask);
330
331 *valp = (mask & (1 << EFX_PHY_CAP_1000HDX)) ? 1 : 0;
332 break;
333 }
334 case SFXGE_CAP_100FDX: {
335 uint32_t mask;
336
337 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask);
338
339 *valp = (mask & (1 << EFX_PHY_CAP_100FDX)) ? 1 : 0;
340 break;
341 }
342 case SFXGE_CAP_100HDX: {
343 uint32_t mask;
344
345 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask);
346
347 *valp = (mask & (1 << EFX_PHY_CAP_100HDX)) ? 1 : 0;
348 break;
349 }
350 case SFXGE_CAP_10FDX: {
351 uint32_t mask;
352
353 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask);
354
355 *valp = (mask & (1 << EFX_PHY_CAP_10FDX)) ? 1 : 0;
356 break;
357 }
358 case SFXGE_CAP_10HDX: {
359 uint32_t mask;
360
361 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask);
362
363 *valp = (mask & (1 << EFX_PHY_CAP_10HDX)) ? 1 : 0;
364 break;
365 }
366 case SFXGE_CAP_PAUSE: {
367 uint32_t mask;
368
369 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask);
370
371 *valp = (mask & (1 << EFX_PHY_CAP_PAUSE)) ? 1 : 0;
372 break;
373 }
374 case SFXGE_CAP_ASM_PAUSE: {
375 uint32_t mask;
376
377 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask);
378
379 *valp = (mask & (1 << EFX_PHY_CAP_ASYM)) ? 1 : 0;
380 break;
381 }
382 default:
383 ASSERT(B_FALSE);
384 break;
385 }
386 }
387
388 return (0);
389 fail2:
390 DTRACE_PROBE(fail2);
391 fail1:
392 DTRACE_PROBE1(fail1, int, rc);
393
394 return (rc);
395 }
396
397 #ifdef _USE_NDD_PROPS
398 static int
399 sfxge_gld_nd_get_ioctl(queue_t *q, mblk_t *mp, caddr_t arg, cred_t *credp)
400 {
401 sfxge_ndd_param_t *snpp = (sfxge_ndd_param_t *)arg;
402 sfxge_t *sp = snpp->snp_sp;
403 unsigned int id = snpp->snp_id;
404 uint32_t val;
405 int rc;
406
407 _NOTE(ARGUNUSED(q, credp))
408
409 if ((rc = sfxge_gld_nd_get(sp, id, &val)) != 0)
410 goto fail1;
411
412 (void) mi_mpprintf(mp, "%d", val);
413
414 return (0);
415
416 fail1:
417 DTRACE_PROBE1(fail1, int, rc);
418
419 return (rc);
420 }
421 #else
422 static int
423 sfxge_gld_nd_get_ioctl(queue_t *q, mblk_t *mp, caddr_t arg, cred_t *credp)
424 {
425 ASSERT(B_FALSE);
426 return (-ENODEV);
427 }
428 #endif
429
430
431 static int
432 sfxge_gld_nd_set(sfxge_t *sp, unsigned int id, uint32_t val)
433 {
434 efx_nic_t *enp = sp->s_enp;
435 unsigned int nprops;
436 int rc;
437
438 nprops = efx_nic_cfg_get(enp)->enc_phy_nprops;
439
440 ASSERT3U(id, <, nprops + SFXGE_NPROPS);
441
442 if (id < nprops) {
443 if ((rc = efx_phy_prop_set(enp, id, val)) != 0)
444 goto fail1;
445 } else {
446 id -= nprops;
447
448 switch (id) {
449 case SFXGE_RX_COALESCE_MODE: {
450 sfxge_rx_coalesce_mode_t mode =
451 (sfxge_rx_coalesce_mode_t)val;
452
453 if ((rc = sfxge_rx_coalesce_mode_set(sp, mode)) != 0)
454 goto fail1;
455
456 break;
457 }
458 case SFXGE_RX_SCALE_COUNT: {
459 unsigned int count = (unsigned int)val;
460
461 if ((rc = sfxge_rx_scale_count_set(sp, count)) != 0)
462 goto fail1;
463
464 break;
465 }
466 case SFXGE_FCNTL_RESPOND: {
467 unsigned int fcntl;
468
469 sfxge_mac_fcntl_get(sp, &fcntl);
470
471 if (val != 0)
472 fcntl |= EFX_FCNTL_RESPOND;
473 else
474 fcntl &= ~EFX_FCNTL_RESPOND;
475
476 if ((rc = sfxge_mac_fcntl_set(sp, fcntl)) != 0)
477 goto fail1;
478
479 break;
480 }
481 case SFXGE_FCNTL_GENERATE: {
482 unsigned int fcntl;
483
484 sfxge_mac_fcntl_get(sp, &fcntl);
485
486 if (val != 0)
487 fcntl |= EFX_FCNTL_GENERATE;
488 else
489 fcntl &= ~EFX_FCNTL_GENERATE;
490
491 if ((rc = sfxge_mac_fcntl_set(sp, fcntl)) != 0)
492 goto fail1;
493
494 break;
495 }
496 case SFXGE_INTR_MODERATION: {
497 unsigned int us = (unsigned int)val;
498
499 if ((rc = sfxge_ev_moderation_set(sp, us)) != 0)
500 goto fail1;
501 break;
502 }
503 case SFXGE_ADV_AUTONEG: {
504 uint32_t mask;
505
506 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
507
508 if (val != 0)
509 mask |= (1 << EFX_PHY_CAP_AN);
510 else
511 mask &= ~(1 << EFX_PHY_CAP_AN);
512
513 if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0)
514 goto fail1;
515
516 break;
517 }
518 case SFXGE_ADV_10GFDX: {
519 uint32_t mask;
520
521 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
522
523 if (val != 0)
524 mask |= (1 << EFX_PHY_CAP_10000FDX);
525 else
526 mask &= ~(1 << EFX_PHY_CAP_10000FDX);
527
528 if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0)
529 goto fail1;
530
531 break;
532 }
533 case SFXGE_ADV_1000FDX: {
534 uint32_t mask;
535
536 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
537
538 if (val != 0)
539 mask |= (1 << EFX_PHY_CAP_1000FDX);
540 else
541 mask &= ~(1 << EFX_PHY_CAP_1000FDX);
542
543 if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0)
544 goto fail1;
545
546 break;
547 }
548 case SFXGE_ADV_1000HDX: {
549 uint32_t mask;
550
551 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
552
553 if (val != 0)
554 mask |= (1 << EFX_PHY_CAP_1000HDX);
555 else
556 mask &= ~(1 << EFX_PHY_CAP_1000HDX);
557
558 if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0)
559 goto fail1;
560
561 break;
562 }
563 case SFXGE_ADV_100FDX: {
564 uint32_t mask;
565
566 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
567
568 if (val != 0)
569 mask |= (1 << EFX_PHY_CAP_100FDX);
570 else
571 mask &= ~(1 << EFX_PHY_CAP_100FDX);
572
573 if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0)
574 goto fail1;
575
576 break;
577 }
578 case SFXGE_ADV_100HDX: {
579 uint32_t mask;
580
581 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
582
583 if (val != 0)
584 mask |= (1 << EFX_PHY_CAP_100HDX);
585 else
586 mask &= ~(1 << EFX_PHY_CAP_100HDX);
587
588 if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0)
589 goto fail1;
590
591 break;
592 }
593 case SFXGE_ADV_10FDX: {
594 uint32_t mask;
595
596 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
597
598 if (val != 0)
599 mask |= (1 << EFX_PHY_CAP_10FDX);
600 else
601 mask &= ~(1 << EFX_PHY_CAP_10FDX);
602
603 if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0)
604 goto fail1;
605
606 break;
607 }
608 case SFXGE_ADV_10HDX: {
609 uint32_t mask;
610
611 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
612
613 if (val != 0)
614 mask |= (1 << EFX_PHY_CAP_10HDX);
615 else
616 mask &= ~(1 << EFX_PHY_CAP_10HDX);
617
618 if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0)
619 goto fail1;
620
621 break;
622 }
623 case SFXGE_ADV_PAUSE: {
624 uint32_t mask;
625
626 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
627
628 if (val != 0)
629 mask |= (1 << EFX_PHY_CAP_PAUSE);
630 else
631 mask &= ~(1 << EFX_PHY_CAP_PAUSE);
632
633 if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0)
634 goto fail1;
635
636 break;
637 }
638 case SFXGE_ADV_ASM_PAUSE: {
639 uint32_t mask;
640
641 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
642
643 if (val != 0)
644 mask |= (1 << EFX_PHY_CAP_ASYM);
645 else
646 mask &= ~(1 << EFX_PHY_CAP_ASYM);
647
648 if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0)
649 goto fail1;
650
651 break;
652 }
653 /* Ignore other kstat writes. Might be for the link partner */
654 default:
655 DTRACE_PROBE1(ignore_kstat_write, int, id);
656 }
657 }
658
659 return (0);
660
661 fail1:
662 DTRACE_PROBE1(fail1, int, rc);
663
664 return (rc);
665 }
666
667
668 #ifdef _USE_NDD_PROPS
669 static int
670 sfxge_gld_nd_set_ioctl(queue_t *q, mblk_t *mp, char *valp, caddr_t arg,
671 cred_t *credp)
672 {
673 sfxge_ndd_param_t *snpp = (sfxge_ndd_param_t *)arg;
674 sfxge_t *sp = snpp->snp_sp;
675 unsigned int id = snpp->snp_id;
676 long val;
677 int rc;
678
679 _NOTE(ARGUNUSED(q, mp, credp))
680
681 (void) ddi_strtol(valp, (char **)NULL, 0, &val);
682
683 if ((rc = sfxge_gld_nd_set(sp, id, (uint32_t)val)) != 0)
684 goto fail1;
685
686 return (0);
687
688 fail1:
689 DTRACE_PROBE1(fail1, int, rc);
690
691 return (rc);
692 }
693 #else
694 static int
695 sfxge_gld_nd_set_ioctl(queue_t *q, mblk_t *mp, char *valp, caddr_t arg,
696 cred_t *credp)
697 {
698 ASSERT(B_FALSE);
699 return (-ENODEV);
700 }
701 #endif
702
703
704 static int
705 sfxge_gld_nd_update(kstat_t *ksp, int rw)
706 {
707 sfxge_t *sp = ksp->ks_private;
708 efx_nic_t *enp = sp->s_enp;
709 unsigned int nprops;
710 unsigned int id;
711 int rc = 0;
712
713 nprops = efx_nic_cfg_get(enp)->enc_phy_nprops;
714
715 for (id = 0; id < nprops + SFXGE_NPROPS; id++) {
716 kstat_named_t *knp = &(sp->s_nd_stat[id]);
717
718 if (rw == KSTAT_READ)
719 rc = sfxge_gld_nd_get(sp, id, &(knp->value.ui32));
720 else if (rw == KSTAT_WRITE)
721 rc = sfxge_gld_nd_set(sp, id, knp->value.ui32);
722 else
723 rc = EACCES;
724
725 if (rc != 0)
726 goto fail1;
727 }
728
729 return (0);
730
731 fail1:
732 DTRACE_PROBE1(fail1, int, rc);
733 return (rc);
734 }
735
736
737 static sfxge_ndd_param_t sfxge_ndd_param[] = {
738 {
739 NULL,
740 SFXGE_RX_COALESCE_MODE,
741 "rx_coalesce_mode",
742 sfxge_gld_nd_get_ioctl,
743 sfxge_gld_nd_set_ioctl
744 },
745 {
746 NULL,
747 SFXGE_RX_SCALE_COUNT,
748 "rx_scale_count",
749 sfxge_gld_nd_get_ioctl,
750 sfxge_gld_nd_set_ioctl
751 },
752 {
753 NULL,
754 SFXGE_FCNTL_RESPOND,
755 "fcntl_respond",
756 sfxge_gld_nd_get_ioctl,
757 sfxge_gld_nd_set_ioctl
758 },
759 {
760 NULL,
761 SFXGE_FCNTL_GENERATE,
762 "fcntl_generate",
763 sfxge_gld_nd_get_ioctl,
764 sfxge_gld_nd_set_ioctl
765 },
766 {
767 NULL,
768 SFXGE_INTR_MODERATION,
769 "intr_moderation",
770 sfxge_gld_nd_get_ioctl,
771 sfxge_gld_nd_set_ioctl
772 },
773 {
774 NULL,
775 SFXGE_ADV_AUTONEG,
776 "adv_cap_autoneg",
777 sfxge_gld_nd_get_ioctl,
778 sfxge_gld_nd_set_ioctl
779 },
780 {
781 NULL,
782 SFXGE_ADV_10GFDX,
783 "adv_cap_10gfdx",
784 sfxge_gld_nd_get_ioctl,
785 sfxge_gld_nd_set_ioctl
786 },
787 {
788 NULL,
789 SFXGE_ADV_1000FDX,
790 "adv_cap_1000fdx",
791 sfxge_gld_nd_get_ioctl,
792 sfxge_gld_nd_set_ioctl
793 },
794 {
795 NULL,
796 SFXGE_ADV_1000HDX,
797 "adv_cap_1000hdx",
798 sfxge_gld_nd_get_ioctl,
799 sfxge_gld_nd_set_ioctl
800 },
801 {
802 NULL,
803 SFXGE_ADV_100FDX,
804 "adv_cap_100fdx",
805 sfxge_gld_nd_get_ioctl,
806 sfxge_gld_nd_set_ioctl
807 },
808 {
809 NULL,
810 SFXGE_ADV_100HDX,
811 "adv_cap_100hdx",
812 sfxge_gld_nd_get_ioctl,
813 sfxge_gld_nd_set_ioctl
814 },
815 {
816 NULL,
817 SFXGE_ADV_10FDX,
818 "adv_cap_10fdx",
819 sfxge_gld_nd_get_ioctl,
820 sfxge_gld_nd_set_ioctl
821 },
822 {
823 NULL,
824 SFXGE_ADV_10HDX,
825 "adv_cap_10hdx",
826 sfxge_gld_nd_get_ioctl,
827 sfxge_gld_nd_set_ioctl
828 },
829 {
830 NULL,
831 SFXGE_ADV_PAUSE,
832 "adv_cap_pause",
833 sfxge_gld_nd_get_ioctl,
834 sfxge_gld_nd_set_ioctl
835 },
836 {
837 NULL,
838 SFXGE_ADV_ASM_PAUSE,
839 "adv_cap_asm_pause",
840 sfxge_gld_nd_get_ioctl,
841 sfxge_gld_nd_set_ioctl
842 },
843 {
844 NULL,
845 SFXGE_LP_AUTONEG,
846 "lp_cap_autoneg",
847 sfxge_gld_nd_get_ioctl,
848 NULL
849 },
850 {
851 NULL,
852 SFXGE_LP_10GFDX,
853 "lp_cap_10gfdx",
854 sfxge_gld_nd_get_ioctl,
855 NULL
856 },
857 {
858 NULL,
859 SFXGE_LP_1000FDX,
860 "lp_cap_1000fdx",
861 sfxge_gld_nd_get_ioctl,
862 NULL
863 },
864 {
865 NULL,
866 SFXGE_LP_1000HDX,
867 "lp_cap_1000hdx",
868 sfxge_gld_nd_get_ioctl,
869 NULL
870 },
871 {
872 NULL,
873 SFXGE_LP_100FDX,
874 "lp_cap_100fdx",
875 sfxge_gld_nd_get_ioctl,
876 NULL
877 },
878 {
879 NULL,
880 SFXGE_LP_100HDX,
881 "lp_cap_100hdx",
882 sfxge_gld_nd_get_ioctl,
883 NULL
884 },
885 {
886 NULL,
887 SFXGE_LP_10FDX,
888 "lp_cap_10fdx",
889 sfxge_gld_nd_get_ioctl,
890 NULL
891 },
892 {
893 NULL,
894 SFXGE_LP_10HDX,
895 "lp_cap_10hdx",
896 sfxge_gld_nd_get_ioctl,
897 NULL
898 },
899 {
900 NULL,
901 SFXGE_LP_PAUSE,
902 "lp_cap_pause",
903 sfxge_gld_nd_get_ioctl,
904 NULL
905 },
906 {
907 NULL,
908 SFXGE_LP_ASM_PAUSE,
909 "lp_cap_asm_pause",
910 sfxge_gld_nd_get_ioctl,
911 NULL
912 },
913 {
914 NULL,
915 SFXGE_CAP_AUTONEG,
916 "cap_autoneg",
917 sfxge_gld_nd_get_ioctl,
918 NULL
919 },
920 {
921 NULL,
922 SFXGE_CAP_10GFDX,
923 "cap_10gfdx",
924 sfxge_gld_nd_get_ioctl,
925 NULL
926 },
927 {
928 NULL,
929 SFXGE_CAP_1000FDX,
930 "cap_1000fdx",
931 sfxge_gld_nd_get_ioctl,
932 NULL
933 },
934 {
935 NULL,
936 SFXGE_CAP_1000HDX,
937 "cap_1000hdx",
938 sfxge_gld_nd_get_ioctl,
939 NULL
940 },
941 {
942 NULL,
943 SFXGE_CAP_100FDX,
944 "cap_100fdx",
945 sfxge_gld_nd_get_ioctl,
946 NULL
947 },
948 {
949 NULL,
950 SFXGE_CAP_100HDX,
951 "cap_100hdx",
952 sfxge_gld_nd_get_ioctl,
953 NULL
954 },
955 {
956 NULL,
957 SFXGE_CAP_10FDX,
958 "cap_10fdx",
959 sfxge_gld_nd_get_ioctl,
960 NULL
961 },
962 {
963 NULL,
964 SFXGE_CAP_10HDX,
965 "cap_10hdx",
966 sfxge_gld_nd_get_ioctl,
967 NULL
968 },
969 {
970 NULL,
971 SFXGE_CAP_PAUSE,
972 "cap_pause",
973 sfxge_gld_nd_get_ioctl,
974 NULL
975 },
976 {
977 NULL,
978 SFXGE_CAP_ASM_PAUSE,
979 "cap_asm_pause",
980 sfxge_gld_nd_get_ioctl,
981 NULL
982 }
983 };
984
985
986 int
987 sfxge_gld_nd_register(sfxge_t *sp)
988 {
989 #ifdef _USE_NDD_PROPS
990 caddr_t *ndhp = &(sp->s_ndh);
991 #endif
992 efx_nic_t *enp = sp->s_enp;
993 unsigned int nprops;
994 unsigned int id;
995 char name[MAXNAMELEN];
996 kstat_t *ksp;
997 int rc;
998
999 ASSERT3P(sp->s_ndh, ==, NULL);
1000
1001 nprops = efx_nic_cfg_get(enp)->enc_phy_nprops;
1002
1003 #ifdef _USE_NDD_PROPS
1004 /* Register with the NDD framework */
1005 if ((sp->s_ndp = kmem_zalloc(sizeof (sfxge_ndd_param_t) *
1006 (nprops + SFXGE_NPROPS), KM_NOSLEEP)) == NULL) {
1007 rc = ENOMEM;
1008 goto fail1;
1009 }
1010
1011 for (id = 0; id < nprops; id++) {
1012 sfxge_ndd_param_t *snpp = &(sp->s_ndp[id]);
1013
1014 snpp->snp_sp = sp;
1015 snpp->snp_id = id;
1016 snpp->snp_name = efx_phy_prop_name(enp, id);
1017 snpp->snp_get = sfxge_gld_nd_get_ioctl;
1018 snpp->snp_set = sfxge_gld_nd_set_ioctl;
1019
1020 ASSERT(snpp->snp_name != NULL);
1021
1022 (void) nd_load(ndhp, (char *)(snpp->snp_name),
1023 snpp->snp_get, snpp->snp_set, (caddr_t)snpp);
1024 }
1025
1026 for (id = 0; id < SFXGE_NPROPS; id++) {
1027 sfxge_ndd_param_t *snpp = &(sp->s_ndp[id + nprops]);
1028
1029 *snpp = sfxge_ndd_param[id];
1030 ASSERT3U(snpp->snp_id, ==, id);
1031
1032 snpp->snp_sp = sp;
1033 snpp->snp_id += nprops;
1034
1035 (void) nd_load(ndhp, (char *)(snpp->snp_name),
1036 snpp->snp_get, snpp->snp_set, (caddr_t)snpp);
1037 }
1038 #endif
1039
1040 /* Also create a kstat set */
1041 (void) snprintf(name, MAXNAMELEN - 1, "%s_ndd",
1042 ddi_driver_name(sp->s_dip));
1043
1044 if ((ksp = kstat_create((char *)ddi_driver_name(sp->s_dip),
1045 ddi_get_instance(sp->s_dip), name, "ndd", KSTAT_TYPE_NAMED,
1046 (nprops + SFXGE_NPROPS), KSTAT_FLAG_WRITABLE)) == NULL) {
1047 rc = ENOMEM;
1048 goto fail2;
1049 }
1050
1051 sp->s_nd_ksp = ksp;
1052
1053 ksp->ks_update = sfxge_gld_nd_update;
1054 ksp->ks_private = sp;
1055
1056 sp->s_nd_stat = ksp->ks_data;
1057
1058 for (id = 0; id < nprops; id++) {
1059 kstat_named_t *knp = &(sp->s_nd_stat[id]);
1060
1061 kstat_named_init(knp, (char *)efx_phy_prop_name(enp, id),
1062 KSTAT_DATA_UINT32);
1063 }
1064
1065 for (id = 0; id < SFXGE_NPROPS; id++) {
1066 kstat_named_t *knp = &(sp->s_nd_stat[id + nprops]);
1067 sfxge_ndd_param_t *snpp = &sfxge_ndd_param[id];
1068
1069 kstat_named_init(knp, (char *)(snpp->snp_name),
1070 KSTAT_DATA_UINT32);
1071 }
1072
1073 kstat_install(ksp);
1074
1075 return (0);
1076
1077 fail2:
1078 DTRACE_PROBE(fail2);
1079
1080 #ifdef _USE_NDD_PROPS
1081 nd_free(ndhp);
1082 sp->s_ndh = NULL;
1083
1084 kmem_free(sp->s_ndp, sizeof (sfxge_ndd_param_t) *
1085 (nprops + SFXGE_NPROPS));
1086 sp->s_ndp = NULL;
1087
1088 fail1:
1089 DTRACE_PROBE1(fail1, int, rc);
1090 #endif
1091
1092 return (rc);
1093 }
1094
1095
1096 void
1097 sfxge_gld_nd_unregister(sfxge_t *sp)
1098 {
1099 #ifdef _USE_NDD_PROPS
1100 caddr_t *ndhp = &(sp->s_ndh);
1101 #endif
1102 efx_nic_t *enp = sp->s_enp;
1103 unsigned int nprops;
1104
1105 nprops = efx_nic_cfg_get(enp)->enc_phy_nprops;
1106
1107 /* Destroy the kstat set */
1108 kstat_delete(sp->s_nd_ksp);
1109 sp->s_nd_ksp = NULL;
1110 sp->s_nd_stat = NULL;
1111
1112 /* Unregister from the NDD framework */
1113 #ifdef _USE_NDD_PROPS
1114 nd_free(ndhp);
1115
1116 sp->s_ndh = NULL;
1117
1118 kmem_free(sp->s_ndp, sizeof (sfxge_ndd_param_t) *
1119 (nprops + SFXGE_NPROPS));
1120 sp->s_ndp = NULL;
1121 #endif
1122 }