struct udevice *current;
};
+/* eth_errno - This stores the most recent failure code from DM functions */
+static int eth_errno;
+
static struct eth_uclass_priv *eth_get_uclass_priv(void)
{
struct uclass *uc;
uclass_first_device(UCLASS_ETH, &uc_priv->current);
}
+/*
+ * Typically this will simply return the active device.
+ * In the case where the most recent active device was unset, this will attempt
+ * to return the first device. If that device doesn't exist or fails to probe,
+ * this function will return NULL.
+ */
struct udevice *eth_get_dev(void)
{
struct eth_uclass_priv *uc_priv;
uc_priv = eth_get_uclass_priv();
if (!uc_priv->current)
- uclass_first_device(UCLASS_ETH,
+ eth_errno = uclass_first_device(UCLASS_ETH,
&uc_priv->current);
return uc_priv->current;
}
+/*
+ * Typically this will just store a device pointer.
+ * In case it was not probed, we will attempt to do so.
+ * dev may be NULL to unset the active device.
+ */
static void eth_set_dev(struct udevice *dev)
{
- device_probe(dev);
+ if (dev && !device_active(dev))
+ eth_errno = device_probe(dev);
eth_get_uclass_priv()->current = dev;
}
uclass_get(UCLASS_ETH, &uc);
uclass_foreach_dev(it, uc) {
- /* We need the seq to be valid, so make sure it's probed */
+ /*
+ * We need the seq to be valid, so try to probe it.
+ * If the probe fails, the seq will not match since it will be
+ * -1 instead of what we are looking for.
+ * We don't care about errors from probe here. Either they won't
+ * match an alias or it will match a literal name and we'll pick
+ * up the error when we try to probe again in eth_set_dev().
+ */
device_probe(it);
/*
* Check for the name or the sequence number to match
{
struct udevice *current;
struct udevice *old_current;
+ int ret = -ENODEV;
current = eth_get_dev();
if (!current) {
else
memset(pdata->enetaddr, 0, 6);
- if (eth_get_ops(current)->start(current) >= 0) {
+ ret = eth_get_ops(current)->start(current);
+ if (ret >= 0) {
struct eth_device_priv *priv =
current->uclass_priv;
priv->state = ETH_STATE_ACTIVE;
return 0;
}
- }
+ } else
+ ret = eth_errno;
+
debug("FAIL\n");
- /* This will ensure the new "current" attempted to probe */
+ /*
+ * If ethrotate is enabled, this will change "current",
+ * otherwise we will drop out of this while loop immediately
+ */
eth_try_another(0);
+ /* This will ensure the new "current" attempted to probe */
current = eth_get_dev();
} while (old_current != current);
- return -ENODEV;
+ return ret;
}
void eth_halt(void)
int eth_send(void *packet, int length)
{
struct udevice *current;
+ int ret;
current = eth_get_dev();
if (!current)
if (!device_active(current))
return -EINVAL;
- return eth_get_ops(current)->send(current, packet, length);
+ ret = eth_get_ops(current)->send(current, packet, length);
+ if (ret < 0) {
+ /* We cannot completely return the error at present */
+ debug("%s: send() returned error %d\n", __func__, ret);
+ }
+ return ret;
}
int eth_rx(void)
}
if (ret == -EAGAIN)
ret = 0;
+ if (ret < 0) {
+ /* We cannot completely return the error at present */
+ debug("%s: recv() returned error %d\n", __func__, ret);
+ }
return ret;
}
#include <common.h>
#include <command.h>
#include <environment.h>
+#include <errno.h>
#include <net.h>
#if defined(CONFIG_STATUS_LED)
#include <miiphy.h>
int NetLoop(enum proto_t protocol)
{
- int ret = -1;
+ int ret = -EINVAL;
NetRestarted = 0;
NetDevExists = 0;
if (eth_is_on_demand_init() || protocol != NETCONS) {
eth_halt();
eth_set_current();
- if (eth_init() < 0) {
+ ret = eth_init();
+ if (ret < 0) {
eth_halt();
- return -1;
+ return ret;
}
} else
eth_init_state_only();
case 1:
/* network not configured */
eth_halt();
- return -1;
+ return -ENODEV;
case 2:
/* network device not configured */
/*
* Check the ethernet for a new packet. The ethernet
* receive routine will process it.
+ * Most drivers return the most recent packet size, but not
+ * errors that may have happened.
*/
eth_rx();
}
if (net_state == NETLOOP_FAIL)
- NetStartAgain();
+ ret = NetStartAgain();
switch (net_state) {
net_set_state(NETLOOP_RESTART);
}
-void NetStartAgain(void)
+int NetStartAgain(void)
{
char *nretry;
int retry_forever = 0;
unsigned long retrycnt = 0;
+ int ret;
nretry = getenv("netretry");
if (nretry) {
if ((!retry_forever) && (NetTryCount >= retrycnt)) {
eth_halt();
net_set_state(NETLOOP_FAIL);
- return;
+ /*
+ * We don't provide a way for the protocol to return an error,
+ * but this is almost always the reason.
+ */
+ return -ETIMEDOUT;
}
NetTryCount++;
#if !defined(CONFIG_NET_DO_NOT_TRY_ANOTHER)
eth_try_another(!NetRestarted);
#endif
- eth_init();
+ ret = eth_init();
if (NetRestartWrap) {
NetRestartWrap = 0;
if (NetDevExists) {
} else {
net_set_state(NETLOOP_RESTART);
}
+ return ret;
}
/**********************************************************************/
/* If ethrotate is no, then we should fail on a bad MAC */
setenv("ethact", "eth@10004000");
setenv("ethrotate", "no");
- ut_asserteq(-1, NetLoop(PING));
+ ut_asserteq(-EINVAL, NetLoop(PING));
ut_asserteq_str("eth@10004000", getenv("ethact"));
/* Restore the env */
*/
setenv("ethact", "eth@10004000");
setenv("netretry", "no");
- ut_asserteq(-1, NetLoop(PING));
+ ut_asserteq(-ETIMEDOUT, NetLoop(PING));
ut_asserteq_str("eth@10004000", getenv("ethact"));
/* Restore the env */