1/*-
2 * Copyright (c) 2010-2016 Solarflare Communications Inc.
3 * All rights reserved.
4 *
5 * This software was developed in part by Philip Paeps under contract for
6 * Solarflare Communications, Inc.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright notice,
12 *    this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 *    this list of conditions and the following disclaimer in the documentation
15 *    and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * The views and conclusions contained in the software and documentation are
30 * those of the authors and should not be interpreted as representing official
31 * policies, either expressed or implied, of the FreeBSD Project.
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD: stable/10/sys/dev/sfxge/sfxge_port.c 312169 2017-01-14 10:59:25Z arybchik $");
36
37#include <sys/types.h>
38#include <sys/limits.h>
39#include <net/ethernet.h>
40#include <net/if_dl.h>
41
42#include "common/efx.h"
43
44#include "sfxge.h"
45
46#define	SFXGE_PARAM_STATS_UPDATE_PERIOD_MS \
47	SFXGE_PARAM(stats_update_period_ms)
48static int sfxge_stats_update_period_ms = SFXGE_STATS_UPDATE_PERIOD_MS;
49TUNABLE_INT(SFXGE_PARAM_STATS_UPDATE_PERIOD_MS,
50	    &sfxge_stats_update_period_ms);
51SYSCTL_INT(_hw_sfxge, OID_AUTO, stats_update_period_ms, CTLFLAG_RDTUN,
52	   &sfxge_stats_update_period_ms, 0,
53	   "netstat interface statistics update period in milliseconds");
54
55static int sfxge_phy_cap_mask(struct sfxge_softc *, int, uint32_t *);
56
57static int
58sfxge_mac_stat_update(struct sfxge_softc *sc)
59{
60	struct sfxge_port *port = &sc->port;
61	efsys_mem_t *esmp = &(port->mac_stats.dma_buf);
62	clock_t now;
63	unsigned int min_ticks;
64	unsigned int count;
65	int rc;
66
67	SFXGE_PORT_LOCK_ASSERT_OWNED(port);
68
69	if (__predict_false(port->init_state != SFXGE_PORT_STARTED)) {
70		rc = 0;
71		goto out;
72	}
73
74	min_ticks = (unsigned int)hz * port->stats_update_period_ms / 1000;
75
76	now = ticks;
77	if ((unsigned int)(now - port->mac_stats.update_time) < min_ticks) {
78		rc = 0;
79		goto out;
80	}
81
82	port->mac_stats.update_time = now;
83
84	/* If we're unlucky enough to read statistics wduring the DMA, wait
85	 * up to 10ms for it to finish (typically takes <500us) */
86	for (count = 0; count < 100; ++count) {
87		EFSYS_PROBE1(wait, unsigned int, count);
88
89		/* Try to update the cached counters */
90		if ((rc = efx_mac_stats_update(sc->enp, esmp,
91		    port->mac_stats.decode_buf, NULL)) != EAGAIN)
92			goto out;
93
94		DELAY(100);
95	}
96
97	rc = ETIMEDOUT;
98out:
99	return (rc);
100}
101
102void
103sfxge_port_update_stats(struct sfxge_softc *sc)
104{
105	struct ifnet *ifp;
106	uint64_t *mac_stats;
107
108	SFXGE_PORT_LOCK(&sc->port);
109
110	/* Ignore error and use old values */
111	(void)sfxge_mac_stat_update(sc);
112
113	ifp = sc->ifnet;
114	mac_stats = (uint64_t *)sc->port.mac_stats.decode_buf;
115
116	ifp->if_ipackets = mac_stats[EFX_MAC_RX_PKTS];
117	ifp->if_ierrors = mac_stats[EFX_MAC_RX_ERRORS];
118	ifp->if_opackets = mac_stats[EFX_MAC_TX_PKTS];
119	ifp->if_oerrors = mac_stats[EFX_MAC_TX_ERRORS];
120	ifp->if_collisions =
121	    mac_stats[EFX_MAC_TX_SGL_COL_PKTS] +
122	    mac_stats[EFX_MAC_TX_MULT_COL_PKTS] +
123	    mac_stats[EFX_MAC_TX_EX_COL_PKTS] +
124	    mac_stats[EFX_MAC_TX_LATE_COL_PKTS];
125	ifp->if_ibytes = mac_stats[EFX_MAC_RX_OCTETS];
126	ifp->if_obytes = mac_stats[EFX_MAC_TX_OCTETS];
127	/* if_imcasts is maintained in net/if_ethersubr.c */
128	ifp->if_omcasts =
129	    mac_stats[EFX_MAC_TX_MULTICST_PKTS] +
130	    mac_stats[EFX_MAC_TX_BRDCST_PKTS];
131	/* if_iqdrops is maintained in net/if_ethersubr.c */
132	/* if_noproto is maintained in net/if_ethersubr.c */
133
134	SFXGE_PORT_UNLOCK(&sc->port);
135}
136
137static int
138sfxge_mac_stat_handler(SYSCTL_HANDLER_ARGS)
139{
140	struct sfxge_softc *sc = arg1;
141	unsigned int id = arg2;
142	int rc;
143	uint64_t val;
144
145	SFXGE_PORT_LOCK(&sc->port);
146	if ((rc = sfxge_mac_stat_update(sc)) == 0)
147		val = ((uint64_t *)sc->port.mac_stats.decode_buf)[id];
148	SFXGE_PORT_UNLOCK(&sc->port);
149
150	if (rc == 0)
151		rc = SYSCTL_OUT(req, &val, sizeof(val));
152	return (rc);
153}
154
155static void
156sfxge_mac_stat_init(struct sfxge_softc *sc)
157{
158	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->dev);
159	struct sysctl_oid_list *stat_list;
160	unsigned int id;
161	const char *name;
162
163	stat_list = SYSCTL_CHILDREN(sc->stats_node);
164
165	/* Initialise the named stats */
166	for (id = 0; id < EFX_MAC_NSTATS; id++) {
167		name = efx_mac_stat_name(sc->enp, id);
168		SYSCTL_ADD_PROC(
169			ctx, stat_list,
170			OID_AUTO, name, CTLTYPE_U64|CTLFLAG_RD,
171			sc, id, sfxge_mac_stat_handler, "Q",
172			"");
173	}
174}
175
176#ifdef SFXGE_HAVE_PAUSE_MEDIAOPTS
177
178static unsigned int
179sfxge_port_wanted_fc(struct sfxge_softc *sc)
180{
181	struct ifmedia_entry *ifm = sc->media.ifm_cur;
182
183	if (ifm->ifm_media == (IFM_ETHER | IFM_AUTO))
184		return (EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE);
185	return (((ifm->ifm_media & IFM_ETH_RXPAUSE) ? EFX_FCNTL_RESPOND : 0) |
186		((ifm->ifm_media & IFM_ETH_TXPAUSE) ? EFX_FCNTL_GENERATE : 0));
187}
188
189static unsigned int
190sfxge_port_link_fc_ifm(struct sfxge_softc *sc)
191{
192	unsigned int wanted_fc, link_fc;
193
194	efx_mac_fcntl_get(sc->enp, &wanted_fc, &link_fc);
195	return ((link_fc & EFX_FCNTL_RESPOND) ? IFM_ETH_RXPAUSE : 0) |
196		((link_fc & EFX_FCNTL_GENERATE) ? IFM_ETH_TXPAUSE : 0);
197}
198
199#else /* !SFXGE_HAVE_PAUSE_MEDIAOPTS */
200
201static unsigned int
202sfxge_port_wanted_fc(struct sfxge_softc *sc)
203{
204	return (sc->port.wanted_fc);
205}
206
207static unsigned int
208sfxge_port_link_fc_ifm(struct sfxge_softc *sc)
209{
210	return (0);
211}
212
213static int
214sfxge_port_wanted_fc_handler(SYSCTL_HANDLER_ARGS)
215{
216	struct sfxge_softc *sc;
217	struct sfxge_port *port;
218	unsigned int fcntl;
219	int error;
220
221	sc = arg1;
222	port = &sc->port;
223
224	if (req->newptr != NULL) {
225		if ((error = SYSCTL_IN(req, &fcntl, sizeof(fcntl))) != 0)
226			return (error);
227
228		SFXGE_PORT_LOCK(port);
229
230		if (port->wanted_fc != fcntl) {
231			if (port->init_state == SFXGE_PORT_STARTED)
232				error = efx_mac_fcntl_set(sc->enp,
233							  port->wanted_fc,
234							  B_TRUE);
235			if (error == 0)
236				port->wanted_fc = fcntl;
237		}
238
239		SFXGE_PORT_UNLOCK(port);
240	} else {
241		SFXGE_PORT_LOCK(port);
242		fcntl = port->wanted_fc;
243		SFXGE_PORT_UNLOCK(port);
244
245		error = SYSCTL_OUT(req, &fcntl, sizeof(fcntl));
246	}
247
248	return (error);
249}
250
251static int
252sfxge_port_link_fc_handler(SYSCTL_HANDLER_ARGS)
253{
254	struct sfxge_softc *sc;
255	struct sfxge_port *port;
256	unsigned int wanted_fc, link_fc;
257
258	sc = arg1;
259	port = &sc->port;
260
261	SFXGE_PORT_LOCK(port);
262	if (__predict_true(port->init_state == SFXGE_PORT_STARTED) &&
263	    SFXGE_LINK_UP(sc))
264		efx_mac_fcntl_get(sc->enp, &wanted_fc, &link_fc);
265	else
266		link_fc = 0;
267	SFXGE_PORT_UNLOCK(port);
268
269	return (SYSCTL_OUT(req, &link_fc, sizeof(link_fc)));
270}
271
272#endif /* SFXGE_HAVE_PAUSE_MEDIAOPTS */
273
274static const uint64_t sfxge_link_baudrate[EFX_LINK_NMODES] = {
275	[EFX_LINK_10HDX]	= IF_Mbps(10),
276	[EFX_LINK_10FDX]	= IF_Mbps(10),
277	[EFX_LINK_100HDX]	= IF_Mbps(100),
278	[EFX_LINK_100FDX]	= IF_Mbps(100),
279	[EFX_LINK_1000HDX]	= IF_Gbps(1),
280	[EFX_LINK_1000FDX]	= IF_Gbps(1),
281	[EFX_LINK_10000FDX]	= IF_Gbps(10),
282	[EFX_LINK_40000FDX]	= IF_Gbps(40),
283};
284
285void
286sfxge_mac_link_update(struct sfxge_softc *sc, efx_link_mode_t mode)
287{
288	struct sfxge_port *port;
289	int link_state;
290
291	port = &sc->port;
292
293	if (port->link_mode == mode)
294		return;
295
296	port->link_mode = mode;
297
298	/* Push link state update to the OS */
299	link_state = (SFXGE_LINK_UP(sc) ? LINK_STATE_UP : LINK_STATE_DOWN);
300	if_initbaudrate(sc->ifnet, sfxge_link_baudrate[port->link_mode]);
301	if_link_state_change(sc->ifnet, link_state);
302}
303
304static void
305sfxge_mac_poll_work(void *arg, int npending)
306{
307	struct sfxge_softc *sc;
308	efx_nic_t *enp;
309	struct sfxge_port *port;
310	efx_link_mode_t mode;
311
312	sc = (struct sfxge_softc *)arg;
313	enp = sc->enp;
314	port = &sc->port;
315
316	SFXGE_PORT_LOCK(port);
317
318	if (__predict_false(port->init_state != SFXGE_PORT_STARTED))
319		goto done;
320
321	/* This may sleep waiting for MCDI completion */
322	(void)efx_port_poll(enp, &mode);
323	sfxge_mac_link_update(sc, mode);
324
325done:
326	SFXGE_PORT_UNLOCK(port);
327}
328
329static int
330sfxge_mac_multicast_list_set(struct sfxge_softc *sc)
331{
332	struct ifnet *ifp = sc->ifnet;
333	struct sfxge_port *port = &sc->port;
334	uint8_t *mcast_addr = port->mcast_addrs;
335	struct ifmultiaddr *ifma;
336	struct sockaddr_dl *sa;
337	int rc = 0;
338
339	mtx_assert(&port->lock, MA_OWNED);
340
341	port->mcast_count = 0;
342	if_maddr_rlock(ifp);
343	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
344		if (ifma->ifma_addr->sa_family == AF_LINK) {
345			if (port->mcast_count == EFX_MAC_MULTICAST_LIST_MAX) {
346				device_printf(sc->dev,
347				    "Too many multicast addresses\n");
348				rc = EINVAL;
349				break;
350			}
351
352			sa = (struct sockaddr_dl *)ifma->ifma_addr;
353			memcpy(mcast_addr, LLADDR(sa), EFX_MAC_ADDR_LEN);
354			mcast_addr += EFX_MAC_ADDR_LEN;
355			++port->mcast_count;
356		}
357	}
358	if_maddr_runlock(ifp);
359
360	if (rc == 0) {
361		rc = efx_mac_multicast_list_set(sc->enp, port->mcast_addrs,
362						port->mcast_count);
363		if (rc != 0)
364			device_printf(sc->dev,
365			    "Cannot set multicast address list\n");
366	}
367
368	return (rc);
369}
370
371static int
372sfxge_mac_filter_set_locked(struct sfxge_softc *sc)
373{
374	struct ifnet *ifp = sc->ifnet;
375	struct sfxge_port *port = &sc->port;
376	boolean_t all_mulcst;
377	int rc;
378
379	mtx_assert(&port->lock, MA_OWNED);
380
381	all_mulcst = !!(ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI));
382
383	rc = sfxge_mac_multicast_list_set(sc);
384	/* Fallback to all multicast if cannot set multicast list */
385	if (rc != 0)
386		all_mulcst = B_TRUE;
387
388	rc = efx_mac_filter_set(sc->enp, !!(ifp->if_flags & IFF_PROMISC),
389				(port->mcast_count > 0), all_mulcst, B_TRUE);
390
391	return (rc);
392}
393
394int
395sfxge_mac_filter_set(struct sfxge_softc *sc)
396{
397	struct sfxge_port *port = &sc->port;
398	int rc;
399
400	SFXGE_PORT_LOCK(port);
401	/*
402	 * The function may be called without softc_lock held in the
403	 * case of SIOCADDMULTI and SIOCDELMULTI ioctls. ioctl handler
404	 * checks IFF_DRV_RUNNING flag which implies port started, but
405	 * it is not guaranteed to remain. softc_lock shared lock can't
406	 * be held in the case of these ioctls processing, since it
407	 * results in failure where kernel complains that non-sleepable
408	 * lock is held in sleeping thread. Both problems are repeatable
409	 * on LAG with LACP proto bring up.
410	 */
411	if (__predict_true(port->init_state == SFXGE_PORT_STARTED))
412		rc = sfxge_mac_filter_set_locked(sc);
413	else
414		rc = 0;
415	SFXGE_PORT_UNLOCK(port);
416	return (rc);
417}
418
419void
420sfxge_port_stop(struct sfxge_softc *sc)
421{
422	struct sfxge_port *port;
423	efx_nic_t *enp;
424
425	port = &sc->port;
426	enp = sc->enp;
427
428	SFXGE_PORT_LOCK(port);
429
430	KASSERT(port->init_state == SFXGE_PORT_STARTED,
431	    ("port not started"));
432
433	port->init_state = SFXGE_PORT_INITIALIZED;
434
435	port->mac_stats.update_time = 0;
436
437	/* This may call MCDI */
438	(void)efx_mac_drain(enp, B_TRUE);
439
440	(void)efx_mac_stats_periodic(enp, &port->mac_stats.dma_buf, 0, B_FALSE);
441
442	port->link_mode = EFX_LINK_UNKNOWN;
443
444	/* Destroy the common code port object. */
445	efx_port_fini(enp);
446
447	efx_filter_fini(enp);
448
449	SFXGE_PORT_UNLOCK(port);
450}
451
452int
453sfxge_port_start(struct sfxge_softc *sc)
454{
455	uint8_t mac_addr[ETHER_ADDR_LEN];
456	struct ifnet *ifp = sc->ifnet;
457	struct sfxge_port *port;
458	efx_nic_t *enp;
459	size_t pdu;
460	int rc;
461	uint32_t phy_cap_mask;
462
463	port = &sc->port;
464	enp = sc->enp;
465
466	SFXGE_PORT_LOCK(port);
467
468	KASSERT(port->init_state == SFXGE_PORT_INITIALIZED,
469	    ("port not initialized"));
470
471	/* Initialise the required filtering */
472	if ((rc = efx_filter_init(enp)) != 0)
473		goto fail_filter_init;
474
475	/* Initialize the port object in the common code. */
476	if ((rc = efx_port_init(sc->enp)) != 0)
477		goto fail;
478
479	/* Set the SDU */
480	pdu = EFX_MAC_PDU(ifp->if_mtu);
481	if ((rc = efx_mac_pdu_set(enp, pdu)) != 0)
482		goto fail2;
483
484	if ((rc = efx_mac_fcntl_set(enp, sfxge_port_wanted_fc(sc), B_TRUE))
485	    != 0)
486		goto fail3;
487
488	/* Set the unicast address */
489	if_addr_rlock(ifp);
490	bcopy(LLADDR((struct sockaddr_dl *)ifp->if_addr->ifa_addr),
491	      mac_addr, sizeof(mac_addr));
492	if_addr_runlock(ifp);
493	if ((rc = efx_mac_addr_set(enp, mac_addr)) != 0)
494		goto fail4;
495
496	sfxge_mac_filter_set_locked(sc);
497
498	/* Update MAC stats by DMA every period */
499	if ((rc = efx_mac_stats_periodic(enp, &port->mac_stats.dma_buf,
500					 port->stats_update_period_ms,
501					 B_FALSE)) != 0)
502		goto fail6;
503
504	if ((rc = efx_mac_drain(enp, B_FALSE)) != 0)
505		goto fail8;
506
507	if ((rc = sfxge_phy_cap_mask(sc, sc->media.ifm_cur->ifm_media,
508				     &phy_cap_mask)) != 0)
509		goto fail9;
510
511	if ((rc = efx_phy_adv_cap_set(sc->enp, phy_cap_mask)) != 0)
512		goto fail10;
513
514	port->init_state = SFXGE_PORT_STARTED;
515
516	/* Single poll in case there were missing initial events */
517	SFXGE_PORT_UNLOCK(port);
518	sfxge_mac_poll_work(sc, 0);
519
520	return (0);
521
522fail10:
523fail9:
524	(void)efx_mac_drain(enp, B_TRUE);
525fail8:
526	(void)efx_mac_stats_periodic(enp, &port->mac_stats.dma_buf, 0, B_FALSE);
527fail6:
528fail4:
529fail3:
530
531fail2:
532	efx_port_fini(enp);
533fail:
534	efx_filter_fini(enp);
535fail_filter_init:
536	SFXGE_PORT_UNLOCK(port);
537
538	return (rc);
539}
540
541static int
542sfxge_phy_stat_update(struct sfxge_softc *sc)
543{
544	struct sfxge_port *port = &sc->port;
545	efsys_mem_t *esmp = &port->phy_stats.dma_buf;
546	clock_t now;
547	unsigned int count;
548	int rc;
549
550	SFXGE_PORT_LOCK_ASSERT_OWNED(port);
551
552	if (__predict_false(port->init_state != SFXGE_PORT_STARTED)) {
553		rc = 0;
554		goto out;
555	}
556
557	now = ticks;
558	if ((unsigned int)(now - port->phy_stats.update_time) < (unsigned int)hz) {
559		rc = 0;
560		goto out;
561	}
562
563	port->phy_stats.update_time = now;
564
565	/* If we're unlucky enough to read statistics wduring the DMA, wait
566	 * up to 10ms for it to finish (typically takes <500us) */
567	for (count = 0; count < 100; ++count) {
568		EFSYS_PROBE1(wait, unsigned int, count);
569
570		/* Synchronize the DMA memory for reading */
571		bus_dmamap_sync(esmp->esm_tag, esmp->esm_map,
572		    BUS_DMASYNC_POSTREAD);
573
574		/* Try to update the cached counters */
575		if ((rc = efx_phy_stats_update(sc->enp, esmp,
576		    port->phy_stats.decode_buf)) != EAGAIN)
577			goto out;
578
579		DELAY(100);
580	}
581
582	rc = ETIMEDOUT;
583out:
584	return (rc);
585}
586
587static int
588sfxge_phy_stat_handler(SYSCTL_HANDLER_ARGS)
589{
590	struct sfxge_softc *sc = arg1;
591	unsigned int id = arg2;
592	int rc;
593	uint32_t val;
594
595	SFXGE_PORT_LOCK(&sc->port);
596	if ((rc = sfxge_phy_stat_update(sc)) == 0)
597		val = ((uint32_t *)sc->port.phy_stats.decode_buf)[id];
598	SFXGE_PORT_UNLOCK(&sc->port);
599
600	if (rc == 0)
601		rc = SYSCTL_OUT(req, &val, sizeof(val));
602	return (rc);
603}
604
605static void
606sfxge_phy_stat_init(struct sfxge_softc *sc)
607{
608	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->dev);
609	struct sysctl_oid_list *stat_list;
610	unsigned int id;
611	const char *name;
612	uint64_t stat_mask = efx_nic_cfg_get(sc->enp)->enc_phy_stat_mask;
613
614	stat_list = SYSCTL_CHILDREN(sc->stats_node);
615
616	/* Initialise the named stats */
617	for (id = 0; id < EFX_PHY_NSTATS; id++) {
618		if (!(stat_mask & ((uint64_t)1 << id)))
619			continue;
620		name = efx_phy_stat_name(sc->enp, id);
621		SYSCTL_ADD_PROC(
622			ctx, stat_list,
623			OID_AUTO, name, CTLTYPE_UINT|CTLFLAG_RD,
624			sc, id, sfxge_phy_stat_handler,
625			id == EFX_PHY_STAT_OUI ? "IX" : "IU",
626			"");
627	}
628}
629
630void
631sfxge_port_fini(struct sfxge_softc *sc)
632{
633	struct sfxge_port *port;
634	efsys_mem_t *esmp;
635
636	port = &sc->port;
637	esmp = &port->mac_stats.dma_buf;
638
639	KASSERT(port->init_state == SFXGE_PORT_INITIALIZED,
640	    ("Port not initialized"));
641
642	port->init_state = SFXGE_PORT_UNINITIALIZED;
643
644	port->link_mode = EFX_LINK_UNKNOWN;
645
646	/* Finish with PHY DMA memory */
647	sfxge_dma_free(&port->phy_stats.dma_buf);
648	free(port->phy_stats.decode_buf, M_SFXGE);
649
650	sfxge_dma_free(esmp);
651	free(port->mac_stats.decode_buf, M_SFXGE);
652
653	SFXGE_PORT_LOCK_DESTROY(port);
654
655	port->sc = NULL;
656}
657
658static uint16_t
659sfxge_port_stats_update_period_ms(struct sfxge_softc *sc)
660{
661	int period_ms = sfxge_stats_update_period_ms;
662
663	if (period_ms < 0) {
664		device_printf(sc->dev,
665			"treat negative stats update period %d as 0 (disable)\n",
666			 period_ms);
667		period_ms = 0;
668	} else if (period_ms > UINT16_MAX) {
669		device_printf(sc->dev,
670			"treat too big stats update period %d as %u\n",
671			period_ms, UINT16_MAX);
672		period_ms = UINT16_MAX;
673	}
674
675	return period_ms;
676}
677
678static int
679sfxge_port_stats_update_period_ms_handler(SYSCTL_HANDLER_ARGS)
680{
681	struct sfxge_softc *sc;
682	struct sfxge_port *port;
683	unsigned int period_ms;
684	int error;
685
686	sc = arg1;
687	port = &sc->port;
688
689	if (req->newptr != NULL) {
690		error = SYSCTL_IN(req, &period_ms, sizeof(period_ms));
691		if (error != 0)
692			return (error);
693
694		if (period_ms > UINT16_MAX)
695			return (EINVAL);
696
697		SFXGE_PORT_LOCK(port);
698
699		if (port->stats_update_period_ms != period_ms) {
700			if (port->init_state == SFXGE_PORT_STARTED)
701				error = efx_mac_stats_periodic(sc->enp,
702						&port->mac_stats.dma_buf,
703						period_ms, B_FALSE);
704			if (error == 0)
705				port->stats_update_period_ms = period_ms;
706		}
707
708		SFXGE_PORT_UNLOCK(port);
709	} else {
710		SFXGE_PORT_LOCK(port);
711		period_ms = port->stats_update_period_ms;
712		SFXGE_PORT_UNLOCK(port);
713
714		error = SYSCTL_OUT(req, &period_ms, sizeof(period_ms));
715	}
716
717	return (error);
718}
719
720int
721sfxge_port_init(struct sfxge_softc *sc)
722{
723	struct sfxge_port *port;
724	struct sysctl_ctx_list *sysctl_ctx;
725	struct sysctl_oid *sysctl_tree;
726	efsys_mem_t *mac_stats_buf, *phy_stats_buf;
727	int rc;
728
729	port = &sc->port;
730	mac_stats_buf = &port->mac_stats.dma_buf;
731	phy_stats_buf = &port->phy_stats.dma_buf;
732
733	KASSERT(port->init_state == SFXGE_PORT_UNINITIALIZED,
734	    ("Port already initialized"));
735
736	port->sc = sc;
737
738	SFXGE_PORT_LOCK_INIT(port, device_get_nameunit(sc->dev));
739
740	DBGPRINT(sc->dev, "alloc PHY stats");
741	port->phy_stats.decode_buf = malloc(EFX_PHY_NSTATS * sizeof(uint32_t),
742					    M_SFXGE, M_WAITOK | M_ZERO);
743	if ((rc = sfxge_dma_alloc(sc, EFX_PHY_STATS_SIZE, phy_stats_buf)) != 0)
744		goto fail;
745	sfxge_phy_stat_init(sc);
746
747	DBGPRINT(sc->dev, "init sysctl");
748	sysctl_ctx = device_get_sysctl_ctx(sc->dev);
749	sysctl_tree = device_get_sysctl_tree(sc->dev);
750
751#ifndef SFXGE_HAVE_PAUSE_MEDIAOPTS
752	/* If flow control cannot be configured or reported through
753	 * ifmedia, provide sysctls for it. */
754	port->wanted_fc = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
755	SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
756	    "wanted_fc", CTLTYPE_UINT|CTLFLAG_RW, sc, 0,
757	    sfxge_port_wanted_fc_handler, "IU", "wanted flow control mode");
758	SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
759	    "link_fc", CTLTYPE_UINT|CTLFLAG_RD, sc, 0,
760	    sfxge_port_link_fc_handler, "IU", "link flow control mode");
761#endif
762
763	DBGPRINT(sc->dev, "alloc MAC stats");
764	port->mac_stats.decode_buf = malloc(EFX_MAC_NSTATS * sizeof(uint64_t),
765					    M_SFXGE, M_WAITOK | M_ZERO);
766	if ((rc = sfxge_dma_alloc(sc, EFX_MAC_STATS_SIZE, mac_stats_buf)) != 0)
767		goto fail2;
768	port->stats_update_period_ms = sfxge_port_stats_update_period_ms(sc);
769	sfxge_mac_stat_init(sc);
770
771	SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
772	    "stats_update_period_ms", CTLTYPE_UINT|CTLFLAG_RW, sc, 0,
773	    sfxge_port_stats_update_period_ms_handler, "IU",
774	    "interface statistics refresh period");
775
776	port->init_state = SFXGE_PORT_INITIALIZED;
777
778	DBGPRINT(sc->dev, "success");
779	return (0);
780
781fail2:
782	free(port->mac_stats.decode_buf, M_SFXGE);
783	sfxge_dma_free(phy_stats_buf);
784fail:
785	free(port->phy_stats.decode_buf, M_SFXGE);
786	SFXGE_PORT_LOCK_DESTROY(port);
787	port->sc = NULL;
788	DBGPRINT(sc->dev, "failed %d", rc);
789	return (rc);
790}
791
792static const int sfxge_link_mode[EFX_PHY_MEDIA_NTYPES][EFX_LINK_NMODES] = {
793	[EFX_PHY_MEDIA_CX4] = {
794		[EFX_LINK_10000FDX]	= IFM_ETHER | IFM_FDX | IFM_10G_CX4,
795	},
796	[EFX_PHY_MEDIA_KX4] = {
797		[EFX_LINK_10000FDX]	= IFM_ETHER | IFM_FDX | IFM_10G_KX4,
798	},
799	[EFX_PHY_MEDIA_XFP] = {
800		/* Don't know the module type, but assume SR for now. */
801		[EFX_LINK_10000FDX]	= IFM_ETHER | IFM_FDX | IFM_10G_SR,
802	},
803	[EFX_PHY_MEDIA_QSFP_PLUS] = {
804		/* Don't know the module type, but assume SR for now. */
805		[EFX_LINK_10000FDX]	= IFM_ETHER | IFM_FDX | IFM_10G_SR,
806		[EFX_LINK_40000FDX]	= IFM_ETHER | IFM_FDX | IFM_40G_CR4,
807	},
808	[EFX_PHY_MEDIA_SFP_PLUS] = {
809		/* Don't know the module type, but assume SX/SR for now. */
810		[EFX_LINK_1000FDX]	= IFM_ETHER | IFM_FDX | IFM_1000_SX,
811		[EFX_LINK_10000FDX]	= IFM_ETHER | IFM_FDX | IFM_10G_SR,
812	},
813	[EFX_PHY_MEDIA_BASE_T] = {
814		[EFX_LINK_10HDX]	= IFM_ETHER | IFM_HDX | IFM_10_T,
815		[EFX_LINK_10FDX]	= IFM_ETHER | IFM_FDX | IFM_10_T,
816		[EFX_LINK_100HDX]	= IFM_ETHER | IFM_HDX | IFM_100_TX,
817		[EFX_LINK_100FDX]	= IFM_ETHER | IFM_FDX | IFM_100_TX,
818		[EFX_LINK_1000HDX]	= IFM_ETHER | IFM_HDX | IFM_1000_T,
819		[EFX_LINK_1000FDX]	= IFM_ETHER | IFM_FDX | IFM_1000_T,
820		[EFX_LINK_10000FDX]	= IFM_ETHER | IFM_FDX | IFM_10G_T,
821	},
822};
823
824static void
825sfxge_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
826{
827	struct sfxge_softc *sc;
828	efx_phy_media_type_t medium_type;
829	efx_link_mode_t mode;
830
831	sc = ifp->if_softc;
832	SFXGE_ADAPTER_LOCK(sc);
833
834	ifmr->ifm_status = IFM_AVALID;
835	ifmr->ifm_active = IFM_ETHER;
836
837	if (SFXGE_RUNNING(sc) && SFXGE_LINK_UP(sc)) {
838		ifmr->ifm_status |= IFM_ACTIVE;
839
840		efx_phy_media_type_get(sc->enp, &medium_type);
841		mode = sc->port.link_mode;
842		ifmr->ifm_active |= sfxge_link_mode[medium_type][mode];
843		ifmr->ifm_active |= sfxge_port_link_fc_ifm(sc);
844	}
845
846	SFXGE_ADAPTER_UNLOCK(sc);
847}
848
849static efx_phy_cap_type_t
850sfxge_link_mode_to_phy_cap(efx_link_mode_t mode)
851{
852	switch (mode) {
853	case EFX_LINK_10HDX:
854		return (EFX_PHY_CAP_10HDX);
855	case EFX_LINK_10FDX:
856		return (EFX_PHY_CAP_10FDX);
857	case EFX_LINK_100HDX:
858		return (EFX_PHY_CAP_100HDX);
859	case EFX_LINK_100FDX:
860		return (EFX_PHY_CAP_100FDX);
861	case EFX_LINK_1000HDX:
862		return (EFX_PHY_CAP_1000HDX);
863	case EFX_LINK_1000FDX:
864		return (EFX_PHY_CAP_1000FDX);
865	case EFX_LINK_10000FDX:
866		return (EFX_PHY_CAP_10000FDX);
867	case EFX_LINK_40000FDX:
868		return (EFX_PHY_CAP_40000FDX);
869	default:
870		EFSYS_ASSERT(B_FALSE);
871		return (EFX_PHY_CAP_INVALID);
872	}
873}
874
875static int
876sfxge_phy_cap_mask(struct sfxge_softc *sc, int ifmedia, uint32_t *phy_cap_mask)
877{
878	/* Get global options (duplex), type and subtype bits */
879	int ifmedia_masked = ifmedia & (IFM_GMASK | IFM_NMASK | IFM_TMASK);
880	efx_phy_media_type_t medium_type;
881	boolean_t mode_found = B_FALSE;
882	uint32_t cap_mask, mode_cap_mask;
883	efx_link_mode_t mode;
884	efx_phy_cap_type_t phy_cap;
885
886	efx_phy_media_type_get(sc->enp, &medium_type);
887	if (medium_type >= nitems(sfxge_link_mode)) {
888		if_printf(sc->ifnet, "unexpected media type %d\n", medium_type);
889		return (EINVAL);
890	}
891
892	efx_phy_adv_cap_get(sc->enp, EFX_PHY_CAP_PERM, &cap_mask);
893
894	for (mode = EFX_LINK_10HDX; mode < EFX_LINK_NMODES; mode++) {
895		if (ifmedia_masked == sfxge_link_mode[medium_type][mode]) {
896			mode_found = B_TRUE;
897			break;
898		}
899	}
900
901	if (!mode_found) {
902		/*
903		 * If media is not in the table, it must be IFM_AUTO.
904		 */
905		KASSERT((cap_mask & (1 << EFX_PHY_CAP_AN)) &&
906		    ifmedia_masked == (IFM_ETHER | IFM_AUTO),
907		    ("%s: no mode for media %#x", __func__, ifmedia));
908		*phy_cap_mask = (cap_mask & ~(1 << EFX_PHY_CAP_ASYM));
909		return (0);
910	}
911
912	phy_cap = sfxge_link_mode_to_phy_cap(mode);
913	if (phy_cap == EFX_PHY_CAP_INVALID) {
914		if_printf(sc->ifnet,
915			  "cannot map link mode %d to phy capability\n",
916			  mode);
917		return (EINVAL);
918	}
919
920	mode_cap_mask = (1 << phy_cap);
921	mode_cap_mask |= cap_mask & (1 << EFX_PHY_CAP_AN);
922#ifdef SFXGE_HAVE_PAUSE_MEDIAOPTS
923	if (ifmedia & IFM_ETH_RXPAUSE)
924		mode_cap_mask |= cap_mask & (1 << EFX_PHY_CAP_PAUSE);
925	if (!(ifmedia & IFM_ETH_TXPAUSE))
926		mode_cap_mask |= cap_mask & (1 << EFX_PHY_CAP_ASYM);
927#else
928	mode_cap_mask |= cap_mask & (1 << EFX_PHY_CAP_PAUSE);
929#endif
930
931	*phy_cap_mask = mode_cap_mask;
932	return (0);
933}
934
935static int
936sfxge_media_change(struct ifnet *ifp)
937{
938	struct sfxge_softc *sc;
939	struct ifmedia_entry *ifm;
940	int rc;
941	uint32_t phy_cap_mask;
942
943	sc = ifp->if_softc;
944	ifm = sc->media.ifm_cur;
945
946	SFXGE_ADAPTER_LOCK(sc);
947
948	if (!SFXGE_RUNNING(sc)) {
949		rc = 0;
950		goto out;
951	}
952
953	rc = efx_mac_fcntl_set(sc->enp, sfxge_port_wanted_fc(sc), B_TRUE);
954	if (rc != 0)
955		goto out;
956
957	if ((rc = sfxge_phy_cap_mask(sc, ifm->ifm_media, &phy_cap_mask)) != 0)
958		goto out;
959
960	rc = efx_phy_adv_cap_set(sc->enp, phy_cap_mask);
961out:
962	SFXGE_ADAPTER_UNLOCK(sc);
963
964	return (rc);
965}
966
967int sfxge_port_ifmedia_init(struct sfxge_softc *sc)
968{
969	efx_phy_media_type_t medium_type;
970	uint32_t cap_mask, mode_cap_mask;
971	efx_link_mode_t mode;
972	efx_phy_cap_type_t phy_cap;
973	int mode_ifm, best_mode_ifm = 0;
974	int rc;
975
976	/*
977	 * We need port state to initialise the ifmedia list.
978	 * It requires initialized NIC what is already done in
979	 * sfxge_create() when resources are estimated.
980	 */
981	if ((rc = efx_filter_init(sc->enp)) != 0)
982		goto out1;
983	if ((rc = efx_port_init(sc->enp)) != 0)
984		goto out2;
985
986	/*
987	 * Register ifconfig callbacks for querying and setting the
988	 * link mode and link status.
989	 */
990	ifmedia_init(&sc->media, IFM_IMASK, sfxge_media_change,
991	    sfxge_media_status);
992
993	/*
994	 * Map firmware medium type and capabilities to ifmedia types.
995	 * ifmedia does not distinguish between forcing the link mode
996	 * and disabling auto-negotiation.  1000BASE-T and 10GBASE-T
997	 * require AN even if only one link mode is enabled, and for
998	 * 100BASE-TX it is useful even if the link mode is forced.
999	 * Therefore we never disable auto-negotiation.
1000	 *
1001	 * Also enable and advertise flow control by default.
1002	 */
1003
1004	efx_phy_media_type_get(sc->enp, &medium_type);
1005	efx_phy_adv_cap_get(sc->enp, EFX_PHY_CAP_PERM, &cap_mask);
1006
1007	for (mode = EFX_LINK_10HDX; mode < EFX_LINK_NMODES; mode++) {
1008		phy_cap = sfxge_link_mode_to_phy_cap(mode);
1009		if (phy_cap == EFX_PHY_CAP_INVALID)
1010			continue;
1011
1012		mode_cap_mask = (1 << phy_cap);
1013		mode_ifm = sfxge_link_mode[medium_type][mode];
1014
1015		if ((cap_mask & mode_cap_mask) && mode_ifm) {
1016			/* No flow-control */
1017			ifmedia_add(&sc->media, mode_ifm, 0, NULL);
1018
1019#ifdef SFXGE_HAVE_PAUSE_MEDIAOPTS
1020			/* Respond-only.  If using AN, we implicitly
1021			 * offer symmetric as well, but that doesn't
1022			 * mean we *have* to generate pause frames.
1023			 */
1024			mode_ifm |= IFM_ETH_RXPAUSE;
1025			ifmedia_add(&sc->media, mode_ifm, 0, NULL);
1026
1027			/* Symmetric */
1028			mode_ifm |= IFM_ETH_TXPAUSE;
1029			ifmedia_add(&sc->media, mode_ifm, 0, NULL);
1030#endif
1031
1032			/* Link modes are numbered in order of speed,
1033			 * so assume the last one available is the best.
1034			 */
1035			best_mode_ifm = mode_ifm;
1036		}
1037	}
1038
1039	if (cap_mask & (1 << EFX_PHY_CAP_AN)) {
1040		/* Add autoselect mode. */
1041		mode_ifm = IFM_ETHER | IFM_AUTO;
1042		ifmedia_add(&sc->media, mode_ifm, 0, NULL);
1043		best_mode_ifm = mode_ifm;
1044	}
1045
1046	if (best_mode_ifm != 0)
1047		ifmedia_set(&sc->media, best_mode_ifm);
1048
1049	/* Now discard port state until interface is started. */
1050	efx_port_fini(sc->enp);
1051out2:
1052	efx_filter_fini(sc->enp);
1053out1:
1054	return (rc);
1055}
1056