On 07/25/2010 04:23 PM, Wolfgang Grandegger wrote:
> On 07/25/2010 03:35 PM, Marc Kleine-Budde wrote:
>> Wolfgang Grandegger wrote:
>>> I found some time to work on this issue.
>>>
>>> So far we only report CAN error state changes to the worse:
>>> "error-active -> error-warning -> error-passive -> bus-off", but not
>>> "bus-off -> error-active" or "error-passive -> error-warning ->
>>> error-active". There have been request from other users to correct
>>> this behavior.
>>>
>>> This patch reports any state change reported by the SJA1000 and
>>> MSCAN-MPC5200 controller. It introduces "CAN_ERR_CRTL_ACTIVE" to
>>> signal state changes to error active. Furthermore, the SJA1000
>>> triggers now the bus-off recovery procedure when restarted. So far,
>>> the controller was *stopped* and then restarted. I did two tests to
>>> analyze the state changes behavior:
>>>
>>> 1. First I forced the controller into the error-passive by sending
>>>    a message (with cansend) without cable connected (*). Then I
>>>    reconnected the cable (**) and continued to send messages (with
>>>    cangen) (***) until the error active state is reached:
>>>
>>>    On SJA1000:
>>>
>>>    # candump any,0:0,#FFFFFFFF
>>>    (*)
>>>    can0  20000004  [8] 00 08 00 00 00 00 60 00   ERROR-WARNING
>>>    can0  20000004  [8] 00 20 00 00 00 00 80 00   ERROR-PASSIVE
>>>    (**)
>>>    can0  123  [4] DE AD BE EF
>>>    (***)
>>>    can0  42A  [1] 00
>>>    ...
>>>    can0  42A  [1] 07
>>>    can0  20000004  [8] 00 08 00 00 00 00 7F 00   ERROR-WARNING
>>
>> Is it possible to tell apart whether the driver goes from passive to
>> warning or from active to warning? Without the need to have a state
>> machine in userspace, too?
> 
> Yes, I realized that side effect as well. The user must monitor state
> changes to understand if the state gets worse or better. We could use an
> error bit to indicate state improvements.
> 
>> Looking at the tx/rx error level might be an option, but I've seen that
>> the level can rise very quickly.
> 
> Be aware that the tx/rx error counters are *not* readable on all CAN
> controllers.
> 
>>>    can0  42A  [1] 08
>>>    ...
>>>    can0  42A  [1] 27
>>>    can0  20000004  [8] 00 40 00 00 00 00 5F 00   ERROR-ACTIVE
>>>                                           \-- tx-err !!!
>>>    On MSCAN:
>>>
>>>    # candump any,0:0,#FFFFFFFF
>>>    (*)
>>>    can2  20000004  [8] 00 08 00 00 00 00 00 00   ERROR-WARNING
>>>    can2  20000004  [8] 00 20 00 00 00 00 00 00   ERROR-PASSIVE
>>>    (**)
>>>    can2  123  [4] DE AD BE EF
>>>    can2  20000004  [8] 00 08 00 00 00 00 00 00   ERROR-WARNING
>>>    (***)
>>>    can2  42A  [1] 00
>>>    can2  42A  [1] 01
>>>    ...
>>>    can2  42A  [1] 1E
>>>    can2  42A  [1] 1F
>>>    can2  20000004  [8] 00 40 00 00 00 00 00 00   ERROR-ACTIVE
>>>
>>>    As you can see, the state change to error-active is signaled
>>>    differently. The MSCAN seems not to respect the specs :-(.
>>
>> Do you mean the fact that error active is signalled with tx err == 0?
> 
> Yes, the SJA1000 triggers an interrupt to signal error active when the
> error counter goes below 96.
> 
>> From the patch below you only changed the part of the driver that runs
>> if a change of state is detected "(old_state != priv->can.state)".
>>
>> Maybe it's a problem in the driver, that calculated the new state wrong.
>> Maybe due to a problem with the hardware. (I don't know the driver nor
>> the hardware).
> 
> I monitored the interrupt generation as well:
> 
> [ 1234.089446] mpc5xxx_can f0000900.can: error interrupt (canrflg=0x44)
> [ 1234.092228] mpc5xxx_can f0000900.can: error interrupt (canrflg=0x48)
> [ 1240.960487] mpc5xxx_can f0000900.can: error interrupt (canrflg=0x44)
> [ 1352.336647] mpc5xxx_can f0000900.can: error interrupt (canrflg=0x40)
> 
> The last interrupt comes that late, even if the state is misinterpreted.
> Note also that the MSCAN has a dedicated state field for TX and RX.
> Therefore the state is defined without a state machine in software.
> 
>> Looking at you patches below I want to rise my old proposal again. I
>> think we should move the state machine that assembles and sends the
>> error frames into a common function. Each driver just needs to have a
>> proper function that calculates the current state and then call the
>> state handling state machine.
> 
> The error handling code is already quite large and complex, especially
> for the purpose it serves. Any common function improving that situation
> would be nice. But unfortunately, we rely on the hardware :-(.
> 
>>>    When time permits, I will also try the MSCAN of the MPC5121.
>>
>>> 2. I forced the controller into bus-off by short-circuiting
>>>    the low and hi lines and sending a message (*), Then I
>>>    restarted the controller manually with
>>>    "ip link set can0 type can restart" (**):
>>>
>>>    On SJA1000:
>>>
>>>    # ./candump -t d any,0:0,#FFFFFFFF
>>>    (*)
>>>    can0  20000004  [8] 00 08 00 00 00 00 88 00   ERROR-WARNING
>>>    can0  20000004  [8] 00 20 00 00 00 00 88 00   ERROR-PASSIVE
>>>    can0  20000044  [8] 00 00 00 00 00 00 7F 00   BUS-OFF
>>>    (**)
>>>    can0  20000100  [8] 00 00 00 00 00 00 00 00   RESTARTED
>>>    can0  20000004  [8] 00 40 00 00 00 00 00 00   ERROR-ACTIVE
>>>                                           \-- tx-err !!!
>>>
>>>    On MSCAN:
>>>
>>>    # ./candump -t d any,0:0,#FFFFFFFF
>>>    (*)
>>>    can2  20000004  [8] 00 08 00 00 00 00 00 00   ERROR-WARNING
>>>    can2  20000040  [8] 00 00 00 00 00 00 00 00   BUS-OFF
>>>    (**)
>>>    can2  20000100  [8] 00 00 00 00 00 00 00 00   RESTARTED
>>>    can2  20000004  [8] 00 40 00 00 00 00 00 00   ERROR-ACTIVE
>>>
>>>    The MSCAN seems not to signal the ERROR-PASSIVE state before
>>>    going bus-off.
>>
>> I think the signalling of ERROR-PASSIVE depends on multiple things:
>> - the current bitrate.
>>   I think this doesn't count so much in this short circuit test.
>> - the CAN hardware itself: does it signal this "in-the-middle-passive"
>>   interrupt
>> - overall speed and load of your system:
>>   reaction time on interrupts,
>>   is your system fast enough to handle these two back-to-back interrupts
>>   as two single events
>> - driver design, i.e.
>> - is the state change signalled from the hard-irq or from napi:
>>   the second interrupt may occur somewhere between hardirq and napi,
>>   so napi just sees bus off
>> - design of the error state machine:
>>   in the at91 and flexcan I always send a warning interrupt if going
>>   from active to passive.
>>
>> The last point is another argument for a common state machine.
> 
> Well, yes, a common state handling function would be nice, but as the
> hardware is not really smart, a simple state machine is not enough. It's
> not just reading the current state and check if it has changed. Have a
> look to the SJA1000 and MSCAN driver, e.g.:
> 
>         if (isrc & IRQ_EPI) {
>                 /* error passive interrupt */
>                 dev_dbg(dev->dev.parent, "error passive interrupt\n",
>                         status);
>                 if (status & SR_ES) {
>                         if (priv->can.state == CAN_STATE_ERROR_WARNING)
>                                 state = CAN_STATE_ERROR_PASSIVE;
>                         else
>                                 state = CAN_STATE_ERROR_WARNING;
>                 } else {
>                         state = CAN_STATE_ERROR_ACTIVE;
>                 }
>         }
> 
> No need for another state machine. But a common function is still useful
> to fill an error frame for the state change, of course. I will try to
> come up with a proposal soon.


  int can_handle_state_change(struct net_device *dev,
                              struct can_frame *cf,
                              enum can_state new_state,
                              u16 tx_err, u16 rx_err)

If "tx_err" or "rx_err == -1", they are ignored. If "new_state ==
CAN_STATE_UNKNOWN", the state could be derived from tx_err or rx_err.
What do you think?

Wolfgang.
_______________________________________________
Socketcan-core mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/socketcan-core

Reply via email to