All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] FEC and EFI Simple Network
@ 2018-03-27 12:12 Patrick Wildt
  2018-03-28 21:54 ` Fabio Estevam
  0 siblings, 1 reply; 6+ messages in thread
From: Patrick Wildt @ 2018-03-27 12:12 UTC (permalink / raw)
  To: u-boot

Hi,

I have been debugging network issues when running an EFI Application
that uses the EFI Simple Network protocol on an i.MX6 machine (FEC).

The symptom is that u-boot's (FEC) internal RX ring index is reset to 0,
while the controller is still at idx 3 (or something else).  This is
caused by the following circumstances:

The Simple Network protocol offers methods like Start(), Stop(),
Initialize(), Shutdown(), Reset().  Also the protocol has a state.  The
states are Stopped, Started, Initialized.  The transition is as follows:

Stopped ---Start()---> Started ---Initialize()--> Initialized

Start() does some initialization, Initialize() allocates the TX/RX
descriptors and actually kicks off the network engine.

So far, only Initialize() is implemented in our u-boot interface, and it
calls eth_init() which in the end calls fec_init().  Our network state
is _always_ Started.  This means that EFI Applications see that that the
state is Started and then call Initialize() to start the actual network
traffic.  There is no call to Stop()/Shutdown()/Reset() as it's supposed
to be in a sane state.

In my case the FEC is already initialized since I booted using network
and the RX desc index is already non-zero.  Now the EFI Application sees
that the state is Started, calls Initialize() which makes u-boot call
eth_init() which then calls fec_init().

fec_init() does not reset the controller so that the controller-internal
RX desc index is not reset to zero.  fec_init() calls fec_open() which
then resets the driver-internal RX desc index to zero.  Now they are out
of sync, boom.

This means that fec_init() without a previous fec_halt() breaks the
whole network if it was already running.  The Designware driver as used
by some sunxi platforms does a reset of the controller in the init
function.  Maybe calling fec_halt() at the start of fec_init() could be
a possible solution?

Patrick

diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index ff7ad91116..ba8bd9920d 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -522,6 +522,12 @@ static int fec_open(struct eth_device *edev)
 	return 0;
 }
 
+#ifdef CONFIG_DM_ETH
+static void fecmxc_halt(struct udevice *dev);
+#else
+static void fec_halt(struct eth_device *dev);
+#endif
+
 #ifdef CONFIG_DM_ETH
 static int fecmxc_init(struct udevice *dev)
 #else
@@ -537,6 +543,15 @@ static int fec_init(struct eth_device *dev, bd_t *bd)
 	u8 *i;
 	ulong addr;
 
+#ifdef CONFIG_DM_ETH
+	fecmxc_halt(dev);
+#else
+	fec_halt(dev);
+#endif
+
+	writel(~FEC_TCNTRL_GTS & readl(&fec->eth->x_cntrl),
+	       &fec->eth->x_cntrl);
+
 	/* Initialize MAC address */
 #ifdef CONFIG_DM_ETH
 	fecmxc_set_hwaddr(dev);
@@ -825,19 +840,12 @@ static int fec_recv(struct eth_device *dev)
 	}
 	if (ievent & FEC_IEVENT_HBERR) {
 		/* Heartbeat error */
-		writel(0x00000001 | readl(&fec->eth->x_cntrl),
+		writel(FEC_TCNTRL_GTS | readl(&fec->eth->x_cntrl),
 		       &fec->eth->x_cntrl);
 	}
 	if (ievent & FEC_IEVENT_GRA) {
 		/* Graceful stop complete */
-		if (readl(&fec->eth->x_cntrl) & 0x00000001) {
-#ifdef CONFIG_DM_ETH
-			fecmxc_halt(dev);
-#else
-			fec_halt(dev);
-#endif
-			writel(~0x00000001 & readl(&fec->eth->x_cntrl),
-			       &fec->eth->x_cntrl);
+		if (readl(&fec->eth->x_cntrl) & FEC_TCNTRL_GTS) {
 #ifdef CONFIG_DM_ETH
 			fecmxc_init(dev);
 #else

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

* [U-Boot] FEC and EFI Simple Network
  2018-03-27 12:12 [U-Boot] FEC and EFI Simple Network Patrick Wildt
@ 2018-03-28 21:54 ` Fabio Estevam
  2018-03-29  4:02   ` Joe Hershberger
  0 siblings, 1 reply; 6+ messages in thread
From: Fabio Estevam @ 2018-03-28 21:54 UTC (permalink / raw)
  To: u-boot

Adding Joe in case he has some ideas.

On Tue, Mar 27, 2018 at 9:12 AM, Patrick Wildt <patrick@blueri.se> wrote:
> Hi,
>
> I have been debugging network issues when running an EFI Application
> that uses the EFI Simple Network protocol on an i.MX6 machine (FEC).
>
> The symptom is that u-boot's (FEC) internal RX ring index is reset to 0,
> while the controller is still at idx 3 (or something else).  This is
> caused by the following circumstances:
>
> The Simple Network protocol offers methods like Start(), Stop(),
> Initialize(), Shutdown(), Reset().  Also the protocol has a state.  The
> states are Stopped, Started, Initialized.  The transition is as follows:
>
> Stopped ---Start()---> Started ---Initialize()--> Initialized
>
> Start() does some initialization, Initialize() allocates the TX/RX
> descriptors and actually kicks off the network engine.
>
> So far, only Initialize() is implemented in our u-boot interface, and it
> calls eth_init() which in the end calls fec_init().  Our network state
> is _always_ Started.  This means that EFI Applications see that that the
> state is Started and then call Initialize() to start the actual network
> traffic.  There is no call to Stop()/Shutdown()/Reset() as it's supposed
> to be in a sane state.
>
> In my case the FEC is already initialized since I booted using network
> and the RX desc index is already non-zero.  Now the EFI Application sees
> that the state is Started, calls Initialize() which makes u-boot call
> eth_init() which then calls fec_init().
>
> fec_init() does not reset the controller so that the controller-internal
> RX desc index is not reset to zero.  fec_init() calls fec_open() which
> then resets the driver-internal RX desc index to zero.  Now they are out
> of sync, boom.
>
> This means that fec_init() without a previous fec_halt() breaks the
> whole network if it was already running.  The Designware driver as used
> by some sunxi platforms does a reset of the controller in the init
> function.  Maybe calling fec_halt() at the start of fec_init() could be
> a possible solution?
>
> Patrick
>
> diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
> index ff7ad91116..ba8bd9920d 100644
> --- a/drivers/net/fec_mxc.c
> +++ b/drivers/net/fec_mxc.c
> @@ -522,6 +522,12 @@ static int fec_open(struct eth_device *edev)
>         return 0;
>  }
>
> +#ifdef CONFIG_DM_ETH
> +static void fecmxc_halt(struct udevice *dev);
> +#else
> +static void fec_halt(struct eth_device *dev);
> +#endif
> +
>  #ifdef CONFIG_DM_ETH
>  static int fecmxc_init(struct udevice *dev)
>  #else
> @@ -537,6 +543,15 @@ static int fec_init(struct eth_device *dev, bd_t *bd)
>         u8 *i;
>         ulong addr;
>
> +#ifdef CONFIG_DM_ETH
> +       fecmxc_halt(dev);
> +#else
> +       fec_halt(dev);
> +#endif
> +
> +       writel(~FEC_TCNTRL_GTS & readl(&fec->eth->x_cntrl),
> +              &fec->eth->x_cntrl);
> +
>         /* Initialize MAC address */
>  #ifdef CONFIG_DM_ETH
>         fecmxc_set_hwaddr(dev);
> @@ -825,19 +840,12 @@ static int fec_recv(struct eth_device *dev)
>         }
>         if (ievent & FEC_IEVENT_HBERR) {
>                 /* Heartbeat error */
> -               writel(0x00000001 | readl(&fec->eth->x_cntrl),
> +               writel(FEC_TCNTRL_GTS | readl(&fec->eth->x_cntrl),
>                        &fec->eth->x_cntrl);
>         }
>         if (ievent & FEC_IEVENT_GRA) {
>                 /* Graceful stop complete */
> -               if (readl(&fec->eth->x_cntrl) & 0x00000001) {
> -#ifdef CONFIG_DM_ETH
> -                       fecmxc_halt(dev);
> -#else
> -                       fec_halt(dev);
> -#endif
> -                       writel(~0x00000001 & readl(&fec->eth->x_cntrl),
> -                              &fec->eth->x_cntrl);
> +               if (readl(&fec->eth->x_cntrl) & FEC_TCNTRL_GTS) {
>  #ifdef CONFIG_DM_ETH
>                         fecmxc_init(dev);
>  #else
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot

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

* [U-Boot] FEC and EFI Simple Network
  2018-03-28 21:54 ` Fabio Estevam
