All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH] net: eth: Do sanity test on eth dev before eth_get_ops(dev)->start
@ 2015-09-06  2:38 Bin Meng
  2015-09-08 15:32 ` Joe Hershberger
  0 siblings, 1 reply; 9+ messages in thread
From: Bin Meng @ 2015-09-06  2:38 UTC (permalink / raw)
  To: u-boot

In eth_init(), eth_get_dev() can return NULL. We should do sanity
test on eth dev before calling its start function.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
---

 net/eth.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/net/eth.c b/net/eth.c
index 26520d3..6ec3a86 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -370,6 +370,10 @@ int eth_init(void)
 		eth_try_another(0);
 		/* This will ensure the new "current" attempted to probe */
 		current = eth_get_dev();
+		if (!current) {
+			printf("No ethernet found.\n");
+			break;
+		}
 	} while (old_current != current);
 
 	return ret;
-- 
1.8.2.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [U-Boot] [PATCH] net: eth: Do sanity test on eth dev before eth_get_ops(dev)->start
  2015-09-06  2:38 [U-Boot] [PATCH] net: eth: Do sanity test on eth dev before eth_get_ops(dev)->start Bin Meng
@ 2015-09-08 15:32 ` Joe Hershberger
  2015-09-08 15:44   ` Bin Meng
  0 siblings, 1 reply; 9+ messages in thread
From: Joe Hershberger @ 2015-09-08 15:32 UTC (permalink / raw)
  To: u-boot

Hi Bin,

On Sat, Sep 5, 2015 at 9:38 PM, Bin Meng <bmeng.cn@gmail.com> wrote:
> In eth_init(), eth_get_dev() can return NULL. We should do sanity
> test on eth dev before calling its start function.
>
> Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
> ---
>
>  net/eth.c | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/net/eth.c b/net/eth.c
> index 26520d3..6ec3a86 100644
> --- a/net/eth.c
> +++ b/net/eth.c
> @@ -370,6 +370,10 @@ int eth_init(void)
>                 eth_try_another(0);
>                 /* This will ensure the new "current" attempted to probe */
>                 current = eth_get_dev();
> +               if (!current) {
> +                       printf("No ethernet found.\n");
> +                       break;
> +               }

I'm not sure I get the point of this. We already have a check above...

        current = eth_get_dev();
        if (!current) {
                printf("No ethernet found.\n");
                return -ENODEV;
        }

>         } while (old_current != current);
>
>         return ret;
> --
> 1.8.2.1
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [U-Boot] [PATCH] net: eth: Do sanity test on eth dev before eth_get_ops(dev)->start
  2015-09-08 15:32 ` Joe Hershberger
@ 2015-09-08 15:44   ` Bin Meng
  2015-09-08 16:01     ` Joe Hershberger
  0 siblings, 1 reply; 9+ messages in thread
From: Bin Meng @ 2015-09-08 15:44 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On Tue, Sep 8, 2015 at 11:32 PM, Joe Hershberger
<joe.hershberger@gmail.com> wrote:
> Hi Bin,
>
> On Sat, Sep 5, 2015 at 9:38 PM, Bin Meng <bmeng.cn@gmail.com> wrote:
>> In eth_init(), eth_get_dev() can return NULL. We should do sanity
>> test on eth dev before calling its start function.
>>
>> Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
>> ---
>>
>>  net/eth.c | 4 ++++
>>  1 file changed, 4 insertions(+)
>>
>> diff --git a/net/eth.c b/net/eth.c
>> index 26520d3..6ec3a86 100644
>> --- a/net/eth.c
>> +++ b/net/eth.c
>> @@ -370,6 +370,10 @@ int eth_init(void)
>>                 eth_try_another(0);
>>                 /* This will ensure the new "current" attempted to probe */
>>                 current = eth_get_dev();
>> +               if (!current) {
>> +                       printf("No ethernet found.\n");
>> +                       break;
>> +               }
>
> I'm not sure I get the point of this. We already have a check above...
>
>         current = eth_get_dev();
>         if (!current) {
>                 printf("No ethernet found.\n");
>                 return -ENODEV;
>         }
>

But this does not help. Each time eth_get_dev() is called, current can
be NULL as driver's probe can fail.

