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/sysmacros.h>
29 #include <sys/ddi.h>
30 #include <sys/sunddi.h>
31 #include <sys/cyclic.h>
32
33 #include "sfxge.h"
34 #include "efx.h"
35
36 /*
37 * All efx_phy_*() must be after efx_port_init()
38 *
39 * LOCKING STRATEGY: Aquire sm_lock and test sm_state==SFXGE_MAC_STARTED
40 * to serialise against sfxge_restart()
41 *
42 * Note that there is no seperate PHY lock
43 * Everything is driven from MAC code and the MAC lock is used
44 */
45
46 /* PHY DMA attributes */
47 static ddi_device_acc_attr_t sfxge_phy_devacc = {
48
49 DDI_DEVICE_ATTR_V0, /* devacc_attr_version */
50 DDI_NEVERSWAP_ACC, /* devacc_attr_endian_flags */
51 DDI_STRICTORDER_ACC /* devacc_attr_dataorder */
52 };
53
54 static ddi_dma_attr_t sfxge_phy_dma_attr = {
55 DMA_ATTR_V0, /* dma_attr_version */
56 0, /* dma_attr_addr_lo */
57 0xffffffffffffffffull, /* dma_attr_addr_hi */
58 0xffffffffffffffffull, /* dma_attr_count_max */
59 0x1000, /* dma_attr_align */
60 0xffffffff, /* dma_attr_burstsizes */
61 1, /* dma_attr_minxfer */
62 0xffffffffffffffffull, /* dma_attr_maxxfer */
63 0xffffffffffffffffull, /* dma_attr_seg */
64 1, /* dma_attr_sgllen */
65 1, /* dma_attr_granular */
66 0 /* dma_attr_flags */
67 };
68
69
70 /* The common code requires the loader *without* the REFLASH_HEADER */
71 #if EFSYS_OPT_FALCON && EFSYS_OPT_NVRAM_SFT9001
72 static const uint8_t SFT9001_FULL_LOADER[] = {
73 #include "firmware/image.h"
74 #include "firmware/SFT9001A_LOADER.c"
75 };
76 const uint8_t * const sft9001_loader = SFT9001_FULL_LOADER +
77 sizeof (image_header_t);
78 const size_t sft9001_loader_size = sizeof (SFT9001_FULL_LOADER) -
79 sizeof (image_header_t);
80 #endif
81
82 #if EFSYS_OPT_FALCON && EFSYS_OPT_NVRAM_SFX7101
83 static const uint8_t SFX7101_FULL_LOADER[] = {
84 #include "firmware/image.h"
85 #include "firmware/SFX7101B_LOADER.c"
86 };
87 const uint8_t * const sfx7101_loader = SFX7101_FULL_LOADER +
88 sizeof (image_header_t);
89 const size_t sfx7101_loader_size = sizeof (SFX7101_FULL_LOADER) -
90 sizeof (image_header_t);
91 #endif
92
93
94 static int
95 sfxge_phy_kstat_update(kstat_t *ksp, int rw)
96 {
97 sfxge_t *sp = ksp->ks_private;
98 sfxge_mac_t *smp = &(sp->s_mac);
99 sfxge_phy_t *spp = &(smp->sm_phy);
100 efx_nic_t *enp = sp->s_enp;
101 kstat_named_t *knp;
102 const efx_nic_cfg_t *encp;
103 int rc, sn;
104
105 if (rw != KSTAT_READ) {
106 rc = EACCES;
107 goto fail1;
108 }
109
110 ASSERT(mutex_owned(&(smp->sm_lock)));
111
112 if (smp->sm_state != SFXGE_MAC_STARTED)
113 goto done;
114
115 /* Synchronize the DMA memory for reading */
116 (void) ddi_dma_sync(spp->sp_mem.esm_dma_handle,
117 0,
118 EFX_PHY_STATS_SIZE,
119 DDI_DMA_SYNC_FORKERNEL);
120
121 if ((rc = efx_phy_stats_update(enp, &spp->sp_mem, spp->sp_statbuf))
122 != 0)
123 goto fail2;
124
125 knp = spp->sp_stat;
126 for (sn = 0; sn < EFX_PHY_NSTATS; sn++) {
127 knp->value.ui64 = spp->sp_statbuf[sn];
128 knp++;
129 }
130
131 encp = efx_nic_cfg_get(enp);
132 knp->value.ui64 = encp->enc_port;
133
134 done:
135 return (0);
136
137 fail2:
138 DTRACE_PROBE(fail2);
139 fail1:
140 DTRACE_PROBE1(fail1, int, rc);
141
142 return (rc);
143 }
144
145 int
146 sfxge_phy_kstat_init(sfxge_t *sp)
147 {
148 dev_info_t *dip = sp->s_dip;
149 sfxge_phy_t *spp = &(sp->s_mac.sm_phy);
150 efx_nic_t *enp = sp->s_enp;
151 kstat_t *ksp;
152 kstat_named_t *knp;
153 const efx_nic_cfg_t *encp;
154 unsigned int id;
155 char name[MAXNAMELEN];
156 int rc;
157
158 if ((spp->sp_statbuf = kmem_zalloc(sizeof (uint32_t) * EFX_PHY_NSTATS,
159 KM_NOSLEEP)) == NULL) {
160 rc = ENOMEM;
161 goto fail1;
162 }
163
164 encp = efx_nic_cfg_get(enp);
165
166 (void) snprintf(name, MAXNAMELEN - 1, "%s_%s", ddi_driver_name(dip),
167 encp->enc_phy_name);
168
169 /* Create the set */
170 if ((ksp = kstat_create((char *)ddi_driver_name(dip),
171 ddi_get_instance(dip), name, "phy", KSTAT_TYPE_NAMED,
172 EFX_PHY_NSTATS + 1, 0)) == NULL) {
173 rc = ENOMEM;
174 goto fail2;
175 }
176
177 spp->sp_ksp = ksp;
178
179 ksp->ks_update = sfxge_phy_kstat_update;
180 ksp->ks_private = sp;
181 ksp->ks_lock = &(sp->s_mac.sm_lock);
182
183 /* Initialise the named stats */
184 spp->sp_stat = knp = ksp->ks_data;
185 for (id = 0; id < EFX_PHY_NSTATS; id++) {
186 kstat_named_init(knp, (char *)efx_phy_stat_name(enp, id),
187 KSTAT_DATA_UINT64);
188 knp++;
189 }
190
191 kstat_named_init(knp, "port", KSTAT_DATA_UINT64);
192 kstat_install(ksp);
193
194 return (0);
195
196 fail2:
197 DTRACE_PROBE(fail2)
198 kmem_free(spp->sp_statbuf, sizeof (uint32_t) * EFX_PHY_NSTATS);
199
200 fail1:
201 DTRACE_PROBE1(fail1, int, rc);
202
203 return (rc);
204 }
205
206 void
207 sfxge_phy_kstat_fini(sfxge_t *sp)
208 {
209 sfxge_phy_t *spp = &(sp->s_mac.sm_phy);
210
211 /* Destroy the set */
212 kstat_delete(spp->sp_ksp);
213 spp->sp_ksp = NULL;
214 spp->sp_stat = NULL;
215
216 kmem_free(spp->sp_statbuf, sizeof (uint32_t) * EFX_PHY_NSTATS);
217 }
218
219
220 int
221 sfxge_phy_init(sfxge_t *sp)
222 {
223 sfxge_phy_t *spp = &(sp->s_mac.sm_phy);
224 efsys_mem_t *esmp = &(spp->sp_mem);
225 sfxge_dma_buffer_attr_t dma_attr;
226 int rc;
227
228 dma_attr.sdba_dip = sp->s_dip;
229 dma_attr.sdba_dattrp = &sfxge_phy_dma_attr;
230 dma_attr.sdba_callback = DDI_DMA_SLEEP;
231 dma_attr.sdba_length = EFX_PHY_STATS_SIZE;
232 dma_attr.sdba_memflags = DDI_DMA_CONSISTENT;
233 dma_attr.sdba_devaccp = &sfxge_phy_devacc;
234 dma_attr.sdba_bindflags = DDI_DMA_READ | DDI_DMA_CONSISTENT;
235 dma_attr.sdba_maxcookies = 1;
236 dma_attr.sdba_zeroinit = B_TRUE;
237
238 if ((rc = sfxge_dma_buffer_create(esmp, &dma_attr)) != 0)
239 goto fail1;
240
241 return (0);
242
243 fail1:
244 DTRACE_PROBE1(fail1, int, rc);
245 SFXGE_OBJ_CHECK(spp, sfxge_phy_t);
246
247 return (rc);
248 }
249
250 static int
251 sfxge_phy_led_mode_set(sfxge_t *sp, efx_phy_led_mode_t mode)
252 {
253 sfxge_mac_t *smp = &(sp->s_mac);
254 int rc;
255
256 ASSERT3U(smp->sm_state, ==, SFXGE_MAC_STARTED);
257
258 if (mode >= EFX_PHY_LED_NMODES) {
259 rc = EINVAL;
260 goto fail1;
261 }
262
263 mutex_enter(&(smp->sm_lock));
264
265 if ((rc = efx_phy_led_set(sp->s_enp, mode)) != 0)
266 goto fail2;
267
268 mutex_exit(&(smp->sm_lock));
269
270 return (0);
271
272 fail2:
273 DTRACE_PROBE(fail2);
274
275 mutex_exit(&(smp->sm_lock));
276
277 fail1:
278 DTRACE_PROBE1(fail1, int, rc);
279
280 return (rc);
281 }
282
283
284 int
285 sfxge_phy_ioctl(sfxge_t *sp, sfxge_phy_ioc_t *spip)
286 {
287 int rc;
288
289 switch (spip->spi_op) {
290 case SFXGE_PHY_OP_LINK: {
291 break;
292 }
293 case SFXGE_PHY_OP_LED: {
294 efx_phy_led_mode_t mode = spip->spi_data;
295
296 if ((rc = sfxge_phy_led_mode_set(sp, mode)) != 0)
297 goto fail1;
298
299 break;
300 }
301 default:
302 rc = ENOTSUP;
303 goto fail1;
304 }
305
306 return (0);
307
308 fail1:
309 DTRACE_PROBE1(fail1, int, rc);
310
311 return (rc);
312 }
313
314
315 static uint8_t
316 bist_status(unsigned long value)
317 {
318 uint8_t ret;
319
320 efx_phy_cable_status_t status = (efx_phy_cable_status_t)value;
321 switch (status) {
322 case EFX_PHY_CABLE_STATUS_OK:
323 ret = SFXGE_PHY_BIST_CABLE_OK;
324 break;
325 case EFX_PHY_CABLE_STATUS_INVALID:
326 ret = SFXGE_PHY_BIST_CABLE_INVALID;
327 break;
328 case EFX_PHY_CABLE_STATUS_OPEN:
329 ret = SFXGE_PHY_BIST_CABLE_OPEN;
330 break;
331 case EFX_PHY_CABLE_STATUS_INTRAPAIRSHORT:
332 ret = SFXGE_PHY_BIST_CABLE_INTRAPAIRSHORT;
333 break;
334 case EFX_PHY_CABLE_STATUS_INTERPAIRSHORT:
335 ret = SFXGE_PHY_BIST_CABLE_INTERPAIRSHORT;
336 break;
337 case EFX_PHY_CABLE_STATUS_BUSY:
338 ret = SFXGE_PHY_BIST_CABLE_BUSY;
339 break;
340 default:
341 ret = SFXGE_PHY_BIST_CABLE_UNKNOWN;
342 }
343
344 return (ret);
345 }
346
347
348 int
349 sfxge_phy_bist_ioctl(sfxge_t *sp, sfxge_phy_bist_ioc_t *spbip)
350 {
351 sfxge_mac_t *smp = &(sp->s_mac);
352 efx_phy_bist_type_t bist_type;
353 efx_nic_t *enp;
354 const efx_nic_cfg_t *encp;
355 efx_phy_bist_result_t result;
356 unsigned long values[EFX_PHY_BIST_NVALUES];
357 uint32_t mask;
358 int rc;
359
360 mutex_enter(&(smp->sm_lock));
361 enp = sp->s_enp;
362 encp = efx_nic_cfg_get(enp);
363
364 bist_type = spbip->spbi_break_link ? EFX_PHY_BIST_TYPE_CABLE_LONG :
365 EFX_PHY_BIST_TYPE_CABLE_SHORT;
366
367 if (~encp->enc_bist_mask & (1 << bist_type)) {
368 rc = ENOTSUP;
369 goto fail1;
370 }
371
372 if ((rc = efx_phy_bist_start(enp, bist_type)) != 0)
373 goto fail2;
374
375 do {
376 /* Spin for 1 ms */
377 drv_usecwait(1000);
378
379 if ((rc = efx_phy_bist_poll(enp, bist_type, &result, &mask,
380 values, sizeof (values) / sizeof (values[0]))) != 0)
381 goto fail3;
382
383 ASSERT3U(result, !=, EFX_PHY_BIST_RESULT_UNKNOWN);
384
385 } while (result == EFX_PHY_BIST_RESULT_RUNNING);
386
387 ASSERT3U(mask, ==, ((1 << EFX_PHY_BIST_CABLE_LENGTH_A) |
388 (1 << EFX_PHY_BIST_CABLE_LENGTH_B) |
389 (1 << EFX_PHY_BIST_CABLE_LENGTH_C) |
390 (1 << EFX_PHY_BIST_CABLE_LENGTH_D) |
391 (1 << EFX_PHY_BIST_CABLE_STATUS_A) |
392 (1 << EFX_PHY_BIST_CABLE_STATUS_B) |
393 (1 << EFX_PHY_BIST_CABLE_STATUS_C) |
394 (1 << EFX_PHY_BIST_CABLE_STATUS_D)));
395
396 spbip->spbi_status_a = bist_status(values[EFX_PHY_BIST_CABLE_STATUS_A]);
397 spbip->spbi_status_b = bist_status(values[EFX_PHY_BIST_CABLE_STATUS_B]);
398 spbip->spbi_status_c = bist_status(values[EFX_PHY_BIST_CABLE_STATUS_C]);
399 spbip->spbi_status_d = bist_status(values[EFX_PHY_BIST_CABLE_STATUS_D]);
400
401 spbip->spbi_length_ind_a =
402 (uint16_t)values[EFX_PHY_BIST_CABLE_LENGTH_A];
403 spbip->spbi_length_ind_b =
404 (uint16_t)values[EFX_PHY_BIST_CABLE_LENGTH_B];
405 spbip->spbi_length_ind_c =
406 (uint16_t)values[EFX_PHY_BIST_CABLE_LENGTH_C];
407 spbip->spbi_length_ind_d =
408 (uint16_t)values[EFX_PHY_BIST_CABLE_LENGTH_D];
409
410 /* Bring the PHY back to life */
411 efx_phy_bist_stop(enp, bist_type);
412
413 mutex_exit(&(smp->sm_lock));
414
415 return (0);
416
417 fail3:
418 DTRACE_PROBE(fail3);
419 efx_phy_bist_stop(enp, bist_type);
420 fail2:
421 DTRACE_PROBE(fail2);
422 fail1:
423 mutex_exit(&(smp->sm_lock));
424 DTRACE_PROBE1(fail1, int, rc);
425
426 return (rc);
427 }
428
429
430 uint8_t
431 sfxge_phy_lp_cap_test(sfxge_t *sp, uint32_t field)
432 {
433 sfxge_mac_t *smp = &(sp->s_mac);
434 uint32_t cap = 0;
435
436 mutex_enter(&(smp->sm_lock));
437
438 if (smp->sm_state != SFXGE_MAC_STARTED)
439 goto done;
440
441 efx_phy_lp_cap_get(sp->s_enp, &cap);
442
443 done:
444 mutex_exit(&(smp->sm_lock));
445
446 return (cap & (1 << field));
447 }
448
449 /*
450 * Set up the advertised capabilities that may have been asked for
451 * when the mac was not in the state SFXGE_MAC_STARTED.
452 * Must be called after efx_port_init().
453 */
454 int
455 sfxge_phy_cap_apply(sfxge_t *sp, boolean_t use_default)
456 {
457 sfxge_mac_t *smp = &(sp->s_mac);
458 efx_nic_t *enp;
459 uint32_t adv_cap;
460 int rc;
461 int err;
462
463 ASSERT(mutex_owned(&(smp->sm_lock)));
464
465 enp = sp->s_enp;
466
467 if (use_default)
468 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &adv_cap);
469 else
470 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &adv_cap);
471
472 adv_cap |= smp->sm_phy_cap_to_set;
473 smp->sm_phy_cap_to_set = 0;
474 adv_cap &= ~(smp->sm_phy_cap_to_unset);
475 smp->sm_phy_cap_to_unset = 0;
476 if ((err = efx_phy_adv_cap_set(enp, adv_cap)) != 0) {
477 if (err == EINVAL) {
478 /*
479 * The configuation wasn't accepted, so set to
480 * defaults.
481 */
482 uint32_t requested = adv_cap;
483 uint32_t supported;
484 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_PERM, &supported);
485 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &adv_cap);
486 if ((rc = efx_phy_adv_cap_set(enp, adv_cap)) != 0)
487 goto fail1;
488 cmn_err(CE_WARN, SFXGE_CMN_ERR
489 "[%s%d] Setting of advertised link "
490 "capabilities failed. "
491 "Using default settings. "
492 "(Requested 0x%x Given 0x%x Supported 0x%x)",
493 ddi_driver_name(sp->s_dip),
494 ddi_get_instance(sp->s_dip),
495 requested,
496 adv_cap,
497 supported);
498 } else {
499 rc = err;
500 goto fail2;
501 }
502 }
503
504 return (0);
505
506 fail2:
507 DTRACE_PROBE(fail2);
508
509 fail1:
510 DTRACE_PROBE1(fail1, int, rc);
511
512 return (rc);
513 }
514
515 uint8_t
516 sfxge_phy_cap_test(sfxge_t *sp, uint32_t flag, uint32_t field,
517 boolean_t *mutablep)
518 {
519 sfxge_mac_t *smp = &(sp->s_mac);
520 efx_nic_t *enp;
521 uint32_t cap = 0;
522 uint32_t perm = 0;
523
524 mutex_enter(&(smp->sm_lock));
525 enp = sp->s_enp;
526
527 if (smp->sm_state != SFXGE_MAC_STARTED)
528 goto done;
529
530 efx_phy_adv_cap_get(enp, flag, &cap);
531 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_PERM, &perm);
532
533 done:
534 mutex_exit(&(smp->sm_lock));
535
536 if (mutablep)
537 *mutablep = (perm & (1 << field)) ? B_TRUE : B_FALSE;
538
539 return ((cap & (1 << field)) ? 1 : 0);
540 }
541
542
543 int
544 sfxge_phy_cap_set(sfxge_t *sp, uint32_t field, int set)
545 {
546 sfxge_mac_t *smp = &(sp->s_mac);
547 efx_nic_t *enp = sp->s_enp;
548 uint32_t cap;
549 int rc = 0;
550
551 mutex_enter(&(smp->sm_lock));
552
553 if (smp->sm_state != SFXGE_MAC_STARTED) {
554 /* Store the request for when the mac is started */
555 if (set)
556 smp->sm_phy_cap_to_set |= (1 << field);
557 else
558 smp->sm_phy_cap_to_unset |= (1 << field);
559 goto done;
560 }
561
562 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &cap);
563
564 if (set)
565 cap |= (1 << field);
566 else
567 cap &= ~(1 << field);
568
569 rc = efx_phy_adv_cap_set(enp, cap);
570 done:
571 mutex_exit(&(smp->sm_lock));
572
573 return (rc);
574 }
575
576
577 int
578 sfxge_phy_prop_get(sfxge_t *sp, unsigned int id, uint32_t flags, uint32_t *valp)
579 {
580 sfxge_mac_t *smp = &(sp->s_mac);
581 efx_nic_t *enp = sp->s_enp;
582 int rc = 0;
583
584 mutex_enter(&(smp->sm_lock));
585
586 if (smp->sm_state != SFXGE_MAC_STARTED)
587 goto done;
588
589 rc = efx_phy_prop_get(enp, id, flags, valp);
590
591 done:
592 mutex_exit(&(smp->sm_lock));
593
594 return (rc);
595 }
596
597
598 int
599 sfxge_phy_prop_set(sfxge_t *sp, unsigned int id, uint32_t val)
600 {
601 sfxge_mac_t *smp = &(sp->s_mac);
602 efx_nic_t *enp = sp->s_enp;
603 int rc = 0;
604
605 mutex_enter(&(smp->sm_lock));
606
607 if (smp->sm_state != SFXGE_MAC_STARTED)
608 goto done;
609
610 rc = efx_phy_prop_set(enp, id, val);
611
612 done:
613 mutex_exit(&(smp->sm_lock));
614
615 return (rc);
616 }
617
618
619 void
620 sfxge_phy_fini(sfxge_t *sp)
621 {
622 sfxge_phy_t *spp = &(sp->s_mac.sm_phy);
623 efsys_mem_t *esmp = &(spp->sp_mem);
624
625 sfxge_dma_buffer_destroy(esmp);
626 }