@ 2018-03-29  4:02   ` Joe Hershberger
  2018-12-02 21:42     ` Alexander Graf
  0 siblings, 1 reply; 6+ messages in thread
From: Joe Hershberger @ 2018-03-29  4:02 UTC (permalink / raw)
  To: u-boot

Hi Patrick,

On Wed, Mar 28, 2018 at 4:54 PM, Fabio Estevam <festevam@gmail.com> wrote:
> Adding Joe in case he has some ideas.
>
> On Tue, Mar 27, 2018 at 9:12 AM, Patrick Wildt <patrick@blueri.se> wrote:
>> Hi,
>>
>> I have been debugging network issues when running an EFI Application
>> that uses the EFI Simple Network protocol on an i.MX6 machine (FEC).
>>
>> The symptom is that u-boot's (FEC) internal RX ring index is reset to 0,
>> while the controller is still at idx 3 (or something else).  This is
>> caused by the following circumstances:
>>
>> The Simple Network protocol offers methods like Start(), Stop(),
>> Initialize(), Shutdown(), Reset().  Also the protocol has a state.  The
>> states are Stopped, Started, Initialized.  The transition is as follows:
>>
>> Stopped ---Start()---> Started ---Initialize()--> Initialized
>>
>> Start() does some initialization, Initialize() allocates the TX/RX
>> descriptors and actually kicks off the network engine.
>>
>> So far, only Initialize() is implemented in our u-boot interface, and it
>> calls eth_init() which in the end calls fec_init().  Our network state
>> is _always_ Started.  This means that EFI Applications see that that the
>> state is Started and then call Initialize() to start the actual network
>> traffic.  There is no call to Stop()/Shutdown()/Reset() as it's supposed
>> to be in a sane state.
>>
>> In my case the FEC is already initialized since I booted using network
>> and the RX desc index is already non-zero.  Now the EFI Application sees
>> that the state is Started, calls Initialize() which makes u-boot call
>> eth_init() which then calls fec_init().
>>
>> fec_init() does not reset the controller so that the controller-internal
>> RX desc index is not reset to zero.  fec_init() calls fec_open() which
>> then resets the driver-internal RX desc index to zero.  Now they are out
>> of sync, boom.

