aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/can/c_can
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2014-04-11 04:13:12 -0400
committerMarc Kleine-Budde <mkl@pengutronix.de>2014-04-24 16:08:56 -0400
commitf058d548e8071a1d148d6ebd94888d011c3ca71e (patch)
tree57640ef92b3896fc7801f0443cbbf441fdf17085 /drivers/net/can/c_can
parent9c64863a49bd23c5a3a983680eb500f7796c81be (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>
Diffstat (limited to 'drivers/net/can/c_can')
-rw-r--r--drivers/net/can/c_can/c_can.c25
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;