aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ppp/ppp_generic.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ppp/ppp_generic.c')
-rw-r--r--drivers/net/ppp/ppp_generic.c30
1 files changed, 21 insertions, 9 deletions
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 13028833bee3..bd4303944e44 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -120,6 +120,7 @@ struct ppp {
120 int n_channels; /* how many channels are attached 54 */ 120 int n_channels; /* how many channels are attached 54 */
121 spinlock_t rlock; /* lock for receive side 58 */ 121 spinlock_t rlock; /* lock for receive side 58 */
122 spinlock_t wlock; /* lock for transmit side 5c */ 122 spinlock_t wlock; /* lock for transmit side 5c */
123 int *xmit_recursion __percpu; /* xmit recursion detect */
123 int mru; /* max receive unit 60 */ 124 int mru; /* max receive unit 60 */
124 unsigned int flags; /* control bits 64 */ 125 unsigned int flags; /* control bits 64 */
125 unsigned int xstate; /* transmit state bits 68 */ 126 unsigned int xstate; /* transmit state bits 68 */
@@ -1025,6 +1026,7 @@ static int ppp_dev_configure(struct net *src_net, struct net_device *dev,
1025 struct ppp *ppp = netdev_priv(dev); 1026 struct ppp *ppp = netdev_priv(dev);
1026 int indx; 1027 int indx;
1027 int err; 1028 int err;
1029 int cpu;
1028 1030
1029 ppp->dev = dev; 1031 ppp->dev = dev;
1030 ppp->ppp_net = src_net; 1032 ppp->ppp_net = src_net;
@@ -1039,6 +1041,15 @@ static int ppp_dev_configure(struct net *src_net, struct net_device *dev,
1039 INIT_LIST_HEAD(&ppp->channels); 1041 INIT_LIST_HEAD(&ppp->channels);
1040 spin_lock_init(&ppp->rlock); 1042 spin_lock_init(&ppp->rlock);
1041 spin_lock_init(&ppp->wlock); 1043 spin_lock_init(&ppp->wlock);
1044
1045 ppp->xmit_recursion = alloc_percpu(int);
1046 if (!ppp->xmit_recursion) {
1047 err = -ENOMEM;
1048 goto err1;
1049 }
1050 for_each_possible_cpu(cpu)
1051 (*per_cpu_ptr(ppp->xmit_recursion, cpu)) = 0;
1052
1042#ifdef CONFIG_PPP_MULTILINK 1053#ifdef CONFIG_PPP_MULTILINK
1043 ppp->minseq = -1; 1054 ppp->minseq = -1;
1044 skb_queue_head_init(&ppp->mrq); 1055 skb_queue_head_init(&ppp->mrq);
@@ -1050,11 +1061,15 @@ static int ppp_dev_configure(struct net *src_net, struct net_device *dev,
1050 1061
1051 err = ppp_unit_register(ppp, conf->unit, conf->ifname_is_set); 1062 err = ppp_unit_register(ppp, conf->unit, conf->ifname_is_set);
1052 if (err < 0) 1063 if (err < 0)
1053 return err; 1064 goto err2;
1054 1065
1055 conf->file->private_data = &ppp->file; 1066 conf->file->private_data = &ppp->file;
1056 1067
1057 return 0; 1068 return 0;
1069err2:
1070 free_percpu(ppp->xmit_recursion);
1071err1:
1072 return err;
1058} 1073}
1059 1074
1060static const struct nla_policy ppp_nl_policy[IFLA_PPP_MAX + 1] = { 1075static const struct nla_policy ppp_nl_policy[IFLA_PPP_MAX + 1] = {
@@ -1400,18 +1415,16 @@ static void __ppp_xmit_process(struct ppp *ppp)
1400 ppp_xmit_unlock(ppp); 1415 ppp_xmit_unlock(ppp);
1401} 1416}
1402 1417
1403static DEFINE_PER_CPU(int, ppp_xmit_recursion);
1404
1405static void ppp_xmit_process(struct ppp *ppp) 1418static void ppp_xmit_process(struct ppp *ppp)
1406{ 1419{
1407 local_bh_disable(); 1420 local_bh_disable();
1408 1421
1409 if (unlikely(__this_cpu_read(ppp_xmit_recursion))) 1422 if (unlikely(*this_cpu_ptr(ppp->xmit_recursion)))
1410 goto err; 1423 goto err;
1411 1424
1412 __this_cpu_inc(ppp_xmit_recursion); 1425 (*this_cpu_ptr(ppp->xmit_recursion))++;
1413 __ppp_xmit_process(ppp); 1426 __ppp_xmit_process(ppp);
1414 __this_cpu_dec(ppp_xmit_recursion); 1427 (*this_cpu_ptr(ppp->xmit_recursion))--;
1415 1428
1416 local_bh_enable(); 1429 local_bh_enable();
1417 1430
@@ -1905,7 +1918,7 @@ static void __ppp_channel_push(struct channel *pch)
1905 read_lock(&pch->upl); 1918 read_lock(&pch->upl);
1906 ppp = pch->ppp; 1919 ppp = pch->ppp;
1907 if (ppp) 1920 if (ppp)
1908 __ppp_xmit_process(ppp); 1921 ppp_xmit_process(ppp);
1909 read_unlock(&pch->upl); 1922 read_unlock(&pch->upl);
1910 } 1923 }
1911} 1924}
@@ -1914,9 +1927,7 @@ static void ppp_channel_push(struct channel *pch)
1914{ 1927{
1915 local_bh_disable(); 1928 local_bh_disable();
1916 1929
1917 __this_cpu_inc(ppp_xmit_recursion);
1918 __ppp_channel_push(pch); 1930 __ppp_channel_push(pch);
1919 __this_cpu_dec(ppp_xmit_recursion);
1920 1931
1921 local_bh_enable(); 1932 local_bh_enable();
1922} 1933}
@@ -3057,6 +3068,7 @@ static void ppp_destroy_interface(struct ppp *ppp)
3057#endif /* CONFIG_PPP_FILTER */ 3068#endif /* CONFIG_PPP_FILTER */
3058 3069
3059 kfree_skb(ppp->xmit_pending); 3070 kfree_skb(ppp->xmit_pending);
3071 free_percpu(ppp->xmit_recursion);
3060 3072
3061 free_netdev(ppp->dev); 3073 free_netdev(ppp->dev);
3062} 3074}