Would it be reasonable for fec_init to use a state variable to keep
track of if it (and the HW) is already initialized and not call
fec_open in that case? Also, fec_halt would need to update that state
as well.

>>
>> This means that fec_init() without a previous fec_halt() breaks the
>> whole network if it was already running.  The Designware driver as used
>> by some sunxi platforms does a reset of the controller in the init
>> function.  Maybe calling fec_halt() at the start of fec_init() could be
>> a possible solution?
>>
>> Patrick
>>
>> diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
>> index ff7ad91116..ba8bd9920d 100644
>> --- a/drivers/net/fec_mxc.c
>> +++ b/drivers/net/fec_mxc.c
>> @@ -522,6 +522,12 @@ static int fec_open(struct eth_device *edev)
>>         return 0;
>>  }
>>
>> +#ifdef CONFIG_DM_ETH
>> +static void fecmxc_halt(struct udevice *dev);
>> +#else
>> +static void fec_halt(struct eth_device *dev);
>> +#endif
>> +
>>  #ifdef CONFIG_DM_ETH
>>  static int fecmxc_init(struct udevice *dev)
>>  #else
>> @@ -537,6 +543,15 @@ static int fec_init(struct eth_device *dev, bd_t *bd)
>>         u8 *i;
>>         ulong addr;
>>
>> +#ifdef CONFIG_DM_ETH
>> +       fecmxc_halt(dev);
>> +#else
>> +       fec_halt(dev);
>> +#endif
>> +
>> +       writel(~FEC_TCNTRL_GTS & readl(&fec->eth->x_cntrl),
>> +              &fec->eth->x_cntrl);
>> +
>>         /* Initialize MAC address */
>>  #ifdef CONFIG_DM_ETH
>>         fecmxc_set_hwaddr(dev);
>> @@ -825,19 +840,12 @@ static int fec_recv(struct eth_device *dev)
>>         }
>>         if (ievent & FEC_IEVENT_HBERR) {
>>                 /* Heartbeat error */
>> -               writel(0x00000001 | readl(&fec->eth->x_cntrl),
>> +               writel(FEC_TCNTRL_GTS | readl(&fec->eth->x_cntrl),
>>                        &fec->eth->x_cntrl);
>>         }
>>         if (ievent & FEC_IEVENT_GRA) {
>>                 /* Graceful stop complete */
>> -               if (readl(&fec->eth->x_cntrl) & 0x00000001) {
>> -#ifdef CONFIG_DM_ETH
>> -                       fecmxc_halt(dev);
>> -#else
>> -                       fec_halt(dev);
>> -#endif
>> -                       writel(~0x00000001 & readl(&fec->eth->x_cntrl),
>> -                              &fec->eth->x_cntrl);
>> +               if (readl(&fec->eth->x_cntrl) & FEC_TCNTRL_GTS) {
>>  #ifdef CONFIG_DM_ETH
>>                         fecmxc_init(dev);
>>  #else
>> _______________________________________________
>> U-Boot mailing list
>> U-Boot at lists.denx.de
>> https://lists.denx.de/listinfo/u-boot
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot

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

* [U-Boot] FEC and EFI Simple Network
  2018-03-29  4:02   ` Joe Hershberger
@ 2018-12-02 21:42     ` Alexander Graf
  2019-02-23 14:23       ` Alexander Graf
  0 siblings, 1 reply; 6+ messages in thread
From: Alexander Graf @ 2018-12-02 21:42 UTC (permalink / raw)
  To: u-boot



On 29.03.18 06:02, Joe Hershberger wrote:
> Hi Patrick,
> 
> On Wed, Mar 28, 2018 at 4:54 PM, Fabio Estevam <festevam@gmail.com> wrote:
>> Adding Joe in case he has some ideas.
>>
>> On Tue, Mar 27, 2018 at 9:12 AM, Patrick Wildt <patrick@blueri.se> wrote:
>>> Hi,
>>>
>>> I have been debugging network issues when running an EFI Application
>>> that uses the EFI Simple Network protocol on an i.MX6 machine (FEC).
>>>
>>> The symptom is that u-boot's (FEC) internal RX ring index is reset to 0,
>>> while the controller is still at idx 3 (or something else).  This is
>>> caused by the following circumstances:
>>>
>>> The Simple Network protocol offers methods like Start(), Stop(),
>>> Initialize(), Shutdown(), Reset().  Also the protocol has a state.  The
>>> states are Stopped, Started, Initialized.  The transition is as follows:
>>>
>>> Stopped ---Start()---> Started ---Initialize()--> Initialized
>>>
>>> Start() does some initialization, Initialize() allocates the TX/RX
>>> descriptors and actually kicks off the network engine.
>>>
>>> So far, only Initialize() is implemented in our u-boot interface, and it
>>> calls eth_init() which in the end calls fec_init().  Our network state
>>> is _always_ Started.  This means that EFI Applications see that that the
>>> state is Started and then call Initialize() to start the actual network
>>> traffic.  There is no call to Stop()/Shutdown()/Reset() as it's supposed
>>> to be in a sane state.
>>>
>>> In my case the FEC is already initialized since I booted using network
>>> and the RX desc index is already non-zero.  Now the EFI Application sees
>>> that the state is Started, calls Initialize() which makes u-boot call
>>> eth_init() which then calls fec_init().
>>>
>>> fec_init() does not reset the controller so that the controller-internal
>>> RX desc index is not reset to zero.  fec_init() calls fec_open() which
>>> then resets the driver-internal RX desc index to zero.  Now they are out
>>> of sync, boom.
> 
> Would it be reasonable for fec_init to use a state variable to keep
> track of if it (and the HW) is already initialized and not call
> fec_open in that case? Also, fec_halt would need to update that state
> as well.

Ping? Is this still an issue?


Alex

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

* [U-Boot] FEC and EFI Simple Network
  2018-12-02 21:42     ` Alexander Graf
@ 2019-02-23 14:23       ` Alexander Graf
  2019-02-24  4:48         ` Heinrich Schuchardt
  0 siblings, 1 reply; 6+ messages in thread
From: Alexander Graf @ 2019-02-23 14:23 UTC (permalink / raw)
  To: u-boot



On 02.12.18 22:42, Alexander Graf wrote:
> 
> 
> On 29.03.18 06:02, Joe Hershberger wrote:
>> Hi Patrick,
>>
>> On Wed, Mar 28, 2018 at 4:54 PM, Fabio Estevam <festevam@gmail.com> wrote:
>>> Adding Joe in case he has some ideas.
>>>
>>> On Tue, Mar 27, 2018 at 9:12 AM, Patrick Wildt <patrick@blueri.se> wrote:
>>>> Hi,
>>>>
>>>> I have been debugging network issues when running an EFI Application
>>>> that uses the EFI Simple Network protocol on an i.MX6 machine (FEC).
>>>>
>>>> The symptom is that u-boot's (FEC) internal RX ring index is reset to 0,
>>>> while the controller is still at idx 3 (or something else).  This is
>>>> caused by the following circumstances:
>>>>
>>>> The Simple Network protocol offers methods like Start(), Stop(),
>>>> Initialize(), Shutdown(), Reset().  Also the protocol has a state.  The
>>>> states are Stopped, Started, Initialized.  The transition is as follows:
>>>>
>>>> Stopped ---Start()---> Started ---Initialize()--> Initialized
>>>>
>>>> Start() does some initialization, Initialize() allocates the TX/RX
>>>> descriptors and actually kicks off the network engine.
>>>>
>>>> So far, only Initialize() is implemented in our u-boot interface, and it
>>>> calls eth_init() which in the end calls fec_init().  Our network state
>>>> is _always_ Started.  This means that EFI Applications see that that the
>>>> state is Started and then call Initialize() to start the actual network
>>>> traffic.  There is no call to Stop()/Shutdown()/Reset() as it's supposed
>>>> to be in a sane state.
>>>>
>>>> In my case the FEC is already initialized since I booted using network
>>>> and the RX desc index is already non-zero.  Now the EFI Application sees
>>>> that the state is Started, calls Initialize() which makes u-boot call
>>>> eth_init() which then calls fec_init().
>>>>
>>>> fec_init() does not reset the controller so that the controller-internal
>>>> RX desc index is not reset to zero.  fec_init() calls fec_open() which
>>>> then resets the driver-internal RX desc index to zero.  Now they are out
>>>> of sync, boom.
>>
>> Would it be reasonable for fec_init to use a state variable to keep
>> track of if it (and the HW) is already initialized and not call
>> fec_open in that case? Also, fec_halt would need to update that state
>> as well.
> 
> Ping? Is this still an issue?

Last Ping.


Alex

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

* [U-Boot] FEC and EFI Simple Network
  2019-02-23 14:23       ` Alexander Graf
@ 2019-02-24  4:48         ` Heinrich Schuchardt
  0 siblings, 0 replies; 6+ messages in thread
From: Heinrich Schuchardt @ 2019-02-24  4:48 UTC (permalink / raw)
  To: u-boot

On 2/23/19 3:23 PM, Alexander Graf wrote:
> 
> 
> On 02.12.18 22:42, Alexander Graf wrote:
>>
>>
>> On 29.03.18 06:02, Joe Hershberger wrote:
>>> Hi Patrick,
>>>
>>> On Wed, Mar 28, 2018 at 4:54 PM, Fabio Estevam <festevam@gmail.com> wrote:
>>>> Adding Joe in case he has some ideas.
>>>>
>>>> On Tue, Mar 27, 2018 at 9:12 AM, Patrick Wildt <patrick@blueri.se> wrote:
>>>>> Hi,
>>>>>
>>>>> I have been debugging network issues when running an EFI Application
>>>>> that uses the EFI Simple Network protocol on an i.MX6 machine (FEC).
>>>>>
>>>>> The symptom is that u-boot's (FEC) internal RX ring index is reset to 0,
>>>>> while the controller is still at idx 3 (or something else).  This is
>>>>> caused by the following circumstances:
>>>>>
>>>>> The Simple Network protocol offers methods like Start(), Stop(),
>>>>> Initialize(), Shutdown(), Reset().  Also the protocol has a state.  The
>>>>> states are Stopped, Started, Initialized.  The transition is as follows:
>>>>>
>>>>> Stopped ---Start()---> Started ---Initialize()--> Initialized
>>>>>
>>>>> Start() does some initialization, Initialize() allocates the TX/RX
>>>>> descriptors and actually kicks off the network engine.
>>>>>
>>>>> So far, only Initialize() is implemented in our u-boot interface, and it
>>>>> calls eth_init() which in the end calls fec_init().  Our network state
>>>>> is _always_ Started.  This means that EFI Applications see that that the
>>>>> state is Started and then call Initialize() to start the actual network
>>>>> traffic.  There is no call to Stop()/Shutdown()/Reset() as it's supposed
>>>>> to be in a sane state.
>>>>>
>>>>> In my case the FEC is already initialized since I booted using network
>>>>> and the RX desc index is already non-zero.  Now the EFI Application sees
>>>>> that the state is Started, calls Initialize() which makes u-boot call
>>>>> eth_init() which then calls fec_init().
>>>>>
>>>>> fec_init() does not reset the controller so that the controller-internal
>>>>> RX desc index is not reset to zero.  fec_init() calls fec_open() which
>>>>> then resets the driver-internal RX desc index to zero.  Now they are out
>>>>> of sync, boom.
>>>
>>> Would it be reasonable for fec_init to use a state variable to keep
>>> track of if it (and the HW) is already initialized and not call
>>> fec_open in that case? Also, fec_halt would need to update that state
>>> as well.
>>
>> Ping? Is this still an issue?
> 
> Last Ping.
> 
> 
> Alex
> 

With commit 0c5d2a3dac01 ("efi_loader: completely initialize network")
we changed efi_net_initialize() from only calling eth_init() to execute
the following sequence:

        /* Setup packet buffers */
        net_init();
        /* Disable hardware and put it into the reset state */
        eth_halt();
        /* Set current device according to environment variables */
        eth_set_current();
        /* Get hardware ready for send and receive operations */
        ret = eth_init();

So I am wondering if our additional call to eth_halt() shouldn't have
fixed the problem that Patrick originally reported.

Best regards

Heinrich

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

end of thread, other threads:[~2019-02-24  4:48 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-27 12:12 [U-Boot] FEC and EFI Simple Network Patrick Wildt
2018-03-28 21:54 ` Fabio Estevam
2018-03-29  4:02   ` Joe Hershberger
2018-12-02 21:42     ` Alexander Graf
2019-02-23 14:23       ` Alexander Graf
2019-02-24  4:48         ` Heinrich Schuchardt

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.