On 11/11/19 11:36 AM, Joakim Zhang wrote: >> - What did you do before wakeup? >> - Clean reboot? >> - ifdown/ifup? > > Clean boot Fine, so the chip should fill mailbox 0 first. > Sender side: > ip link set can0 up type can bitrate 1000000 > echo enabled > /sys/bus/platform/drivers/flexcan/30a10000.caower/wakeup > candump can0 & > echo mem > /sys/power/state > > Receive side: > ip link set can0 up type can bitrate 1000000 > cangen can0 -vv > >> - sending other packets? > No. >> - Does this happen on every wakeup? > Yes. >> - Is the wake up frame always "received" as 6th frame? > No, different with different frame gap. If the frame gap is unchanged, does the order change? >> - Is the situation the same, if you add some delay between the frames, >> using the "cangen -g option"? > The situation is different with different "cangen -g option" >> - How big can you make the -g until the frames are received in order >> again? > I am not sure, I can do a test later. > >> The reception path works like this: >> In the interrupt handler the rx-offload reads all mailboxes based on the iflag >> register. It iterates over all set mailboxes, starting with the first. All mailboxes >> are read including the rx-timestamp, sorted and added into a queue. At the end >> of the IRQ handler the queue is added to the per device queue thats read in the >> NAPI and pushed into the networking stack. >> >> Maybe something with the timestamp of the first packet is wrong, as the >> counter is only 16 bits wide, it will overflow quite often. >> >> Maybe you can trace_printk the mailbox number, timestamp and can_id in >> mailbox_read() and analyse output after wakeup. Feel free to post the output >> of the tracer here. > > I also suspect this, but I check the flow of the receive path is the > same with v4.14 and v4.19. > > Another thing confused me is that how does the driver handle the > counter overflow. If the counter overflow in one round mailbox read, > the receive order is not consistent with reality. I do not the handle > of this case in driver. The overflow handling consists of two tricks: 1) Make the 16 bit timestamp a 32 bit one: https://elixir.bootlin.com/linux/latest/source/drivers/net/can/flexcan.c#L800 2) Subtract two u32 timestamps and treat result as (singed) int. A u32 overflows at 2^32 = 4294967295 = 0xffffffff 2^32 + 1 = 1 = 0x00000001 A s32 overflows 2147483647 to -2147483648 = 0x7fffffff to 0x80000000. Let's assume one frame arrives at: 0xfffffffe and the next one 0x00000002. The difference from new to old is -4: 0x00000002 - 0xfffffffe = 0xfffffffc Interpreting 0xfffffffc as a signed value means -4. The trick basically moves the overflow from 0xffffffff to 0x7fffffff. https://elixir.bootlin.com/linux/latest/source/drivers/net/can/rx-offload.c#L107 > I will use the trace_printk() to post the output here. Marc -- Pengutronix e.K. | Marc Kleine-Budde | Embedded Linux | https://www.pengutronix.de | Vertretung West/Dortmund | Phone: +49-231-2826-924 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
Attachment:
signature.asc
Description: OpenPGP digital signature