diff options
| author | Thomas Gleixner <tglx@linutronix.de> | 2014-04-11 04:13:12 -0400 |
|---|---|---|
| committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2014-04-24 16:08:56 -0400 |
| commit | f058d548e8071a1d148d6ebd94888d011c3ca71e (patch) | |
| tree | 57640ef92b3896fc7801f0443cbbf441fdf17085 | |
| parent | 9c64863a49bd23c5a3a983680eb500f7796c81be (diff) | |
can: c_can: Handle state change correctly
If the allocation of an error skb fails, the state change handling
returns w/o doing any work. That leaves the interface in a wreckaged
state as the internal status is wrong.
Split the interface handling and the skb handling.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Alexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
| -rw-r--r-- | drivers/net/can/c_can/c_can.c | 25 |
1 files changed, 20 insertions, 5 deletions
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 603876109ba8..246bcf92558c 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c | |||
| @@ -914,6 +914,26 @@ static int c_can_handle_state_change(struct net_device *dev, | |||
| 914 | struct sk_buff *skb; | 914 | struct sk_buff *skb; |
| 915 | struct can_berr_counter bec; | 915 | struct can_berr_counter bec; |
| 916 | 916 | ||
| 917 | switch (error_type) { | ||
| 918 | case C_CAN_ERROR_WARNING: | ||
| 919 | /* error warning state */ | ||
| 920 | priv->can.can_stats.error_warning++; | ||
| 921 | priv->can.state = CAN_STATE_ERROR_WARNING; | ||
| 922 | break; | ||
| 923 | case C_CAN_ERROR_PASSIVE: | ||
| 924 | /* error passive state */ | ||
| 925 | priv->can.can_stats.error_passive++; | ||
| 926 | priv->can.state = CAN_STATE_ERROR_PASSIVE; | ||
| 927 | break; | ||
| 928 | case C_CAN_BUS_OFF: | ||
| 929 | /* bus-off state */ | ||
| 930 | priv->can.state = CAN_STATE_BUS_OFF; | ||
| 931 | can_bus_off(dev); | ||
| 932 | break; | ||
| 933 | default: | ||
| 934 | break; | ||
| 935 | } | ||
| 936 | |||
| 917 | /* propagate the error condition to the CAN stack */ | 937 | /* propagate the error condition to the CAN stack */ |
| 918 | skb = alloc_can_err_skb(dev, &cf); | 938 | skb = alloc_can_err_skb(dev, &cf); |
| 919 | if (unlikely(!skb)) | 939 | if (unlikely(!skb)) |
| @@ -927,8 +947,6 @@ static int c_can_handle_state_change(struct net_device *dev, | |||
| 927 | switch (error_type) { | 947 | switch (error_type) { |
| 928 | case C_CAN_ERROR_WARNING: | 948 | case C_CAN_ERROR_WARNING: |
| 929 | /* error warning state */ | 949 | /* error warning state */ |
| 930 | priv->can.can_stats.error_warning++; | ||
| 931 | priv->can.state = CAN_STATE_ERROR_WARNING; | ||
| 932 | cf->can_id |= CAN_ERR_CRTL; | 950 | cf->can_id |= CAN_ERR_CRTL; |
| 933 | cf->data[1] = (bec.txerr > bec.rxerr) ? | 951 | cf->data[1] = (bec.txerr > bec.rxerr) ? |
| 934 | CAN_ERR_CRTL_TX_WARNING : | 952 | CAN_ERR_CRTL_TX_WARNING : |
| @@ -939,8 +957,6 @@ static int c_can_handle_state_change(struct net_device *dev, | |||
| 939 | break; | 957 | break; |
| 940 | case C_CAN_ERROR_PASSIVE: | 958 | case C_CAN_ERROR_PASSIVE: |
| 941 | /* error passive state */ | 959 | /* error passive state */ |
| 942 | priv->can.can_stats.error_passive++; | ||
| 943 | priv->can.state = CAN_STATE_ERROR_PASSIVE; | ||
| 944 | cf->can_id |= CAN_ERR_CRTL; | 960 | cf->can_id |= CAN_ERR_CRTL; |
| 945 | if (rx_err_passive) | 961 | if (rx_err_passive) |
| 946 | cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE; | 962 | cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE; |
| @@ -952,7 +968,6 @@ static int c_can_handle_state_change(struct net_device *dev, | |||
| 952 | break; | 968 | break; |
| 953 | case C_CAN_BUS_OFF: | 969 | case C_CAN_BUS_OFF: |
| 954 | /* bus-off state */ | 970 | /* bus-off state */ |
| 955 | priv->can.state = CAN_STATE_BUS_OFF; | ||
| 956 | cf->can_id |= CAN_ERR_BUSOFF; | 971 | cf->can_id |= CAN_ERR_BUSOFF; |
| 957 | can_bus_off(dev); | 972 | can_bus_off(dev); |
| 958 | break; | 973 | break; |
