xref: /openbmc/u-boot/net/eth-uclass.c (revision 32c1a6ee)
1 /*
2  * (C) Copyright 2001-2015
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  * Joe Hershberger, National Instruments
5  *
6  * SPDX-License-Identifier:	GPL-2.0+
7  */
8 
9 #include <common.h>
10 #include <dm.h>
11 #include <environment.h>
12 #include <net.h>
13 #include <dm/device-internal.h>
14 #include <dm/uclass-internal.h>
15 #include "eth_internal.h"
16 
17 /**
18  * struct eth_device_priv - private structure for each Ethernet device
19  *
20  * @state: The state of the Ethernet MAC driver (defined by enum eth_state_t)
21  */
22 struct eth_device_priv {
23 	enum eth_state_t state;
24 };
25 
26 /**
27  * struct eth_uclass_priv - The structure attached to the uclass itself
28  *
29  * @current: The Ethernet device that the network functions are using
30  */
31 struct eth_uclass_priv {
32 	struct udevice *current;
33 };
34 
35 /* eth_errno - This stores the most recent failure code from DM functions */
36 static int eth_errno;
37 
38 static struct eth_uclass_priv *eth_get_uclass_priv(void)
39 {
40 	struct uclass *uc;
41 
42 	uclass_get(UCLASS_ETH, &uc);
43 	assert(uc);
44 	return uc->priv;
45 }
46 
47 void eth_set_current_to_next(void)
48 {
49 	struct eth_uclass_priv *uc_priv;
50 
51 	uc_priv = eth_get_uclass_priv();
52 	if (uc_priv->current)
53 		uclass_next_device(&uc_priv->current);
54 	if (!uc_priv->current)
55 		uclass_first_device(UCLASS_ETH, &uc_priv->current);
56 }
57 
58 /*
59  * Typically this will simply return the active device.
60  * In the case where the most recent active device was unset, this will attempt
61  * to return the first device. If that device doesn't exist or fails to probe,
62  * this function will return NULL.
63  */
64 struct udevice *eth_get_dev(void)
65 {
66 	struct eth_uclass_priv *uc_priv;
67 
68 	uc_priv = eth_get_uclass_priv();
69 	if (!uc_priv->current)
70 		eth_errno = uclass_first_device(UCLASS_ETH,
71 				    &uc_priv->current);
72 	return uc_priv->current;
73 }
74 
75 /*
76  * Typically this will just store a device pointer.
77  * In case it was not probed, we will attempt to do so.
78  * dev may be NULL to unset the active device.
79  */
80 void eth_set_dev(struct udevice *dev)
81 {
82 	if (dev && !device_active(dev)) {
83 		eth_errno = device_probe(dev);
84 		if (eth_errno)
85 			dev = NULL;
86 	}
87 
88 	eth_get_uclass_priv()->current = dev;
89 }
90 
91 /*
92  * Find the udevice that either has the name passed in as devname or has an
93  * alias named devname.
94  */
95 struct udevice *eth_get_dev_by_name(const char *devname)
96 {
97 	int seq = -1;
98 	char *endp = NULL;
99 	const char *startp = NULL;
100 	struct udevice *it;
101 	struct uclass *uc;
102 	int len = strlen("eth");
103 
104 	/* Must be longer than 3 to be an alias */
105 	if (!strncmp(devname, "eth", len) && strlen(devname) > len) {
106 		startp = devname + len;
107 		seq = simple_strtoul(startp, &endp, 10);
108 	}
109 
110 	uclass_get(UCLASS_ETH, &uc);
111 	uclass_foreach_dev(it, uc) {
112 		/*
113 		 * We need the seq to be valid, so try to probe it.
114 		 * If the probe fails, the seq will not match since it will be
115 		 * -1 instead of what we are looking for.
116 		 * We don't care about errors from probe here. Either they won't
117 		 * match an alias or it will match a literal name and we'll pick
118 		 * up the error when we try to probe again in eth_set_dev().
119 		 */
120 		if (device_probe(it))
121 			continue;
122 		/* Check for the name or the sequence number to match */
123 		if (strcmp(it->name, devname) == 0 ||
124 		    (endp > startp && it->seq == seq))
125 			return it;
126 	}
127 
128 	return NULL;
129 }
130 
131 unsigned char *eth_get_ethaddr(void)
132 {
133 	struct eth_pdata *pdata;
134 
135 	if (eth_get_dev()) {
136 		pdata = eth_get_dev()->platdata;
137 		return pdata->enetaddr;
138 	}
139 
140 	return NULL;
141 }
142 
143 /* Set active state without calling start on the driver */
144 int eth_init_state_only(void)
145 {
146 	struct udevice *current;
147 	struct eth_device_priv *priv;
148 
149 	current = eth_get_dev();
150 	if (!current || !device_active(current))
151 		return -EINVAL;
152 
153 	priv = current->uclass_priv;
154 	priv->state = ETH_STATE_ACTIVE;
155 
156 	return 0;
157 }
158 
159 /* Set passive state without calling stop on the driver */
160 void eth_halt_state_only(void)
161 {
162 	struct udevice *current;
163 	struct eth_device_priv *priv;
164 
165 	current = eth_get_dev();
166 	if (!current || !device_active(current))
167 		return;
168 
169 	priv = current->uclass_priv;
170 	priv->state = ETH_STATE_PASSIVE;
171 }
172 
173 int eth_get_dev_index(void)
174 {
175 	if (eth_get_dev())
176 		return eth_get_dev()->seq;
177 	return -1;
178 }
179 
180 static int eth_write_hwaddr(struct udevice *dev)
181 {
182 	struct eth_pdata *pdata = dev->platdata;
183 	int ret = 0;
184 
185 	if (!dev || !device_active(dev))
186 		return -EINVAL;
187 
188 	/* seq is valid since the device is active */
189 	if (eth_get_ops(dev)->write_hwaddr && !eth_mac_skip(dev->seq)) {
190 		if (!is_valid_ethaddr(pdata->enetaddr)) {
191 			printf("\nError: %s address %pM illegal value\n",
192 			       dev->name, pdata->enetaddr);
193 			return -EINVAL;
194 		}
195 
196 		/*
197 		 * Drivers are allowed to decide not to implement this at
198 		 * run-time. E.g. Some devices may use it and some may not.
199 		 */
200 		ret = eth_get_ops(dev)->write_hwaddr(dev);
201 		if (ret == -ENOSYS)
202 			ret = 0;
203 		if (ret)
204 			printf("\nWarning: %s failed to set MAC address\n",
205 			       dev->name);
206 	}
207 
208 	return ret;
209 }
210 
211 static int on_ethaddr(const char *name, const char *value, enum env_op op,
212 	int flags)
213 {
214 	int index;
215 	int retval;
216 	struct udevice *dev;
217 
218 	/* look for an index after "eth" */
219 	index = simple_strtoul(name + 3, NULL, 10);
220 
221 	retval = uclass_find_device_by_seq(UCLASS_ETH, index, false, &dev);
222 	if (!retval) {
223 		struct eth_pdata *pdata = dev->platdata;
224 		switch (op) {
225 		case env_op_create:
226 		case env_op_overwrite:
227 			eth_parse_enetaddr(value, pdata->enetaddr);
228 			break;
229 		case env_op_delete:
230 			memset(pdata->enetaddr, 0, 6);
231 		}
232 	}
233 
234 	return 0;
235 }
236 U_BOOT_ENV_CALLBACK(ethaddr, on_ethaddr);
237 
238 int eth_init(void)
239 {
240 	char *ethact = getenv("ethact");
241 	char *ethrotate = getenv("ethrotate");
242 	struct udevice *current = NULL;
243 	struct udevice *old_current;
244 	int ret = -ENODEV;
245 
246 	/*
247 	 * When 'ethrotate' variable is set to 'no' and 'ethact' variable
248 	 * is already set to an ethernet device, we should stick to 'ethact'.
249 	 */
250 	if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0)) {
251 		if (ethact) {
252 			current = eth_get_dev_by_name(ethact);
253 			if (!current)
254 				return -EINVAL;
255 		}
256 	}
257 
258 	if (!current) {
259 		current = eth_get_dev();
260 		if (!current) {
261 			printf("No ethernet found.\n");
262 			return -ENODEV;
263 		}
264 	}
265 
266 	old_current = current;
267 	do {
268 		if (current) {
269 			debug("Trying %s\n", current->name);
270 
271 			if (device_active(current)) {
272 				ret = eth_get_ops(current)->start(current);
273 				if (ret >= 0) {
274 					struct eth_device_priv *priv =
275 						current->uclass_priv;
276 
277 					priv->state = ETH_STATE_ACTIVE;
278 					return 0;
279 				}
280 			} else {
281 				ret = eth_errno;
282 			}
283 
284 			debug("FAIL\n");
285 		} else {
286 			debug("PROBE FAIL\n");
287 		}
288 
289 		/*
290 		 * If ethrotate is enabled, this will change "current",
291 		 * otherwise we will drop out of this while loop immediately
292 		 */
293 		eth_try_another(0);
294 		/* This will ensure the new "current" attempted to probe */
295 		current = eth_get_dev();
296 	} while (old_current != current);
297 
298 	return ret;
299 }
300 
301 void eth_halt(void)
302 {
303 	struct udevice *current;
304 	struct eth_device_priv *priv;
305 
306 	current = eth_get_dev();
307 	if (!current || !device_active(current))
308 		return;
309 
310 	eth_get_ops(current)->stop(current);
311 	priv = current->uclass_priv;
312 	priv->state = ETH_STATE_PASSIVE;
313 }
314 
315 int eth_is_active(struct udevice *dev)
316 {
317 	struct eth_device_priv *priv;
318 
319 	if (!dev || !device_active(dev))
320 		return 0;
321 
322 	priv = dev_get_uclass_priv(dev);
323 	return priv->state == ETH_STATE_ACTIVE;
324 }
325 
326 int eth_send(void *packet, int length)
327 {
328 	struct udevice *current;
329 	int ret;
330 
331 	current = eth_get_dev();
332 	if (!current)
333 		return -ENODEV;
334 
335 	if (!device_active(current))
336 		return -EINVAL;
337 
338 	ret = eth_get_ops(current)->send(current, packet, length);
339 	if (ret < 0) {
340 		/* We cannot completely return the error at present */
341 		debug("%s: send() returned error %d\n", __func__, ret);
342 	}
343 	return ret;
344 }
345 
346 int eth_rx(void)
347 {
348 	struct udevice *current;
349 	uchar *packet;
350 	int flags;
351 	int ret;
352 	int i;
353 
354 	current = eth_get_dev();
355 	if (!current)
356 		return -ENODEV;
357 
358 	if (!device_active(current))
359 		return -EINVAL;
360 
361 	/* Process up to 32 packets at one time */
362 	flags = ETH_RECV_CHECK_DEVICE;
363 	for (i = 0; i < 32; i++) {
364 		ret = eth_get_ops(current)->recv(current, flags, &packet);
365 		flags = 0;
366 		if (ret > 0)
367 			net_process_received_packet(packet, ret);
368 		if (ret >= 0 && eth_get_ops(current)->free_pkt)
369 			eth_get_ops(current)->free_pkt(current, packet, ret);
370 		if (ret <= 0)
371 			break;
372 	}
373 	if (ret == -EAGAIN)
374 		ret = 0;
375 	if (ret < 0) {
376 		/* We cannot completely return the error at present */
377 		debug("%s: recv() returned error %d\n", __func__, ret);
378 	}
379 	return ret;
380 }
381 
382 int eth_initialize(void)
383 {
384 	int num_devices = 0;
385 	struct udevice *dev;
386 
387 	eth_common_init();
388 
389 	/*
390 	 * Devices need to write the hwaddr even if not started so that Linux
391 	 * will have access to the hwaddr that u-boot stored for the device.
392 	 * This is accomplished by attempting to probe each device and calling
393 	 * their write_hwaddr() operation.
394 	 */
395 	uclass_first_device(UCLASS_ETH, &dev);
396 	if (!dev) {
397 		printf("No ethernet found.\n");
398 		bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
399 	} else {
400 		char *ethprime = getenv("ethprime");
401 		struct udevice *prime_dev = NULL;
402 
403 		if (ethprime)
404 			prime_dev = eth_get_dev_by_name(ethprime);
405 		if (prime_dev) {
406 			eth_set_dev(prime_dev);
407 			eth_current_changed();
408 		} else {
409 			eth_set_dev(NULL);
410 		}
411 
412 		bootstage_mark(BOOTSTAGE_ID_NET_ETH_INIT);
413 		do {
414 			if (num_devices)
415 				printf(", ");
416 
417 			printf("eth%d: %s", dev->seq, dev->name);
418 
419 			if (ethprime && dev == prime_dev)
420 				printf(" [PRIME]");
421 
422 			eth_write_hwaddr(dev);
423 
424 			uclass_next_device(&dev);
425 			num_devices++;
426 		} while (dev);
427 
428 		putc('\n');
429 	}
430 
431 	return num_devices;
432 }
433 
434 static int eth_post_bind(struct udevice *dev)
435 {
436 	if (strchr(dev->name, ' ')) {
437 		printf("\nError: eth device name \"%s\" has a space!\n",
438 		       dev->name);
439 		return -EINVAL;
440 	}
441 
442 	return 0;
443 }
444 
445 static int eth_pre_unbind(struct udevice *dev)
446 {
447 	/* Don't hang onto a pointer that is going away */
448 	if (dev == eth_get_uclass_priv()->current)
449 		eth_set_dev(NULL);
450 
451 	return 0;
452 }
453 
454 static int eth_post_probe(struct udevice *dev)
455 {
456 	struct eth_device_priv *priv = dev->uclass_priv;
457 	struct eth_pdata *pdata = dev->platdata;
458 	unsigned char env_enetaddr[6];
459 
460 #if defined(CONFIG_NEEDS_MANUAL_RELOC)
461 	struct eth_ops *ops = eth_get_ops(dev);
462 	static int reloc_done;
463 
464 	if (!reloc_done) {
465 		if (ops->start)
466 			ops->start += gd->reloc_off;
467 		if (ops->send)
468 			ops->send += gd->reloc_off;
469 		if (ops->recv)
470 			ops->recv += gd->reloc_off;
471 		if (ops->free_pkt)
472 			ops->free_pkt += gd->reloc_off;
473 		if (ops->stop)
474 			ops->stop += gd->reloc_off;
475 #ifdef CONFIG_MCAST_TFTP
476 		if (ops->mcast)
477 			ops->mcast += gd->reloc_off;
478 #endif
479 		if (ops->write_hwaddr)
480 			ops->write_hwaddr += gd->reloc_off;
481 		if (ops->read_rom_hwaddr)
482 			ops->read_rom_hwaddr += gd->reloc_off;
483 
484 		reloc_done++;
485 	}
486 #endif
487 
488 	priv->state = ETH_STATE_INIT;
489 
490 	/* Check if the device has a MAC address in ROM */
491 	if (eth_get_ops(dev)->read_rom_hwaddr)
492 		eth_get_ops(dev)->read_rom_hwaddr(dev);
493 
494 	eth_getenv_enetaddr_by_index("eth", dev->seq, env_enetaddr);
495 	if (!is_zero_ethaddr(env_enetaddr)) {
496 		if (!is_zero_ethaddr(pdata->enetaddr) &&
497 		    memcmp(pdata->enetaddr, env_enetaddr, 6)) {
498 			printf("\nWarning: %s MAC addresses don't match:\n",
499 			       dev->name);
500 			printf("Address in SROM is         %pM\n",
501 			       pdata->enetaddr);
502 			printf("Address in environment is  %pM\n",
503 			       env_enetaddr);
504 		}
505 
506 		/* Override the ROM MAC address */
507 		memcpy(pdata->enetaddr, env_enetaddr, 6);
508 	} else if (is_valid_ethaddr(pdata->enetaddr)) {
509 		eth_setenv_enetaddr_by_index("eth", dev->seq, pdata->enetaddr);
510 		printf("\nWarning: %s using MAC address from ROM\n",
511 		       dev->name);
512 	} else if (is_zero_ethaddr(pdata->enetaddr)) {
513 #ifdef CONFIG_NET_RANDOM_ETHADDR
514 		net_random_ethaddr(pdata->enetaddr);
515 		printf("\nWarning: %s (eth%d) using random MAC address - %pM\n",
516 		       dev->name, dev->seq, pdata->enetaddr);
517 #else
518 		printf("\nError: %s address not set.\n",
519 		       dev->name);
520 		return -EINVAL;
521 #endif
522 	}
523 
524 	return 0;
525 }
526 
527 static int eth_pre_remove(struct udevice *dev)
528 {
529 	struct eth_pdata *pdata = dev->platdata;
530 
531 	eth_get_ops(dev)->stop(dev);
532 
533 	/* clear the MAC address */
534 	memset(pdata->enetaddr, 0, 6);
535 
536 	return 0;
537 }
538 
539 UCLASS_DRIVER(eth) = {
540 	.name		= "eth",
541 	.id		= UCLASS_ETH,
542 	.post_bind	= eth_post_bind,
543 	.pre_unbind	= eth_pre_unbind,
544 	.post_probe	= eth_post_probe,
545 	.pre_remove	= eth_pre_remove,
546 	.priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
547 	.per_device_auto_alloc_size = sizeof(struct eth_device_priv),
548 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
549 };
550