xref: /f-stack/dpdk/drivers/net/sfc/sfc_port.c (revision 031be553)
1 /*-
2  *   BSD LICENSE
3  *
4  * Copyright (c) 2016-2017 Solarflare Communications Inc.
5  * All rights reserved.
6  *
7  * This software was jointly developed between OKTET Labs (under contract
8  * for Solarflare) and Solarflare Communications, Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright notice,
14  *    this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  *    this list of conditions and the following disclaimer in the documentation
17  *    and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
29  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "efx.h"
33 
34 #include "sfc.h"
35 #include "sfc_log.h"
36 #include "sfc_kvargs.h"
37 
38 /** Default MAC statistics update period is 1 second */
39 #define SFC_MAC_STATS_UPDATE_PERIOD_MS_DEF	MS_PER_S
40 
41 /** The number of microseconds to sleep on attempt to get statistics update */
42 #define SFC_MAC_STATS_UPDATE_RETRY_INTERVAL_US	10
43 
44 /** The number of attempts to await arrival of freshly generated statistics */
45 #define SFC_MAC_STATS_UPDATE_NB_ATTEMPTS	50
46 
47 /**
48  * Update MAC statistics in the buffer.
49  *
50  * @param	sa	Adapter
51  *
52  * @return Status code
53  * @retval	0	Success
54  * @retval	EAGAIN	Try again
55  * @retval	ENOMEM	Memory allocation failure
56  */
57 int
58 sfc_port_update_mac_stats(struct sfc_adapter *sa)
59 {
60 	struct sfc_port *port = &sa->port;
61 	efsys_mem_t *esmp = &port->mac_stats_dma_mem;
62 	uint32_t *genp = NULL;
63 	uint32_t gen_old;
64 	unsigned int nb_attempts = 0;
65 	int rc;
66 
67 	SFC_ASSERT(rte_spinlock_is_locked(&port->mac_stats_lock));
68 
69 	if (sa->state != SFC_ADAPTER_STARTED)
70 		return EINVAL;
71 
72 	/*
73 	 * If periodic statistics DMA'ing is off or if not supported,
74 	 * make a manual request and keep an eye on timer if need be
75 	 */
76 	if (!port->mac_stats_periodic_dma_supported ||
77 	    (port->mac_stats_update_period_ms == 0)) {
78 		if (port->mac_stats_update_period_ms != 0) {
79 			uint64_t timestamp = sfc_get_system_msecs();
80 
81 			if ((timestamp -
82 			     port->mac_stats_last_request_timestamp) <
83 			    port->mac_stats_update_period_ms)
84 				return 0;
85 
86 			port->mac_stats_last_request_timestamp = timestamp;
87 		}
88 
89 		rc = efx_mac_stats_upload(sa->nic, esmp);
90 		if (rc != 0)
91 			return rc;
92 
93 		genp = &port->mac_stats_update_generation;
94 		gen_old = *genp;
95 	}
96 
97 	do {
98 		if (nb_attempts > 0)
99 			rte_delay_us(SFC_MAC_STATS_UPDATE_RETRY_INTERVAL_US);
100 
101 		rc = efx_mac_stats_update(sa->nic, esmp,
102 					  port->mac_stats_buf, genp);
103 		if (rc != 0)
104 			return rc;
105 
106 	} while ((genp != NULL) && (*genp == gen_old) &&
107 		 (++nb_attempts < SFC_MAC_STATS_UPDATE_NB_ATTEMPTS));
108 
109 	return 0;
110 }
111 
112 int
113 sfc_port_reset_mac_stats(struct sfc_adapter *sa)
114 {
115 	struct sfc_port *port = &sa->port;
116 	int rc;
117 
118 	rte_spinlock_lock(&port->mac_stats_lock);
119 	rc = efx_mac_stats_clear(sa->nic);
120 	rte_spinlock_unlock(&port->mac_stats_lock);
121 
122 	return rc;
123 }
124 
125 static int
126 sfc_port_init_dev_link(struct sfc_adapter *sa)
127 {
128 	struct rte_eth_link *dev_link = &sa->eth_dev->data->dev_link;
129 	int rc;
130 	efx_link_mode_t link_mode;
131 	struct rte_eth_link current_link;
132 
133 	rc = efx_port_poll(sa->nic, &link_mode);
134 	if (rc != 0)
135 		return rc;
136 
137 	sfc_port_link_mode_to_info(link_mode, &current_link);
138 
139 	EFX_STATIC_ASSERT(sizeof(*dev_link) == sizeof(rte_atomic64_t));
140 	rte_atomic64_set((rte_atomic64_t *)dev_link,
141 			 *(uint64_t *)&current_link);
142 
143 	return 0;
144 }
145 
146 int
147 sfc_port_start(struct sfc_adapter *sa)
148 {
149 	struct sfc_port *port = &sa->port;
150 	int rc;
151 	uint32_t phy_adv_cap;
152 	const uint32_t phy_pause_caps =
153 		((1u << EFX_PHY_CAP_PAUSE) | (1u << EFX_PHY_CAP_ASYM));
154 	unsigned int i;
155 
156 	sfc_log_init(sa, "entry");
157 
158 	sfc_log_init(sa, "init filters");
159 	rc = efx_filter_init(sa->nic);
160 	if (rc != 0)
161 		goto fail_filter_init;
162 
163 	sfc_log_init(sa, "init port");
164 	rc = efx_port_init(sa->nic);
165 	if (rc != 0)
166 		goto fail_port_init;
167 
168 	sfc_log_init(sa, "set flow control to %#x autoneg=%u",
169 		     port->flow_ctrl, port->flow_ctrl_autoneg);
170 	rc = efx_mac_fcntl_set(sa->nic, port->flow_ctrl,
171 			       port->flow_ctrl_autoneg);
172 	if (rc != 0)
173 		goto fail_mac_fcntl_set;
174 
175 	/* Preserve pause capabilities set by above efx_mac_fcntl_set()  */
176 	efx_phy_adv_cap_get(sa->nic, EFX_PHY_CAP_CURRENT, &phy_adv_cap);
177 	SFC_ASSERT((port->phy_adv_cap & phy_pause_caps) == 0);
178 	phy_adv_cap = port->phy_adv_cap | (phy_adv_cap & phy_pause_caps);
179 
180 	sfc_log_init(sa, "set phy adv caps to %#x", phy_adv_cap);
181 	rc = efx_phy_adv_cap_set(sa->nic, phy_adv_cap);
182 	if (rc != 0)
183 		goto fail_phy_adv_cap_set;
184 
185 	sfc_log_init(sa, "set MAC PDU %u", (unsigned int)port->pdu);
186 	rc = efx_mac_pdu_set(sa->nic, port->pdu);
187 	if (rc != 0)
188 		goto fail_mac_pdu_set;
189 
190 	if (!port->isolated) {
191 		struct ether_addr *addr = &port->default_mac_addr;
192 
193 		sfc_log_init(sa, "set MAC address");
194 		rc = efx_mac_addr_set(sa->nic, addr->addr_bytes);
195 		if (rc != 0)
196 			goto fail_mac_addr_set;
197 
198 		sfc_log_init(sa, "set MAC filters");
199 		port->promisc = (sa->eth_dev->data->promiscuous != 0) ?
200 				B_TRUE : B_FALSE;
201 		port->allmulti = (sa->eth_dev->data->all_multicast != 0) ?
202 				 B_TRUE : B_FALSE;
203 		rc = sfc_set_rx_mode(sa);
204 		if (rc != 0)
205 			goto fail_mac_filter_set;
206 
207 		sfc_log_init(sa, "set multicast address list");
208 		rc = efx_mac_multicast_list_set(sa->nic, port->mcast_addrs,
209 						port->nb_mcast_addrs);
210 		if (rc != 0)
211 			goto fail_mcast_address_list_set;
212 	}
213 
214 	if (port->mac_stats_reset_pending) {
215 		rc = sfc_port_reset_mac_stats(sa);
216 		if (rc != 0)
217 			sfc_err(sa, "statistics reset failed (requested "
218 				    "before the port was started)");
219 
220 		port->mac_stats_reset_pending = B_FALSE;
221 	}
222 
223 	efx_mac_stats_get_mask(sa->nic, port->mac_stats_mask,
224 			       sizeof(port->mac_stats_mask));
225 
226 	for (i = 0, port->mac_stats_nb_supported = 0; i < EFX_MAC_NSTATS; ++i)
227 		if (EFX_MAC_STAT_SUPPORTED(port->mac_stats_mask, i))
228 			port->mac_stats_nb_supported++;
229 
230 	port->mac_stats_update_generation = 0;
231 
232 	if (port->mac_stats_update_period_ms != 0) {
233 		/*
234 		 * Update MAC stats using periodic DMA;
235 		 * any positive update interval different from
236 		 * 1000 ms can be set only on SFN8xxx provided
237 		 * that FW version is 6.2.1.1033 or higher
238 		 */
239 		sfc_log_init(sa, "request MAC stats DMA'ing");
240 		rc = efx_mac_stats_periodic(sa->nic, &port->mac_stats_dma_mem,
241 					    port->mac_stats_update_period_ms,
242 					    B_FALSE);
243 		if (rc == 0) {
244 			port->mac_stats_periodic_dma_supported = B_TRUE;
245 		} else if (rc == EOPNOTSUPP) {
246 			port->mac_stats_periodic_dma_supported = B_FALSE;
247 			port->mac_stats_last_request_timestamp = 0;
248 		} else {
249 			goto fail_mac_stats_periodic;
250 		}
251 	}
252 
253 	if ((port->mac_stats_update_period_ms != 0) &&
254 	    port->mac_stats_periodic_dma_supported) {
255 		/*
256 		 * Request an explicit MAC stats upload immediately to
257 		 * preclude bogus figures readback if the user decides
258 		 * to read stats before periodic DMA is really started
259 		 */
260 		rc = efx_mac_stats_upload(sa->nic, &port->mac_stats_dma_mem);
261 		if (rc != 0)
262 			goto fail_mac_stats_upload;
263 	}
264 
265 	sfc_log_init(sa, "disable MAC drain");
266 	rc = efx_mac_drain(sa->nic, B_FALSE);
267 	if (rc != 0)
268 		goto fail_mac_drain;
269 
270 	/* Synchronize link status knowledge */
271 	rc = sfc_port_init_dev_link(sa);
272 	if (rc != 0)
273 		goto fail_port_init_dev_link;
274 
275 	sfc_log_init(sa, "done");
276 	return 0;
277 
278 fail_port_init_dev_link:
279 	(void)efx_mac_drain(sa->nic, B_TRUE);
280 
281 fail_mac_drain:
282 fail_mac_stats_upload:
283 	(void)efx_mac_stats_periodic(sa->nic, &port->mac_stats_dma_mem,
284 				     0, B_FALSE);
285 
286 fail_mac_stats_periodic:
287 fail_mcast_address_list_set:
288 fail_mac_filter_set:
289 fail_mac_addr_set:
290 fail_mac_pdu_set:
291 fail_phy_adv_cap_set:
292 fail_mac_fcntl_set:
293 	efx_port_fini(sa->nic);
294 
295 fail_port_init:
296 	efx_filter_fini(sa->nic);
297 
298 fail_filter_init:
299 	sfc_log_init(sa, "failed %d", rc);
300 	return rc;
301 }
302 
303 void
304 sfc_port_stop(struct sfc_adapter *sa)
305 {
306 	sfc_log_init(sa, "entry");
307 
308 	efx_mac_drain(sa->nic, B_TRUE);
309 
310 	(void)efx_mac_stats_periodic(sa->nic, &sa->port.mac_stats_dma_mem,
311 				     0, B_FALSE);
312 
313 	efx_port_fini(sa->nic);
314 	efx_filter_fini(sa->nic);
315 
316 	sfc_log_init(sa, "done");
317 }
318 
319 int
320 sfc_port_configure(struct sfc_adapter *sa)
321 {
322 	const struct rte_eth_dev_data *dev_data = sa->eth_dev->data;
323 	struct sfc_port *port = &sa->port;
324 
325 	sfc_log_init(sa, "entry");
326 
327 	if (dev_data->dev_conf.rxmode.jumbo_frame)
328 		port->pdu = dev_data->dev_conf.rxmode.max_rx_pkt_len;
329 	else
330 		port->pdu = EFX_MAC_PDU(dev_data->mtu);
331 
332 	return 0;
333 }
334 
335 void
336 sfc_port_close(struct sfc_adapter *sa)
337 {
338 	sfc_log_init(sa, "entry");
339 }
340 
341 int
342 sfc_port_attach(struct sfc_adapter *sa)
343 {
344 	struct sfc_port *port = &sa->port;
345 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
346 	const struct ether_addr *from;
347 	long kvarg_stats_update_period_ms;
348 	int rc;
349 
350 	sfc_log_init(sa, "entry");
351 
352 	efx_phy_adv_cap_get(sa->nic, EFX_PHY_CAP_PERM, &port->phy_adv_cap_mask);
353 
354 	/* Enable flow control by default */
355 	port->flow_ctrl = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
356 	port->flow_ctrl_autoneg = B_TRUE;
357 
358 	RTE_BUILD_BUG_ON(sizeof(encp->enc_mac_addr) != sizeof(*from));
359 	from = (const struct ether_addr *)(encp->enc_mac_addr);
360 	ether_addr_copy(from, &port->default_mac_addr);
361 
362 	port->max_mcast_addrs = EFX_MAC_MULTICAST_LIST_MAX;
363 	port->nb_mcast_addrs = 0;
364 	port->mcast_addrs = rte_calloc_socket("mcast_addr_list_buf",
365 					      port->max_mcast_addrs,
366 					      EFX_MAC_ADDR_LEN, 0,
367 					      sa->socket_id);
368 	if (port->mcast_addrs == NULL) {
369 		rc = ENOMEM;
370 		goto fail_mcast_addr_list_buf_alloc;
371 	}
372 
373 	rte_spinlock_init(&port->mac_stats_lock);
374 
375 	rc = ENOMEM;
376 	port->mac_stats_buf = rte_calloc_socket("mac_stats_buf", EFX_MAC_NSTATS,
377 						sizeof(uint64_t), 0,
378 						sa->socket_id);
379 	if (port->mac_stats_buf == NULL)
380 		goto fail_mac_stats_buf_alloc;
381 
382 	rc = sfc_dma_alloc(sa, "mac_stats", 0, EFX_MAC_STATS_SIZE,
383 			   sa->socket_id, &port->mac_stats_dma_mem);
384 	if (rc != 0)
385 		goto fail_mac_stats_dma_alloc;
386 
387 	port->mac_stats_reset_pending = B_FALSE;
388 
389 	kvarg_stats_update_period_ms = SFC_MAC_STATS_UPDATE_PERIOD_MS_DEF;
390 
391 	rc = sfc_kvargs_process(sa, SFC_KVARG_STATS_UPDATE_PERIOD_MS,
392 				sfc_kvarg_long_handler,
393 				&kvarg_stats_update_period_ms);
394 	if ((rc == 0) &&
395 	    ((kvarg_stats_update_period_ms < 0) ||
396 	     (kvarg_stats_update_period_ms > UINT16_MAX))) {
397 		sfc_err(sa, "wrong '" SFC_KVARG_STATS_UPDATE_PERIOD_MS "' "
398 			    "was set (%ld);", kvarg_stats_update_period_ms);
399 		sfc_err(sa, "it must not be less than 0 "
400 			    "or greater than %" PRIu16, UINT16_MAX);
401 		rc = EINVAL;
402 		goto fail_kvarg_stats_update_period_ms;
403 	} else if (rc != 0) {
404 		goto fail_kvarg_stats_update_period_ms;
405 	}
406 
407 	port->mac_stats_update_period_ms = kvarg_stats_update_period_ms;
408 
409 	sfc_log_init(sa, "done");
410 	return 0;
411 
412 fail_kvarg_stats_update_period_ms:
413 	sfc_dma_free(sa, &port->mac_stats_dma_mem);
414 
415 fail_mac_stats_dma_alloc:
416 	rte_free(port->mac_stats_buf);
417 
418 fail_mac_stats_buf_alloc:
419 	rte_free(port->mcast_addrs);
420 
421 fail_mcast_addr_list_buf_alloc:
422 	sfc_log_init(sa, "failed %d", rc);
423 	return rc;
424 }
425 
426 void
427 sfc_port_detach(struct sfc_adapter *sa)
428 {
429 	struct sfc_port *port = &sa->port;
430 
431 	sfc_log_init(sa, "entry");
432 
433 	sfc_dma_free(sa, &port->mac_stats_dma_mem);
434 	rte_free(port->mac_stats_buf);
435 
436 	rte_free(port->mcast_addrs);
437 
438 	sfc_log_init(sa, "done");
439 }
440 
441 int
442 sfc_set_rx_mode(struct sfc_adapter *sa)
443 {
444 	struct sfc_port *port = &sa->port;
445 	int rc;
446 
447 	rc = efx_mac_filter_set(sa->nic, port->promisc, B_TRUE,
448 				port->promisc || port->allmulti, B_TRUE);
449 
450 	return rc;
451 }
452 
453 void
454 sfc_port_link_mode_to_info(efx_link_mode_t link_mode,
455 			   struct rte_eth_link *link_info)
456 {
457 	SFC_ASSERT(link_mode < EFX_LINK_NMODES);
458 
459 	memset(link_info, 0, sizeof(*link_info));
460 	if ((link_mode == EFX_LINK_DOWN) || (link_mode == EFX_LINK_UNKNOWN))
461 		link_info->link_status = ETH_LINK_DOWN;
462 	else
463 		link_info->link_status = ETH_LINK_UP;
464 
465 	switch (link_mode) {
466 	case EFX_LINK_10HDX:
467 		link_info->link_speed  = ETH_SPEED_NUM_10M;
468 		link_info->link_duplex = ETH_LINK_HALF_DUPLEX;
469 		break;
470 	case EFX_LINK_10FDX:
471 		link_info->link_speed  = ETH_SPEED_NUM_10M;
472 		link_info->link_duplex = ETH_LINK_FULL_DUPLEX;
473 		break;
474 	case EFX_LINK_100HDX:
475 		link_info->link_speed  = ETH_SPEED_NUM_100M;
476 		link_info->link_duplex = ETH_LINK_HALF_DUPLEX;
477 		break;
478 	case EFX_LINK_100FDX:
479 		link_info->link_speed  = ETH_SPEED_NUM_100M;
480 		link_info->link_duplex = ETH_LINK_FULL_DUPLEX;
481 		break;
482 	case EFX_LINK_1000HDX:
483 		link_info->link_speed  = ETH_SPEED_NUM_1G;
484 		link_info->link_duplex = ETH_LINK_HALF_DUPLEX;
485 		break;
486 	case EFX_LINK_1000FDX:
487 		link_info->link_speed  = ETH_SPEED_NUM_1G;
488 		link_info->link_duplex = ETH_LINK_FULL_DUPLEX;
489 		break;
490 	case EFX_LINK_10000FDX:
491 		link_info->link_speed  = ETH_SPEED_NUM_10G;
492 		link_info->link_duplex = ETH_LINK_FULL_DUPLEX;
493 		break;
494 	case EFX_LINK_40000FDX:
495 		link_info->link_speed  = ETH_SPEED_NUM_40G;
496 		link_info->link_duplex = ETH_LINK_FULL_DUPLEX;
497 		break;
498 	default:
499 		SFC_ASSERT(B_FALSE);
500 		/* FALLTHROUGH */
501 	case EFX_LINK_UNKNOWN:
502 	case EFX_LINK_DOWN:
503 		link_info->link_speed  = ETH_SPEED_NUM_NONE;
504 		link_info->link_duplex = 0;
505 		break;
506 	}
507 
508 	link_info->link_autoneg = ETH_LINK_AUTONEG;
509 }
510