>>         } while (old_current != current);
>>
>>         return ret;
>> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [U-Boot] [PATCH] net: eth: Do sanity test on eth dev before eth_get_ops(dev)->start
  2015-09-08 15:44   ` Bin Meng
@ 2015-09-08 16:01     ` Joe Hershberger
  2015-09-08 16:24       ` Bin Meng
  0 siblings, 1 reply; 9+ messages in thread
From: Joe Hershberger @ 2015-09-08 16:01 UTC (permalink / raw)
  To: u-boot

Hi Bin,

On Tue, Sep 8, 2015 at 10:44 AM, Bin Meng <bmeng.cn@gmail.com> wrote:
> Hi Joe,
>
> On Tue, Sep 8, 2015 at 11:32 PM, Joe Hershberger
> <joe.hershberger@gmail.com> wrote:
>> Hi Bin,
>>
>> On Sat, Sep 5, 2015 at 9:38 PM, Bin Meng <bmeng.cn@gmail.com> wrote:
>>> In eth_init(), eth_get_dev() can return NULL. We should do sanity
>>> test on eth dev before calling its start function.
>>>
>>> Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
>>> ---
>>>
>>>  net/eth.c | 4 ++++
>>>  1 file changed, 4 insertions(+)
>>>
>>> diff --git a/net/eth.c b/net/eth.c
>>> index 26520d3..6ec3a86 100644
>>> --- a/net/eth.c
>>> +++ b/net/eth.c
>>> @@ -370,6 +370,10 @@ int eth_init(void)
>>>                 eth_try_another(0);
>>>                 /* This will ensure the new "current" attempted to probe */
>>>                 current = eth_get_dev();
>>> +               if (!current) {
>>> +                       printf("No ethernet found.\n");
>>> +                       break;
>>> +               }
>>
>> I'm not sure I get the point of this. We already have a check above...
>>
>>         current = eth_get_dev();
>>         if (!current) {
>>                 printf("No ethernet found.\n");
>>                 return -ENODEV;
>>         }
>>
>
> But this does not help. Each time eth_get_dev() is called, current can
> be NULL as driver's probe can fail.

If that's the issue you are hitting it seems like you should attempt
to skip the device instead of printing the message. It doesn't make
sense to me to move to the next device and then print that there is no
Ethernet.

Also, this is fundamental to the eth subsystem. You should add a unit
test that fails in your case.

>>>         } while (old_current != current);
>>>
>>>         return ret;
>>> --
>
> Regards,
> Bin

Thanks,
-Joe

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [U-Boot] [PATCH] net: eth: Do sanity test on eth dev before eth_get_ops(dev)->start
  2015-09-08 16:01     ` Joe Hershberger
@ 2015-09-08 16:24       ` Bin Meng
  2015-09-08 17:23         ` Joe Hershberger
  0 siblings, 1 reply; 9+ messages in thread
From: Bin Meng @ 2015-09-08 16:24 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On Wed, Sep 9, 2015 at 12:01 AM, Joe Hershberger
<joe.hershberger@gmail.com> wrote:
> Hi Bin,
>
> On Tue, Sep 8, 2015 at 10:44 AM, Bin Meng <bmeng.cn@gmail.com> wrote:
>> Hi Joe,
>>
>> On Tue, Sep 8, 2015 at 11:32 PM, Joe Hershberger
>> <joe.hershberger@gmail.com> wrote:
>>> Hi Bin,
>>>
>>> On Sat, Sep 5, 2015 at 9:38 PM, Bin Meng <bmeng.cn@gmail.com> wrote:
>>>> In eth_init(), eth_get_dev() can return NULL. We should do sanity
>>>> test on eth dev before calling its start function.
>>>>
>>>> Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
>>>> ---
>>>>
>>>>  net/eth.c | 4 ++++
>>>>  1 file changed, 4 insertions(+)
>>>>
>>>> diff --git a/net/eth.c b/net/eth.c
>>>> index 26520d3..6ec3a86 100644
>>>> --- a/net/eth.c
>>>> +++ b/net/eth.c
>>>> @@ -370,6 +370,10 @@ int eth_init(void)
>>>>                 eth_try_another(0);
>>>>                 /* This will ensure the new "current" attempted to probe */
>>>>                 current = eth_get_dev();
>>>> +               if (!current) {
>>>> +                       printf("No ethernet found.\n");
>>>> +                       break;
>>>> +               }
>>>
>>> I'm not sure I get the point of this. We already have a check above...
>>>
>>>         current = eth_get_dev();
>>>         if (!current) {
>>>                 printf("No ethernet found.\n");
>>>                 return -ENODEV;
>>>         }
>>>
>>
>> But this does not help. Each time eth_get_dev() is called, current can
>> be NULL as driver's probe can fail.
>
> If that's the issue you are hitting it seems like you should attempt
> to skip the device instead of printing the message. It doesn't make
> sense to me to move to the next device and then print that there is no
> Ethernet.

