diff options
Diffstat (limited to 'drivers/net/ppp_generic.c')
-rw-r--r-- | drivers/net/ppp_generic.c | 52 |
1 files changed, 29 insertions, 23 deletions
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 09cf56d0416a..89294b43c4a9 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c | |||
@@ -1285,6 +1285,11 @@ ppp_push(struct ppp *ppp) | |||
1285 | } | 1285 | } |
1286 | 1286 | ||
1287 | #ifdef CONFIG_PPP_MULTILINK | 1287 | #ifdef CONFIG_PPP_MULTILINK |
1288 | static bool mp_protocol_compress __read_mostly = true; | ||
1289 | module_param(mp_protocol_compress, bool, S_IRUGO | S_IWUSR); | ||
1290 | MODULE_PARM_DESC(mp_protocol_compress, | ||
1291 | "compress protocol id in multilink fragments"); | ||
1292 | |||
1288 | /* | 1293 | /* |
1289 | * Divide a packet to be transmitted into fragments and | 1294 | * Divide a packet to be transmitted into fragments and |
1290 | * send them out the individual links. | 1295 | * send them out the individual links. |
@@ -1347,10 +1352,10 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) | |||
1347 | if (nfree == 0 || nfree < navail / 2) | 1352 | if (nfree == 0 || nfree < navail / 2) |
1348 | return 0; /* can't take now, leave it in xmit_pending */ | 1353 | return 0; /* can't take now, leave it in xmit_pending */ |
1349 | 1354 | ||
1350 | /* Do protocol field compression (XXX this should be optional) */ | 1355 | /* Do protocol field compression */ |
1351 | p = skb->data; | 1356 | p = skb->data; |
1352 | len = skb->len; | 1357 | len = skb->len; |
1353 | if (*p == 0) { | 1358 | if (*p == 0 && mp_protocol_compress) { |
1354 | ++p; | 1359 | ++p; |
1355 | --len; | 1360 | --len; |
1356 | } | 1361 | } |
@@ -2584,16 +2589,16 @@ ppp_create_interface(struct net *net, int unit, int *retp) | |||
2584 | */ | 2589 | */ |
2585 | dev_net_set(dev, net); | 2590 | dev_net_set(dev, net); |
2586 | 2591 | ||
2587 | ret = -EEXIST; | ||
2588 | mutex_lock(&pn->all_ppp_mutex); | 2592 | mutex_lock(&pn->all_ppp_mutex); |
2589 | 2593 | ||
2590 | if (unit < 0) { | 2594 | if (unit < 0) { |
2591 | unit = unit_get(&pn->units_idr, ppp); | 2595 | unit = unit_get(&pn->units_idr, ppp); |
2592 | if (unit < 0) { | 2596 | if (unit < 0) { |
2593 | *retp = unit; | 2597 | ret = unit; |
2594 | goto out2; | 2598 | goto out2; |
2595 | } | 2599 | } |
2596 | } else { | 2600 | } else { |
2601 | ret = -EEXIST; | ||
2597 | if (unit_find(&pn->units_idr, unit)) | 2602 | if (unit_find(&pn->units_idr, unit)) |
2598 | goto out2; /* unit already exists */ | 2603 | goto out2; /* unit already exists */ |
2599 | /* | 2604 | /* |
@@ -2668,10 +2673,10 @@ static void ppp_shutdown_interface(struct ppp *ppp) | |||
2668 | ppp->closing = 1; | 2673 | ppp->closing = 1; |
2669 | ppp_unlock(ppp); | 2674 | ppp_unlock(ppp); |
2670 | unregister_netdev(ppp->dev); | 2675 | unregister_netdev(ppp->dev); |
2676 | unit_put(&pn->units_idr, ppp->file.index); | ||
2671 | } else | 2677 | } else |
2672 | ppp_unlock(ppp); | 2678 | ppp_unlock(ppp); |
2673 | 2679 | ||
2674 | unit_put(&pn->units_idr, ppp->file.index); | ||
2675 | ppp->file.dead = 1; | 2680 | ppp->file.dead = 1; |
2676 | ppp->owner = NULL; | 2681 | ppp->owner = NULL; |
2677 | wake_up_interruptible(&ppp->file.rwait); | 2682 | wake_up_interruptible(&ppp->file.rwait); |
@@ -2859,8 +2864,7 @@ static void __exit ppp_cleanup(void) | |||
2859 | * by holding all_ppp_mutex | 2864 | * by holding all_ppp_mutex |
2860 | */ | 2865 | */ |
2861 | 2866 | ||
2862 | /* associate pointer with specified number */ | 2867 | static int __unit_alloc(struct idr *p, void *ptr, int n) |
2863 | static int unit_set(struct idr *p, void *ptr, int n) | ||
2864 | { | 2868 | { |
2865 | int unit, err; | 2869 | int unit, err; |
2866 | 2870 | ||
@@ -2871,10 +2875,24 @@ again: | |||
2871 | } | 2875 | } |
2872 | 2876 | ||
2873 | err = idr_get_new_above(p, ptr, n, &unit); | 2877 | err = idr_get_new_above(p, ptr, n, &unit); |
2874 | if (err == -EAGAIN) | 2878 | if (err < 0) { |
2875 | goto again; | 2879 | if (err == -EAGAIN) |
2880 | goto again; | ||
2881 | return err; | ||
2882 | } | ||
2876 | 2883 | ||
2877 | if (unit != n) { | 2884 | return unit; |
2885 | } | ||
2886 | |||
2887 | /* associate pointer with specified number */ | ||
2888 | static int unit_set(struct idr *p, void *ptr, int n) | ||
2889 | { | ||
2890 | int unit; | ||
2891 | |||
2892 | unit = __unit_alloc(p, ptr, n); | ||
2893 | if (unit < 0) | ||
2894 | return unit; | ||
2895 | else if (unit != n) { | ||
2878 | idr_remove(p, unit); | 2896 | idr_remove(p, unit); |
2879 | return -EINVAL; | 2897 | return -EINVAL; |
2880 | } | 2898 | } |
@@ -2885,19 +2903,7 @@ again: | |||
2885 | /* get new free unit number and associate pointer with it */ | 2903 | /* get new free unit number and associate pointer with it */ |
2886 | static int unit_get(struct idr *p, void *ptr) | 2904 | static int unit_get(struct idr *p, void *ptr) |
2887 | { | 2905 | { |
2888 | int unit, err; | 2906 | return __unit_alloc(p, ptr, 0); |
2889 | |||
2890 | again: | ||
2891 | if (!idr_pre_get(p, GFP_KERNEL)) { | ||
2892 | printk(KERN_ERR "PPP: No free memory for idr\n"); | ||
2893 | return -ENOMEM; | ||
2894 | } | ||
2895 | |||
2896 | err = idr_get_new_above(p, ptr, 0, &unit); | ||
2897 | if (err == -EAGAIN) | ||
2898 | goto again; | ||
2899 | |||
2900 | return unit; | ||
2901 | } | 2907 | } |
2902 | 2908 | ||
2903 | /* put unit number back to a pool */ | 2909 | /* put unit number back to a pool */ |