[U-Boot] FEC and EFI Simple Network
Joe Hershberger
joe.hershberger at ni.com
Thu Mar 29 04:02:22 UTC 2018
Hi Patrick,
On Wed, Mar 28, 2018 at 4:54 PM, Fabio Estevam <festevam at gmail.com> wrote:
> Adding Joe in case he has some ideas.
>
> On Tue, Mar 27, 2018 at 9:12 AM, Patrick Wildt <patrick at 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
More information about the U-Boot
mailing list