| .. | .. | 
|---|
| 773 | 773 | * signed 16 bit values. | 
|---|
| 774 | 774 | */ | 
|---|
| 775 | 775 |  | 
|---|
| 776 |  | -static int get_dist_table(struct Qdisc *sch, struct disttable **tbl, | 
|---|
| 777 |  | -			  const struct nlattr *attr) | 
|---|
|  | 776 | +static int get_dist_table(struct disttable **tbl, const struct nlattr *attr) | 
|---|
| 778 | 777 | { | 
|---|
| 779 | 778 | size_t n = nla_len(attr)/sizeof(__s16); | 
|---|
| 780 | 779 | const __s16 *data = nla_data(attr); | 
|---|
| 781 |  | -	spinlock_t *root_lock; | 
|---|
| 782 | 780 | struct disttable *d; | 
|---|
| 783 | 781 | int i; | 
|---|
| 784 | 782 |  | 
|---|
| .. | .. | 
|---|
| 793 | 791 | for (i = 0; i < n; i++) | 
|---|
| 794 | 792 | d->table[i] = data[i]; | 
|---|
| 795 | 793 |  | 
|---|
| 796 |  | -	root_lock = qdisc_root_sleeping_lock(sch); | 
|---|
| 797 |  | - | 
|---|
| 798 |  | -	spin_lock_bh(root_lock); | 
|---|
| 799 |  | -	swap(*tbl, d); | 
|---|
| 800 |  | -	spin_unlock_bh(root_lock); | 
|---|
| 801 |  | - | 
|---|
| 802 |  | -	dist_free(d); | 
|---|
|  | 794 | +	*tbl = d; | 
|---|
| 803 | 795 | return 0; | 
|---|
| 804 | 796 | } | 
|---|
| 805 | 797 |  | 
|---|
| .. | .. | 
|---|
| 956 | 948 | { | 
|---|
| 957 | 949 | struct netem_sched_data *q = qdisc_priv(sch); | 
|---|
| 958 | 950 | struct nlattr *tb[TCA_NETEM_MAX + 1]; | 
|---|
|  | 951 | +	struct disttable *delay_dist = NULL; | 
|---|
|  | 952 | +	struct disttable *slot_dist = NULL; | 
|---|
| 959 | 953 | struct tc_netem_qopt *qopt; | 
|---|
| 960 | 954 | struct clgstate old_clg; | 
|---|
| 961 | 955 | int old_loss_model = CLG_RANDOM; | 
|---|
| .. | .. | 
|---|
| 969 | 963 | if (ret < 0) | 
|---|
| 970 | 964 | return ret; | 
|---|
| 971 | 965 |  | 
|---|
|  | 966 | +	if (tb[TCA_NETEM_DELAY_DIST]) { | 
|---|
|  | 967 | +		ret = get_dist_table(&delay_dist, tb[TCA_NETEM_DELAY_DIST]); | 
|---|
|  | 968 | +		if (ret) | 
|---|
|  | 969 | +			goto table_free; | 
|---|
|  | 970 | +	} | 
|---|
|  | 971 | + | 
|---|
|  | 972 | +	if (tb[TCA_NETEM_SLOT_DIST]) { | 
|---|
|  | 973 | +		ret = get_dist_table(&slot_dist, tb[TCA_NETEM_SLOT_DIST]); | 
|---|
|  | 974 | +		if (ret) | 
|---|
|  | 975 | +			goto table_free; | 
|---|
|  | 976 | +	} | 
|---|
|  | 977 | + | 
|---|
|  | 978 | +	sch_tree_lock(sch); | 
|---|
| 972 | 979 | /* backup q->clg and q->loss_model */ | 
|---|
| 973 | 980 | old_clg = q->clg; | 
|---|
| 974 | 981 | old_loss_model = q->loss_model; | 
|---|
| .. | .. | 
|---|
| 977 | 984 | ret = get_loss_clg(q, tb[TCA_NETEM_LOSS]); | 
|---|
| 978 | 985 | if (ret) { | 
|---|
| 979 | 986 | q->loss_model = old_loss_model; | 
|---|
| 980 |  | -			return ret; | 
|---|
|  | 987 | +			q->clg = old_clg; | 
|---|
|  | 988 | +			goto unlock; | 
|---|
| 981 | 989 | } | 
|---|
| 982 | 990 | } else { | 
|---|
| 983 | 991 | q->loss_model = CLG_RANDOM; | 
|---|
| 984 | 992 | } | 
|---|
| 985 | 993 |  | 
|---|
| 986 |  | -	if (tb[TCA_NETEM_DELAY_DIST]) { | 
|---|
| 987 |  | -		ret = get_dist_table(sch, &q->delay_dist, | 
|---|
| 988 |  | -				     tb[TCA_NETEM_DELAY_DIST]); | 
|---|
| 989 |  | -		if (ret) | 
|---|
| 990 |  | -			goto get_table_failure; | 
|---|
| 991 |  | -	} | 
|---|
| 992 |  | - | 
|---|
| 993 |  | -	if (tb[TCA_NETEM_SLOT_DIST]) { | 
|---|
| 994 |  | -		ret = get_dist_table(sch, &q->slot_dist, | 
|---|
| 995 |  | -				     tb[TCA_NETEM_SLOT_DIST]); | 
|---|
| 996 |  | -		if (ret) | 
|---|
| 997 |  | -			goto get_table_failure; | 
|---|
| 998 |  | -	} | 
|---|
| 999 |  | - | 
|---|
|  | 994 | +	if (delay_dist) | 
|---|
|  | 995 | +		swap(q->delay_dist, delay_dist); | 
|---|
|  | 996 | +	if (slot_dist) | 
|---|
|  | 997 | +		swap(q->slot_dist, slot_dist); | 
|---|
| 1000 | 998 | sch->limit = qopt->limit; | 
|---|
| 1001 | 999 |  | 
|---|
| 1002 | 1000 | q->latency = PSCHED_TICKS2NS(qopt->latency); | 
|---|
| .. | .. | 
|---|
| 1044 | 1042 | /* capping jitter to the range acceptable by tabledist() */ | 
|---|
| 1045 | 1043 | q->jitter = min_t(s64, abs(q->jitter), INT_MAX); | 
|---|
| 1046 | 1044 |  | 
|---|
| 1047 |  | -	return ret; | 
|---|
|  | 1045 | +unlock: | 
|---|
|  | 1046 | +	sch_tree_unlock(sch); | 
|---|
| 1048 | 1047 |  | 
|---|
| 1049 |  | -get_table_failure: | 
|---|
| 1050 |  | -	/* recover clg and loss_model, in case of | 
|---|
| 1051 |  | -	 * q->clg and q->loss_model were modified | 
|---|
| 1052 |  | -	 * in get_loss_clg() | 
|---|
| 1053 |  | -	 */ | 
|---|
| 1054 |  | -	q->clg = old_clg; | 
|---|
| 1055 |  | -	q->loss_model = old_loss_model; | 
|---|
|  | 1048 | +table_free: | 
|---|
|  | 1049 | +	dist_free(delay_dist); | 
|---|
|  | 1050 | +	dist_free(slot_dist); | 
|---|
| 1056 | 1051 | return ret; | 
|---|
| 1057 | 1052 | } | 
|---|
| 1058 | 1053 |  | 
|---|