Hello Marc,

On 7/24/19 10:26 AM, Marc Kleine-Budde wrote:
> On 4/29/19 2:03 PM, Jeroen Hofstee wrote:
>> As already mentioned in [1] and included in [2], there is an off by one
>> issue since the high bank is already enabled when the _next_ mailbox to
>> be read has index 12, so the mailbox being read was 13. The message can
>> therefore go into mailbox 31 and the driver will be repolled until the
>> mailbox 12 eventually receives a msg. Or the message might end up in the
>> 12th mailbox, but then it would become disabled after reading it and only
>> be enabled again in the next "round" after mailbox 13 was read, which can
>> cause out of order messages, since the lower priority mailboxes can
>> accept messages in the meantime.
>>
>> As mentioned in [3] there is a hardware race condition when changing the
>> CANME register while messages are being received. Even when including a
>> busy poll on reception, like in [2] there are still overflows and out of
>> order messages at times, but less then without the busy loop polling.
>> Unlike what the patch suggests, the polling time is not in the microsecond
>> range, but takes as long as a current CAN bus reception needs to finish,
>> so typically more in the fraction of millisecond range. Since the timeout
>> is in jiffies it won't timeout.
>>
>> Even with these additional fixes the driver is still not able to provide a
>> proper FIFO which doesn't drop packages. So change the driver to use
>> rx-offload and base order on timestamp instead of message box numbers. As
>> a side affect, this also fixes [4] and [5].
>>
>> Before this change messages with a single byte counter were dropped /
>> received out of order at a bitrate of 250kbit/s on an am3517. With this
>> patch that no longer occurs up to and including 1Mbit/s.
>>
>> [1] 
>> https://linux-can.vger.kernel.narkive.com/zgO9inVi/patch-can-ti-hecc-fix-rx-wrong-sequence-issue#post6
>> [2] 
>> http://arago-project.org/git/projects/?p=linux-omap3.git;a=commit;h=02346892777f07245de4d5af692513ebd852dcb2
>> [3] 
>> https://linux-can.vger.kernel.narkive.com/zgO9inVi/patch-can-ti-hecc-fix-rx-wrong-sequence-issue#post5
>> [4] https://patchwork.ozlabs.org/patch/895956/
>> [5] https://www.spinics.net/lists/netdev/msg494971.html
>>
>> Cc: Anant Gole <anantg...@ti.com>
>> Cc: AnilKumar Ch <anilku...@ti.com>
>> Signed-off-by: Jeroen Hofstee <jhofs...@victronenergy.com>
>> ---
>>   drivers/net/can/ti_hecc.c | 189 
>> +++++++++++++---------------------------------
>>   1 file changed, 53 insertions(+), 136 deletions(-)
>>
>> diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c
>> index db6ea93..fe7ffff 100644
>> --- a/drivers/net/can/ti_hecc.c
>> +++ b/drivers/net/can/ti_hecc.c
>> @@ -5,6 +5,7 @@
>>    * specs for the same is available at <http://www.ti.com>
>>    *
>>    * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
>> + * Copyright (C) 2019 Jeroen Hofstee <jhofs...@victronenergy.com>
>>    *
>>    * This program is free software; you can redistribute it and/or
>>    * modify it under the terms of the GNU General Public License as
>> @@ -34,6 +35,7 @@
>>   #include <linux/can/dev.h>
>>   #include <linux/can/error.h>
>>   #include <linux/can/led.h>
>> +#include <linux/can/rx-offload.h>
>>   
>>   #define DRV_NAME "ti_hecc"
>>   #define HECC_MODULE_VERSION     "0.7"
>> @@ -63,29 +65,16 @@ MODULE_VERSION(HECC_MODULE_VERSION);
>>   #define HECC_TX_PRIO_MASK  (MAX_TX_PRIO << HECC_MB_TX_SHIFT)
>>   #define HECC_TX_MB_MASK            (HECC_MAX_TX_MBOX - 1)
>>   #define HECC_TX_MASK               ((HECC_MAX_TX_MBOX - 1) | 
>> HECC_TX_PRIO_MASK)
>> -#define HECC_TX_MBOX_MASK   (~(BIT(HECC_MAX_TX_MBOX) - 1))
>> -#define HECC_DEF_NAPI_WEIGHT        HECC_MAX_RX_MBOX
>>   
>>   /*
>> - * Important Note: RX mailbox configuration
>> - * RX mailboxes are further logically split into two - main and buffer
>> - * mailboxes. The goal is to get all packets into main mailboxes as
>> - * driven by mailbox number and receive priority (higher to lower) and
>> - * buffer mailboxes are used to receive pkts while main mailboxes are being
>> - * processed. This ensures in-order packet reception.
>> - *
>> - * Here are the recommended values for buffer mailbox. Note that RX 
>> mailboxes
>> - * start after TX mailboxes:
>> - *
>> - * HECC_MAX_RX_MBOX         HECC_RX_BUFFER_MBOX     No of buffer mailboxes
>> - * 28                               12                      8
>> - * 16                               20                      4
>> + * RX mailbox configuration
>> + * The remaining mailboxes are used for reception and are delivered based on
>> + * their timestamp, to avoid a hardware race when CANME is changed while
>> + * CAN-bus traffix is being received.
>>    */
>>   
>>   #define HECC_MAX_RX_MBOX   (HECC_MAX_MAILBOXES - HECC_MAX_TX_MBOX)
>> -#define HECC_RX_BUFFER_MBOX 12 /* as per table above */
>>   #define HECC_RX_FIRST_MBOX (HECC_MAX_MAILBOXES - 1)
>> -#define HECC_RX_HIGH_MBOX_MASK      (~(BIT(HECC_RX_BUFFER_MBOX) - 1))
>>   
>>   /* TI HECC module registers */
>>   #define HECC_CANME         0x0     /* Mailbox enable */
>> @@ -123,6 +112,8 @@ MODULE_VERSION(HECC_MODULE_VERSION);
>>   #define HECC_CANMDL                0x8
>>   #define HECC_CANMDH                0xC
>>   
>> +#define HECC_CANMOTS                0x100
> It's actually 0x80
>
>> +
>>   #define HECC_SET_REG               0xFFFFFFFF
>>   #define HECC_CANID_MASK            0x3FF   /* 18 bits mask for extended 
>> id's */
>>   #define HECC_CCE_WAIT_COUNT     100        /* Wait for ~1 sec for CCE bit 
>> */
>> @@ -193,7 +184,7 @@ static const struct can_bittiming_const 
>> ti_hecc_bittiming_const = {
>>   
>>   struct ti_hecc_priv {
>>      struct can_priv can;    /* MUST be first member/field */
>> -    struct napi_struct napi;
>> +    struct can_rx_offload offload;
>>      struct net_device *ndev;
>>      struct clk *clk;
>>      void __iomem *base;
>> @@ -203,7 +194,6 @@ struct ti_hecc_priv {
>>      spinlock_t mbx_lock; /* CANME register needs protection */
>>      u32 tx_head;
>>      u32 tx_tail;
>> -    u32 rx_next;
>>      struct regulator *reg_xceiver;
>>   };
>>   
>> @@ -265,6 +255,11 @@ static inline u32 hecc_get_bit(struct ti_hecc_priv 
>> *priv, int reg, u32 bit_mask)
>>      return (hecc_read(priv, reg) & bit_mask) ? 1 : 0;
>>   }
>>   
>> +static inline u32 hecc_read_stamp(struct ti_hecc_priv *priv, u32 mbxno)
>> +{
>> +    return __raw_readl(priv->hecc_ram + 0x80 + 4 * mbxno);
> I've changed this function to use HECC_CANMOTS.
>

That is correct. For completeness the HECC_CANMOTS wasn't
even used in the original patch, so there is no functional difference.

Thanks,

Jeroen


Reply via email to