aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/can/c_can
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2014-03-18 13:19:10 -0400
committerMarc Kleine-Budde <mkl@pengutronix.de>2014-04-01 05:54:59 -0400
commit07c7b6f6161be52b8ab6bca70ed6a7140708c94e (patch)
tree66410feb92de31d004ec2dfbf3cf69d307145cb0 /drivers/net/can/c_can
parent64f08f2f3544eb8b6b14fd35e6087d7d3ede77cd (diff)
can: c_can: Fix the lost message handling
The lost message handling is broken in several ways. 1) Clearing the message lost flag is done by writing 0 to the message control register of the object. #define IF_MCONT_CLR_MSGLST (0 << 14) That clears the object buffer configuration in the worst case, which results in a loss of the EOB flag. That leaves the FIFO chain without a limit and causes a complete lockup of the HW 2) In case that the error skb allocation fails, the code happily claims that it handed down a packet. Just an accounting bug, but .... 3) The code adds a lot of pointless overhead to that error case, where we need to get stuff done as fast as possible to avoid more packet loss. - printk an annoying error message - reread the object buffer for nothing Fix is simple again: - Use the already known MSGCTRL content and only clear the MSGLST bit - Fix the buffer accounting by adding a proper return code - Remove the pointless operations Signed-off-by: Thomas Gleixner <tglx@linutronix.de> 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.c31
1 files changed, 15 insertions, 16 deletions
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index cef9967eff93..ef5f3b8099f4 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -122,7 +122,6 @@
122/* IFx message control */ 122/* IFx message control */
123#define IF_MCONT_NEWDAT BIT(15) 123#define IF_MCONT_NEWDAT BIT(15)
124#define IF_MCONT_MSGLST BIT(14) 124#define IF_MCONT_MSGLST BIT(14)
125#define IF_MCONT_CLR_MSGLST (0 << 14)
126#define IF_MCONT_INTPND BIT(13) 125#define IF_MCONT_INTPND BIT(13)
127#define IF_MCONT_UMASK BIT(12) 126#define IF_MCONT_UMASK BIT(12)
128#define IF_MCONT_TXIE BIT(11) 127#define IF_MCONT_TXIE BIT(11)
@@ -411,27 +410,22 @@ static inline void c_can_activate_rx_msg_obj(struct net_device *dev,
411 c_can_object_put(dev, iface, obj, IF_COMM_CONTROL); 410 c_can_object_put(dev, iface, obj, IF_COMM_CONTROL);
412} 411}
413 412
414static void c_can_handle_lost_msg_obj(struct net_device *dev, 413static int c_can_handle_lost_msg_obj(struct net_device *dev,
415 int iface, int objno) 414 int iface, int objno, u32 ctrl)
416{ 415{
417 struct c_can_priv *priv = netdev_priv(dev);
418 struct net_device_stats *stats = &dev->stats; 416 struct net_device_stats *stats = &dev->stats;
419 struct sk_buff *skb; 417 struct c_can_priv *priv = netdev_priv(dev);
420 struct can_frame *frame; 418 struct can_frame *frame;
419 struct sk_buff *skb;
421 420
422 netdev_err(dev, "msg lost in buffer %d\n", objno); 421 ctrl &= ~(IF_MCONT_MSGLST | IF_MCONT_INTPND | IF_MCONT_NEWDAT);
423 422 priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl);
424 c_can_object_get(dev, iface, objno, IF_COMM_ALL & ~IF_COMM_TXRQST);
425
426 priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface),
427 IF_MCONT_CLR_MSGLST);
428
429 c_can_object_put(dev, iface, objno, IF_COMM_CONTROL); 423 c_can_object_put(dev, iface, objno, IF_COMM_CONTROL);
430 424
431 /* create an error msg */ 425 /* create an error msg */
432 skb = alloc_can_err_skb(dev, &frame); 426 skb = alloc_can_err_skb(dev, &frame);
433 if (unlikely(!skb)) 427 if (unlikely(!skb))
434 return; 428 return 0;
435 429
436 frame->can_id |= CAN_ERR_CRTL; 430 frame->can_id |= CAN_ERR_CRTL;
437 frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; 431 frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
@@ -439,6 +433,7 @@ static void c_can_handle_lost_msg_obj(struct net_device *dev,
439 stats->rx_over_errors++; 433 stats->rx_over_errors++;
440 434
441 netif_receive_skb(skb); 435 netif_receive_skb(skb);
436 return 1;
442} 437}
443 438
444static int c_can_read_msg_object(struct net_device *dev, int iface, int ctrl) 439static int c_can_read_msg_object(struct net_device *dev, int iface, int ctrl)
@@ -910,9 +905,13 @@ static int c_can_do_rx_poll(struct net_device *dev, int quota)
910 C_CAN_IFACE(MSGCTRL_REG, IF_RX)); 905 C_CAN_IFACE(MSGCTRL_REG, IF_RX));
911 906
912 if (msg_ctrl_save & IF_MCONT_MSGLST) { 907 if (msg_ctrl_save & IF_MCONT_MSGLST) {
913 c_can_handle_lost_msg_obj(dev, IF_RX, msg_obj); 908 int n;
914 num_rx_pkts++; 909
915 quota--; 910 n = c_can_handle_lost_msg_obj(dev, IF_RX,
911 msg_obj,
912 msg_ctrl_save);
913 num_rx_pkts += n;
914 quota -=n;
916 continue; 915 continue;
917 } 916 }
918 917