diff options
author | David S. Miller <davem@davemloft.net> | 2016-09-23 07:13:55 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-09-23 07:13:55 -0400 |
commit | f44ace4d06aab8210d29c731f70b657a7524198b (patch) | |
tree | 1ed4182b585c331e465a2f9d200c2065789e6b50 | |
parent | 3d4357fba82b3cf19ebf0a04d1c9cb086af15d02 (diff) | |
parent | 9abefcb1aaa58b9d5aa40a8bb12c87d02415e4c8 (diff) |
Merge tag 'linux-can-fixes-for-4.8-20160922' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can
Marc Kleine-Budde says:
====================
pull-request: can 2016-09-22
this is a pull request of one patch for the upcoming linux-4.8 release.
The patch by Sergei Miroshnichenko fixes a potential deadlock in the generic
CAN device code that cann occour after a bus-off.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/can/dev.c | 27 | ||||
-rw-r--r-- | include/linux/can/dev.h | 3 |
2 files changed, 19 insertions, 11 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 | */ |
504 | static void can_restart(unsigned long data) | 505 | static 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 | ||
546 | static 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 | |||
546 | int can_restart_now(struct net_device *dev) | 554 | int 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 | } |
584 | EXPORT_SYMBOL_GPL(can_bus_off); | 592 | EXPORT_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 | } |
785 | EXPORT_SYMBOL_GPL(open_candev); | 792 | EXPORT_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 | } |
800 | EXPORT_SYMBOL_GPL(close_candev); | 807 | EXPORT_SYMBOL_GPL(close_candev); |
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h index 5261751f6bd4..5f5270941ba0 100644 --- a/include/linux/can/dev.h +++ b/include/linux/can/dev.h | |||
@@ -32,6 +32,7 @@ enum can_mode { | |||
32 | * CAN common private data | 32 | * CAN common private data |
33 | */ | 33 | */ |
34 | struct can_priv { | 34 | struct can_priv { |
35 | struct net_device *dev; | ||
35 | struct can_device_stats can_stats; | 36 | struct can_device_stats can_stats; |
36 | 37 | ||
37 | struct can_bittiming bittiming, data_bittiming; | 38 | struct can_bittiming bittiming, data_bittiming; |
@@ -47,7 +48,7 @@ struct can_priv { | |||
47 | u32 ctrlmode_static; /* static enabled options for driver/hardware */ | 48 | u32 ctrlmode_static; /* static enabled options for driver/hardware */ |
48 | 49 | ||
49 | int restart_ms; | 50 | int restart_ms; |
50 | struct timer_list restart_timer; | 51 | struct delayed_work restart_work; |
51 | 52 | ||
52 | int (*do_set_bittiming)(struct net_device *dev); | 53 | int (*do_set_bittiming)(struct net_device *dev); |
53 | int (*do_set_data_bittiming)(struct net_device *dev); | 54 | int (*do_set_data_bittiming)(struct net_device *dev); |