aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/can
diff options
context:
space:
mode:
authorSergei Miroshnichenko <sergeimir@emcraft.com>2016-09-07 09:51:12 -0400
committerMarc Kleine-Budde <mkl@pengutronix.de>2016-09-22 04:01:21 -0400
commit9abefcb1aaa58b9d5aa40a8bb12c87d02415e4c8 (patch)
treeff081f6644b855d62aae2a48a8f6f4a8c00d7a78 /drivers/net/can
parent7e32b44361abc77fbc01f2b97b045c405b2583e5 (diff)
can: dev: fix deadlock reported after bus-off
A timer was used to restart after the bus-off state, leading to a relatively large can_restart() executed in an interrupt context, which in turn sets up pinctrl. When this happens during system boot, there is a high probability of grabbing the pinctrl_list_mutex, which is locked already by the probe() of other device, making the kernel suspect a deadlock condition [1]. To resolve this issue, the restart_timer is replaced by a delayed work. [1] https://github.com/victronenergy/venus/issues/24 Signed-off-by: Sergei Miroshnichenko <sergeimir@emcraft.com> Cc: linux-stable <stable@vger.kernel.org> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Diffstat (limited to 'drivers/net/can')
-rw-r--r--drivers/net/can/dev.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index e21f7cc5ae4d..8d6208c0b400 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -21,6 +21,7 @@
21#include <linux/slab.h> 21#include <linux/slab.h>
22#include <linux/netdevice.h> 22#include <linux/netdevice.h>
23#include <linux/if_arp.h> 23#include <linux/if_arp.h>
24#include <linux/workqueue.h>
24#include <linux/can.h> 25#include <linux/can.h>
25#include <linux/can/dev.h> 26#include <linux/can/dev.h>
26#include <linux/can/skb.h> 27#include <linux/can/skb.h>
@@ -501,9 +502,8 @@ EXPORT_SYMBOL_GPL(can_free_echo_skb);
501/* 502/*
502 * CAN device restart for bus-off recovery 503 * CAN device restart for bus-off recovery
503 */ 504 */
504static void can_restart(unsigned long data) 505static void can_restart(struct net_device *dev)
505{ 506{
506 struct net_device *dev = (struct net_device *)data;
507 struct can_priv *priv = netdev_priv(dev); 507 struct can_priv *priv = netdev_priv(dev);
508 struct net_device_stats *stats = &dev->stats; 508 struct net_device_stats *stats = &dev->stats;
509 struct sk_buff *skb; 509 struct sk_buff *skb;
@@ -543,6 +543,14 @@ restart:
543 netdev_err(dev, "Error %d during restart", err); 543 netdev_err(dev, "Error %d during restart", err);
544} 544}
545 545
546static void can_restart_work(struct work_struct *work)
547{
548 struct delayed_work *dwork = to_delayed_work(work);
549 struct can_priv *priv = container_of(dwork, struct can_priv, restart_work);
550
551 can_restart(priv->dev);
552}
553
546int can_restart_now(struct net_device *dev) 554int can_restart_now(struct net_device *dev)
547{ 555{
548 struct can_priv *priv = netdev_priv(dev); 556 struct can_priv *priv = netdev_priv(dev);
@@ -556,8 +564,8 @@ int can_restart_now(struct net_device *dev)
556 if (priv->state != CAN_STATE_BUS_OFF) 564 if (priv->state != CAN_STATE_BUS_OFF)
557 return -EBUSY; 565 return -EBUSY;
558 566
559 /* Runs as soon as possible in the timer context */ 567 cancel_delayed_work_sync(&priv->restart_work);
560 mod_timer(&priv->restart_timer, jiffies); 568 can_restart(dev);
561 569
562 return 0; 570 return 0;
563} 571}
@@ -578,8 +586,8 @@ void can_bus_off(struct net_device *dev)
578 netif_carrier_off(dev); 586 netif_carrier_off(dev);
579 587
580 if (priv->restart_ms) 588 if (priv->restart_ms)
581 mod_timer(&priv->restart_timer, 589 schedule_delayed_work(&priv->restart_work,
582 jiffies + (priv->restart_ms * HZ) / 1000); 590 msecs_to_jiffies(priv->restart_ms));
583} 591}
584EXPORT_SYMBOL_GPL(can_bus_off); 592EXPORT_SYMBOL_GPL(can_bus_off);
585 593
@@ -688,6 +696,7 @@ struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max)
688 return NULL; 696 return NULL;
689 697
690 priv = netdev_priv(dev); 698 priv = netdev_priv(dev);
699 priv->dev = dev;
691 700
692 if (echo_skb_max) { 701 if (echo_skb_max) {
693 priv->echo_skb_max = echo_skb_max; 702 priv->echo_skb_max = echo_skb_max;
@@ -697,7 +706,7 @@ struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max)
697 706
698 priv->state = CAN_STATE_STOPPED; 707 priv->state = CAN_STATE_STOPPED;
699 708
700 init_timer(&priv->restart_timer); 709 INIT_DELAYED_WORK(&priv->restart_work, can_restart_work);
701 710
702 return dev; 711 return dev;
703} 712}
@@ -778,8 +787,6 @@ int open_candev(struct net_device *dev)
778 if (!netif_carrier_ok(dev)) 787 if (!netif_carrier_ok(dev))
779 netif_carrier_on(dev); 788 netif_carrier_on(dev);
780 789
781 setup_timer(&priv->restart_timer, can_restart, (unsigned long)dev);
782
783 return 0; 790 return 0;
784} 791}
785EXPORT_SYMBOL_GPL(open_candev); 792EXPORT_SYMBOL_GPL(open_candev);
@@ -794,7 +801,7 @@ void close_candev(struct net_device *dev)
794{ 801{
795 struct can_priv *priv = netdev_priv(dev); 802 struct can_priv *priv = netdev_priv(dev);
796 803
797 del_timer_sync(&priv->restart_timer); 804 cancel_delayed_work_sync(&priv->restart_work);
798 can_flush_echo_skb(dev); 805 can_flush_echo_skb(dev);
799} 806}
800EXPORT_SYMBOL_GPL(close_candev); 807EXPORT_SYMBOL_GPL(close_candev);