Do you mean we should not printf("No ethernet found.\n") and just break here?

If it fails, U-Boot just crashes as there is a NULL pointer. I am not
sure if test case is able to handle this?

>
> Also, this is fundamental to the eth subsystem. You should add a unit
> test that fails in your case.
>
>>>>         } while (old_current != current);
>>>>
>>>>         return ret;
>>>> --
>>

Regards,
Bin

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [U-Boot] [PATCH] net: eth: Do sanity test on eth dev before eth_get_ops(dev)->start
  2015-09-08 16:24       ` Bin Meng
@ 2015-09-08 17:23         ` Joe Hershberger
  2015-09-09  3:19           ` Bin Meng
  0 siblings, 1 reply; 9+ messages in thread
From: Joe Hershberger @ 2015-09-08 17:23 UTC (permalink / raw)
  To: u-boot

Hi Bin,

On Tue, Sep 8, 2015 at 11:24 AM, Bin Meng <bmeng.cn@gmail.com> wrote:
> Hi Joe,
>
> On Wed, Sep 9, 2015 at 12:01 AM, Joe Hershberger
> <joe.hershberger@gmail.com> wrote:
>> Hi Bin,
>>
>> On Tue, Sep 8, 2015 at 10:44 AM, Bin Meng <bmeng.cn@gmail.com> wrote:
>>> Hi Joe,
>>>
>>> On Tue, Sep 8, 2015 at 11:32 PM, Joe Hershberger
>>> <joe.hershberger@gmail.com> wrote:
>>>> Hi Bin,
>>>>
>>>> On Sat, Sep 5, 2015 at 9:38 PM, Bin Meng <bmeng.cn@gmail.com> wrote:
>>>>> In eth_init(), eth_get_dev() can return NULL. We should do sanity
>>>>> test on eth dev before calling its start function.
>>>>>
>>>>> Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
>>>>> ---
>>>>>
>>>>>  net/eth.c | 4 ++++
>>>>>  1 file changed, 4 insertions(+)
>>>>>
>>>>> diff --git a/net/eth.c b/net/eth.c
>>>>> index 26520d3..6ec3a86 100644
>>>>> --- a/net/eth.c
>>>>> +++ b/net/eth.c
>>>>> @@ -370,6 +370,10 @@ int eth_init(void)
>>>>>                 eth_try_another(0);
>>>>>                 /* This will ensure the new "current" attempted to probe */
>>>>>                 current = eth_get_dev();
>>>>> +               if (!current) {
>>>>> +                       printf("No ethernet found.\n");
>>>>> +                       break;
>>>>> +               }
>>>>
>>>> I'm not sure I get the point of this. We already have a check above...
>>>>
>>>>         current = eth_get_dev();
>>>>         if (!current) {
>>>>                 printf("No ethernet found.\n");
>>>>                 return -ENODEV;
>>>>         }
>>>>
>>>
>>> But this does not help. Each time eth_get_dev() is called, current can
>>> be NULL as driver's probe can fail.
>>
>> If that's the issue you are hitting it seems like you should attempt
>> to skip the device instead of printing the message. It doesn't make
>> sense to me to move to the next device and then print that there is no
>> Ethernet.
>
> Do you mean we should not printf("No ethernet found.\n") and just break here?

I think you shouldn't break, but rather should have an if check around
the top half of the loop. I.e.:

diff --git a/net/eth.c b/net/eth.c
index d3ec8d6..78ffb5f 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -343,23 +343,27 @@ int eth_init(void)

        old_current = current;
        do {
-               debug("Trying %s\n", current->name);
-
-               if (device_active(current)) {
-                       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;
+               if (current) {
+                       debug("Trying %s\n", current->name);
+
+                       if (device_active(current)) {
+                               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");
                } else {
-                       ret = eth_errno;
+                       debug("PROBE FAIL\n");
                }

-               debug("FAIL\n");
-
                /*
                 * If ethrotate is enabled, this will change "current",
                 * otherwise we will drop out of this while loop immediately
---

Note that I have not tested this, it's just what I'm thinking is more
appropriate.

> If it fails, U-Boot just crashes as there is a NULL pointer. I am not
> sure if test case is able to handle this?

I think it's good to have the a test that hits your scenario. The bug
fix will prevent the crash, so it's not like we expect it to crash,
but it will lock down the desired behavior for this condition.

>> Also, this is fundamental to the eth subsystem. You should add a unit
>> test that fails in your case.
>>
>>>>>         } while (old_current != current);
>>>>>
>>>>>         return ret;
>>>>> --
>>>
>
> Regards,
> Bin

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [U-Boot] [PATCH] net: eth: Do sanity test on eth dev before eth_get_ops(dev)->start
  2015-09-08 17:23         ` Joe Hershberger
