On 1/4/25 04:05, E Shattow wrote:
> On 1/3/25 09:58, E Shattow wrote:
>>
>>
>> On 1/3/25 02:03, Jerome Forissier wrote:
>>>
>>>
>>> On 1/3/25 02:52, E Shattow wrote:
>>>>
>>>>
>>>> On 1/2/25 17:40, Tom Rini wrote:
>>>>> On Thu, Jan 02, 2025 at 05:34:57PM -0800, E Shattow wrote:
>>>>>
>>>>>> Tom sorry about sending this reply twice, struggle here is with
>>>>>> Thunderbird
>>>>>> mail UI sometimes hiding "Reply All" and it missed the mail list first
>>>>>> time
>>>>>> around.
>>>>>
>>>>> No problem.
>>>>>
>>>>>> On 1/2/25 14:47, Tom Rini wrote:
>>>>>>> On Thu, Jan 02, 2025 at 02:26:06PM -0800, E Shattow wrote:
>>>>>>>> Problem: 'dhcp' must be ran twice when the network cable is plugged
>>>>>>>> into a
>>>>>>>> port other than the first network port.
>>>>>>>>
>>>>>>>> Network cable plugged into bottom (first) Ethernet port:
>>>>>>>> 1. Power on
>>>>>>>> 2. StarFive # dhcp
>>>>>>>>
>>>>>>>> ethernet@16030000 Waiting for PHY auto negotiation to complete.......
>>>>>>>> done
>>>>>>>> DHCP client bound to address 192.168.2.51 (3678 ms)
>>>>>>>>
>>>>>>>>
>>>>>>>> Network cable plugged into top (second) Ethernet port:
>>>>>>>> 1. Power on
>>>>>>>> 2. StarFive # dhcp
>>>>>>>> ethernet@16030000 Waiting for PHY auto negotiation to complete.........
>>>>>>>> TIMEOUT !
>>>>>>>> phy_startup() failed: -110
>>>>>>>> FAILED: -110
>>>>>>>> ethernet@16040000 Waiting for PHY auto negotiation to complete......
>>>>>>>> done
>>>>>>>> ethernet@16030000 Waiting for PHY auto negotiation to complete.........
>>>>>>>> TIMEOUT !
>>>>>>>> phy_startup() failed: -110
>>>>>>>> FAILED: -110
>>>>>>>> Could not start ethernet@16030000
>>>>>>>> 3. StarFive # dhcp
>>>>>>>> DHCP client bound to address 192.168.2.77 (31 ms)
>>>>>>>
>>>>>>> What happens when you set ethact to 1 first?
>>>>>>>
>>>>>>
>>>>>>
>>>>>> '1' literal does not seem to do something so I guess it is meant the id
>>>>>> of
>>>>>> the first ethernet interface:
>>>>>
>>>>> Yes, I misspoke sorry.
>>>>>
>>>>>> From power-on:
>>>>>>
>>>>>> ...
>>>>>> starfive_7110_pcie pcie@2b000000: Starfive PCIe bus probed.
>>>>>> starfive_7110_pcie pcie@2c000000: Starfive PCIe bus probed.
>>>>>> In: serial@10000000
>>>>>> Out: serial@10000000
>>>>>> Err: serial@10000000
>>>>>> Net: eth0: ethernet@16030000, eth1: ethernet@16040000
>>>>>> starting USB...
>>>>>> No USB controllers found
>>>>>> Working FDT set to ff700a10
>>>>>> StarFive # env print ethact
>>>>>> ## Error: "ethact" not defined
>>>>>> StarFive # env set ethact 1
>>>>>> StarFive # dhcp
>>>>>> ethernet@16030000 Waiting for PHY auto negotiation to complete.........
>>>>>> TIMEOUT !
>>>>>> phy_startup() failed: -110
>>>>>> FAILED: -110
>>>>>> ethernet@16040000 Waiting for PHY auto negotiation to complete...... done
>>>>>> EQOS_DMA_MODE_SWR stuck
>>>>>> FAILED: -110
>>>>>> Could not start ethernet@16030000
>>>>>>
>>>>>> Again, from power-on:
>>>>>>
>>>>>> starfive_7110_pcie pcie@2b000000: Starfive PCIe bus probed.
>>>>>> starfive_7110_pcie pcie@2c000000: Starfive PCIe bus probed.
>>>>>> In: serial@10000000
>>>>>> Out: serial@10000000
>>>>>> Err: serial@10000000
>>>>>> Net: eth0: ethernet@16030000, eth1: ethernet@16040000
>>>>>> starting USB...
>>>>>> No USB controllers found
>>>>>> Working FDT set to ff700a10
>>>>>> StarFive # env print ethact
>>>>>> ## Error: "ethact" not defined
>>>>>> StarFive # env set ethact ethernet@16040000
>>>>>> StarFive # dhcp
>>>>>> ethernet@16040000 Waiting for PHY auto negotiation to complete...... done
>>>>>> DHCP client bound to address 192.168.2.77 (149 ms)
>>>>>
>>>>> So then yes, the second interface works when ethact is set to use that
>>>>> directly. This is the same behavior as the legacy stack I believe.
>>>>>
>>>>
>>>> Legacy stack does actually rotate and complete successfully when ethact
>>>> environment variable does not exist and (eventually) configure the second
>>>> interface though. Here with LwIP the procedure fails.
>>>>
>>>> Notice that here it starts with ethernet@16030000, then rotates to
>>>> ethernet@16040000 unsuccessfully, and back again to ethernet@16030000
>>>> before (again) failing and giving up. There is a network cable plugged
>>>> into 'ethernet@16040000' port and if we try the command again the
>>>> environment variable ethact retained 'ethact=ethernet@16040000' from the
>>>> failed procedure so you're right it works as it should... except that it
>>>> totally failed to do what was expected the first time.
>>>
>>> That's unexpected indeed.
>>>
>>>> Is this exposing a problem with this board network driver and behavior or
>>>> is it something with LwIP ?
>>> Hard to tell at this point. One thing I know for sure is that lwIP expects
>>> eth_set_current() (called from do_dhcp()) to actually pick a valid
>>> interface if there is one. So it should definitely select ethernet@16040000
>>> in your scenario. Adding debug prints to eth_set_current(),
>>> eth_current_changed() etc. should help.
>>>
>>> Thanks,
>>
>> StarFive # dhcp
>> !!! eth_set_current(): entered function
>> !!! eth_set_current(): conditional 1
>> !!! eth_set_current(): conditional 2
>> !!! eth_set_current(): conditional 5
>> !!! eth_current_changed(): entered function
>> !!! eth_current_changed(): conditional 2
>> !!! eth_current_changed(): conditional 3
>> !!! eth_current_changed(): leaving function
>> !!! eth_set_current(): leaving function
>> ethernet@16030000 Waiting for PHY auto negotiation to complete.........
>> TIMEOUT !
>> phy_startup() failed: -110
>> FAILED: -110
>> !!! eth_current_changed(): entered function
>> !!! eth_current_changed(): conditional 2
>> !!! eth_current_changed(): conditional 3
>> !!! eth_current_changed(): leaving function
>> ethernet@16040000 Waiting for PHY auto negotiation to complete...... done
>> ethernet@16030000 Waiting for PHY auto negotiation to complete.........
>> TIMEOUT !
>> phy_startup() failed: -110
>> FAILED: -110
>> Could not start ethernet@16030000
>> StarFive #
>>
>> For reference the modified functions:
>>
>> void eth_current_changed(void)
>> {
>> char *act = env_get("ethact");
>> char *ethrotate;
>>
>> printf("!!! eth_current_changed(): entered function\n");
>> /*
>> * The call to eth_get_dev() below has a side effect of rotating
>> * ethernet device if uc_priv->current == NULL. This is not what
>> * we want when 'ethrotate' variable is 'no'.
>> */
>> ethrotate = env_get("ethrotate");
>> if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0))
>> {
>> printf("!!! eth_current_changed(): conditional 1\n");
>> return;
>> }
>>
>> /* update current ethernet name */
>> if (eth_get_dev()) {
>> printf("!!! eth_current_changed(): conditional 2\n");
>> if (act == NULL || strcmp(act, eth_get_name()) != 0)
>> {
>> printf("!!! eth_current_changed(): conditional 3\n");
>> env_set("ethact", eth_get_name());
>> }
>> }
>> /*
>> * remove the variable completely if there is no active
>> * interface
>> */
>> else if (act != NULL)
>> {
>> printf("!!! eth_current_changed(): conditional 4\n");
>> env_set("ethact", NULL);
>> }
>> printf("!!! eth_current_changed(): leaving function\n");
>> }
>>
>> void eth_set_current(void)
>> {
>> static char *act;
>> static int env_changed_id;
>> int env_id;
>>
>> printf("!!! eth_set_current(): entered function\n");
>> env_id = env_get_id();
>> if ((act == NULL) || (env_changed_id != env_id)) {
>> printf("!!! eth_set_current(): conditional 1\n");
>> act = env_get("ethact");
>> env_changed_id = env_id;
>> }
>>
>> if (act == NULL) {
>> printf("!!! eth_set_current(): conditional 2\n");
>> char *ethprime = env_get("ethprime");
>> void *dev = NULL;
>>
>> if (ethprime)
>> {
>> printf("!!! eth_set_current(): conditional 3\n");
>> dev = eth_get_dev_by_name(ethprime);
>> }
>> if (dev)
>> {
>> printf("!!! eth_set_current(): conditional 4\n");
>> eth_set_dev(dev);
>> }
>> else
>> {
>> printf("!!! eth_set_current(): conditional 5\n");
>> eth_set_dev(NULL);
>> }
>> } else {
>> printf("!!! eth_set_current(): conditional 6\n");
>> eth_set_dev(eth_get_dev_by_name(act));
>> }
>>
>> eth_current_changed();
>> printf("!!! eth_set_current(): leaving function\n");
>> }
>>
>> Hopefully this is enough to make sense of it? Let me know, thanks!
>>
>> -E
>
> Postscript I've narrowed it down a bit to net/lwip/net-lwip.c:new_netif()
> where returning from eth_init() the eth_get_dev() is the second interface
> (with network cable plugged in) but variable reference udev is still the
> first interface (with no network cable) when the call to lwip_init() is made.
> So lwip_init() tries and fails on the first interface even though we already
> know from eth_init() which interface is valid and ready.
>
> So that is what is happening but I don't know what you would want to do to
> fix this?
Perhaps eth_init() has to be called before eth_set_current()/
eth_get_dev()? Can you please try the following patch:
---8<-------8<-------8<-------8<-------8<-------8<-------8<----
diff --git a/net/lwip/net-lwip.c b/net/lwip/net-lwip.c
index b863047f598..a6fb3824af1 100644
--- a/net/lwip/net-lwip.c
+++ b/net/lwip/net-lwip.c
@@ -127,18 +127,10 @@ static int get_udev_ipv4_info(struct udevice *dev,
ip4_addr_t *ip,
return 0;
}
-static struct netif *new_netif(struct udevice *udev, bool with_ip)
+static void net_lwip_init(void)
{
- unsigned char enetaddr[ARP_HLEN];
- char hwstr[MAC_ADDR_STRLEN];
- ip4_addr_t ip, mask, gw;
- struct netif *netif;
- int ret = 0;
static bool first_call = true;
- if (!udev)
- return NULL;
-
if (first_call) {
eth_init_rings();
/* Pick a valid active device, if any */
@@ -146,6 +138,18 @@ static struct netif *new_netif(struct udevice *udev, bool
with_ip)
lwip_init();
first_call = false;
}
+}
+
+static struct netif *new_netif(struct udevice *udev, bool with_ip)
+{
+ unsigned char enetaddr[ARP_HLEN];
+ char hwstr[MAC_ADDR_STRLEN];
+ ip4_addr_t ip, mask, gw;
+ struct netif *netif;
+ int ret = 0;
+
+ if (!udev)
+ return NULL;
if (eth_start_udev(udev) < 0) {
log_err("Could not start %s\n", udev->name);
@@ -198,11 +202,15 @@ static struct netif *new_netif(struct udevice *udev, bool
with_ip)
struct netif *net_lwip_new_netif(struct udevice *udev)
{
+ net_lwip_init();
+
return new_netif(udev, true);
}
struct netif *net_lwip_new_netif_noip(struct udevice *udev)
{
+ net_lwip_init();
+
return new_netif(udev, false);
}
---8<-------8<-------8<-------8<-------8<-------8<-------8<----
Thanks,
--
Jerome