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