@ 2015-09-09  3:19           ` Bin Meng
  2015-09-09  6:14             ` Bin Meng
  0 siblings, 1 reply; 9+ messages in thread
From: Bin Meng @ 2015-09-09  3:19 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On Wed, Sep 9, 2015 at 1:23 AM, Joe Hershberger
<joe.hershberger@gmail.com> wrote:
> Hi Bin,
>
> On Tue, Sep 8, 2015 at 11:24 AM, Bin Meng <bmeng.cn@gmail.com> wrote:
>> Hi Joe,
>>
>> On Wed, Sep 9, 2015 at 12:01 AM, Joe Hershberger
>> <joe.hershberger@gmail.com> wrote:
>>> Hi Bin,
>>>
>>> On Tue, Sep 8, 2015 at 10:44 AM, Bin Meng <bmeng.cn@gmail.com> wrote:
>>>> Hi Joe,
>>>>
>>>> On Tue, Sep 8, 2015 at 11:32 PM, Joe Hershberger
>>>> <joe.hershberger@gmail.com> wrote:
>>>>> Hi Bin,
>>>>>
>>>>> On Sat, Sep 5, 2015 at 9:38 PM, Bin Meng <bmeng.cn@gmail.com> wrote:
>>>>>> In eth_init(), eth_get_dev() can return NULL. We should do sanity
>>>>>> test on eth dev before calling its start function.
>>>>>>
>>>>>> Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
>>>>>> ---
>>>>>>
>>>>>>  net/eth.c | 4 ++++
>>>>>>  1 file changed, 4 insertions(+)
>>>>>>
>>>>>> diff --git a/net/eth.c b/net/eth.c
>>>>>> index 26520d3..6ec3a86 100644
>>>>>> --- a/net/eth.c
>>>>>> +++ b/net/eth.c
>>>>>> @@ -370,6 +370,10 @@ int eth_init(void)
>>>>>>                 eth_try_another(0);
>>>>>>                 /* This will ensure the new "current" attempted to probe */
>>>>>>                 current = eth_get_dev();
>>>>>> +               if (!current) {
>>>>>> +                       printf("No ethernet found.\n");
>>>>>> +                       break;
>>>>>> +               }
>>>>>
>>>>> I'm not sure I get the point of this. We already have a check above...
>>>>>
>>>>>         current = eth_get_dev();
>>>>>         if (!current) {
>>>>>                 printf("No ethernet found.\n");
>>>>>                 return -ENODEV;
>>>>>         }
>>>>>
>>>>
>>>> But this does not help. Each time eth_get_dev() is called, current can
>>>> be NULL as driver's probe can fail.
>>>
>>> If that's the issue you are hitting it seems like you should attempt
>>> to skip the device instead of printing the message. It doesn't make
>>> sense to me to move to the next device and then print that there is no
>>> Ethernet.
>>
>> Do you mean we should not printf("No ethernet found.\n") and just break here?
>
> I think you shouldn't break, but rather should have an if check around
> the top half of the loop. I.e.:
>
> diff --git a/net/eth.c b/net/eth.c
> index d3ec8d6..78ffb5f 100644
> --- a/net/eth.c
> +++ b/net/eth.c
> @@ -343,23 +343,27 @@ int eth_init(void)
>
>         old_current = current;
>         do {
> -               debug("Trying %s\n", current->name);
> -
> -               if (device_active(current)) {
> -                       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;
> +               if (current) {
> +                       debug("Trying %s\n", current->name);
> +
> +                       if (device_active(current)) {
> +                               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");
>                 } else {
> -                       ret = eth_errno;
> +                       debug("PROBE FAIL\n");
>                 }
>
> -               debug("FAIL\n");
> -
>                 /*
>                  * If ethrotate is enabled, this will change "current",
>                  * otherwise we will drop out of this while loop immediately
> ---
>
> Note that I have not tested this, it's just what I'm thinking is more
> appropriate.
>
>> If it fails, U-Boot just crashes as there is a NULL pointer. I am not
>> sure if test case is able to handle this?
>
> I think it's good to have the a test that hits your scenario. The bug
> fix will prevent the crash, so it's not like we expect it to crash,
> but it will lock down the desired behavior for this condition.
>

I am afraid creating a test case to cover this scenario is not that
easy. Checking function return value does not bring any harm. It makes
our codes safer. In fact, during further debug today, I found another
two places which does not check device_probe() return value. And it is
indeed these two places which causes the subsequent failure here.

>>> Also, this is fundamental to the eth subsystem. You should add a unit
>>> test that fails in your case.
>>>
>>>>>>         } while (old_current != current);
>>>>>>
>>>>>>         return ret;
>>>>>> --
>>>>
>>

Regards,
Bin

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [U-Boot] [PATCH] net: eth: Do sanity test on eth dev before eth_get_ops(dev)->start
  2015-09-09  3:19           ` Bin Meng
@ 2015-09-09  6:14             ` Bin Meng
  2015-09-10 22:47               ` Joe Hershberger
  0 siblings, 1 reply; 9+ messages in thread
From: Bin Meng @ 2015-09-09  6:14 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On Wed, Sep 9, 2015 at 11:19 AM, Bin Meng <bmeng.cn@gmail.com> wrote:
> Hi Joe,
>
> On Wed, Sep 9, 2015 at 1:23 AM, Joe Hershberger
> <joe.hershberger@gmail.com> wrote:
>> Hi Bin,
>>
>> On Tue, Sep 8, 2015 at 11:24 AM, Bin Meng <bmeng.cn@gmail.com> wrote:
>>> Hi Joe,
>>>
>>> On Wed, Sep 9, 2015 at 12:01 AM, Joe Hershberger
>>> <joe.hershberger@gmail.com> wrote:
>>>> Hi Bin,
>>>>
>>>> On Tue, Sep 8, 2015 at 10:44 AM, Bin Meng <bmeng.cn@gmail.com> wrote:
>>>>> Hi Joe,
>>>>>
>>>>> On Tue, Sep 8, 2015 at 11:32 PM, Joe Hershberger
>>>>> <joe.hershberger@gmail.com> wrote:
>>>>>> Hi Bin,
>>>>>>
>>>>>> On Sat, Sep 5, 2015 at 9:38 PM, Bin Meng <bmeng.cn@gmail.com> wrote:
>>>>>>> In eth_init(), eth_get_dev() can return NULL. We should do sanity
>>>>>>> test on eth dev before calling its start function.
>>>>>>>
>>>>>>> Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
>>>>>>> ---
>>>>>>>
>>>>>>>  net/eth.c | 4 ++++
>>>>>>>  1 file changed, 4 insertions(+)
>>>>>>>
>>>>>>> diff --git a/net/eth.c b/net/eth.c
>>>>>>> index 26520d3..6ec3a86 100644
>>>>>>> --- a/net/eth.c
>>>>>>> +++ b/net/eth.c
>>>>>>> @@ -370,6 +370,10 @@ int eth_init(void)
>>>>>>>                 eth_try_another(0);
>>>>>>>                 /* This will ensure the new "current" attempted to probe */
>>>>>>>                 current = eth_get_dev();
>>>>>>> +               if (!current) {
>>>>>>> +                       printf("No ethernet found.\n");
>>>>>>> +                       break;
>>>>>>> +               }
>>>>>>
>>>>>> I'm not sure I get the point of this. We already have a check above...
>>>>>>
>>>>>>         current = eth_get_dev();
>>>>>>         if (!current) {
>>>>>>                 printf("No ethernet found.\n");
>>>>>>                 return -ENODEV;
>>>>>>         }
>>>>>>
>>>>>
>>>>> But this does not help. Each time eth_get_dev() is called, current can
>>>>> be NULL as driver's probe can fail.
>>>>
>>>> If that's the issue you are hitting it seems like you should attempt
>>>> to skip the device instead of printing the message. It doesn't make
>>>> sense to me to move to the next device and then print that there is no
>>>> Ethernet.
>>>
>>> Do you mean we should not printf("No ethernet found.\n") and just break here?
>>
>> I think you shouldn't break, but rather should have an if check around
>> the top half of the loop. I.e.:
>>
>> diff --git a/net/eth.c b/net/eth.c
>> index d3ec8d6..78ffb5f 100644
>> --- a/net/eth.c
>> +++ b/net/eth.c
>> @@ -343,23 +343,27 @@ int eth_init(void)
>>
>>         old_current = current;
>>         do {
>> -               debug("Trying %s\n", current->name);
>> -
>> -               if (device_active(current)) {
>> -                       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;
>> +               if (current) {
>> +                       debug("Trying %s\n", current->name);
>> +
>> +                       if (device_active(current)) {
>> +                               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");
>>                 } else {
>> -                       ret = eth_errno;
>> +                       debug("PROBE FAIL\n");
>>                 }
>>
>> -               debug("FAIL\n");
>> -
>>                 /*
>>                  * If ethrotate is enabled, this will change "current",
>>                  * otherwise we will drop out of this while loop immediately
>> ---
>>
>> Note that I have not tested this, it's just what I'm thinking is more
>> appropriate.
>>
>>> If it fails, U-Boot just crashes as there is a NULL pointer. I am not
>>> sure if test case is able to handle this?
>>
>> I think it's good to have the a test that hits your scenario. The bug
>> fix will prevent the crash, so it's not like we expect it to crash,
>> but it will lock down the desired behavior for this condition.
>>
>
> I am afraid creating a test case to cover this scenario is not that
> easy. Checking function return value does not bring any harm. It makes
> our codes safer. In fact, during further debug today, I found another
> two places which does not check device_probe() return value. And it is
> indeed these two places which causes the subsequent failure here.
>

OK, I've found a way in the DM test codes to trigger this fault, but
unfortunately by creating this test case I've found another potential
issue. I will send a v2 patch for all of these.

Regards,
Bin

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [U-Boot] [PATCH] net: eth: Do sanity test on eth dev before eth_get_ops(dev)->start
  2015-09-09  6:14             ` Bin Meng
@ 2015-09-10 22:47               ` Joe Hershberger
  0 siblings, 0 replies; 9+ messages in thread
From: Joe Hershberger @ 2015-09-10 22:47 UTC (permalink / raw)
  To: u-boot

Hi Bin,

On Wed, Sep 9, 2015 at 1:14 AM, Bin Meng <bmeng.cn@gmail.com> wrote:
> Hi Joe,
>
> On Wed, Sep 9, 2015 at 11:19 AM, Bin Meng <bmeng.cn@gmail.com> wrote:
>> Hi Joe,
>>
>> On Wed, Sep 9, 2015 at 1:23 AM, Joe Hershberger
>> <joe.hershberger@gmail.com> wrote:
>>> Hi Bin,
>>>
>>> On Tue, Sep 8, 2015 at 11:24 AM, Bin Meng <bmeng.cn@gmail.com> wrote:
>>>> Hi Joe,
>>>>
>>>> On Wed, Sep 9, 2015 at 12:01 AM, Joe Hershberger
>>>> <joe.hershberger@gmail.com> wrote:
>>>>> Hi Bin,
>>>>>
>>>>> On Tue, Sep 8, 2015 at 10:44 AM, Bin Meng <bmeng.cn@gmail.com> wrote:
>>>>>> Hi Joe,
>>>>>>
>>>>>> On Tue, Sep 8, 2015 at 11:32 PM, Joe Hershberger
>>>>>> <joe.hershberger@gmail.com> wrote:
>>>>>>> Hi Bin,
>>>>>>>
>>>>>>> On Sat, Sep 5, 2015 at 9:38 PM, Bin Meng <bmeng.cn@gmail.com> wrote:
>>>>>>>> In eth_init(), eth_get_dev() can return NULL. We should do sanity
>>>>>>>> test on eth dev before calling its start function.
>>>>>>>>
>>>>>>>> Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
>>>>>>>> ---
>>>>>>>>
>>>>>>>>  net/eth.c | 4 ++++
>>>>>>>>  1 file changed, 4 insertions(+)
>>>>>>>>
>>>>>>>> diff --git a/net/eth.c b/net/eth.c
>>>>>>>> index 26520d3..6ec3a86 100644
>>>>>>>> --- a/net/eth.c
>>>>>>>> +++ b/net/eth.c
>>>>>>>> @@ -370,6 +370,10 @@ int eth_init(void)
>>>>>>>>                 eth_try_another(0);
>>>>>>>>                 /* This will ensure the new "current" attempted to probe */
>>>>>>>>                 current = eth_get_dev();
>>>>>>>> +               if (!current) {
>>>>>>>> +                       printf("No ethernet found.\n");
>>>>>>>> +                       break;
>>>>>>>> +               }
>>>>>>>
>>>>>>> I'm not sure I get the point of this. We already have a check above...
>>>>>>>
>>>>>>>         current = eth_get_dev();
>>>>>>>         if (!current) {
>>>>>>>                 printf("No ethernet found.\n");
>>>>>>>                 return -ENODEV;
>>>>>>>         }
>>>>>>>
>>>>>>
>>>>>> But this does not help. Each time eth_get_dev() is called, current can
>>>>>> be NULL as driver's probe can fail.
>>>>>
>>>>> If that's the issue you are hitting it seems like you should attempt
>>>>> to skip the device instead of printing the message. It doesn't make
>>>>> sense to me to move to the next device and then print that there is no
>>>>> Ethernet.
>>>>
>>>> Do you mean we should not printf("No ethernet found.\n") and just break here?
>>>
>>> I think you shouldn't break, but rather should have an if check around
>>> the top half of the loop. I.e.:
>>>
>>> diff --git a/net/eth.c b/net/eth.c
>>> index d3ec8d6..78ffb5f 100644
>>> --- a/net/eth.c
>>> +++ b/net/eth.c
>>> @@ -343,23 +343,27 @@ int eth_init(void)
>>>
>>>         old_current = current;
>>>         do {
>>> -               debug("Trying %s\n", current->name);
>>> -
>>> -               if (device_active(current)) {
>>> -                       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;
>>> +               if (current) {
>>> +                       debug("Trying %s\n", current->name);
>>> +
>>> +                       if (device_active(current)) {
>>> +                               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");
>>>                 } else {
>>> -                       ret = eth_errno;
>>> +                       debug("PROBE FAIL\n");
>>>                 }
>>>
>>> -               debug("FAIL\n");
>>> -
>>>                 /*
>>>                  * If ethrotate is enabled, this will change "current",
>>>                  * otherwise we will drop out of this while loop immediately
>>> ---
>>>
>>> Note that I have not tested this, it's just what I'm thinking is more
>>> appropriate.
>>>
>>>> If it fails, U-Boot just crashes as there is a NULL pointer. I am not
>>>> sure if test case is able to handle this?
>>>
>>> I think it's good to have the a test that hits your scenario. The bug
>>> fix will prevent the crash, so it's not like we expect it to crash,
>>> but it will lock down the desired behavior for this condition.
>>>
>>
>> I am afraid creating a test case to cover this scenario is not that
>> easy. Checking function return value does not bring any harm. It makes
>> our codes safer. In fact, during further debug today, I found another
>> two places which does not check device_probe() return value. And it is
>> indeed these two places which causes the subsequent failure here.
>>
>
> OK, I've found a way in the DM test codes to trigger this fault, but
> unfortunately by creating this test case I've found another potential
> issue. I will send a v2 patch for all of these.

Thanks for looking into this.

Cheers,
-Joe

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2015-09-10 22:47 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-06  2:38 [U-Boot] [PATCH] net: eth: Do sanity test on eth dev before eth_get_ops(dev)->start Bin Meng
2015-09-08 15:32 ` Joe Hershberger
2015-09-08 15:44   ` Bin Meng
2015-09-08 16:01     ` Joe Hershberger
2015-09-08 16:24       ` Bin Meng
2015-09-08 17:23         ` Joe Hershberger
2015-09-09  3:19           ` Bin Meng
2015-09-09  6:14             ` Bin Meng
2015-09-10 22:47               ` Joe Hershberger

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.