Hi,

On 1/6/25 20:09, E Shattow wrote:
> 
> 
> On 1/6/25 07:43, Jerome Forissier wrote:
>>
>>
>> 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,
> 
> Testing with commands:
> 
> env set test_url http://ipv4.download.thinkbroadband.com/5MB.zip
> echo "TEST dhcp"
> dhcp
> echo "TEST wget"
> wget ${test_url}
> echo "TEST dhcp"
> dhcp
> echo "TEST wget"
> wget ${test_url}
> 
> env set test_url http://ipv4.download.thinkbroadband.com/5MB.zip;echo "TEST 
> dhcp";dhcp;echo "TEST wget";wget ${test_url};echo "TEST dhcp";dhcp;echo "TEST 
> wget";wget ${test_url}
> 
> # Without patch, board power-on for network cable in ethernet@16030000:
> TEST dhcp
> ethernet@16030000 Waiting for PHY auto negotiation to complete...... done
> DHCP client bound to address 192.168.2.51 (568 ms)
> TEST wget
> ##################################################
> 5242880 bytes transferred in 2632 ms (1.9 MiB/s)
> Bytes transferred = 5242880 (500000 hex)
> TEST dhcp
> DHCP client bound to address 192.168.2.51 (255 ms)
> TEST wget
> ##################################################
> 5242880 bytes transferred in 10763 ms (475.6 KiB/s)
> Bytes transferred = 5242880 (500000 hex)
> 
> 
> # With patch, board power-on for network cable in ethernet@16030000:
> TEST dhcp
> ethernet@16030000 Waiting for PHY auto negotiation to complete...... done
> DHCP client bound to address 192.168.2.51 (620 ms)
> TEST wget
> ##################################################
> 5242880 bytes transferred in 1580 ms (3.2 MiB/s)
> Bytes transferred = 5242880 (500000 hex)
> TEST dhcp
> DHCP client bound to address 192.168.2.51 (42 ms)
> TEST wget
> ##################################################
> 5242880 bytes transferred in 1580 ms (3.2 MiB/s)
> Bytes transferred = 5242880 (500000 hex)
> 
> 
> # Without patch, board power-on for network cable in ethernet@16040000:
> TEST 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
> TEST wget
> TEST dhcp
> DHCP client bound to address 192.168.2.77 (33 ms)
> TEST wget
> ##################################################
> 5242880 bytes transferred in 1490 ms (3.4 MiB/s)
> Bytes transferred = 5242880 (500000 hex)
> 
> 
> # With patch, board power-on for network cable in ethernet@16040000:
> TEST 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
> TEST wget
> TEST dhcp
> DHCP client bound to address 192.168.2.77 (24 ms)
> TEST wget
> ##################################################
> 5242880 bytes transferred in 1938 ms (2.6 MiB/s)
> Bytes transferred = 5242880 (500000 hex)
> 
> 
> This appears no change in outcome with patch applied?

Please check [1] and let me know if it works for you.

[1] https://lists.denx.de/pipermail/u-boot/2025-January/578982.html

Thanks,
-- 
Jerome
> 
> -E

Reply via email to