diff options
Diffstat (limited to 'net')
88 files changed, 1735 insertions, 1399 deletions
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h index 5685296017e9..6abdcac1b2e8 100644 --- a/net/8021q/vlan.h +++ b/net/8021q/vlan.h | |||
@@ -61,7 +61,7 @@ struct vlan_dev_info { | |||
61 | struct proc_dir_entry *dent; | 61 | struct proc_dir_entry *dent; |
62 | unsigned long cnt_inc_headroom_on_tx; | 62 | unsigned long cnt_inc_headroom_on_tx; |
63 | unsigned long cnt_encap_on_xmit; | 63 | unsigned long cnt_encap_on_xmit; |
64 | struct vlan_rx_stats *vlan_rx_stats; | 64 | struct vlan_rx_stats __percpu *vlan_rx_stats; |
65 | }; | 65 | }; |
66 | 66 | ||
67 | static inline struct vlan_dev_info *vlan_dev_info(const struct net_device *dev) | 67 | static inline struct vlan_dev_info *vlan_dev_info(const struct net_device *dev) |
diff --git a/net/9p/client.c b/net/9p/client.c index 8af95b2dddd6..09d4f1e2e4a8 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
@@ -69,7 +69,7 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...); | |||
69 | 69 | ||
70 | static int parse_opts(char *opts, struct p9_client *clnt) | 70 | static int parse_opts(char *opts, struct p9_client *clnt) |
71 | { | 71 | { |
72 | char *options; | 72 | char *options, *tmp_options; |
73 | char *p; | 73 | char *p; |
74 | substring_t args[MAX_OPT_ARGS]; | 74 | substring_t args[MAX_OPT_ARGS]; |
75 | int option; | 75 | int option; |
@@ -81,12 +81,13 @@ static int parse_opts(char *opts, struct p9_client *clnt) | |||
81 | if (!opts) | 81 | if (!opts) |
82 | return 0; | 82 | return 0; |
83 | 83 | ||
84 | options = kstrdup(opts, GFP_KERNEL); | 84 | tmp_options = kstrdup(opts, GFP_KERNEL); |
85 | if (!options) { | 85 | if (!tmp_options) { |
86 | P9_DPRINTK(P9_DEBUG_ERROR, | 86 | P9_DPRINTK(P9_DEBUG_ERROR, |
87 | "failed to allocate copy of option string\n"); | 87 | "failed to allocate copy of option string\n"); |
88 | return -ENOMEM; | 88 | return -ENOMEM; |
89 | } | 89 | } |
90 | options = tmp_options; | ||
90 | 91 | ||
91 | while ((p = strsep(&options, ",")) != NULL) { | 92 | while ((p = strsep(&options, ",")) != NULL) { |
92 | int token; | 93 | int token; |
@@ -108,6 +109,13 @@ static int parse_opts(char *opts, struct p9_client *clnt) | |||
108 | break; | 109 | break; |
109 | case Opt_trans: | 110 | case Opt_trans: |
110 | clnt->trans_mod = v9fs_get_trans_by_name(&args[0]); | 111 | clnt->trans_mod = v9fs_get_trans_by_name(&args[0]); |
112 | if(clnt->trans_mod == NULL) { | ||
113 | P9_DPRINTK(P9_DEBUG_ERROR, | ||
114 | "Could not find request transport: %s\n", | ||
115 | (char *) &args[0]); | ||
116 | ret = -EINVAL; | ||
117 | goto free_and_return; | ||
118 | } | ||
111 | break; | 119 | break; |
112 | case Opt_legacy: | 120 | case Opt_legacy: |
113 | clnt->dotu = 0; | 121 | clnt->dotu = 0; |
@@ -117,7 +125,8 @@ static int parse_opts(char *opts, struct p9_client *clnt) | |||
117 | } | 125 | } |
118 | } | 126 | } |
119 | 127 | ||
120 | kfree(options); | 128 | free_and_return: |
129 | kfree(tmp_options); | ||
121 | return ret; | 130 | return ret; |
122 | } | 131 | } |
123 | 132 | ||
@@ -667,18 +676,12 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) | |||
667 | clnt->trans = NULL; | 676 | clnt->trans = NULL; |
668 | spin_lock_init(&clnt->lock); | 677 | spin_lock_init(&clnt->lock); |
669 | INIT_LIST_HEAD(&clnt->fidlist); | 678 | INIT_LIST_HEAD(&clnt->fidlist); |
670 | clnt->fidpool = p9_idpool_create(); | ||
671 | if (IS_ERR(clnt->fidpool)) { | ||
672 | err = PTR_ERR(clnt->fidpool); | ||
673 | clnt->fidpool = NULL; | ||
674 | goto error; | ||
675 | } | ||
676 | 679 | ||
677 | p9_tag_init(clnt); | 680 | p9_tag_init(clnt); |
678 | 681 | ||
679 | err = parse_opts(options, clnt); | 682 | err = parse_opts(options, clnt); |
680 | if (err < 0) | 683 | if (err < 0) |
681 | goto error; | 684 | goto free_client; |
682 | 685 | ||
683 | if (!clnt->trans_mod) | 686 | if (!clnt->trans_mod) |
684 | clnt->trans_mod = v9fs_get_default_trans(); | 687 | clnt->trans_mod = v9fs_get_default_trans(); |
@@ -687,7 +690,14 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) | |||
687 | err = -EPROTONOSUPPORT; | 690 | err = -EPROTONOSUPPORT; |
688 | P9_DPRINTK(P9_DEBUG_ERROR, | 691 | P9_DPRINTK(P9_DEBUG_ERROR, |
689 | "No transport defined or default transport\n"); | 692 | "No transport defined or default transport\n"); |
690 | goto error; | 693 | goto free_client; |
694 | } | ||
695 | |||
696 | clnt->fidpool = p9_idpool_create(); | ||
697 | if (IS_ERR(clnt->fidpool)) { | ||
698 | err = PTR_ERR(clnt->fidpool); | ||
699 | clnt->fidpool = NULL; | ||
700 | goto put_trans; | ||
691 | } | 701 | } |
692 | 702 | ||
693 | P9_DPRINTK(P9_DEBUG_MUX, "clnt %p trans %p msize %d dotu %d\n", | 703 | P9_DPRINTK(P9_DEBUG_MUX, "clnt %p trans %p msize %d dotu %d\n", |
@@ -695,19 +705,25 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) | |||
695 | 705 | ||
696 | err = clnt->trans_mod->create(clnt, dev_name, options); | 706 | err = clnt->trans_mod->create(clnt, dev_name, options); |
697 | if (err) | 707 | if (err) |
698 | goto error; | 708 | goto destroy_fidpool; |
699 | 709 | ||
700 | if ((clnt->msize+P9_IOHDRSZ) > clnt->trans_mod->maxsize) | 710 | if ((clnt->msize+P9_IOHDRSZ) > clnt->trans_mod->maxsize) |
701 | clnt->msize = clnt->trans_mod->maxsize-P9_IOHDRSZ; | 711 | clnt->msize = clnt->trans_mod->maxsize-P9_IOHDRSZ; |
702 | 712 | ||
703 | err = p9_client_version(clnt); | 713 | err = p9_client_version(clnt); |
704 | if (err) | 714 | if (err) |
705 | goto error; | 715 | goto close_trans; |
706 | 716 | ||
707 | return clnt; | 717 | return clnt; |
708 | 718 | ||
709 | error: | 719 | close_trans: |
710 | p9_client_destroy(clnt); | 720 | clnt->trans_mod->close(clnt); |
721 | destroy_fidpool: | ||
722 | p9_idpool_destroy(clnt->fidpool); | ||
723 | put_trans: | ||
724 | v9fs_put_trans(clnt->trans_mod); | ||
725 | free_client: | ||
726 | kfree(clnt); | ||
711 | return ERR_PTR(err); | 727 | return ERR_PTR(err); |
712 | } | 728 | } |
713 | EXPORT_SYMBOL(p9_client_create); | 729 | EXPORT_SYMBOL(p9_client_create); |
@@ -1214,10 +1230,11 @@ static int p9_client_statsize(struct p9_wstat *wst, int optional) | |||
1214 | { | 1230 | { |
1215 | int ret; | 1231 | int ret; |
1216 | 1232 | ||
1233 | /* NOTE: size shouldn't include its own length */ | ||
1217 | /* size[2] type[2] dev[4] qid[13] */ | 1234 | /* size[2] type[2] dev[4] qid[13] */ |
1218 | /* mode[4] atime[4] mtime[4] length[8]*/ | 1235 | /* mode[4] atime[4] mtime[4] length[8]*/ |
1219 | /* name[s] uid[s] gid[s] muid[s] */ | 1236 | /* name[s] uid[s] gid[s] muid[s] */ |
1220 | ret = 2+2+4+13+4+4+4+8+2+2+2+2; | 1237 | ret = 2+4+13+4+4+4+8+2+2+2+2; |
1221 | 1238 | ||
1222 | if (wst->name) | 1239 | if (wst->name) |
1223 | ret += strlen(wst->name); | 1240 | ret += strlen(wst->name); |
@@ -1258,7 +1275,7 @@ int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) | |||
1258 | wst->name, wst->uid, wst->gid, wst->muid, wst->extension, | 1275 | wst->name, wst->uid, wst->gid, wst->muid, wst->extension, |
1259 | wst->n_uid, wst->n_gid, wst->n_muid); | 1276 | wst->n_uid, wst->n_gid, wst->n_muid); |
1260 | 1277 | ||
1261 | req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size, wst); | 1278 | req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size+2, wst); |
1262 | if (IS_ERR(req)) { | 1279 | if (IS_ERR(req)) { |
1263 | err = PTR_ERR(req); | 1280 | err = PTR_ERR(req); |
1264 | goto error; | 1281 | goto error; |
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index be1cb909d8c0..31d0b05582a9 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c | |||
@@ -714,7 +714,7 @@ static int parse_opts(char *params, struct p9_fd_opts *opts) | |||
714 | char *p; | 714 | char *p; |
715 | substring_t args[MAX_OPT_ARGS]; | 715 | substring_t args[MAX_OPT_ARGS]; |
716 | int option; | 716 | int option; |
717 | char *options; | 717 | char *options, *tmp_options; |
718 | int ret; | 718 | int ret; |
719 | 719 | ||
720 | opts->port = P9_PORT; | 720 | opts->port = P9_PORT; |
@@ -724,12 +724,13 @@ static int parse_opts(char *params, struct p9_fd_opts *opts) | |||
724 | if (!params) | 724 | if (!params) |
725 | return 0; | 725 | return 0; |
726 | 726 | ||
727 | options = kstrdup(params, GFP_KERNEL); | 727 | tmp_options = kstrdup(params, GFP_KERNEL); |
728 | if (!options) { | 728 | if (!tmp_options) { |
729 | P9_DPRINTK(P9_DEBUG_ERROR, | 729 | P9_DPRINTK(P9_DEBUG_ERROR, |
730 | "failed to allocate copy of option string\n"); | 730 | "failed to allocate copy of option string\n"); |
731 | return -ENOMEM; | 731 | return -ENOMEM; |
732 | } | 732 | } |
733 | options = tmp_options; | ||
733 | 734 | ||
734 | while ((p = strsep(&options, ",")) != NULL) { | 735 | while ((p = strsep(&options, ",")) != NULL) { |
735 | int token; | 736 | int token; |
@@ -760,7 +761,8 @@ static int parse_opts(char *params, struct p9_fd_opts *opts) | |||
760 | continue; | 761 | continue; |
761 | } | 762 | } |
762 | } | 763 | } |
763 | kfree(options); | 764 | |
765 | kfree(tmp_options); | ||
764 | return 0; | 766 | return 0; |
765 | } | 767 | } |
766 | 768 | ||
diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index 65cb29db03f8..2c95a89c0f46 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c | |||
@@ -166,7 +166,7 @@ static int parse_opts(char *params, struct p9_rdma_opts *opts) | |||
166 | char *p; | 166 | char *p; |
167 | substring_t args[MAX_OPT_ARGS]; | 167 | substring_t args[MAX_OPT_ARGS]; |
168 | int option; | 168 | int option; |
169 | char *options; | 169 | char *options, *tmp_options; |
170 | int ret; | 170 | int ret; |
171 | 171 | ||
172 | opts->port = P9_PORT; | 172 | opts->port = P9_PORT; |
@@ -177,12 +177,13 @@ static int parse_opts(char *params, struct p9_rdma_opts *opts) | |||
177 | if (!params) | 177 | if (!params) |
178 | return 0; | 178 | return 0; |
179 | 179 | ||
180 | options = kstrdup(params, GFP_KERNEL); | 180 | tmp_options = kstrdup(params, GFP_KERNEL); |
181 | if (!options) { | 181 | if (!tmp_options) { |
182 | P9_DPRINTK(P9_DEBUG_ERROR, | 182 | P9_DPRINTK(P9_DEBUG_ERROR, |
183 | "failed to allocate copy of option string\n"); | 183 | "failed to allocate copy of option string\n"); |
184 | return -ENOMEM; | 184 | return -ENOMEM; |
185 | } | 185 | } |
186 | options = tmp_options; | ||
186 | 187 | ||
187 | while ((p = strsep(&options, ",")) != NULL) { | 188 | while ((p = strsep(&options, ",")) != NULL) { |
188 | int token; | 189 | int token; |
@@ -216,7 +217,7 @@ static int parse_opts(char *params, struct p9_rdma_opts *opts) | |||
216 | } | 217 | } |
217 | /* RQ must be at least as large as the SQ */ | 218 | /* RQ must be at least as large as the SQ */ |
218 | opts->rq_depth = max(opts->rq_depth, opts->sq_depth); | 219 | opts->rq_depth = max(opts->rq_depth, opts->sq_depth); |
219 | kfree(options); | 220 | kfree(tmp_options); |
220 | return 0; | 221 | return 0; |
221 | } | 222 | } |
222 | 223 | ||
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index ea1e3daabefe..cb50f4ae5eef 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c | |||
@@ -102,7 +102,8 @@ static void p9_virtio_close(struct p9_client *client) | |||
102 | struct virtio_chan *chan = client->trans; | 102 | struct virtio_chan *chan = client->trans; |
103 | 103 | ||
104 | mutex_lock(&virtio_9p_lock); | 104 | mutex_lock(&virtio_9p_lock); |
105 | chan->inuse = false; | 105 | if (chan) |
106 | chan->inuse = false; | ||
106 | mutex_unlock(&virtio_9p_lock); | 107 | mutex_unlock(&virtio_9p_lock); |
107 | } | 108 | } |
108 | 109 | ||
@@ -311,6 +312,7 @@ p9_virtio_create(struct p9_client *client, const char *devname, char *args) | |||
311 | } | 312 | } |
312 | 313 | ||
313 | client->trans = (void *)chan; | 314 | client->trans = (void *)chan; |
315 | client->status = Connected; | ||
314 | chan->client = client; | 316 | chan->client = client; |
315 | 317 | ||
316 | return 0; | 318 | return 0; |
diff --git a/net/appletalk/atalk_proc.c b/net/appletalk/atalk_proc.c index 80caad1a31a5..6ef0e761e5de 100644 --- a/net/appletalk/atalk_proc.c +++ b/net/appletalk/atalk_proc.c | |||
@@ -144,40 +144,16 @@ out: | |||
144 | return 0; | 144 | return 0; |
145 | } | 145 | } |
146 | 146 | ||
147 | static __inline__ struct sock *atalk_get_socket_idx(loff_t pos) | ||
148 | { | ||
149 | struct sock *s; | ||
150 | struct hlist_node *node; | ||
151 | |||
152 | sk_for_each(s, node, &atalk_sockets) | ||
153 | if (!pos--) | ||
154 | goto found; | ||
155 | s = NULL; | ||
156 | found: | ||
157 | return s; | ||
158 | } | ||
159 | |||
160 | static void *atalk_seq_socket_start(struct seq_file *seq, loff_t *pos) | 147 | static void *atalk_seq_socket_start(struct seq_file *seq, loff_t *pos) |
161 | __acquires(atalk_sockets_lock) | 148 | __acquires(atalk_sockets_lock) |
162 | { | 149 | { |
163 | loff_t l = *pos; | ||
164 | |||
165 | read_lock_bh(&atalk_sockets_lock); | 150 | read_lock_bh(&atalk_sockets_lock); |
166 | return l ? atalk_get_socket_idx(--l) : SEQ_START_TOKEN; | 151 | return seq_hlist_start_head(&atalk_sockets, *pos); |
167 | } | 152 | } |
168 | 153 | ||
169 | static void *atalk_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos) | 154 | static void *atalk_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos) |
170 | { | 155 | { |
171 | struct sock *i; | 156 | return seq_hlist_next(v, &atalk_sockets, pos); |
172 | |||
173 | ++*pos; | ||
174 | if (v == SEQ_START_TOKEN) { | ||
175 | i = sk_head(&atalk_sockets); | ||
176 | goto out; | ||
177 | } | ||
178 | i = sk_next(v); | ||
179 | out: | ||
180 | return i; | ||
181 | } | 157 | } |
182 | 158 | ||
183 | static void atalk_seq_socket_stop(struct seq_file *seq, void *v) | 159 | static void atalk_seq_socket_stop(struct seq_file *seq, void *v) |
@@ -197,7 +173,7 @@ static int atalk_seq_socket_show(struct seq_file *seq, void *v) | |||
197 | goto out; | 173 | goto out; |
198 | } | 174 | } |
199 | 175 | ||
200 | s = v; | 176 | s = sk_entry(v); |
201 | at = at_sk(s); | 177 | at = at_sk(s); |
202 | 178 | ||
203 | seq_printf(seq, "%02X %04X:%02X:%02X %04X:%02X:%02X %08X:%08X " | 179 | seq_printf(seq, "%02X %04X:%02X:%02X %04X:%02X:%02X %08X:%08X " |
diff --git a/net/atm/proc.c b/net/atm/proc.c index 476779d845eb..7a96b2376bd7 100644 --- a/net/atm/proc.c +++ b/net/atm/proc.c | |||
@@ -238,7 +238,7 @@ static int atm_dev_seq_show(struct seq_file *seq, void *v) | |||
238 | "Itf Type ESI/\"MAC\"addr " | 238 | "Itf Type ESI/\"MAC\"addr " |
239 | "AAL(TX,err,RX,err,drop) ... [refcnt]\n"; | 239 | "AAL(TX,err,RX,err,drop) ... [refcnt]\n"; |
240 | 240 | ||
241 | if (v == SEQ_START_TOKEN) | 241 | if (v == &atm_devs) |
242 | seq_puts(seq, atm_dev_banner); | 242 | seq_puts(seq, atm_dev_banner); |
243 | else { | 243 | else { |
244 | struct atm_dev *dev = list_entry(v, struct atm_dev, dev_list); | 244 | struct atm_dev *dev = list_entry(v, struct atm_dev, dev_list); |
diff --git a/net/atm/resources.c b/net/atm/resources.c index 447ed89205d8..90082904f20d 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c | |||
@@ -444,21 +444,10 @@ done: | |||
444 | return error; | 444 | return error; |
445 | } | 445 | } |
446 | 446 | ||
447 | static inline void *dev_get_idx(loff_t left) | ||
448 | { | ||
449 | struct list_head *p; | ||
450 | |||
451 | list_for_each(p, &atm_devs) { | ||
452 | if (!--left) | ||
453 | break; | ||
454 | } | ||
455 | return (p != &atm_devs) ? p : NULL; | ||
456 | } | ||
457 | |||
458 | void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos) | 447 | void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos) |
459 | { | 448 | { |
460 | mutex_lock(&atm_dev_mutex); | 449 | mutex_lock(&atm_dev_mutex); |
461 | return *pos ? dev_get_idx(*pos) : SEQ_START_TOKEN; | 450 | return seq_list_start_head(&atm_devs, *pos); |
462 | } | 451 | } |
463 | 452 | ||
464 | void atm_dev_seq_stop(struct seq_file *seq, void *v) | 453 | void atm_dev_seq_stop(struct seq_file *seq, void *v) |
@@ -468,8 +457,5 @@ void atm_dev_seq_stop(struct seq_file *seq, void *v) | |||
468 | 457 | ||
469 | void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 458 | void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
470 | { | 459 | { |
471 | ++*pos; | 460 | return seq_list_next(v, &atm_devs, pos); |
472 | v = (v == SEQ_START_TOKEN) | ||
473 | ? atm_devs.next : ((struct list_head *)v)->next; | ||
474 | return (v == &atm_devs) ? NULL : v; | ||
475 | } | 461 | } |
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 5588ba69c468..a5beedf43e2d 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c | |||
@@ -1863,25 +1863,13 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1863 | static void *ax25_info_start(struct seq_file *seq, loff_t *pos) | 1863 | static void *ax25_info_start(struct seq_file *seq, loff_t *pos) |
1864 | __acquires(ax25_list_lock) | 1864 | __acquires(ax25_list_lock) |
1865 | { | 1865 | { |
1866 | struct ax25_cb *ax25; | ||
1867 | struct hlist_node *node; | ||
1868 | int i = 0; | ||
1869 | |||
1870 | spin_lock_bh(&ax25_list_lock); | 1866 | spin_lock_bh(&ax25_list_lock); |
1871 | ax25_for_each(ax25, node, &ax25_list) { | 1867 | return seq_hlist_start(&ax25_list, *pos); |
1872 | if (i == *pos) | ||
1873 | return ax25; | ||
1874 | ++i; | ||
1875 | } | ||
1876 | return NULL; | ||
1877 | } | 1868 | } |
1878 | 1869 | ||
1879 | static void *ax25_info_next(struct seq_file *seq, void *v, loff_t *pos) | 1870 | static void *ax25_info_next(struct seq_file *seq, void *v, loff_t *pos) |
1880 | { | 1871 | { |
1881 | ++*pos; | 1872 | return seq_hlist_next(v, &ax25_list, pos); |
1882 | |||
1883 | return hlist_entry( ((struct ax25_cb *)v)->ax25_node.next, | ||
1884 | struct ax25_cb, ax25_node); | ||
1885 | } | 1873 | } |
1886 | 1874 | ||
1887 | static void ax25_info_stop(struct seq_file *seq, void *v) | 1875 | static void ax25_info_stop(struct seq_file *seq, void *v) |
@@ -1892,7 +1880,7 @@ static void ax25_info_stop(struct seq_file *seq, void *v) | |||
1892 | 1880 | ||
1893 | static int ax25_info_show(struct seq_file *seq, void *v) | 1881 | static int ax25_info_show(struct seq_file *seq, void *v) |
1894 | { | 1882 | { |
1895 | ax25_cb *ax25 = v; | 1883 | ax25_cb *ax25 = hlist_entry(v, struct ax25_cb, ax25_node); |
1896 | char buf[11]; | 1884 | char buf[11]; |
1897 | int k; | 1885 | int k; |
1898 | 1886 | ||
diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c index 832bcf092a01..9f13f6eefcba 100644 --- a/net/ax25/ax25_uid.c +++ b/net/ax25/ax25_uid.c | |||
@@ -146,31 +146,13 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax) | |||
146 | static void *ax25_uid_seq_start(struct seq_file *seq, loff_t *pos) | 146 | static void *ax25_uid_seq_start(struct seq_file *seq, loff_t *pos) |
147 | __acquires(ax25_uid_lock) | 147 | __acquires(ax25_uid_lock) |
148 | { | 148 | { |
149 | struct ax25_uid_assoc *pt; | ||
150 | struct hlist_node *node; | ||
151 | int i = 1; | ||
152 | |||
153 | read_lock(&ax25_uid_lock); | 149 | read_lock(&ax25_uid_lock); |
154 | 150 | return seq_hlist_start_head(&ax25_uid_list, *pos); | |
155 | if (*pos == 0) | ||
156 | return SEQ_START_TOKEN; | ||
157 | |||
158 | ax25_uid_for_each(pt, node, &ax25_uid_list) { | ||
159 | if (i == *pos) | ||
160 | return pt; | ||
161 | ++i; | ||
162 | } | ||
163 | return NULL; | ||
164 | } | 151 | } |
165 | 152 | ||
166 | static void *ax25_uid_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 153 | static void *ax25_uid_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
167 | { | 154 | { |
168 | ++*pos; | 155 | return seq_hlist_next(v, &ax25_uid_list, pos); |
169 | if (v == SEQ_START_TOKEN) | ||
170 | return ax25_uid_list.first; | ||
171 | else | ||
172 | return hlist_entry(((ax25_uid_assoc *)v)->uid_node.next, | ||
173 | ax25_uid_assoc, uid_node); | ||
174 | } | 156 | } |
175 | 157 | ||
176 | static void ax25_uid_seq_stop(struct seq_file *seq, void *v) | 158 | static void ax25_uid_seq_stop(struct seq_file *seq, void *v) |
@@ -186,8 +168,9 @@ static int ax25_uid_seq_show(struct seq_file *seq, void *v) | |||
186 | if (v == SEQ_START_TOKEN) | 168 | if (v == SEQ_START_TOKEN) |
187 | seq_printf(seq, "Policy: %d\n", ax25_uid_policy); | 169 | seq_printf(seq, "Policy: %d\n", ax25_uid_policy); |
188 | else { | 170 | else { |
189 | struct ax25_uid_assoc *pt = v; | 171 | struct ax25_uid_assoc *pt; |
190 | 172 | ||
173 | pt = hlist_entry(v, struct ax25_uid_assoc, uid_node); | ||
191 | seq_printf(seq, "%6d %s\n", pt->uid, ax2asc(buf, &pt->call)); | 174 | seq_printf(seq, "%6d %s\n", pt->uid, ax2asc(buf, &pt->call)); |
192 | } | 175 | } |
193 | return 0; | 176 | return 0; |
diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c index 26fb831ef7e0..b6234b73c4cf 100644 --- a/net/bluetooth/bnep/netdev.c +++ b/net/bluetooth/bnep/netdev.c | |||
@@ -64,7 +64,7 @@ static void bnep_net_set_mc_list(struct net_device *dev) | |||
64 | struct sk_buff *skb; | 64 | struct sk_buff *skb; |
65 | int size; | 65 | int size; |
66 | 66 | ||
67 | BT_DBG("%s mc_count %d", dev->name, dev->mc_count); | 67 | BT_DBG("%s mc_count %d", dev->name, netdev_mc_count(dev)); |
68 | 68 | ||
69 | size = sizeof(*r) + (BNEP_MAX_MULTICAST_FILTERS + 1) * ETH_ALEN * 2; | 69 | size = sizeof(*r) + (BNEP_MAX_MULTICAST_FILTERS + 1) * ETH_ALEN * 2; |
70 | skb = alloc_skb(size, GFP_ATOMIC); | 70 | skb = alloc_skb(size, GFP_ATOMIC); |
@@ -97,7 +97,9 @@ static void bnep_net_set_mc_list(struct net_device *dev) | |||
97 | 97 | ||
98 | /* FIXME: We should group addresses here. */ | 98 | /* FIXME: We should group addresses here. */ |
99 | 99 | ||
100 | for (i = 0; i < dev->mc_count && i < BNEP_MAX_MULTICAST_FILTERS; i++) { | 100 | for (i = 0; |
101 | i < netdev_mc_count(dev) && i < BNEP_MAX_MULTICAST_FILTERS; | ||
102 | i++) { | ||
101 | memcpy(__skb_put(skb, ETH_ALEN), dmi->dmi_addr, ETH_ALEN); | 103 | memcpy(__skb_put(skb, ETH_ALEN), dmi->dmi_addr, ETH_ALEN); |
102 | memcpy(__skb_put(skb, ETH_ALEN), dmi->dmi_addr, ETH_ALEN); | 104 | memcpy(__skb_put(skb, ETH_ALEN), dmi->dmi_addr, ETH_ALEN); |
103 | dmi = dmi->next; | 105 | dmi = dmi->next; |
diff --git a/net/core/dev.c b/net/core/dev.c index 94c1eeed25e5..1968980f513a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -2813,7 +2813,7 @@ gro_result_t napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb, | |||
2813 | switch (ret) { | 2813 | switch (ret) { |
2814 | case GRO_NORMAL: | 2814 | case GRO_NORMAL: |
2815 | case GRO_HELD: | 2815 | case GRO_HELD: |
2816 | skb->protocol = eth_type_trans(skb, napi->dev); | 2816 | skb->protocol = eth_type_trans(skb, skb->dev); |
2817 | 2817 | ||
2818 | if (ret == GRO_HELD) | 2818 | if (ret == GRO_HELD) |
2819 | skb_gro_pull(skb, -ETH_HLEN); | 2819 | skb_gro_pull(skb, -ETH_HLEN); |
@@ -4263,7 +4263,7 @@ static void dev_addr_discard(struct net_device *dev) | |||
4263 | netif_addr_lock_bh(dev); | 4263 | netif_addr_lock_bh(dev); |
4264 | 4264 | ||
4265 | __dev_addr_discard(&dev->mc_list); | 4265 | __dev_addr_discard(&dev->mc_list); |
4266 | dev->mc_count = 0; | 4266 | netdev_mc_count(dev) = 0; |
4267 | 4267 | ||
4268 | netif_addr_unlock_bh(dev); | 4268 | netif_addr_unlock_bh(dev); |
4269 | } | 4269 | } |
@@ -5419,6 +5419,8 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, | |||
5419 | 5419 | ||
5420 | netdev_init_queues(dev); | 5420 | netdev_init_queues(dev); |
5421 | 5421 | ||
5422 | INIT_LIST_HEAD(&dev->ethtool_ntuple_list.list); | ||
5423 | dev->ethtool_ntuple_list.count = 0; | ||
5422 | INIT_LIST_HEAD(&dev->napi_list); | 5424 | INIT_LIST_HEAD(&dev->napi_list); |
5423 | INIT_LIST_HEAD(&dev->unreg_list); | 5425 | INIT_LIST_HEAD(&dev->unreg_list); |
5424 | INIT_LIST_HEAD(&dev->link_watch_list); | 5426 | INIT_LIST_HEAD(&dev->link_watch_list); |
@@ -5455,6 +5457,9 @@ void free_netdev(struct net_device *dev) | |||
5455 | /* Flush device addresses */ | 5457 | /* Flush device addresses */ |
5456 | dev_addr_flush(dev); | 5458 | dev_addr_flush(dev); |
5457 | 5459 | ||
5460 | /* Clear ethtool n-tuple list */ | ||
5461 | ethtool_ntuple_flush(dev); | ||
5462 | |||
5458 | list_for_each_entry_safe(p, n, &dev->napi_list, dev_list) | 5463 | list_for_each_entry_safe(p, n, &dev->napi_list, dev_list) |
5459 | netif_napi_del(p); | 5464 | netif_napi_del(p); |
5460 | 5465 | ||
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index b8e9d3a86887..f8c874975350 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c | |||
@@ -296,7 +296,6 @@ static int dropmon_net_event(struct notifier_block *ev_block, | |||
296 | 296 | ||
297 | new_stat->dev = dev; | 297 | new_stat->dev = dev; |
298 | new_stat->last_rx = jiffies; | 298 | new_stat->last_rx = jiffies; |
299 | INIT_RCU_HEAD(&new_stat->rcu); | ||
300 | spin_lock(&trace_state_lock); | 299 | spin_lock(&trace_state_lock); |
301 | list_add_rcu(&new_stat->list, &hw_stats_list); | 300 | list_add_rcu(&new_stat->list, &hw_stats_list); |
302 | spin_unlock(&trace_state_lock); | 301 | spin_unlock(&trace_state_lock); |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index d8aee584e8d1..31b1eddc1b84 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -120,7 +120,7 @@ int ethtool_op_set_ufo(struct net_device *dev, u32 data) | |||
120 | * NETIF_F_xxx values in include/linux/netdevice.h | 120 | * NETIF_F_xxx values in include/linux/netdevice.h |
121 | */ | 121 | */ |
122 | static const u32 flags_dup_features = | 122 | static const u32 flags_dup_features = |
123 | ETH_FLAG_LRO; | 123 | (ETH_FLAG_LRO | ETH_FLAG_NTUPLE); |
124 | 124 | ||
125 | u32 ethtool_op_get_flags(struct net_device *dev) | 125 | u32 ethtool_op_get_flags(struct net_device *dev) |
126 | { | 126 | { |
@@ -134,19 +134,42 @@ u32 ethtool_op_get_flags(struct net_device *dev) | |||
134 | 134 | ||
135 | int ethtool_op_set_flags(struct net_device *dev, u32 data) | 135 | int ethtool_op_set_flags(struct net_device *dev, u32 data) |
136 | { | 136 | { |
137 | const struct ethtool_ops *ops = dev->ethtool_ops; | ||
138 | |||
137 | if (data & ETH_FLAG_LRO) | 139 | if (data & ETH_FLAG_LRO) |
138 | dev->features |= NETIF_F_LRO; | 140 | dev->features |= NETIF_F_LRO; |
139 | else | 141 | else |
140 | dev->features &= ~NETIF_F_LRO; | 142 | dev->features &= ~NETIF_F_LRO; |
141 | 143 | ||
144 | if (data & ETH_FLAG_NTUPLE) { | ||
145 | if (!ops->set_rx_ntuple) | ||
146 | return -EOPNOTSUPP; | ||
147 | dev->features |= NETIF_F_NTUPLE; | ||
148 | } else { | ||
149 | /* safe to clear regardless */ | ||
150 | dev->features &= ~NETIF_F_NTUPLE; | ||
151 | } | ||
152 | |||
142 | return 0; | 153 | return 0; |
143 | } | 154 | } |
144 | 155 | ||
156 | void ethtool_ntuple_flush(struct net_device *dev) | ||
157 | { | ||
158 | struct ethtool_rx_ntuple_flow_spec_container *fsc, *f; | ||
159 | |||
160 | list_for_each_entry_safe(fsc, f, &dev->ethtool_ntuple_list.list, list) { | ||
161 | list_del(&fsc->list); | ||
162 | kfree(fsc); | ||
163 | } | ||
164 | dev->ethtool_ntuple_list.count = 0; | ||
165 | } | ||
166 | EXPORT_SYMBOL(ethtool_ntuple_flush); | ||
167 | |||
145 | /* Handlers for each ethtool command */ | 168 | /* Handlers for each ethtool command */ |
146 | 169 | ||
147 | static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) | 170 | static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) |
148 | { | 171 | { |
149 | struct ethtool_cmd cmd = { ETHTOOL_GSET }; | 172 | struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET }; |
150 | int err; | 173 | int err; |
151 | 174 | ||
152 | if (!dev->ethtool_ops->get_settings) | 175 | if (!dev->ethtool_ops->get_settings) |
@@ -174,7 +197,10 @@ static int ethtool_set_settings(struct net_device *dev, void __user *useraddr) | |||
174 | return dev->ethtool_ops->set_settings(dev, &cmd); | 197 | return dev->ethtool_ops->set_settings(dev, &cmd); |
175 | } | 198 | } |
176 | 199 | ||
177 | static int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr) | 200 | /* |
201 | * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() | ||
202 | */ | ||
203 | static noinline int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr) | ||
178 | { | 204 | { |
179 | struct ethtool_drvinfo info; | 205 | struct ethtool_drvinfo info; |
180 | const struct ethtool_ops *ops = dev->ethtool_ops; | 206 | const struct ethtool_ops *ops = dev->ethtool_ops; |
@@ -209,7 +235,10 @@ static int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr) | |||
209 | return 0; | 235 | return 0; |
210 | } | 236 | } |
211 | 237 | ||
212 | static int ethtool_set_rxnfc(struct net_device *dev, void __user *useraddr) | 238 | /* |
239 | * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() | ||
240 | */ | ||
241 | static noinline int ethtool_set_rxnfc(struct net_device *dev, void __user *useraddr) | ||
213 | { | 242 | { |
214 | struct ethtool_rxnfc cmd; | 243 | struct ethtool_rxnfc cmd; |
215 | 244 | ||
@@ -222,7 +251,10 @@ static int ethtool_set_rxnfc(struct net_device *dev, void __user *useraddr) | |||
222 | return dev->ethtool_ops->set_rxnfc(dev, &cmd); | 251 | return dev->ethtool_ops->set_rxnfc(dev, &cmd); |
223 | } | 252 | } |
224 | 253 | ||
225 | static int ethtool_get_rxnfc(struct net_device *dev, void __user *useraddr) | 254 | /* |
255 | * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() | ||
256 | */ | ||
257 | static noinline int ethtool_get_rxnfc(struct net_device *dev, void __user *useraddr) | ||
226 | { | 258 | { |
227 | struct ethtool_rxnfc info; | 259 | struct ethtool_rxnfc info; |
228 | const struct ethtool_ops *ops = dev->ethtool_ops; | 260 | const struct ethtool_ops *ops = dev->ethtool_ops; |
@@ -266,6 +298,315 @@ err_out: | |||
266 | return ret; | 298 | return ret; |
267 | } | 299 | } |
268 | 300 | ||
301 | static void __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list, | ||
302 | struct ethtool_rx_ntuple_flow_spec *spec, | ||
303 | struct ethtool_rx_ntuple_flow_spec_container *fsc) | ||
304 | { | ||
305 | |||
306 | /* don't add filters forever */ | ||
307 | if (list->count >= ETHTOOL_MAX_NTUPLE_LIST_ENTRY) { | ||
308 | /* free the container */ | ||
309 | kfree(fsc); | ||
310 | return; | ||
311 | } | ||
312 | |||
313 | /* Copy the whole filter over */ | ||
314 | fsc->fs.flow_type = spec->flow_type; | ||
315 | memcpy(&fsc->fs.h_u, &spec->h_u, sizeof(spec->h_u)); | ||
316 | memcpy(&fsc->fs.m_u, &spec->m_u, sizeof(spec->m_u)); | ||
317 | |||
318 | fsc->fs.vlan_tag = spec->vlan_tag; | ||
319 | fsc->fs.vlan_tag_mask = spec->vlan_tag_mask; | ||
320 | fsc->fs.data = spec->data; | ||
321 | fsc->fs.data_mask = spec->data_mask; | ||
322 | fsc->fs.action = spec->action; | ||
323 | |||
324 | /* add to the list */ | ||
325 | list_add_tail_rcu(&fsc->list, &list->list); | ||
326 | list->count++; | ||
327 | } | ||
328 | |||
329 | /* | ||
330 | * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() | ||
331 | */ | ||
332 | static noinline int ethtool_set_rx_ntuple(struct net_device *dev, void __user *useraddr) | ||
333 | { | ||
334 | struct ethtool_rx_ntuple cmd; | ||
335 | const struct ethtool_ops *ops = dev->ethtool_ops; | ||
336 | struct ethtool_rx_ntuple_flow_spec_container *fsc = NULL; | ||
337 | int ret; | ||
338 | |||
339 | if (!(dev->features & NETIF_F_NTUPLE)) | ||
340 | return -EINVAL; | ||
341 | |||
342 | if (copy_from_user(&cmd, useraddr, sizeof(cmd))) | ||
343 | return -EFAULT; | ||
344 | |||
345 | /* | ||
346 | * Cache filter in dev struct for GET operation only if | ||
347 | * the underlying driver doesn't have its own GET operation, and | ||
348 | * only if the filter was added successfully. First make sure we | ||
349 | * can allocate the filter, then continue if successful. | ||
350 | */ | ||
351 | if (!ops->get_rx_ntuple) { | ||
352 | fsc = kmalloc(sizeof(*fsc), GFP_ATOMIC); | ||
353 | if (!fsc) | ||
354 | return -ENOMEM; | ||
355 | } | ||
356 | |||
357 | ret = ops->set_rx_ntuple(dev, &cmd); | ||
358 | if (ret) { | ||
359 | kfree(fsc); | ||
360 | return ret; | ||
361 | } | ||
362 | |||
363 | if (!ops->get_rx_ntuple) | ||
364 | __rx_ntuple_filter_add(&dev->ethtool_ntuple_list, &cmd.fs, fsc); | ||
365 | |||
366 | return ret; | ||
367 | } | ||
368 | |||
369 | static int ethtool_get_rx_ntuple(struct net_device *dev, void __user *useraddr) | ||
370 | { | ||
371 | struct ethtool_gstrings gstrings; | ||
372 | const struct ethtool_ops *ops = dev->ethtool_ops; | ||
373 | struct ethtool_rx_ntuple_flow_spec_container *fsc; | ||
374 | u8 *data; | ||
375 | char *p; | ||
376 | int ret, i, num_strings = 0; | ||
377 | |||
378 | if (!ops->get_sset_count) | ||
379 | return -EOPNOTSUPP; | ||
380 | |||
381 | if (copy_from_user(&gstrings, useraddr, sizeof(gstrings))) | ||
382 | return -EFAULT; | ||
383 | |||
384 | ret = ops->get_sset_count(dev, gstrings.string_set); | ||
385 | if (ret < 0) | ||
386 | return ret; | ||
387 | |||
388 | gstrings.len = ret; | ||
389 | |||
390 | data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER); | ||
391 | if (!data) | ||
392 | return -ENOMEM; | ||
393 | |||
394 | if (ops->get_rx_ntuple) { | ||
395 | /* driver-specific filter grab */ | ||
396 | ret = ops->get_rx_ntuple(dev, gstrings.string_set, data); | ||
397 | goto copy; | ||
398 | } | ||
399 | |||
400 | /* default ethtool filter grab */ | ||
401 | i = 0; | ||
402 | p = (char *)data; | ||
403 | list_for_each_entry(fsc, &dev->ethtool_ntuple_list.list, list) { | ||
404 | sprintf(p, "Filter %d:\n", i); | ||
405 | p += ETH_GSTRING_LEN; | ||
406 | num_strings++; | ||
407 | |||
408 | switch (fsc->fs.flow_type) { | ||
409 | case TCP_V4_FLOW: | ||
410 | sprintf(p, "\tFlow Type: TCP\n"); | ||
411 | p += ETH_GSTRING_LEN; | ||
412 | num_strings++; | ||
413 | break; | ||
414 | case UDP_V4_FLOW: | ||
415 | sprintf(p, "\tFlow Type: UDP\n"); | ||
416 | p += ETH_GSTRING_LEN; | ||
417 | num_strings++; | ||
418 | break; | ||
419 | case SCTP_V4_FLOW: | ||
420 | sprintf(p, "\tFlow Type: SCTP\n"); | ||
421 | p += ETH_GSTRING_LEN; | ||
422 | num_strings++; | ||
423 | break; | ||
424 | case AH_ESP_V4_FLOW: | ||
425 | sprintf(p, "\tFlow Type: AH ESP\n"); | ||
426 | p += ETH_GSTRING_LEN; | ||
427 | num_strings++; | ||
428 | break; | ||
429 | case ESP_V4_FLOW: | ||
430 | sprintf(p, "\tFlow Type: ESP\n"); | ||
431 | p += ETH_GSTRING_LEN; | ||
432 | num_strings++; | ||
433 | break; | ||
434 | case IP_USER_FLOW: | ||
435 | sprintf(p, "\tFlow Type: Raw IP\n"); | ||
436 | p += ETH_GSTRING_LEN; | ||
437 | num_strings++; | ||
438 | break; | ||
439 | case IPV4_FLOW: | ||
440 | sprintf(p, "\tFlow Type: IPv4\n"); | ||
441 | p += ETH_GSTRING_LEN; | ||
442 | num_strings++; | ||
443 | break; | ||
444 | default: | ||
445 | sprintf(p, "\tFlow Type: Unknown\n"); | ||
446 | p += ETH_GSTRING_LEN; | ||
447 | num_strings++; | ||
448 | goto unknown_filter; | ||
449 | }; | ||
450 | |||
451 | /* now the rest of the filters */ | ||
452 | switch (fsc->fs.flow_type) { | ||
453 | case TCP_V4_FLOW: | ||
454 | case UDP_V4_FLOW: | ||
455 | case SCTP_V4_FLOW: | ||
456 | sprintf(p, "\tSrc IP addr: 0x%x\n", | ||
457 | fsc->fs.h_u.tcp_ip4_spec.ip4src); | ||
458 | p += ETH_GSTRING_LEN; | ||
459 | num_strings++; | ||
460 | sprintf(p, "\tSrc IP mask: 0x%x\n", | ||
461 | fsc->fs.m_u.tcp_ip4_spec.ip4src); | ||
462 | p += ETH_GSTRING_LEN; | ||
463 | num_strings++; | ||
464 | sprintf(p, "\tDest IP addr: 0x%x\n", | ||
465 | fsc->fs.h_u.tcp_ip4_spec.ip4dst); | ||
466 | p += ETH_GSTRING_LEN; | ||
467 | num_strings++; | ||
468 | sprintf(p, "\tDest IP mask: 0x%x\n", | ||
469 | fsc->fs.m_u.tcp_ip4_spec.ip4dst); | ||
470 | p += ETH_GSTRING_LEN; | ||
471 | num_strings++; | ||
472 | sprintf(p, "\tSrc Port: %d, mask: 0x%x\n", | ||
473 | fsc->fs.h_u.tcp_ip4_spec.psrc, | ||
474 | fsc->fs.m_u.tcp_ip4_spec.psrc); | ||
475 | p += ETH_GSTRING_LEN; | ||
476 | num_strings++; | ||
477 | sprintf(p, "\tDest Port: %d, mask: 0x%x\n", | ||
478 | fsc->fs.h_u.tcp_ip4_spec.pdst, | ||
479 | fsc->fs.m_u.tcp_ip4_spec.pdst); | ||
480 | p += ETH_GSTRING_LEN; | ||
481 | num_strings++; | ||
482 | sprintf(p, "\tTOS: %d, mask: 0x%x\n", | ||
483 | fsc->fs.h_u.tcp_ip4_spec.tos, | ||
484 | fsc->fs.m_u.tcp_ip4_spec.tos); | ||
485 | p += ETH_GSTRING_LEN; | ||
486 | num_strings++; | ||
487 | break; | ||
488 | case AH_ESP_V4_FLOW: | ||
489 | case ESP_V4_FLOW: | ||
490 | sprintf(p, "\tSrc IP addr: 0x%x\n", | ||
491 | fsc->fs.h_u.ah_ip4_spec.ip4src); | ||
492 | p += ETH_GSTRING_LEN; | ||
493 | num_strings++; | ||
494 | sprintf(p, "\tSrc IP mask: 0x%x\n", | ||
495 | fsc->fs.m_u.ah_ip4_spec.ip4src); | ||
496 | p += ETH_GSTRING_LEN; | ||
497 | num_strings++; | ||
498 | sprintf(p, "\tDest IP addr: 0x%x\n", | ||
499 | fsc->fs.h_u.ah_ip4_spec.ip4dst); | ||
500 | p += ETH_GSTRING_LEN; | ||
501 | num_strings++; | ||
502 | sprintf(p, "\tDest IP mask: 0x%x\n", | ||
503 | fsc->fs.m_u.ah_ip4_spec.ip4dst); | ||
504 | p += ETH_GSTRING_LEN; | ||
505 | num_strings++; | ||
506 | sprintf(p, "\tSPI: %d, mask: 0x%x\n", | ||
507 | fsc->fs.h_u.ah_ip4_spec.spi, | ||
508 | fsc->fs.m_u.ah_ip4_spec.spi); | ||
509 | p += ETH_GSTRING_LEN; | ||
510 | num_strings++; | ||
511 | sprintf(p, "\tTOS: %d, mask: 0x%x\n", | ||
512 | fsc->fs.h_u.ah_ip4_spec.tos, | ||
513 | fsc->fs.m_u.ah_ip4_spec.tos); | ||
514 | p += ETH_GSTRING_LEN; | ||
515 | num_strings++; | ||
516 | break; | ||
517 | case IP_USER_FLOW: | ||
518 | sprintf(p, "\tSrc IP addr: 0x%x\n", | ||
519 | fsc->fs.h_u.raw_ip4_spec.ip4src); | ||
520 | p += ETH_GSTRING_LEN; | ||
521 | num_strings++; | ||
522 | sprintf(p, "\tSrc IP mask: 0x%x\n", | ||
523 | fsc->fs.m_u.raw_ip4_spec.ip4src); | ||
524 | p += ETH_GSTRING_LEN; | ||
525 | num_strings++; | ||
526 | sprintf(p, "\tDest IP addr: 0x%x\n", | ||
527 | fsc->fs.h_u.raw_ip4_spec.ip4dst); | ||
528 | p += ETH_GSTRING_LEN; | ||
529 | num_strings++; | ||
530 | sprintf(p, "\tDest IP mask: 0x%x\n", | ||
531 | fsc->fs.m_u.raw_ip4_spec.ip4dst); | ||
532 | p += ETH_GSTRING_LEN; | ||
533 | num_strings++; | ||
534 | break; | ||
535 | case IPV4_FLOW: | ||
536 | sprintf(p, "\tSrc IP addr: 0x%x\n", | ||
537 | fsc->fs.h_u.usr_ip4_spec.ip4src); | ||
538 | p += ETH_GSTRING_LEN; | ||
539 | num_strings++; | ||
540 | sprintf(p, "\tSrc IP mask: 0x%x\n", | ||
541 | fsc->fs.m_u.usr_ip4_spec.ip4src); | ||
542 | p += ETH_GSTRING_LEN; | ||
543 | num_strings++; | ||
544 | sprintf(p, "\tDest IP addr: 0x%x\n", | ||
545 | fsc->fs.h_u.usr_ip4_spec.ip4dst); | ||
546 | p += ETH_GSTRING_LEN; | ||
547 | num_strings++; | ||
548 | sprintf(p, "\tDest IP mask: 0x%x\n", | ||
549 | fsc->fs.m_u.usr_ip4_spec.ip4dst); | ||
550 | p += ETH_GSTRING_LEN; | ||
551 | num_strings++; | ||
552 | sprintf(p, "\tL4 bytes: 0x%x, mask: 0x%x\n", | ||
553 | fsc->fs.h_u.usr_ip4_spec.l4_4_bytes, | ||
554 | fsc->fs.m_u.usr_ip4_spec.l4_4_bytes); | ||
555 | p += ETH_GSTRING_LEN; | ||
556 | num_strings++; | ||
557 | sprintf(p, "\tTOS: %d, mask: 0x%x\n", | ||
558 | fsc->fs.h_u.usr_ip4_spec.tos, | ||
559 | fsc->fs.m_u.usr_ip4_spec.tos); | ||
560 | p += ETH_GSTRING_LEN; | ||
561 | num_strings++; | ||
562 | sprintf(p, "\tIP Version: %d, mask: 0x%x\n", | ||
563 | fsc->fs.h_u.usr_ip4_spec.ip_ver, | ||
564 | fsc->fs.m_u.usr_ip4_spec.ip_ver); | ||
565 | p += ETH_GSTRING_LEN; | ||
566 | num_strings++; | ||
567 | sprintf(p, "\tProtocol: %d, mask: 0x%x\n", | ||
568 | fsc->fs.h_u.usr_ip4_spec.proto, | ||
569 | fsc->fs.m_u.usr_ip4_spec.proto); | ||
570 | p += ETH_GSTRING_LEN; | ||
571 | num_strings++; | ||
572 | break; | ||
573 | }; | ||
574 | sprintf(p, "\tVLAN: %d, mask: 0x%x\n", | ||
575 | fsc->fs.vlan_tag, fsc->fs.vlan_tag_mask); | ||
576 | p += ETH_GSTRING_LEN; | ||
577 | num_strings++; | ||
578 | sprintf(p, "\tUser-defined: 0x%Lx\n", fsc->fs.data); | ||
579 | p += ETH_GSTRING_LEN; | ||
580 | num_strings++; | ||
581 | sprintf(p, "\tUser-defined mask: 0x%Lx\n", fsc->fs.data_mask); | ||
582 | p += ETH_GSTRING_LEN; | ||
583 | num_strings++; | ||
584 | if (fsc->fs.action == ETHTOOL_RXNTUPLE_ACTION_DROP) | ||
585 | sprintf(p, "\tAction: Drop\n"); | ||
586 | else | ||
587 | sprintf(p, "\tAction: Direct to queue %d\n", | ||
588 | fsc->fs.action); | ||
589 | p += ETH_GSTRING_LEN; | ||
590 | num_strings++; | ||
591 | unknown_filter: | ||
592 | i++; | ||
593 | } | ||
594 | copy: | ||
595 | /* indicate to userspace how many strings we actually have */ | ||
596 | gstrings.len = num_strings; | ||
597 | ret = -EFAULT; | ||
598 | if (copy_to_user(useraddr, &gstrings, sizeof(gstrings))) | ||
599 | goto out; | ||
600 | useraddr += sizeof(gstrings); | ||
601 | if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN)) | ||
602 | goto out; | ||
603 | ret = 0; | ||
604 | |||
605 | out: | ||
606 | kfree(data); | ||
607 | return ret; | ||
608 | } | ||
609 | |||
269 | static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) | 610 | static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) |
270 | { | 611 | { |
271 | struct ethtool_regs regs; | 612 | struct ethtool_regs regs; |
@@ -324,7 +665,7 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr) | |||
324 | 665 | ||
325 | static int ethtool_get_wol(struct net_device *dev, char __user *useraddr) | 666 | static int ethtool_get_wol(struct net_device *dev, char __user *useraddr) |
326 | { | 667 | { |
327 | struct ethtool_wolinfo wol = { ETHTOOL_GWOL }; | 668 | struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL }; |
328 | 669 | ||
329 | if (!dev->ethtool_ops->get_wol) | 670 | if (!dev->ethtool_ops->get_wol) |
330 | return -EOPNOTSUPP; | 671 | return -EOPNOTSUPP; |
@@ -456,9 +797,12 @@ static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr) | |||
456 | return ret; | 797 | return ret; |
457 | } | 798 | } |
458 | 799 | ||
459 | static int ethtool_get_coalesce(struct net_device *dev, void __user *useraddr) | 800 | /* |
801 | * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() | ||
802 | */ | ||
803 | static noinline int ethtool_get_coalesce(struct net_device *dev, void __user *useraddr) | ||
460 | { | 804 | { |
461 | struct ethtool_coalesce coalesce = { ETHTOOL_GCOALESCE }; | 805 | struct ethtool_coalesce coalesce = { .cmd = ETHTOOL_GCOALESCE }; |
462 | 806 | ||
463 | if (!dev->ethtool_ops->get_coalesce) | 807 | if (!dev->ethtool_ops->get_coalesce) |
464 | return -EOPNOTSUPP; | 808 | return -EOPNOTSUPP; |
@@ -470,7 +814,10 @@ static int ethtool_get_coalesce(struct net_device *dev, void __user *useraddr) | |||
470 | return 0; | 814 | return 0; |
471 | } | 815 | } |
472 | 816 | ||
473 | static int ethtool_set_coalesce(struct net_device *dev, void __user *useraddr) | 817 | /* |
818 | * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() | ||
819 | */ | ||
820 | static noinline int ethtool_set_coalesce(struct net_device *dev, void __user *useraddr) | ||
474 | { | 821 | { |
475 | struct ethtool_coalesce coalesce; | 822 | struct ethtool_coalesce coalesce; |
476 | 823 | ||
@@ -485,7 +832,7 @@ static int ethtool_set_coalesce(struct net_device *dev, void __user *useraddr) | |||
485 | 832 | ||
486 | static int ethtool_get_ringparam(struct net_device *dev, void __user *useraddr) | 833 | static int ethtool_get_ringparam(struct net_device *dev, void __user *useraddr) |
487 | { | 834 | { |
488 | struct ethtool_ringparam ringparam = { ETHTOOL_GRINGPARAM }; | 835 | struct ethtool_ringparam ringparam = { .cmd = ETHTOOL_GRINGPARAM }; |
489 | 836 | ||
490 | if (!dev->ethtool_ops->get_ringparam) | 837 | if (!dev->ethtool_ops->get_ringparam) |
491 | return -EOPNOTSUPP; | 838 | return -EOPNOTSUPP; |
@@ -839,7 +1186,7 @@ static int ethtool_get_perm_addr(struct net_device *dev, void __user *useraddr) | |||
839 | static int ethtool_get_value(struct net_device *dev, char __user *useraddr, | 1186 | static int ethtool_get_value(struct net_device *dev, char __user *useraddr, |
840 | u32 cmd, u32 (*actor)(struct net_device *)) | 1187 | u32 cmd, u32 (*actor)(struct net_device *)) |
841 | { | 1188 | { |
842 | struct ethtool_value edata = { cmd }; | 1189 | struct ethtool_value edata = { .cmd = cmd }; |
843 | 1190 | ||
844 | if (!actor) | 1191 | if (!actor) |
845 | return -EOPNOTSUPP; | 1192 | return -EOPNOTSUPP; |
@@ -880,7 +1227,10 @@ static int ethtool_set_value(struct net_device *dev, char __user *useraddr, | |||
880 | return actor(dev, edata.data); | 1227 | return actor(dev, edata.data); |
881 | } | 1228 | } |
882 | 1229 | ||
883 | static int ethtool_flash_device(struct net_device *dev, char __user *useraddr) | 1230 | /* |
1231 | * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() | ||
1232 | */ | ||
1233 | static noinline int ethtool_flash_device(struct net_device *dev, char __user *useraddr) | ||
884 | { | 1234 | { |
885 | struct ethtool_flash efl; | 1235 | struct ethtool_flash efl; |
886 | 1236 | ||
@@ -927,6 +1277,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) | |||
927 | case ETHTOOL_GPERMADDR: | 1277 | case ETHTOOL_GPERMADDR: |
928 | case ETHTOOL_GUFO: | 1278 | case ETHTOOL_GUFO: |
929 | case ETHTOOL_GGSO: | 1279 | case ETHTOOL_GGSO: |
1280 | case ETHTOOL_GGRO: | ||
930 | case ETHTOOL_GFLAGS: | 1281 | case ETHTOOL_GFLAGS: |
931 | case ETHTOOL_GPFLAGS: | 1282 | case ETHTOOL_GPFLAGS: |
932 | case ETHTOOL_GRXFH: | 1283 | case ETHTOOL_GRXFH: |
@@ -1112,6 +1463,12 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) | |||
1112 | case ETHTOOL_RESET: | 1463 | case ETHTOOL_RESET: |
1113 | rc = ethtool_reset(dev, useraddr); | 1464 | rc = ethtool_reset(dev, useraddr); |
1114 | break; | 1465 | break; |
1466 | case ETHTOOL_SRXNTUPLE: | ||
1467 | rc = ethtool_set_rx_ntuple(dev, useraddr); | ||
1468 | break; | ||
1469 | case ETHTOOL_GRXNTUPLE: | ||
1470 | rc = ethtool_get_rx_ntuple(dev, useraddr); | ||
1471 | break; | ||
1115 | default: | 1472 | default: |
1116 | rc = -EOPNOTSUPP; | 1473 | rc = -EOPNOTSUPP; |
1117 | } | 1474 | } |
diff --git a/net/core/filter.c b/net/core/filter.c index 08db7b9143a3..7517110ff4ae 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
@@ -529,6 +529,7 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) | |||
529 | sk_filter_delayed_uncharge(sk, old_fp); | 529 | sk_filter_delayed_uncharge(sk, old_fp); |
530 | return 0; | 530 | return 0; |
531 | } | 531 | } |
532 | EXPORT_SYMBOL_GPL(sk_attach_filter); | ||
532 | 533 | ||
533 | int sk_detach_filter(struct sock *sk) | 534 | int sk_detach_filter(struct sock *sk) |
534 | { | 535 | { |
@@ -545,3 +546,4 @@ int sk_detach_filter(struct sock *sk) | |||
545 | rcu_read_unlock_bh(); | 546 | rcu_read_unlock_bh(); |
546 | return ret; | 547 | return ret; |
547 | } | 548 | } |
549 | EXPORT_SYMBOL_GPL(sk_detach_filter); | ||
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index f2efd72da799..d102f6d9abdc 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -2556,9 +2556,11 @@ EXPORT_SYMBOL(neigh_app_ns); | |||
2556 | 2556 | ||
2557 | #ifdef CONFIG_SYSCTL | 2557 | #ifdef CONFIG_SYSCTL |
2558 | 2558 | ||
2559 | #define NEIGH_VARS_MAX 19 | ||
2560 | |||
2559 | static struct neigh_sysctl_table { | 2561 | static struct neigh_sysctl_table { |
2560 | struct ctl_table_header *sysctl_header; | 2562 | struct ctl_table_header *sysctl_header; |
2561 | struct ctl_table neigh_vars[__NET_NEIGH_MAX]; | 2563 | struct ctl_table neigh_vars[NEIGH_VARS_MAX]; |
2562 | char *dev_name; | 2564 | char *dev_name; |
2563 | } neigh_sysctl_template __read_mostly = { | 2565 | } neigh_sysctl_template __read_mostly = { |
2564 | .neigh_vars = { | 2566 | .neigh_vars = { |
@@ -2675,8 +2677,7 @@ static struct neigh_sysctl_table { | |||
2675 | }; | 2677 | }; |
2676 | 2678 | ||
2677 | int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p, | 2679 | int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p, |
2678 | int p_id, int pdev_id, char *p_name, | 2680 | char *p_name, proc_handler *handler) |
2679 | proc_handler *handler) | ||
2680 | { | 2681 | { |
2681 | struct neigh_sysctl_table *t; | 2682 | struct neigh_sysctl_table *t; |
2682 | const char *dev_name_source = NULL; | 2683 | const char *dev_name_source = NULL; |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 62f3878a6010..42da96a4eeee 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/security.h> | 35 | #include <linux/security.h> |
36 | #include <linux/mutex.h> | 36 | #include <linux/mutex.h> |
37 | #include <linux/if_addr.h> | 37 | #include <linux/if_addr.h> |
38 | #include <linux/pci.h> | ||
38 | 39 | ||
39 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
40 | #include <asm/system.h> | 41 | #include <asm/system.h> |
@@ -580,6 +581,15 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a, | |||
580 | a->tx_compressed = b->tx_compressed; | 581 | a->tx_compressed = b->tx_compressed; |
581 | }; | 582 | }; |
582 | 583 | ||
584 | static inline int rtnl_vfinfo_size(const struct net_device *dev) | ||
585 | { | ||
586 | if (dev->dev.parent && dev_is_pci(dev->dev.parent)) | ||
587 | return dev_num_vf(dev->dev.parent) * | ||
588 | sizeof(struct ifla_vf_info); | ||
589 | else | ||
590 | return 0; | ||
591 | } | ||
592 | |||
583 | static inline size_t if_nlmsg_size(const struct net_device *dev) | 593 | static inline size_t if_nlmsg_size(const struct net_device *dev) |
584 | { | 594 | { |
585 | return NLMSG_ALIGN(sizeof(struct ifinfomsg)) | 595 | return NLMSG_ALIGN(sizeof(struct ifinfomsg)) |
@@ -597,6 +607,8 @@ static inline size_t if_nlmsg_size(const struct net_device *dev) | |||
597 | + nla_total_size(4) /* IFLA_MASTER */ | 607 | + nla_total_size(4) /* IFLA_MASTER */ |
598 | + nla_total_size(1) /* IFLA_OPERSTATE */ | 608 | + nla_total_size(1) /* IFLA_OPERSTATE */ |
599 | + nla_total_size(1) /* IFLA_LINKMODE */ | 609 | + nla_total_size(1) /* IFLA_LINKMODE */ |
610 | + nla_total_size(4) /* IFLA_NUM_VF */ | ||
611 | + nla_total_size(rtnl_vfinfo_size(dev)) /* IFLA_VFINFO */ | ||
600 | + rtnl_link_get_size(dev); /* IFLA_LINKINFO */ | 612 | + rtnl_link_get_size(dev); /* IFLA_LINKINFO */ |
601 | } | 613 | } |
602 | 614 | ||
@@ -665,6 +677,17 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |||
665 | stats = dev_get_stats(dev); | 677 | stats = dev_get_stats(dev); |
666 | copy_rtnl_link_stats(nla_data(attr), stats); | 678 | copy_rtnl_link_stats(nla_data(attr), stats); |
667 | 679 | ||
680 | if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent) { | ||
681 | int i; | ||
682 | struct ifla_vf_info ivi; | ||
683 | |||
684 | NLA_PUT_U32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent)); | ||
685 | for (i = 0; i < dev_num_vf(dev->dev.parent); i++) { | ||
686 | if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi)) | ||
687 | break; | ||
688 | NLA_PUT(skb, IFLA_VFINFO, sizeof(ivi), &ivi); | ||
689 | } | ||
690 | } | ||
668 | if (dev->rtnl_link_ops) { | 691 | if (dev->rtnl_link_ops) { |
669 | if (rtnl_link_fill(skb, dev) < 0) | 692 | if (rtnl_link_fill(skb, dev) < 0) |
670 | goto nla_put_failure; | 693 | goto nla_put_failure; |
@@ -725,6 +748,12 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = { | |||
725 | [IFLA_LINKINFO] = { .type = NLA_NESTED }, | 748 | [IFLA_LINKINFO] = { .type = NLA_NESTED }, |
726 | [IFLA_NET_NS_PID] = { .type = NLA_U32 }, | 749 | [IFLA_NET_NS_PID] = { .type = NLA_U32 }, |
727 | [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, | 750 | [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, |
751 | [IFLA_VF_MAC] = { .type = NLA_BINARY, | ||
752 | .len = sizeof(struct ifla_vf_mac) }, | ||
753 | [IFLA_VF_VLAN] = { .type = NLA_BINARY, | ||
754 | .len = sizeof(struct ifla_vf_vlan) }, | ||
755 | [IFLA_VF_TX_RATE] = { .type = NLA_BINARY, | ||
756 | .len = sizeof(struct ifla_vf_tx_rate) }, | ||
728 | }; | 757 | }; |
729 | EXPORT_SYMBOL(ifla_policy); | 758 | EXPORT_SYMBOL(ifla_policy); |
730 | 759 | ||
@@ -898,6 +927,44 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, | |||
898 | write_unlock_bh(&dev_base_lock); | 927 | write_unlock_bh(&dev_base_lock); |
899 | } | 928 | } |
900 | 929 | ||
930 | if (tb[IFLA_VF_MAC]) { | ||
931 | struct ifla_vf_mac *ivm; | ||
932 | ivm = nla_data(tb[IFLA_VF_MAC]); | ||
933 | write_lock_bh(&dev_base_lock); | ||
934 | if (ops->ndo_set_vf_mac) | ||
935 | err = ops->ndo_set_vf_mac(dev, ivm->vf, ivm->mac); | ||
936 | write_unlock_bh(&dev_base_lock); | ||
937 | if (err < 0) | ||
938 | goto errout; | ||
939 | modified = 1; | ||
940 | } | ||
941 | |||
942 | if (tb[IFLA_VF_VLAN]) { | ||
943 | struct ifla_vf_vlan *ivv; | ||
944 | ivv = nla_data(tb[IFLA_VF_VLAN]); | ||
945 | write_lock_bh(&dev_base_lock); | ||
946 | if (ops->ndo_set_vf_vlan) | ||
947 | err = ops->ndo_set_vf_vlan(dev, ivv->vf, | ||
948 | (u16)ivv->vlan, | ||
949 | (u8)ivv->qos); | ||
950 | write_unlock_bh(&dev_base_lock); | ||
951 | if (err < 0) | ||
952 | goto errout; | ||
953 | modified = 1; | ||
954 | } | ||
955 | err = 0; | ||
956 | |||
957 | if (tb[IFLA_VF_TX_RATE]) { | ||
958 | struct ifla_vf_tx_rate *ivt; | ||
959 | ivt = nla_data(tb[IFLA_VF_TX_RATE]); | ||
960 | write_lock_bh(&dev_base_lock); | ||
961 | if (ops->ndo_set_vf_tx_rate) | ||
962 | err = ops->ndo_set_vf_tx_rate(dev, ivt->vf, ivt->rate); | ||
963 | write_unlock_bh(&dev_base_lock); | ||
964 | if (err < 0) | ||
965 | goto errout; | ||
966 | modified = 1; | ||
967 | } | ||
901 | err = 0; | 968 | err = 0; |
902 | 969 | ||
903 | errout: | 970 | errout: |
diff --git a/net/core/sock.c b/net/core/sock.c index ceef50bd131b..472a59f205b0 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -2228,13 +2228,10 @@ int proto_register(struct proto *prot, int alloc_slab) | |||
2228 | } | 2228 | } |
2229 | 2229 | ||
2230 | if (prot->rsk_prot != NULL) { | 2230 | if (prot->rsk_prot != NULL) { |
2231 | static const char mask[] = "request_sock_%s"; | 2231 | prot->rsk_prot->slab_name = kasprintf(GFP_KERNEL, "request_sock_%s", prot->name); |
2232 | |||
2233 | prot->rsk_prot->slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL); | ||
2234 | if (prot->rsk_prot->slab_name == NULL) | 2232 | if (prot->rsk_prot->slab_name == NULL) |
2235 | goto out_free_sock_slab; | 2233 | goto out_free_sock_slab; |
2236 | 2234 | ||
2237 | sprintf(prot->rsk_prot->slab_name, mask, prot->name); | ||
2238 | prot->rsk_prot->slab = kmem_cache_create(prot->rsk_prot->slab_name, | 2235 | prot->rsk_prot->slab = kmem_cache_create(prot->rsk_prot->slab_name, |
2239 | prot->rsk_prot->obj_size, 0, | 2236 | prot->rsk_prot->obj_size, 0, |
2240 | SLAB_HWCACHE_ALIGN, NULL); | 2237 | SLAB_HWCACHE_ALIGN, NULL); |
@@ -2247,14 +2244,11 @@ int proto_register(struct proto *prot, int alloc_slab) | |||
2247 | } | 2244 | } |
2248 | 2245 | ||
2249 | if (prot->twsk_prot != NULL) { | 2246 | if (prot->twsk_prot != NULL) { |
2250 | static const char mask[] = "tw_sock_%s"; | 2247 | prot->twsk_prot->twsk_slab_name = kasprintf(GFP_KERNEL, "tw_sock_%s", prot->name); |
2251 | |||
2252 | prot->twsk_prot->twsk_slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL); | ||
2253 | 2248 | ||
2254 | if (prot->twsk_prot->twsk_slab_name == NULL) | 2249 | if (prot->twsk_prot->twsk_slab_name == NULL) |
2255 | goto out_free_request_sock_slab; | 2250 | goto out_free_request_sock_slab; |
2256 | 2251 | ||
2257 | sprintf(prot->twsk_prot->twsk_slab_name, mask, prot->name); | ||
2258 | prot->twsk_prot->twsk_slab = | 2252 | prot->twsk_prot->twsk_slab = |
2259 | kmem_cache_create(prot->twsk_prot->twsk_slab_name, | 2253 | kmem_cache_create(prot->twsk_prot->twsk_slab_name, |
2260 | prot->twsk_prot->twsk_obj_size, | 2254 | prot->twsk_prot->twsk_obj_size, |
diff --git a/net/dccp/ccid.c b/net/dccp/ccid.c index ff16e9df1969..49d27c556bec 100644 --- a/net/dccp/ccid.c +++ b/net/dccp/ccid.c | |||
@@ -63,14 +63,13 @@ int ccid_getsockopt_builtin_ccids(struct sock *sk, int len, | |||
63 | u8 *ccid_array, array_len; | 63 | u8 *ccid_array, array_len; |
64 | int err = 0; | 64 | int err = 0; |
65 | 65 | ||
66 | if (len < ARRAY_SIZE(ccids)) | ||
67 | return -EINVAL; | ||
68 | |||
69 | if (ccid_get_builtin_ccids(&ccid_array, &array_len)) | 66 | if (ccid_get_builtin_ccids(&ccid_array, &array_len)) |
70 | return -ENOBUFS; | 67 | return -ENOBUFS; |
71 | 68 | ||
72 | if (put_user(array_len, optlen) || | 69 | if (put_user(array_len, optlen)) |
73 | copy_to_user(optval, ccid_array, array_len)) | 70 | err = -EFAULT; |
71 | else if (len > 0 && copy_to_user(optval, ccid_array, | ||
72 | len > array_len ? array_len : len)) | ||
74 | err = -EFAULT; | 73 | err = -EFAULT; |
75 | 74 | ||
76 | kfree(ccid_array); | 75 | kfree(ccid_array); |
diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 671cd1413d59..0ef7061920c0 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c | |||
@@ -835,6 +835,8 @@ verify_sock_status: | |||
835 | len = -EFAULT; | 835 | len = -EFAULT; |
836 | break; | 836 | break; |
837 | } | 837 | } |
838 | if (flags & MSG_TRUNC) | ||
839 | len = skb->len; | ||
838 | found_fin_ok: | 840 | found_fin_ok: |
839 | if (!(flags & MSG_PEEK)) | 841 | if (!(flags & MSG_PEEK)) |
840 | sk_eat_skb(sk, skb, 0); | 842 | sk_eat_skb(sk, skb, 0); |
@@ -1003,12 +1005,13 @@ EXPORT_SYMBOL_GPL(dccp_shutdown); | |||
1003 | 1005 | ||
1004 | static inline int dccp_mib_init(void) | 1006 | static inline int dccp_mib_init(void) |
1005 | { | 1007 | { |
1006 | return snmp_mib_init((void**)dccp_statistics, sizeof(struct dccp_mib)); | 1008 | return snmp_mib_init((void __percpu **)dccp_statistics, |
1009 | sizeof(struct dccp_mib)); | ||
1007 | } | 1010 | } |
1008 | 1011 | ||
1009 | static inline void dccp_mib_exit(void) | 1012 | static inline void dccp_mib_exit(void) |
1010 | { | 1013 | { |
1011 | snmp_mib_free((void**)dccp_statistics); | 1014 | snmp_mib_free((void __percpu **)dccp_statistics); |
1012 | } | 1015 | } |
1013 | 1016 | ||
1014 | static int thash_entries; | 1017 | static int thash_entries; |
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 7d12c6a9b19b..33b7dffa7732 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -1385,7 +1385,7 @@ int inet_ctl_sock_create(struct sock **sk, unsigned short family, | |||
1385 | } | 1385 | } |
1386 | EXPORT_SYMBOL_GPL(inet_ctl_sock_create); | 1386 | EXPORT_SYMBOL_GPL(inet_ctl_sock_create); |
1387 | 1387 | ||
1388 | unsigned long snmp_fold_field(void *mib[], int offt) | 1388 | unsigned long snmp_fold_field(void __percpu *mib[], int offt) |
1389 | { | 1389 | { |
1390 | unsigned long res = 0; | 1390 | unsigned long res = 0; |
1391 | int i; | 1391 | int i; |
@@ -1398,7 +1398,7 @@ unsigned long snmp_fold_field(void *mib[], int offt) | |||
1398 | } | 1398 | } |
1399 | EXPORT_SYMBOL_GPL(snmp_fold_field); | 1399 | EXPORT_SYMBOL_GPL(snmp_fold_field); |
1400 | 1400 | ||
1401 | int snmp_mib_init(void *ptr[2], size_t mibsize) | 1401 | int snmp_mib_init(void __percpu *ptr[2], size_t mibsize) |
1402 | { | 1402 | { |
1403 | BUG_ON(ptr == NULL); | 1403 | BUG_ON(ptr == NULL); |
1404 | ptr[0] = __alloc_percpu(mibsize, __alignof__(unsigned long long)); | 1404 | ptr[0] = __alloc_percpu(mibsize, __alignof__(unsigned long long)); |
@@ -1416,7 +1416,7 @@ err0: | |||
1416 | } | 1416 | } |
1417 | EXPORT_SYMBOL_GPL(snmp_mib_init); | 1417 | EXPORT_SYMBOL_GPL(snmp_mib_init); |
1418 | 1418 | ||
1419 | void snmp_mib_free(void *ptr[2]) | 1419 | void snmp_mib_free(void __percpu *ptr[2]) |
1420 | { | 1420 | { |
1421 | BUG_ON(ptr == NULL); | 1421 | BUG_ON(ptr == NULL); |
1422 | free_percpu(ptr[0]); | 1422 | free_percpu(ptr[0]); |
@@ -1460,25 +1460,25 @@ static const struct net_protocol icmp_protocol = { | |||
1460 | 1460 | ||
1461 | static __net_init int ipv4_mib_init_net(struct net *net) | 1461 | static __net_init int ipv4_mib_init_net(struct net *net) |
1462 | { | 1462 | { |
1463 | if (snmp_mib_init((void **)net->mib.tcp_statistics, | 1463 | if (snmp_mib_init((void __percpu **)net->mib.tcp_statistics, |
1464 | sizeof(struct tcp_mib)) < 0) | 1464 | sizeof(struct tcp_mib)) < 0) |
1465 | goto err_tcp_mib; | 1465 | goto err_tcp_mib; |
1466 | if (snmp_mib_init((void **)net->mib.ip_statistics, | 1466 | if (snmp_mib_init((void __percpu **)net->mib.ip_statistics, |
1467 | sizeof(struct ipstats_mib)) < 0) | 1467 | sizeof(struct ipstats_mib)) < 0) |
1468 | goto err_ip_mib; | 1468 | goto err_ip_mib; |
1469 | if (snmp_mib_init((void **)net->mib.net_statistics, | 1469 | if (snmp_mib_init((void __percpu **)net->mib.net_statistics, |
1470 | sizeof(struct linux_mib)) < 0) | 1470 | sizeof(struct linux_mib)) < 0) |
1471 | goto err_net_mib; | 1471 | goto err_net_mib; |
1472 | if (snmp_mib_init((void **)net->mib.udp_statistics, | 1472 | if (snmp_mib_init((void __percpu **)net->mib.udp_statistics, |
1473 | sizeof(struct udp_mib)) < 0) | 1473 | sizeof(struct udp_mib)) < 0) |
1474 | goto err_udp_mib; | 1474 | goto err_udp_mib; |
1475 | if (snmp_mib_init((void **)net->mib.udplite_statistics, | 1475 | if (snmp_mib_init((void __percpu **)net->mib.udplite_statistics, |
1476 | sizeof(struct udp_mib)) < 0) | 1476 | sizeof(struct udp_mib)) < 0) |
1477 | goto err_udplite_mib; | 1477 | goto err_udplite_mib; |
1478 | if (snmp_mib_init((void **)net->mib.icmp_statistics, | 1478 | if (snmp_mib_init((void __percpu **)net->mib.icmp_statistics, |
1479 | sizeof(struct icmp_mib)) < 0) | 1479 | sizeof(struct icmp_mib)) < 0) |
1480 | goto err_icmp_mib; | 1480 | goto err_icmp_mib; |
1481 | if (snmp_mib_init((void **)net->mib.icmpmsg_statistics, | 1481 | if (snmp_mib_init((void __percpu **)net->mib.icmpmsg_statistics, |
1482 | sizeof(struct icmpmsg_mib)) < 0) | 1482 | sizeof(struct icmpmsg_mib)) < 0) |
1483 | goto err_icmpmsg_mib; | 1483 | goto err_icmpmsg_mib; |
1484 | 1484 | ||
@@ -1486,30 +1486,30 @@ static __net_init int ipv4_mib_init_net(struct net *net) | |||
1486 | return 0; | 1486 | return 0; |
1487 | 1487 | ||
1488 | err_icmpmsg_mib: | 1488 | err_icmpmsg_mib: |
1489 | snmp_mib_free((void **)net->mib.icmp_statistics); | 1489 | snmp_mib_free((void __percpu **)net->mib.icmp_statistics); |
1490 | err_icmp_mib: | 1490 | err_icmp_mib: |
1491 | snmp_mib_free((void **)net->mib.udplite_statistics); | 1491 | snmp_mib_free((void __percpu **)net->mib.udplite_statistics); |
1492 | err_udplite_mib: | 1492 | err_udplite_mib: |
1493 | snmp_mib_free((void **)net->mib.udp_statistics); | 1493 | snmp_mib_free((void __percpu **)net->mib.udp_statistics); |
1494 | err_udp_mib: | 1494 | err_udp_mib: |
1495 | snmp_mib_free((void **)net->mib.net_statistics); | 1495 | snmp_mib_free((void __percpu **)net->mib.net_statistics); |
1496 | err_net_mib: | 1496 | err_net_mib: |
1497 | snmp_mib_free((void **)net->mib.ip_statistics); | 1497 | snmp_mib_free((void __percpu **)net->mib.ip_statistics); |
1498 | err_ip_mib: | 1498 | err_ip_mib: |
1499 | snmp_mib_free((void **)net->mib.tcp_statistics); | 1499 | snmp_mib_free((void __percpu **)net->mib.tcp_statistics); |
1500 | err_tcp_mib: | 1500 | err_tcp_mib: |
1501 | return -ENOMEM; | 1501 | return -ENOMEM; |
1502 | } | 1502 | } |
1503 | 1503 | ||
1504 | static __net_exit void ipv4_mib_exit_net(struct net *net) | 1504 | static __net_exit void ipv4_mib_exit_net(struct net *net) |
1505 | { | 1505 | { |
1506 | snmp_mib_free((void **)net->mib.icmpmsg_statistics); | 1506 | snmp_mib_free((void __percpu **)net->mib.icmpmsg_statistics); |
1507 | snmp_mib_free((void **)net->mib.icmp_statistics); | 1507 | snmp_mib_free((void __percpu **)net->mib.icmp_statistics); |
1508 | snmp_mib_free((void **)net->mib.udplite_statistics); | 1508 | snmp_mib_free((void __percpu **)net->mib.udplite_statistics); |
1509 | snmp_mib_free((void **)net->mib.udp_statistics); | 1509 | snmp_mib_free((void __percpu **)net->mib.udp_statistics); |
1510 | snmp_mib_free((void **)net->mib.net_statistics); | 1510 | snmp_mib_free((void __percpu **)net->mib.net_statistics); |
1511 | snmp_mib_free((void **)net->mib.ip_statistics); | 1511 | snmp_mib_free((void __percpu **)net->mib.ip_statistics); |
1512 | snmp_mib_free((void **)net->mib.tcp_statistics); | 1512 | snmp_mib_free((void __percpu **)net->mib.tcp_statistics); |
1513 | } | 1513 | } |
1514 | 1514 | ||
1515 | static __net_initdata struct pernet_operations ipv4_mib_ops = { | 1515 | static __net_initdata struct pernet_operations ipv4_mib_ops = { |
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 1940b4df7699..c4dd13542802 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c | |||
@@ -1284,8 +1284,7 @@ void __init arp_init(void) | |||
1284 | dev_add_pack(&arp_packet_type); | 1284 | dev_add_pack(&arp_packet_type); |
1285 | arp_proc_init(); | 1285 | arp_proc_init(); |
1286 | #ifdef CONFIG_SYSCTL | 1286 | #ifdef CONFIG_SYSCTL |
1287 | neigh_sysctl_register(NULL, &arp_tbl.parms, NET_IPV4, | 1287 | neigh_sysctl_register(NULL, &arp_tbl.parms, "ipv4", NULL); |
1288 | NET_IPV4_NEIGH, "ipv4", NULL); | ||
1289 | #endif | 1288 | #endif |
1290 | register_netdevice_notifier(&arp_netdev_notifier); | 1289 | register_netdevice_notifier(&arp_netdev_notifier); |
1291 | } | 1290 | } |
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index cd71a3908391..014982b61564 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
@@ -64,20 +64,20 @@ | |||
64 | 64 | ||
65 | static struct ipv4_devconf ipv4_devconf = { | 65 | static struct ipv4_devconf ipv4_devconf = { |
66 | .data = { | 66 | .data = { |
67 | [NET_IPV4_CONF_ACCEPT_REDIRECTS - 1] = 1, | 67 | [IPV4_DEVCONF_ACCEPT_REDIRECTS - 1] = 1, |
68 | [NET_IPV4_CONF_SEND_REDIRECTS - 1] = 1, | 68 | [IPV4_DEVCONF_SEND_REDIRECTS - 1] = 1, |
69 | [NET_IPV4_CONF_SECURE_REDIRECTS - 1] = 1, | 69 | [IPV4_DEVCONF_SECURE_REDIRECTS - 1] = 1, |
70 | [NET_IPV4_CONF_SHARED_MEDIA - 1] = 1, | 70 | [IPV4_DEVCONF_SHARED_MEDIA - 1] = 1, |
71 | }, | 71 | }, |
72 | }; | 72 | }; |
73 | 73 | ||
74 | static struct ipv4_devconf ipv4_devconf_dflt = { | 74 | static struct ipv4_devconf ipv4_devconf_dflt = { |
75 | .data = { | 75 | .data = { |
76 | [NET_IPV4_CONF_ACCEPT_REDIRECTS - 1] = 1, | 76 | [IPV4_DEVCONF_ACCEPT_REDIRECTS - 1] = 1, |
77 | [NET_IPV4_CONF_SEND_REDIRECTS - 1] = 1, | 77 | [IPV4_DEVCONF_SEND_REDIRECTS - 1] = 1, |
78 | [NET_IPV4_CONF_SECURE_REDIRECTS - 1] = 1, | 78 | [IPV4_DEVCONF_SECURE_REDIRECTS - 1] = 1, |
79 | [NET_IPV4_CONF_SHARED_MEDIA - 1] = 1, | 79 | [IPV4_DEVCONF_SHARED_MEDIA - 1] = 1, |
80 | [NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE - 1] = 1, | 80 | [IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE - 1] = 1, |
81 | }, | 81 | }, |
82 | }; | 82 | }; |
83 | 83 | ||
@@ -1360,7 +1360,7 @@ int ipv4_doint_and_flush(ctl_table *ctl, int write, | |||
1360 | { \ | 1360 | { \ |
1361 | .procname = name, \ | 1361 | .procname = name, \ |
1362 | .data = ipv4_devconf.data + \ | 1362 | .data = ipv4_devconf.data + \ |
1363 | NET_IPV4_CONF_ ## attr - 1, \ | 1363 | IPV4_DEVCONF_ ## attr - 1, \ |
1364 | .maxlen = sizeof(int), \ | 1364 | .maxlen = sizeof(int), \ |
1365 | .mode = mval, \ | 1365 | .mode = mval, \ |
1366 | .proc_handler = proc, \ | 1366 | .proc_handler = proc, \ |
@@ -1381,7 +1381,7 @@ int ipv4_doint_and_flush(ctl_table *ctl, int write, | |||
1381 | 1381 | ||
1382 | static struct devinet_sysctl_table { | 1382 | static struct devinet_sysctl_table { |
1383 | struct ctl_table_header *sysctl_header; | 1383 | struct ctl_table_header *sysctl_header; |
1384 | struct ctl_table devinet_vars[__NET_IPV4_CONF_MAX]; | 1384 | struct ctl_table devinet_vars[__IPV4_DEVCONF_MAX]; |
1385 | char *dev_name; | 1385 | char *dev_name; |
1386 | } devinet_sysctl = { | 1386 | } devinet_sysctl = { |
1387 | .devinet_vars = { | 1387 | .devinet_vars = { |
@@ -1487,8 +1487,7 @@ static void __devinet_sysctl_unregister(struct ipv4_devconf *cnf) | |||
1487 | 1487 | ||
1488 | static void devinet_sysctl_register(struct in_device *idev) | 1488 | static void devinet_sysctl_register(struct in_device *idev) |
1489 | { | 1489 | { |
1490 | neigh_sysctl_register(idev->dev, idev->arp_parms, NET_IPV4, | 1490 | neigh_sysctl_register(idev->dev, idev->arp_parms, "ipv4", NULL); |
1491 | NET_IPV4_NEIGH, "ipv4", NULL); | ||
1492 | __devinet_sysctl_register(dev_net(idev->dev), idev->dev->name, | 1491 | __devinet_sysctl_register(dev_net(idev->dev), idev->dev->name, |
1493 | &idev->cnf); | 1492 | &idev->cnf); |
1494 | } | 1493 | } |
@@ -1503,7 +1502,7 @@ static struct ctl_table ctl_forward_entry[] = { | |||
1503 | { | 1502 | { |
1504 | .procname = "ip_forward", | 1503 | .procname = "ip_forward", |
1505 | .data = &ipv4_devconf.data[ | 1504 | .data = &ipv4_devconf.data[ |
1506 | NET_IPV4_CONF_FORWARDING - 1], | 1505 | IPV4_DEVCONF_FORWARDING - 1], |
1507 | .maxlen = sizeof(int), | 1506 | .maxlen = sizeof(int), |
1508 | .mode = 0644, | 1507 | .mode = 0644, |
1509 | .proc_handler = devinet_sysctl_forward, | 1508 | .proc_handler = devinet_sysctl_forward, |
@@ -1547,7 +1546,7 @@ static __net_init int devinet_init_net(struct net *net) | |||
1547 | if (tbl == NULL) | 1546 | if (tbl == NULL) |
1548 | goto err_alloc_ctl; | 1547 | goto err_alloc_ctl; |
1549 | 1548 | ||
1550 | tbl[0].data = &all->data[NET_IPV4_CONF_FORWARDING - 1]; | 1549 | tbl[0].data = &all->data[IPV4_DEVCONF_FORWARDING - 1]; |
1551 | tbl[0].extra1 = all; | 1550 | tbl[0].extra1 = all; |
1552 | tbl[0].extra2 = net; | 1551 | tbl[0].extra2 = net; |
1553 | #endif | 1552 | #endif |
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index d28363998743..63bf298ca109 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
@@ -946,7 +946,6 @@ int igmp_rcv(struct sk_buff *skb) | |||
946 | break; | 946 | break; |
947 | case IGMP_HOST_MEMBERSHIP_REPORT: | 947 | case IGMP_HOST_MEMBERSHIP_REPORT: |
948 | case IGMPV2_HOST_MEMBERSHIP_REPORT: | 948 | case IGMPV2_HOST_MEMBERSHIP_REPORT: |
949 | case IGMPV3_HOST_MEMBERSHIP_REPORT: | ||
950 | /* Is it our report looped back? */ | 949 | /* Is it our report looped back? */ |
951 | if (skb_rtable(skb)->fl.iif == 0) | 950 | if (skb_rtable(skb)->fl.iif == 0) |
952 | break; | 951 | break; |
@@ -960,6 +959,7 @@ int igmp_rcv(struct sk_buff *skb) | |||
960 | in_dev_put(in_dev); | 959 | in_dev_put(in_dev); |
961 | return pim_rcv_v1(skb); | 960 | return pim_rcv_v1(skb); |
962 | #endif | 961 | #endif |
962 | case IGMPV3_HOST_MEMBERSHIP_REPORT: | ||
963 | case IGMP_DVMRP: | 963 | case IGMP_DVMRP: |
964 | case IGMP_TRACE: | 964 | case IGMP_TRACE: |
965 | case IGMP_HOST_LEAVE_MESSAGE: | 965 | case IGMP_HOST_LEAVE_MESSAGE: |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 7631b20490f5..a2a5983dbf03 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -1665,14 +1665,15 @@ static int __init ipgre_init(void) | |||
1665 | 1665 | ||
1666 | printk(KERN_INFO "GRE over IPv4 tunneling driver\n"); | 1666 | printk(KERN_INFO "GRE over IPv4 tunneling driver\n"); |
1667 | 1667 | ||
1668 | if (inet_add_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) { | ||
1669 | printk(KERN_INFO "ipgre init: can't add protocol\n"); | ||
1670 | return -EAGAIN; | ||
1671 | } | ||
1672 | |||
1673 | err = register_pernet_device(&ipgre_net_ops); | 1668 | err = register_pernet_device(&ipgre_net_ops); |
1674 | if (err < 0) | 1669 | if (err < 0) |
1675 | goto gen_device_failed; | 1670 | return err; |
1671 | |||
1672 | err = inet_add_protocol(&ipgre_protocol, IPPROTO_GRE); | ||
1673 | if (err < 0) { | ||
1674 | printk(KERN_INFO "ipgre init: can't add protocol\n"); | ||
1675 | goto add_proto_failed; | ||
1676 | } | ||
1676 | 1677 | ||
1677 | err = rtnl_link_register(&ipgre_link_ops); | 1678 | err = rtnl_link_register(&ipgre_link_ops); |
1678 | if (err < 0) | 1679 | if (err < 0) |
@@ -1688,9 +1689,9 @@ out: | |||
1688 | tap_ops_failed: | 1689 | tap_ops_failed: |
1689 | rtnl_link_unregister(&ipgre_link_ops); | 1690 | rtnl_link_unregister(&ipgre_link_ops); |
1690 | rtnl_link_failed: | 1691 | rtnl_link_failed: |
1691 | unregister_pernet_device(&ipgre_net_ops); | ||
1692 | gen_device_failed: | ||
1693 | inet_del_protocol(&ipgre_protocol, IPPROTO_GRE); | 1692 | inet_del_protocol(&ipgre_protocol, IPPROTO_GRE); |
1693 | add_proto_failed: | ||
1694 | unregister_pernet_device(&ipgre_net_ops); | ||
1694 | goto out; | 1695 | goto out; |
1695 | } | 1696 | } |
1696 | 1697 | ||
@@ -1698,9 +1699,9 @@ static void __exit ipgre_fini(void) | |||
1698 | { | 1699 | { |
1699 | rtnl_link_unregister(&ipgre_tap_ops); | 1700 | rtnl_link_unregister(&ipgre_tap_ops); |
1700 | rtnl_link_unregister(&ipgre_link_ops); | 1701 | rtnl_link_unregister(&ipgre_link_ops); |
1701 | unregister_pernet_device(&ipgre_net_ops); | ||
1702 | if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) | 1702 | if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) |
1703 | printk(KERN_INFO "ipgre close: can't remove protocol\n"); | 1703 | printk(KERN_INFO "ipgre close: can't remove protocol\n"); |
1704 | unregister_pernet_device(&ipgre_net_ops); | ||
1704 | } | 1705 | } |
1705 | 1706 | ||
1706 | module_init(ipgre_init); | 1707 | module_init(ipgre_init); |
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index b55a0c3df82f..83ed71500898 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c | |||
@@ -127,16 +127,12 @@ static int ipcomp4_init_state(struct xfrm_state *x) | |||
127 | if (x->props.mode == XFRM_MODE_TUNNEL) { | 127 | if (x->props.mode == XFRM_MODE_TUNNEL) { |
128 | err = ipcomp_tunnel_attach(x); | 128 | err = ipcomp_tunnel_attach(x); |
129 | if (err) | 129 | if (err) |
130 | goto error_tunnel; | 130 | goto out; |
131 | } | 131 | } |
132 | 132 | ||
133 | err = 0; | 133 | err = 0; |
134 | out: | 134 | out: |
135 | return err; | 135 | return err; |
136 | |||
137 | error_tunnel: | ||
138 | ipcomp_destroy(x); | ||
139 | goto out; | ||
140 | } | 136 | } |
141 | 137 | ||
142 | static const struct xfrm_type ipcomp_type = { | 138 | static const struct xfrm_type ipcomp_type = { |
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 95db732e542b..2f302d3ac9a3 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
@@ -830,15 +830,14 @@ static int __init ipip_init(void) | |||
830 | 830 | ||
831 | printk(banner); | 831 | printk(banner); |
832 | 832 | ||
833 | if (xfrm4_tunnel_register(&ipip_handler, AF_INET)) { | 833 | err = register_pernet_device(&ipip_net_ops); |
834 | if (err < 0) | ||
835 | return err; | ||
836 | err = xfrm4_tunnel_register(&ipip_handler, AF_INET); | ||
837 | if (err < 0) { | ||
838 | unregister_pernet_device(&ipip_net_ops); | ||
834 | printk(KERN_INFO "ipip init: can't register tunnel\n"); | 839 | printk(KERN_INFO "ipip init: can't register tunnel\n"); |
835 | return -EAGAIN; | ||
836 | } | 840 | } |
837 | |||
838 | err = register_pernet_device(&ipip_net_ops); | ||
839 | if (err) | ||
840 | xfrm4_tunnel_deregister(&ipip_handler, AF_INET); | ||
841 | |||
842 | return err; | 841 | return err; |
843 | } | 842 | } |
844 | 843 | ||
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 54596f73eff5..8582e12e4a62 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
@@ -1163,9 +1163,6 @@ static int ipmr_device_event(struct notifier_block *this, unsigned long event, v | |||
1163 | int ct; | 1163 | int ct; |
1164 | LIST_HEAD(list); | 1164 | LIST_HEAD(list); |
1165 | 1165 | ||
1166 | if (!net_eq(dev_net(dev), net)) | ||
1167 | return NOTIFY_DONE; | ||
1168 | |||
1169 | if (event != NETDEV_UNREGISTER) | 1166 | if (event != NETDEV_UNREGISTER) |
1170 | return NOTIFY_DONE; | 1167 | return NOTIFY_DONE; |
1171 | v = &net->ipv4.vif_table[0]; | 1168 | v = &net->ipv4.vif_table[0]; |
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 1b09a6dde7c0..242ed2307370 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c | |||
@@ -280,7 +280,7 @@ static void icmpmsg_put(struct seq_file *seq) | |||
280 | 280 | ||
281 | count = 0; | 281 | count = 0; |
282 | for (i = 0; i < ICMPMSG_MIB_MAX; i++) { | 282 | for (i = 0; i < ICMPMSG_MIB_MAX; i++) { |
283 | val = snmp_fold_field((void **) net->mib.icmpmsg_statistics, i); | 283 | val = snmp_fold_field((void __percpu **) net->mib.icmpmsg_statistics, i); |
284 | if (val) { | 284 | if (val) { |
285 | type[count] = i; | 285 | type[count] = i; |
286 | vals[count++] = val; | 286 | vals[count++] = val; |
@@ -307,18 +307,18 @@ static void icmp_put(struct seq_file *seq) | |||
307 | for (i=0; icmpmibmap[i].name != NULL; i++) | 307 | for (i=0; icmpmibmap[i].name != NULL; i++) |
308 | seq_printf(seq, " Out%s", icmpmibmap[i].name); | 308 | seq_printf(seq, " Out%s", icmpmibmap[i].name); |
309 | seq_printf(seq, "\nIcmp: %lu %lu", | 309 | seq_printf(seq, "\nIcmp: %lu %lu", |
310 | snmp_fold_field((void **) net->mib.icmp_statistics, ICMP_MIB_INMSGS), | 310 | snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_INMSGS), |
311 | snmp_fold_field((void **) net->mib.icmp_statistics, ICMP_MIB_INERRORS)); | 311 | snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_INERRORS)); |
312 | for (i=0; icmpmibmap[i].name != NULL; i++) | 312 | for (i=0; icmpmibmap[i].name != NULL; i++) |
313 | seq_printf(seq, " %lu", | 313 | seq_printf(seq, " %lu", |
314 | snmp_fold_field((void **) net->mib.icmpmsg_statistics, | 314 | snmp_fold_field((void __percpu **) net->mib.icmpmsg_statistics, |
315 | icmpmibmap[i].index)); | 315 | icmpmibmap[i].index)); |
316 | seq_printf(seq, " %lu %lu", | 316 | seq_printf(seq, " %lu %lu", |
317 | snmp_fold_field((void **) net->mib.icmp_statistics, ICMP_MIB_OUTMSGS), | 317 | snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_OUTMSGS), |
318 | snmp_fold_field((void **) net->mib.icmp_statistics, ICMP_MIB_OUTERRORS)); | 318 | snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_OUTERRORS)); |
319 | for (i=0; icmpmibmap[i].name != NULL; i++) | 319 | for (i=0; icmpmibmap[i].name != NULL; i++) |
320 | seq_printf(seq, " %lu", | 320 | seq_printf(seq, " %lu", |
321 | snmp_fold_field((void **) net->mib.icmpmsg_statistics, | 321 | snmp_fold_field((void __percpu **) net->mib.icmpmsg_statistics, |
322 | icmpmibmap[i].index | 0x100)); | 322 | icmpmibmap[i].index | 0x100)); |
323 | } | 323 | } |
324 | 324 | ||
@@ -341,7 +341,7 @@ static int snmp_seq_show(struct seq_file *seq, void *v) | |||
341 | 341 | ||
342 | for (i = 0; snmp4_ipstats_list[i].name != NULL; i++) | 342 | for (i = 0; snmp4_ipstats_list[i].name != NULL; i++) |
343 | seq_printf(seq, " %lu", | 343 | seq_printf(seq, " %lu", |
344 | snmp_fold_field((void **)net->mib.ip_statistics, | 344 | snmp_fold_field((void __percpu **)net->mib.ip_statistics, |
345 | snmp4_ipstats_list[i].entry)); | 345 | snmp4_ipstats_list[i].entry)); |
346 | 346 | ||
347 | icmp_put(seq); /* RFC 2011 compatibility */ | 347 | icmp_put(seq); /* RFC 2011 compatibility */ |
@@ -356,11 +356,11 @@ static int snmp_seq_show(struct seq_file *seq, void *v) | |||
356 | /* MaxConn field is signed, RFC 2012 */ | 356 | /* MaxConn field is signed, RFC 2012 */ |
357 | if (snmp4_tcp_list[i].entry == TCP_MIB_MAXCONN) | 357 | if (snmp4_tcp_list[i].entry == TCP_MIB_MAXCONN) |
358 | seq_printf(seq, " %ld", | 358 | seq_printf(seq, " %ld", |
359 | snmp_fold_field((void **)net->mib.tcp_statistics, | 359 | snmp_fold_field((void __percpu **)net->mib.tcp_statistics, |
360 | snmp4_tcp_list[i].entry)); | 360 | snmp4_tcp_list[i].entry)); |
361 | else | 361 | else |
362 | seq_printf(seq, " %lu", | 362 | seq_printf(seq, " %lu", |
363 | snmp_fold_field((void **)net->mib.tcp_statistics, | 363 | snmp_fold_field((void __percpu **)net->mib.tcp_statistics, |
364 | snmp4_tcp_list[i].entry)); | 364 | snmp4_tcp_list[i].entry)); |
365 | } | 365 | } |
366 | 366 | ||
@@ -371,7 +371,7 @@ static int snmp_seq_show(struct seq_file *seq, void *v) | |||
371 | seq_puts(seq, "\nUdp:"); | 371 | seq_puts(seq, "\nUdp:"); |
372 | for (i = 0; snmp4_udp_list[i].name != NULL; i++) | 372 | for (i = 0; snmp4_udp_list[i].name != NULL; i++) |
373 | seq_printf(seq, " %lu", | 373 | seq_printf(seq, " %lu", |
374 | snmp_fold_field((void **)net->mib.udp_statistics, | 374 | snmp_fold_field((void __percpu **)net->mib.udp_statistics, |
375 | snmp4_udp_list[i].entry)); | 375 | snmp4_udp_list[i].entry)); |
376 | 376 | ||
377 | /* the UDP and UDP-Lite MIBs are the same */ | 377 | /* the UDP and UDP-Lite MIBs are the same */ |
@@ -382,7 +382,7 @@ static int snmp_seq_show(struct seq_file *seq, void *v) | |||
382 | seq_puts(seq, "\nUdpLite:"); | 382 | seq_puts(seq, "\nUdpLite:"); |
383 | for (i = 0; snmp4_udp_list[i].name != NULL; i++) | 383 | for (i = 0; snmp4_udp_list[i].name != NULL; i++) |
384 | seq_printf(seq, " %lu", | 384 | seq_printf(seq, " %lu", |
385 | snmp_fold_field((void **)net->mib.udplite_statistics, | 385 | snmp_fold_field((void __percpu **)net->mib.udplite_statistics, |
386 | snmp4_udp_list[i].entry)); | 386 | snmp4_udp_list[i].entry)); |
387 | 387 | ||
388 | seq_putc(seq, '\n'); | 388 | seq_putc(seq, '\n'); |
@@ -419,7 +419,7 @@ static int netstat_seq_show(struct seq_file *seq, void *v) | |||
419 | seq_puts(seq, "\nTcpExt:"); | 419 | seq_puts(seq, "\nTcpExt:"); |
420 | for (i = 0; snmp4_net_list[i].name != NULL; i++) | 420 | for (i = 0; snmp4_net_list[i].name != NULL; i++) |
421 | seq_printf(seq, " %lu", | 421 | seq_printf(seq, " %lu", |
422 | snmp_fold_field((void **)net->mib.net_statistics, | 422 | snmp_fold_field((void __percpu **)net->mib.net_statistics, |
423 | snmp4_net_list[i].entry)); | 423 | snmp4_net_list[i].entry)); |
424 | 424 | ||
425 | seq_puts(seq, "\nIpExt:"); | 425 | seq_puts(seq, "\nIpExt:"); |
@@ -429,7 +429,7 @@ static int netstat_seq_show(struct seq_file *seq, void *v) | |||
429 | seq_puts(seq, "\nIpExt:"); | 429 | seq_puts(seq, "\nIpExt:"); |
430 | for (i = 0; snmp4_ipextstats_list[i].name != NULL; i++) | 430 | for (i = 0; snmp4_ipextstats_list[i].name != NULL; i++) |
431 | seq_printf(seq, " %lu", | 431 | seq_printf(seq, " %lu", |
432 | snmp_fold_field((void **)net->mib.ip_statistics, | 432 | snmp_fold_field((void __percpu **)net->mib.ip_statistics, |
433 | snmp4_ipextstats_list[i].entry)); | 433 | snmp4_ipextstats_list[i].entry)); |
434 | 434 | ||
435 | seq_putc(seq, '\n'); | 435 | seq_putc(seq, '\n'); |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index b16dfadbe6d6..04762d3bef71 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -3334,7 +3334,7 @@ static __net_initdata struct pernet_operations rt_secret_timer_ops = { | |||
3334 | 3334 | ||
3335 | 3335 | ||
3336 | #ifdef CONFIG_NET_CLS_ROUTE | 3336 | #ifdef CONFIG_NET_CLS_ROUTE |
3337 | struct ip_rt_acct *ip_rt_acct __read_mostly; | 3337 | struct ip_rt_acct __percpu *ip_rt_acct __read_mostly; |
3338 | #endif /* CONFIG_NET_CLS_ROUTE */ | 3338 | #endif /* CONFIG_NET_CLS_ROUTE */ |
3339 | 3339 | ||
3340 | static __initdata unsigned long rhash_entries; | 3340 | static __initdata unsigned long rhash_entries; |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index d5d69ea8f249..e471d037fcc9 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -2788,10 +2788,10 @@ EXPORT_SYMBOL(tcp_gro_complete); | |||
2788 | 2788 | ||
2789 | #ifdef CONFIG_TCP_MD5SIG | 2789 | #ifdef CONFIG_TCP_MD5SIG |
2790 | static unsigned long tcp_md5sig_users; | 2790 | static unsigned long tcp_md5sig_users; |
2791 | static struct tcp_md5sig_pool **tcp_md5sig_pool; | 2791 | static struct tcp_md5sig_pool * __percpu *tcp_md5sig_pool; |
2792 | static DEFINE_SPINLOCK(tcp_md5sig_pool_lock); | 2792 | static DEFINE_SPINLOCK(tcp_md5sig_pool_lock); |
2793 | 2793 | ||
2794 | static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool **pool) | 2794 | static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool * __percpu *pool) |
2795 | { | 2795 | { |
2796 | int cpu; | 2796 | int cpu; |
2797 | for_each_possible_cpu(cpu) { | 2797 | for_each_possible_cpu(cpu) { |
@@ -2808,7 +2808,7 @@ static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool **pool) | |||
2808 | 2808 | ||
2809 | void tcp_free_md5sig_pool(void) | 2809 | void tcp_free_md5sig_pool(void) |
2810 | { | 2810 | { |
2811 | struct tcp_md5sig_pool **pool = NULL; | 2811 | struct tcp_md5sig_pool * __percpu *pool = NULL; |
2812 | 2812 | ||
2813 | spin_lock_bh(&tcp_md5sig_pool_lock); | 2813 | spin_lock_bh(&tcp_md5sig_pool_lock); |
2814 | if (--tcp_md5sig_users == 0) { | 2814 | if (--tcp_md5sig_users == 0) { |
@@ -2822,10 +2822,11 @@ void tcp_free_md5sig_pool(void) | |||
2822 | 2822 | ||
2823 | EXPORT_SYMBOL(tcp_free_md5sig_pool); | 2823 | EXPORT_SYMBOL(tcp_free_md5sig_pool); |
2824 | 2824 | ||
2825 | static struct tcp_md5sig_pool **__tcp_alloc_md5sig_pool(struct sock *sk) | 2825 | static struct tcp_md5sig_pool * __percpu * |
2826 | __tcp_alloc_md5sig_pool(struct sock *sk) | ||
2826 | { | 2827 | { |
2827 | int cpu; | 2828 | int cpu; |
2828 | struct tcp_md5sig_pool **pool; | 2829 | struct tcp_md5sig_pool * __percpu *pool; |
2829 | 2830 | ||
2830 | pool = alloc_percpu(struct tcp_md5sig_pool *); | 2831 | pool = alloc_percpu(struct tcp_md5sig_pool *); |
2831 | if (!pool) | 2832 | if (!pool) |
@@ -2852,9 +2853,9 @@ out_free: | |||
2852 | return NULL; | 2853 | return NULL; |
2853 | } | 2854 | } |
2854 | 2855 | ||
2855 | struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(struct sock *sk) | 2856 | struct tcp_md5sig_pool * __percpu *tcp_alloc_md5sig_pool(struct sock *sk) |
2856 | { | 2857 | { |
2857 | struct tcp_md5sig_pool **pool; | 2858 | struct tcp_md5sig_pool * __percpu *pool; |
2858 | int alloc = 0; | 2859 | int alloc = 0; |
2859 | 2860 | ||
2860 | retry: | 2861 | retry: |
@@ -2873,7 +2874,9 @@ retry: | |||
2873 | 2874 | ||
2874 | if (alloc) { | 2875 | if (alloc) { |
2875 | /* we cannot hold spinlock here because this may sleep. */ | 2876 | /* we cannot hold spinlock here because this may sleep. */ |
2876 | struct tcp_md5sig_pool **p = __tcp_alloc_md5sig_pool(sk); | 2877 | struct tcp_md5sig_pool * __percpu *p; |
2878 | |||
2879 | p = __tcp_alloc_md5sig_pool(sk); | ||
2877 | spin_lock_bh(&tcp_md5sig_pool_lock); | 2880 | spin_lock_bh(&tcp_md5sig_pool_lock); |
2878 | if (!p) { | 2881 | if (!p) { |
2879 | tcp_md5sig_users--; | 2882 | tcp_md5sig_users--; |
@@ -2897,7 +2900,7 @@ EXPORT_SYMBOL(tcp_alloc_md5sig_pool); | |||
2897 | 2900 | ||
2898 | struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu) | 2901 | struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu) |
2899 | { | 2902 | { |
2900 | struct tcp_md5sig_pool **p; | 2903 | struct tcp_md5sig_pool * __percpu *p; |
2901 | spin_lock_bh(&tcp_md5sig_pool_lock); | 2904 | spin_lock_bh(&tcp_md5sig_pool_lock); |
2902 | p = tcp_md5sig_pool; | 2905 | p = tcp_md5sig_pool; |
2903 | if (p) | 2906 | if (p) |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 28e029632493..3fddc69ccccc 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -5783,11 +5783,9 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
5783 | 5783 | ||
5784 | /* tcp_ack considers this ACK as duplicate | 5784 | /* tcp_ack considers this ACK as duplicate |
5785 | * and does not calculate rtt. | 5785 | * and does not calculate rtt. |
5786 | * Fix it at least with timestamps. | 5786 | * Force it here. |
5787 | */ | 5787 | */ |
5788 | if (tp->rx_opt.saw_tstamp && | 5788 | tcp_ack_update_rtt(sk, 0, 0); |
5789 | tp->rx_opt.rcv_tsecr && !tp->srtt) | ||
5790 | tcp_ack_saw_tstamp(sk, 0); | ||
5791 | 5789 | ||
5792 | if (tp->rx_opt.tstamp_ok) | 5790 | if (tp->rx_opt.tstamp_ok) |
5793 | tp->advmss -= TCPOLEN_TSTAMP_ALIGNED; | 5791 | tp->advmss -= TCPOLEN_TSTAMP_ALIGNED; |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 4f7d2122d818..608a5446d05b 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -1117,7 +1117,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
1117 | struct inet_sock *inet = inet_sk(sk); | 1117 | struct inet_sock *inet = inet_sk(sk); |
1118 | struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; | 1118 | struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; |
1119 | struct sk_buff *skb; | 1119 | struct sk_buff *skb; |
1120 | unsigned int ulen, copied; | 1120 | unsigned int ulen; |
1121 | int peeked; | 1121 | int peeked; |
1122 | int err; | 1122 | int err; |
1123 | int is_udplite = IS_UDPLITE(sk); | 1123 | int is_udplite = IS_UDPLITE(sk); |
@@ -1138,10 +1138,9 @@ try_again: | |||
1138 | goto out; | 1138 | goto out; |
1139 | 1139 | ||
1140 | ulen = skb->len - sizeof(struct udphdr); | 1140 | ulen = skb->len - sizeof(struct udphdr); |
1141 | copied = len; | 1141 | if (len > ulen) |
1142 | if (copied > ulen) | 1142 | len = ulen; |
1143 | copied = ulen; | 1143 | else if (len < ulen) |
1144 | else if (copied < ulen) | ||
1145 | msg->msg_flags |= MSG_TRUNC; | 1144 | msg->msg_flags |= MSG_TRUNC; |
1146 | 1145 | ||
1147 | /* | 1146 | /* |
@@ -1150,14 +1149,14 @@ try_again: | |||
1150 | * coverage checksum (UDP-Lite), do it before the copy. | 1149 | * coverage checksum (UDP-Lite), do it before the copy. |
1151 | */ | 1150 | */ |
1152 | 1151 | ||
1153 | if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { | 1152 | if (len < ulen || UDP_SKB_CB(skb)->partial_cov) { |
1154 | if (udp_lib_checksum_complete(skb)) | 1153 | if (udp_lib_checksum_complete(skb)) |
1155 | goto csum_copy_err; | 1154 | goto csum_copy_err; |
1156 | } | 1155 | } |
1157 | 1156 | ||
1158 | if (skb_csum_unnecessary(skb)) | 1157 | if (skb_csum_unnecessary(skb)) |
1159 | err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), | 1158 | err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), |
1160 | msg->msg_iov, copied); | 1159 | msg->msg_iov, len); |
1161 | else { | 1160 | else { |
1162 | err = skb_copy_and_csum_datagram_iovec(skb, | 1161 | err = skb_copy_and_csum_datagram_iovec(skb, |
1163 | sizeof(struct udphdr), | 1162 | sizeof(struct udphdr), |
@@ -1186,7 +1185,7 @@ try_again: | |||
1186 | if (inet->cmsg_flags) | 1185 | if (inet->cmsg_flags) |
1187 | ip_cmsg_recv(msg, skb); | 1186 | ip_cmsg_recv(msg, skb); |
1188 | 1187 | ||
1189 | err = copied; | 1188 | err = len; |
1190 | if (flags & MSG_TRUNC) | 1189 | if (flags & MSG_TRUNC) |
1191 | err = ulen; | 1190 | err = ulen; |
1192 | 1191 | ||
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 1593289155ff..b0d4a4b23db5 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -278,31 +278,31 @@ static void addrconf_mod_timer(struct inet6_ifaddr *ifp, | |||
278 | 278 | ||
279 | static int snmp6_alloc_dev(struct inet6_dev *idev) | 279 | static int snmp6_alloc_dev(struct inet6_dev *idev) |
280 | { | 280 | { |
281 | if (snmp_mib_init((void **)idev->stats.ipv6, | 281 | if (snmp_mib_init((void __percpu **)idev->stats.ipv6, |
282 | sizeof(struct ipstats_mib)) < 0) | 282 | sizeof(struct ipstats_mib)) < 0) |
283 | goto err_ip; | 283 | goto err_ip; |
284 | if (snmp_mib_init((void **)idev->stats.icmpv6, | 284 | if (snmp_mib_init((void __percpu **)idev->stats.icmpv6, |
285 | sizeof(struct icmpv6_mib)) < 0) | 285 | sizeof(struct icmpv6_mib)) < 0) |
286 | goto err_icmp; | 286 | goto err_icmp; |
287 | if (snmp_mib_init((void **)idev->stats.icmpv6msg, | 287 | if (snmp_mib_init((void __percpu **)idev->stats.icmpv6msg, |
288 | sizeof(struct icmpv6msg_mib)) < 0) | 288 | sizeof(struct icmpv6msg_mib)) < 0) |
289 | goto err_icmpmsg; | 289 | goto err_icmpmsg; |
290 | 290 | ||
291 | return 0; | 291 | return 0; |
292 | 292 | ||
293 | err_icmpmsg: | 293 | err_icmpmsg: |
294 | snmp_mib_free((void **)idev->stats.icmpv6); | 294 | snmp_mib_free((void __percpu **)idev->stats.icmpv6); |
295 | err_icmp: | 295 | err_icmp: |
296 | snmp_mib_free((void **)idev->stats.ipv6); | 296 | snmp_mib_free((void __percpu **)idev->stats.ipv6); |
297 | err_ip: | 297 | err_ip: |
298 | return -ENOMEM; | 298 | return -ENOMEM; |
299 | } | 299 | } |
300 | 300 | ||
301 | static void snmp6_free_dev(struct inet6_dev *idev) | 301 | static void snmp6_free_dev(struct inet6_dev *idev) |
302 | { | 302 | { |
303 | snmp_mib_free((void **)idev->stats.icmpv6msg); | 303 | snmp_mib_free((void __percpu **)idev->stats.icmpv6msg); |
304 | snmp_mib_free((void **)idev->stats.icmpv6); | 304 | snmp_mib_free((void __percpu **)idev->stats.icmpv6); |
305 | snmp_mib_free((void **)idev->stats.ipv6); | 305 | snmp_mib_free((void __percpu **)idev->stats.ipv6); |
306 | } | 306 | } |
307 | 307 | ||
308 | /* Nobody refers to this device, we may destroy it. */ | 308 | /* Nobody refers to this device, we may destroy it. */ |
@@ -2646,7 +2646,8 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2646 | 2646 | ||
2647 | write_lock_bh(&addrconf_hash_lock); | 2647 | write_lock_bh(&addrconf_hash_lock); |
2648 | while ((ifa = *bifa) != NULL) { | 2648 | while ((ifa = *bifa) != NULL) { |
2649 | if (ifa->idev == idev) { | 2649 | if (ifa->idev == idev && |
2650 | (how || !(ifa->flags&IFA_F_PERMANENT))) { | ||
2650 | *bifa = ifa->lst_next; | 2651 | *bifa = ifa->lst_next; |
2651 | ifa->lst_next = NULL; | 2652 | ifa->lst_next = NULL; |
2652 | addrconf_del_timer(ifa); | 2653 | addrconf_del_timer(ifa); |
@@ -2686,18 +2687,30 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2686 | write_lock_bh(&idev->lock); | 2687 | write_lock_bh(&idev->lock); |
2687 | } | 2688 | } |
2688 | #endif | 2689 | #endif |
2689 | while ((ifa = idev->addr_list) != NULL) { | 2690 | bifa = &idev->addr_list; |
2690 | idev->addr_list = ifa->if_next; | 2691 | while ((ifa = *bifa) != NULL) { |
2691 | ifa->if_next = NULL; | 2692 | if (how == 0 && (ifa->flags&IFA_F_PERMANENT)) { |
2692 | ifa->dead = 1; | 2693 | /* Retain permanent address on admin down */ |
2693 | addrconf_del_timer(ifa); | 2694 | bifa = &ifa->if_next; |
2694 | write_unlock_bh(&idev->lock); | 2695 | |
2696 | /* Restart DAD if needed when link comes back up */ | ||
2697 | if ( !((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) || | ||
2698 | idev->cnf.accept_dad <= 0 || | ||
2699 | (ifa->flags & IFA_F_NODAD))) | ||
2700 | ifa->flags |= IFA_F_TENTATIVE; | ||
2701 | } else { | ||
2702 | *bifa = ifa->if_next; | ||
2703 | ifa->if_next = NULL; | ||
2695 | 2704 | ||
2696 | __ipv6_ifa_notify(RTM_DELADDR, ifa); | 2705 | ifa->dead = 1; |
2697 | atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa); | 2706 | write_unlock_bh(&idev->lock); |
2698 | in6_ifa_put(ifa); | ||
2699 | 2707 | ||
2700 | write_lock_bh(&idev->lock); | 2708 | __ipv6_ifa_notify(RTM_DELADDR, ifa); |
2709 | atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa); | ||
2710 | in6_ifa_put(ifa); | ||
2711 | |||
2712 | write_lock_bh(&idev->lock); | ||
2713 | } | ||
2701 | } | 2714 | } |
2702 | write_unlock_bh(&idev->lock); | 2715 | write_unlock_bh(&idev->lock); |
2703 | 2716 | ||
@@ -2789,14 +2802,14 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
2789 | read_lock_bh(&idev->lock); | 2802 | read_lock_bh(&idev->lock); |
2790 | if (ifp->dead) | 2803 | if (ifp->dead) |
2791 | goto out; | 2804 | goto out; |
2792 | spin_lock_bh(&ifp->lock); | ||
2793 | 2805 | ||
2806 | spin_lock(&ifp->lock); | ||
2794 | if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || | 2807 | if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || |
2795 | idev->cnf.accept_dad < 1 || | 2808 | idev->cnf.accept_dad < 1 || |
2796 | !(ifp->flags&IFA_F_TENTATIVE) || | 2809 | !(ifp->flags&IFA_F_TENTATIVE) || |
2797 | ifp->flags & IFA_F_NODAD) { | 2810 | ifp->flags & IFA_F_NODAD) { |
2798 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); | 2811 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); |
2799 | spin_unlock_bh(&ifp->lock); | 2812 | spin_unlock(&ifp->lock); |
2800 | read_unlock_bh(&idev->lock); | 2813 | read_unlock_bh(&idev->lock); |
2801 | 2814 | ||
2802 | addrconf_dad_completed(ifp); | 2815 | addrconf_dad_completed(ifp); |
@@ -2804,7 +2817,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
2804 | } | 2817 | } |
2805 | 2818 | ||
2806 | if (!(idev->if_flags & IF_READY)) { | 2819 | if (!(idev->if_flags & IF_READY)) { |
2807 | spin_unlock_bh(&ifp->lock); | 2820 | spin_unlock(&ifp->lock); |
2808 | read_unlock_bh(&idev->lock); | 2821 | read_unlock_bh(&idev->lock); |
2809 | /* | 2822 | /* |
2810 | * If the device is not ready: | 2823 | * If the device is not ready: |
@@ -2824,7 +2837,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
2824 | ip6_ins_rt(ifp->rt); | 2837 | ip6_ins_rt(ifp->rt); |
2825 | 2838 | ||
2826 | addrconf_dad_kick(ifp); | 2839 | addrconf_dad_kick(ifp); |
2827 | spin_unlock_bh(&ifp->lock); | 2840 | spin_unlock(&ifp->lock); |
2828 | out: | 2841 | out: |
2829 | read_unlock_bh(&idev->lock); | 2842 | read_unlock_bh(&idev->lock); |
2830 | } | 2843 | } |
@@ -2840,14 +2853,15 @@ static void addrconf_dad_timer(unsigned long data) | |||
2840 | read_unlock_bh(&idev->lock); | 2853 | read_unlock_bh(&idev->lock); |
2841 | goto out; | 2854 | goto out; |
2842 | } | 2855 | } |
2843 | spin_lock_bh(&ifp->lock); | 2856 | |
2857 | spin_lock(&ifp->lock); | ||
2844 | if (ifp->probes == 0) { | 2858 | if (ifp->probes == 0) { |
2845 | /* | 2859 | /* |
2846 | * DAD was successful | 2860 | * DAD was successful |
2847 | */ | 2861 | */ |
2848 | 2862 | ||
2849 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); | 2863 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); |
2850 | spin_unlock_bh(&ifp->lock); | 2864 | spin_unlock(&ifp->lock); |
2851 | read_unlock_bh(&idev->lock); | 2865 | read_unlock_bh(&idev->lock); |
2852 | 2866 | ||
2853 | addrconf_dad_completed(ifp); | 2867 | addrconf_dad_completed(ifp); |
@@ -2857,7 +2871,7 @@ static void addrconf_dad_timer(unsigned long data) | |||
2857 | 2871 | ||
2858 | ifp->probes--; | 2872 | ifp->probes--; |
2859 | addrconf_mod_timer(ifp, AC_DAD, ifp->idev->nd_parms->retrans_time); | 2873 | addrconf_mod_timer(ifp, AC_DAD, ifp->idev->nd_parms->retrans_time); |
2860 | spin_unlock_bh(&ifp->lock); | 2874 | spin_unlock(&ifp->lock); |
2861 | read_unlock_bh(&idev->lock); | 2875 | read_unlock_bh(&idev->lock); |
2862 | 2876 | ||
2863 | /* send a neighbour solicitation for our addr */ | 2877 | /* send a neighbour solicitation for our addr */ |
@@ -2905,12 +2919,12 @@ static void addrconf_dad_run(struct inet6_dev *idev) { | |||
2905 | 2919 | ||
2906 | read_lock_bh(&idev->lock); | 2920 | read_lock_bh(&idev->lock); |
2907 | for (ifp = idev->addr_list; ifp; ifp = ifp->if_next) { | 2921 | for (ifp = idev->addr_list; ifp; ifp = ifp->if_next) { |
2908 | spin_lock_bh(&ifp->lock); | 2922 | spin_lock(&ifp->lock); |
2909 | if (!(ifp->flags & IFA_F_TENTATIVE)) { | 2923 | if (!(ifp->flags & IFA_F_TENTATIVE)) { |
2910 | spin_unlock_bh(&ifp->lock); | 2924 | spin_unlock(&ifp->lock); |
2911 | continue; | 2925 | continue; |
2912 | } | 2926 | } |
2913 | spin_unlock_bh(&ifp->lock); | 2927 | spin_unlock(&ifp->lock); |
2914 | addrconf_dad_kick(ifp); | 2928 | addrconf_dad_kick(ifp); |
2915 | } | 2929 | } |
2916 | read_unlock_bh(&idev->lock); | 2930 | read_unlock_bh(&idev->lock); |
@@ -3752,8 +3766,8 @@ static inline size_t inet6_if_nlmsg_size(void) | |||
3752 | ); | 3766 | ); |
3753 | } | 3767 | } |
3754 | 3768 | ||
3755 | static inline void __snmp6_fill_stats(u64 *stats, void **mib, int items, | 3769 | static inline void __snmp6_fill_stats(u64 *stats, void __percpu **mib, |
3756 | int bytes) | 3770 | int items, int bytes) |
3757 | { | 3771 | { |
3758 | int i; | 3772 | int i; |
3759 | int pad = bytes - sizeof(u64) * items; | 3773 | int pad = bytes - sizeof(u64) * items; |
@@ -3772,10 +3786,10 @@ static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, | |||
3772 | { | 3786 | { |
3773 | switch(attrtype) { | 3787 | switch(attrtype) { |
3774 | case IFLA_INET6_STATS: | 3788 | case IFLA_INET6_STATS: |
3775 | __snmp6_fill_stats(stats, (void **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes); | 3789 | __snmp6_fill_stats(stats, (void __percpu **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes); |
3776 | break; | 3790 | break; |
3777 | case IFLA_INET6_ICMP6STATS: | 3791 | case IFLA_INET6_ICMP6STATS: |
3778 | __snmp6_fill_stats(stats, (void **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes); | 3792 | __snmp6_fill_stats(stats, (void __percpu **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes); |
3779 | break; | 3793 | break; |
3780 | } | 3794 | } |
3781 | } | 3795 | } |
@@ -4402,8 +4416,7 @@ static void __addrconf_sysctl_unregister(struct ipv6_devconf *p) | |||
4402 | 4416 | ||
4403 | static void addrconf_sysctl_register(struct inet6_dev *idev) | 4417 | static void addrconf_sysctl_register(struct inet6_dev *idev) |
4404 | { | 4418 | { |
4405 | neigh_sysctl_register(idev->dev, idev->nd_parms, NET_IPV6, | 4419 | neigh_sysctl_register(idev->dev, idev->nd_parms, "ipv6", |
4406 | NET_IPV6_NEIGH, "ipv6", | ||
4407 | &ndisc_ifinfo_sysctl_change); | 4420 | &ndisc_ifinfo_sysctl_change); |
4408 | __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name, | 4421 | __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name, |
4409 | idev, &idev->cnf); | 4422 | idev, &idev->cnf); |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index e29160ff4a0f..37d14e735c27 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -971,41 +971,41 @@ static void ipv6_packet_cleanup(void) | |||
971 | 971 | ||
972 | static int __net_init ipv6_init_mibs(struct net *net) | 972 | static int __net_init ipv6_init_mibs(struct net *net) |
973 | { | 973 | { |
974 | if (snmp_mib_init((void **)net->mib.udp_stats_in6, | 974 | if (snmp_mib_init((void __percpu **)net->mib.udp_stats_in6, |
975 | sizeof (struct udp_mib)) < 0) | 975 | sizeof (struct udp_mib)) < 0) |
976 | return -ENOMEM; | 976 | return -ENOMEM; |
977 | if (snmp_mib_init((void **)net->mib.udplite_stats_in6, | 977 | if (snmp_mib_init((void __percpu **)net->mib.udplite_stats_in6, |
978 | sizeof (struct udp_mib)) < 0) | 978 | sizeof (struct udp_mib)) < 0) |
979 | goto err_udplite_mib; | 979 | goto err_udplite_mib; |
980 | if (snmp_mib_init((void **)net->mib.ipv6_statistics, | 980 | if (snmp_mib_init((void __percpu **)net->mib.ipv6_statistics, |
981 | sizeof(struct ipstats_mib)) < 0) | 981 | sizeof(struct ipstats_mib)) < 0) |
982 | goto err_ip_mib; | 982 | goto err_ip_mib; |
983 | if (snmp_mib_init((void **)net->mib.icmpv6_statistics, | 983 | if (snmp_mib_init((void __percpu **)net->mib.icmpv6_statistics, |
984 | sizeof(struct icmpv6_mib)) < 0) | 984 | sizeof(struct icmpv6_mib)) < 0) |
985 | goto err_icmp_mib; | 985 | goto err_icmp_mib; |
986 | if (snmp_mib_init((void **)net->mib.icmpv6msg_statistics, | 986 | if (snmp_mib_init((void __percpu **)net->mib.icmpv6msg_statistics, |
987 | sizeof(struct icmpv6msg_mib)) < 0) | 987 | sizeof(struct icmpv6msg_mib)) < 0) |
988 | goto err_icmpmsg_mib; | 988 | goto err_icmpmsg_mib; |
989 | return 0; | 989 | return 0; |
990 | 990 | ||
991 | err_icmpmsg_mib: | 991 | err_icmpmsg_mib: |
992 | snmp_mib_free((void **)net->mib.icmpv6_statistics); | 992 | snmp_mib_free((void __percpu **)net->mib.icmpv6_statistics); |
993 | err_icmp_mib: | 993 | err_icmp_mib: |
994 | snmp_mib_free((void **)net->mib.ipv6_statistics); | 994 | snmp_mib_free((void __percpu **)net->mib.ipv6_statistics); |
995 | err_ip_mib: | 995 | err_ip_mib: |
996 | snmp_mib_free((void **)net->mib.udplite_stats_in6); | 996 | snmp_mib_free((void __percpu **)net->mib.udplite_stats_in6); |
997 | err_udplite_mib: | 997 | err_udplite_mib: |
998 | snmp_mib_free((void **)net->mib.udp_stats_in6); | 998 | snmp_mib_free((void __percpu **)net->mib.udp_stats_in6); |
999 | return -ENOMEM; | 999 | return -ENOMEM; |
1000 | } | 1000 | } |
1001 | 1001 | ||
1002 | static void ipv6_cleanup_mibs(struct net *net) | 1002 | static void ipv6_cleanup_mibs(struct net *net) |
1003 | { | 1003 | { |
1004 | snmp_mib_free((void **)net->mib.udp_stats_in6); | 1004 | snmp_mib_free((void __percpu **)net->mib.udp_stats_in6); |
1005 | snmp_mib_free((void **)net->mib.udplite_stats_in6); | 1005 | snmp_mib_free((void __percpu **)net->mib.udplite_stats_in6); |
1006 | snmp_mib_free((void **)net->mib.ipv6_statistics); | 1006 | snmp_mib_free((void __percpu **)net->mib.ipv6_statistics); |
1007 | snmp_mib_free((void **)net->mib.icmpv6_statistics); | 1007 | snmp_mib_free((void __percpu **)net->mib.icmpv6_statistics); |
1008 | snmp_mib_free((void **)net->mib.icmpv6msg_statistics); | 1008 | snmp_mib_free((void __percpu **)net->mib.icmpv6msg_statistics); |
1009 | } | 1009 | } |
1010 | 1010 | ||
1011 | static int __net_init inet6_net_init(struct net *net) | 1011 | static int __net_init inet6_net_init(struct net *net) |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index f626ea2b304f..77e122f53ea6 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -319,12 +319,26 @@ static int fib6_dump_table(struct fib6_table *table, struct sk_buff *skb, | |||
319 | w->root = &table->tb6_root; | 319 | w->root = &table->tb6_root; |
320 | 320 | ||
321 | if (cb->args[4] == 0) { | 321 | if (cb->args[4] == 0) { |
322 | w->count = 0; | ||
323 | w->skip = 0; | ||
324 | |||
322 | read_lock_bh(&table->tb6_lock); | 325 | read_lock_bh(&table->tb6_lock); |
323 | res = fib6_walk(w); | 326 | res = fib6_walk(w); |
324 | read_unlock_bh(&table->tb6_lock); | 327 | read_unlock_bh(&table->tb6_lock); |
325 | if (res > 0) | 328 | if (res > 0) { |
326 | cb->args[4] = 1; | 329 | cb->args[4] = 1; |
330 | cb->args[5] = w->root->fn_sernum; | ||
331 | } | ||
327 | } else { | 332 | } else { |
333 | if (cb->args[5] != w->root->fn_sernum) { | ||
334 | /* Begin at the root if the tree changed */ | ||
335 | cb->args[5] = w->root->fn_sernum; | ||
336 | w->state = FWS_INIT; | ||
337 | w->node = w->root; | ||
338 | w->skip = w->count; | ||
339 | } else | ||
340 | w->skip = 0; | ||
341 | |||
328 | read_lock_bh(&table->tb6_lock); | 342 | read_lock_bh(&table->tb6_lock); |
329 | res = fib6_walk_continue(w); | 343 | res = fib6_walk_continue(w); |
330 | read_unlock_bh(&table->tb6_lock); | 344 | read_unlock_bh(&table->tb6_lock); |
@@ -1250,9 +1264,18 @@ static int fib6_walk_continue(struct fib6_walker_t *w) | |||
1250 | w->leaf = fn->leaf; | 1264 | w->leaf = fn->leaf; |
1251 | case FWS_C: | 1265 | case FWS_C: |
1252 | if (w->leaf && fn->fn_flags&RTN_RTINFO) { | 1266 | if (w->leaf && fn->fn_flags&RTN_RTINFO) { |
1253 | int err = w->func(w); | 1267 | int err; |
1268 | |||
1269 | if (w->count < w->skip) { | ||
1270 | w->count++; | ||
1271 | continue; | ||
1272 | } | ||
1273 | |||
1274 | err = w->func(w); | ||
1254 | if (err) | 1275 | if (err) |
1255 | return err; | 1276 | return err; |
1277 | |||
1278 | w->count++; | ||
1256 | continue; | 1279 | continue; |
1257 | } | 1280 | } |
1258 | w->state = FWS_U; | 1281 | w->state = FWS_U; |
@@ -1346,6 +1369,8 @@ static void fib6_clean_tree(struct net *net, struct fib6_node *root, | |||
1346 | c.w.root = root; | 1369 | c.w.root = root; |
1347 | c.w.func = fib6_clean_node; | 1370 | c.w.func = fib6_clean_node; |
1348 | c.w.prune = prune; | 1371 | c.w.prune = prune; |
1372 | c.w.count = 0; | ||
1373 | c.w.skip = 0; | ||
1349 | c.func = func; | 1374 | c.func = func; |
1350 | c.arg = arg; | 1375 | c.arg = arg; |
1351 | c.net = net; | 1376 | c.net = net; |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index fbd786981aa9..9b02492d8706 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -1461,27 +1461,29 @@ static int __init ip6_tunnel_init(void) | |||
1461 | { | 1461 | { |
1462 | int err; | 1462 | int err; |
1463 | 1463 | ||
1464 | if (xfrm6_tunnel_register(&ip4ip6_handler, AF_INET)) { | 1464 | err = register_pernet_device(&ip6_tnl_net_ops); |
1465 | if (err < 0) | ||
1466 | goto out_pernet; | ||
1467 | |||
1468 | err = xfrm6_tunnel_register(&ip4ip6_handler, AF_INET); | ||
1469 | if (err < 0) { | ||
1465 | printk(KERN_ERR "ip6_tunnel init: can't register ip4ip6\n"); | 1470 | printk(KERN_ERR "ip6_tunnel init: can't register ip4ip6\n"); |
1466 | err = -EAGAIN; | 1471 | goto out_ip4ip6; |
1467 | goto out; | ||
1468 | } | 1472 | } |
1469 | 1473 | ||
1470 | if (xfrm6_tunnel_register(&ip6ip6_handler, AF_INET6)) { | 1474 | err = xfrm6_tunnel_register(&ip6ip6_handler, AF_INET6); |
1475 | if (err < 0) { | ||
1471 | printk(KERN_ERR "ip6_tunnel init: can't register ip6ip6\n"); | 1476 | printk(KERN_ERR "ip6_tunnel init: can't register ip6ip6\n"); |
1472 | err = -EAGAIN; | 1477 | goto out_ip6ip6; |
1473 | goto unreg_ip4ip6; | ||
1474 | } | 1478 | } |
1475 | 1479 | ||
1476 | err = register_pernet_device(&ip6_tnl_net_ops); | ||
1477 | if (err < 0) | ||
1478 | goto err_pernet; | ||
1479 | return 0; | 1480 | return 0; |
1480 | err_pernet: | 1481 | |
1481 | xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6); | 1482 | out_ip6ip6: |
1482 | unreg_ip4ip6: | ||
1483 | xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET); | 1483 | xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET); |
1484 | out: | 1484 | out_ip4ip6: |
1485 | unregister_pernet_device(&ip6_tnl_net_ops); | ||
1486 | out_pernet: | ||
1485 | return err; | 1487 | return err; |
1486 | } | 1488 | } |
1487 | 1489 | ||
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index a9fbb151bb79..bb42f39c1db8 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c | |||
@@ -157,16 +157,12 @@ static int ipcomp6_init_state(struct xfrm_state *x) | |||
157 | if (x->props.mode == XFRM_MODE_TUNNEL) { | 157 | if (x->props.mode == XFRM_MODE_TUNNEL) { |
158 | err = ipcomp6_tunnel_attach(x); | 158 | err = ipcomp6_tunnel_attach(x); |
159 | if (err) | 159 | if (err) |
160 | goto error_tunnel; | 160 | goto out; |
161 | } | 161 | } |
162 | 162 | ||
163 | err = 0; | 163 | err = 0; |
164 | out: | 164 | out: |
165 | return err; | 165 | return err; |
166 | error_tunnel: | ||
167 | ipcomp_destroy(x); | ||
168 | |||
169 | goto out; | ||
170 | } | 166 | } |
171 | 167 | ||
172 | static const struct xfrm_type ipcomp6_type = | 168 | static const struct xfrm_type ipcomp6_type = |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 25f6cca79e6b..bcd971915969 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -793,10 +793,10 @@ static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im) | |||
793 | } | 793 | } |
794 | spin_unlock_bh(&im->mca_lock); | 794 | spin_unlock_bh(&im->mca_lock); |
795 | 795 | ||
796 | write_lock_bh(&idev->mc_lock); | 796 | spin_lock_bh(&idev->mc_lock); |
797 | pmc->next = idev->mc_tomb; | 797 | pmc->next = idev->mc_tomb; |
798 | idev->mc_tomb = pmc; | 798 | idev->mc_tomb = pmc; |
799 | write_unlock_bh(&idev->mc_lock); | 799 | spin_unlock_bh(&idev->mc_lock); |
800 | } | 800 | } |
801 | 801 | ||
802 | static void mld_del_delrec(struct inet6_dev *idev, struct in6_addr *pmca) | 802 | static void mld_del_delrec(struct inet6_dev *idev, struct in6_addr *pmca) |
@@ -804,7 +804,7 @@ static void mld_del_delrec(struct inet6_dev *idev, struct in6_addr *pmca) | |||
804 | struct ifmcaddr6 *pmc, *pmc_prev; | 804 | struct ifmcaddr6 *pmc, *pmc_prev; |
805 | struct ip6_sf_list *psf, *psf_next; | 805 | struct ip6_sf_list *psf, *psf_next; |
806 | 806 | ||
807 | write_lock_bh(&idev->mc_lock); | 807 | spin_lock_bh(&idev->mc_lock); |
808 | pmc_prev = NULL; | 808 | pmc_prev = NULL; |
809 | for (pmc=idev->mc_tomb; pmc; pmc=pmc->next) { | 809 | for (pmc=idev->mc_tomb; pmc; pmc=pmc->next) { |
810 | if (ipv6_addr_equal(&pmc->mca_addr, pmca)) | 810 | if (ipv6_addr_equal(&pmc->mca_addr, pmca)) |
@@ -817,7 +817,8 @@ static void mld_del_delrec(struct inet6_dev *idev, struct in6_addr *pmca) | |||
817 | else | 817 | else |
818 | idev->mc_tomb = pmc->next; | 818 | idev->mc_tomb = pmc->next; |
819 | } | 819 | } |
820 | write_unlock_bh(&idev->mc_lock); | 820 | spin_unlock_bh(&idev->mc_lock); |
821 | |||
821 | if (pmc) { | 822 | if (pmc) { |
822 | for (psf=pmc->mca_tomb; psf; psf=psf_next) { | 823 | for (psf=pmc->mca_tomb; psf; psf=psf_next) { |
823 | psf_next = psf->sf_next; | 824 | psf_next = psf->sf_next; |
@@ -832,10 +833,10 @@ static void mld_clear_delrec(struct inet6_dev *idev) | |||
832 | { | 833 | { |
833 | struct ifmcaddr6 *pmc, *nextpmc; | 834 | struct ifmcaddr6 *pmc, *nextpmc; |
834 | 835 | ||
835 | write_lock_bh(&idev->mc_lock); | 836 | spin_lock_bh(&idev->mc_lock); |
836 | pmc = idev->mc_tomb; | 837 | pmc = idev->mc_tomb; |
837 | idev->mc_tomb = NULL; | 838 | idev->mc_tomb = NULL; |
838 | write_unlock_bh(&idev->mc_lock); | 839 | spin_unlock_bh(&idev->mc_lock); |
839 | 840 | ||
840 | for (; pmc; pmc = nextpmc) { | 841 | for (; pmc; pmc = nextpmc) { |
841 | nextpmc = pmc->next; | 842 | nextpmc = pmc->next; |
@@ -1696,7 +1697,7 @@ static void mld_send_cr(struct inet6_dev *idev) | |||
1696 | int type, dtype; | 1697 | int type, dtype; |
1697 | 1698 | ||
1698 | read_lock_bh(&idev->lock); | 1699 | read_lock_bh(&idev->lock); |
1699 | write_lock_bh(&idev->mc_lock); | 1700 | spin_lock(&idev->mc_lock); |
1700 | 1701 | ||
1701 | /* deleted MCA's */ | 1702 | /* deleted MCA's */ |
1702 | pmc_prev = NULL; | 1703 | pmc_prev = NULL; |
@@ -1730,7 +1731,7 @@ static void mld_send_cr(struct inet6_dev *idev) | |||
1730 | } else | 1731 | } else |
1731 | pmc_prev = pmc; | 1732 | pmc_prev = pmc; |
1732 | } | 1733 | } |
1733 | write_unlock_bh(&idev->mc_lock); | 1734 | spin_unlock(&idev->mc_lock); |
1734 | 1735 | ||
1735 | /* change recs */ | 1736 | /* change recs */ |
1736 | for (pmc=idev->mc_list; pmc; pmc=pmc->next) { | 1737 | for (pmc=idev->mc_list; pmc; pmc=pmc->next) { |
@@ -2311,7 +2312,7 @@ void ipv6_mc_up(struct inet6_dev *idev) | |||
2311 | void ipv6_mc_init_dev(struct inet6_dev *idev) | 2312 | void ipv6_mc_init_dev(struct inet6_dev *idev) |
2312 | { | 2313 | { |
2313 | write_lock_bh(&idev->lock); | 2314 | write_lock_bh(&idev->lock); |
2314 | rwlock_init(&idev->mc_lock); | 2315 | spin_lock_init(&idev->mc_lock); |
2315 | idev->mc_gq_running = 0; | 2316 | idev->mc_gq_running = 0; |
2316 | setup_timer(&idev->mc_gq_timer, mld_gq_timer_expire, | 2317 | setup_timer(&idev->mc_gq_timer, mld_gq_timer_expire, |
2317 | (unsigned long)idev); | 2318 | (unsigned long)idev); |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 2dfec6bb8ada..8bcc4b7db3bf 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -1820,8 +1820,7 @@ int __init ndisc_init(void) | |||
1820 | neigh_table_init(&nd_tbl); | 1820 | neigh_table_init(&nd_tbl); |
1821 | 1821 | ||
1822 | #ifdef CONFIG_SYSCTL | 1822 | #ifdef CONFIG_SYSCTL |
1823 | err = neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6, | 1823 | err = neigh_sysctl_register(NULL, &nd_tbl.parms, "ipv6", |
1824 | NET_IPV6_NEIGH, "ipv6", | ||
1825 | &ndisc_ifinfo_sysctl_change); | 1824 | &ndisc_ifinfo_sysctl_change); |
1826 | if (err) | 1825 | if (err) |
1827 | goto out_unregister_pernet; | 1826 | goto out_unregister_pernet; |
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index bfe2598dd563..58344c0fbd13 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c | |||
@@ -136,7 +136,7 @@ static const struct snmp_mib snmp6_udplite6_list[] = { | |||
136 | SNMP_MIB_SENTINEL | 136 | SNMP_MIB_SENTINEL |
137 | }; | 137 | }; |
138 | 138 | ||
139 | static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void **mib) | 139 | static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void __percpu **mib) |
140 | { | 140 | { |
141 | char name[32]; | 141 | char name[32]; |
142 | int i; | 142 | int i; |
@@ -170,7 +170,7 @@ static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void **mib) | |||
170 | return; | 170 | return; |
171 | } | 171 | } |
172 | 172 | ||
173 | static void snmp6_seq_show_item(struct seq_file *seq, void **mib, | 173 | static void snmp6_seq_show_item(struct seq_file *seq, void __percpu **mib, |
174 | const struct snmp_mib *itemlist) | 174 | const struct snmp_mib *itemlist) |
175 | { | 175 | { |
176 | int i; | 176 | int i; |
@@ -183,14 +183,15 @@ static int snmp6_seq_show(struct seq_file *seq, void *v) | |||
183 | { | 183 | { |
184 | struct net *net = (struct net *)seq->private; | 184 | struct net *net = (struct net *)seq->private; |
185 | 185 | ||
186 | snmp6_seq_show_item(seq, (void **)net->mib.ipv6_statistics, | 186 | snmp6_seq_show_item(seq, (void __percpu **)net->mib.ipv6_statistics, |
187 | snmp6_ipstats_list); | 187 | snmp6_ipstats_list); |
188 | snmp6_seq_show_item(seq, (void **)net->mib.icmpv6_statistics, | 188 | snmp6_seq_show_item(seq, (void __percpu **)net->mib.icmpv6_statistics, |
189 | snmp6_icmp6_list); | 189 | snmp6_icmp6_list); |
190 | snmp6_seq_show_icmpv6msg(seq, (void **)net->mib.icmpv6msg_statistics); | 190 | snmp6_seq_show_icmpv6msg(seq, |
191 | snmp6_seq_show_item(seq, (void **)net->mib.udp_stats_in6, | 191 | (void __percpu **)net->mib.icmpv6msg_statistics); |
192 | snmp6_seq_show_item(seq, (void __percpu **)net->mib.udp_stats_in6, | ||
192 | snmp6_udp6_list); | 193 | snmp6_udp6_list); |
193 | snmp6_seq_show_item(seq, (void **)net->mib.udplite_stats_in6, | 194 | snmp6_seq_show_item(seq, (void __percpu **)net->mib.udplite_stats_in6, |
194 | snmp6_udplite6_list); | 195 | snmp6_udplite6_list); |
195 | return 0; | 196 | return 0; |
196 | } | 197 | } |
@@ -213,9 +214,11 @@ static int snmp6_dev_seq_show(struct seq_file *seq, void *v) | |||
213 | struct inet6_dev *idev = (struct inet6_dev *)seq->private; | 214 | struct inet6_dev *idev = (struct inet6_dev *)seq->private; |
214 | 215 | ||
215 | seq_printf(seq, "%-32s\t%u\n", "ifIndex", idev->dev->ifindex); | 216 | seq_printf(seq, "%-32s\t%u\n", "ifIndex", idev->dev->ifindex); |
216 | snmp6_seq_show_item(seq, (void **)idev->stats.ipv6, snmp6_ipstats_list); | 217 | snmp6_seq_show_item(seq, (void __percpu **)idev->stats.ipv6, |
217 | snmp6_seq_show_item(seq, (void **)idev->stats.icmpv6, snmp6_icmp6_list); | 218 | snmp6_ipstats_list); |
218 | snmp6_seq_show_icmpv6msg(seq, (void **)idev->stats.icmpv6msg); | 219 | snmp6_seq_show_item(seq, (void __percpu **)idev->stats.icmpv6, |
220 | snmp6_icmp6_list); | ||
221 | snmp6_seq_show_icmpv6msg(seq, (void __percpu **)idev->stats.icmpv6msg); | ||
219 | return 0; | 222 | return 0; |
220 | } | 223 | } |
221 | 224 | ||
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index d93812d09c13..b2847ed6a7d9 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -237,8 +237,7 @@ out: | |||
237 | } | 237 | } |
238 | 238 | ||
239 | static __inline__ struct frag_queue * | 239 | static __inline__ struct frag_queue * |
240 | fq_find(struct net *net, __be32 id, struct in6_addr *src, struct in6_addr *dst, | 240 | fq_find(struct net *net, __be32 id, struct in6_addr *src, struct in6_addr *dst) |
241 | struct inet6_dev *idev) | ||
242 | { | 241 | { |
243 | struct inet_frag_queue *q; | 242 | struct inet_frag_queue *q; |
244 | struct ip6_create_arg arg; | 243 | struct ip6_create_arg arg; |
@@ -254,13 +253,9 @@ fq_find(struct net *net, __be32 id, struct in6_addr *src, struct in6_addr *dst, | |||
254 | 253 | ||
255 | q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); | 254 | q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); |
256 | if (q == NULL) | 255 | if (q == NULL) |
257 | goto oom; | 256 | return NULL; |
258 | 257 | ||
259 | return container_of(q, struct frag_queue, q); | 258 | return container_of(q, struct frag_queue, q); |
260 | |||
261 | oom: | ||
262 | IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_REASMFAILS); | ||
263 | return NULL; | ||
264 | } | 259 | } |
265 | 260 | ||
266 | static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | 261 | static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, |
@@ -606,8 +601,8 @@ static int ipv6_frag_rcv(struct sk_buff *skb) | |||
606 | if (atomic_read(&net->ipv6.frags.mem) > net->ipv6.frags.high_thresh) | 601 | if (atomic_read(&net->ipv6.frags.mem) > net->ipv6.frags.high_thresh) |
607 | ip6_evictor(net, ip6_dst_idev(skb_dst(skb))); | 602 | ip6_evictor(net, ip6_dst_idev(skb_dst(skb))); |
608 | 603 | ||
609 | if ((fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr, | 604 | fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr); |
610 | ip6_dst_idev(skb_dst(skb)))) != NULL) { | 605 | if (fq != NULL) { |
611 | int ret; | 606 | int ret; |
612 | 607 | ||
613 | spin_lock(&fq->q.lock); | 608 | spin_lock(&fq->q.lock); |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 10207cc8cc0e..96eb2d4641c4 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -363,7 +363,6 @@ ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg) | |||
363 | goto out; | 363 | goto out; |
364 | } | 364 | } |
365 | 365 | ||
366 | INIT_RCU_HEAD(&p->rcu_head); | ||
367 | p->next = t->prl; | 366 | p->next = t->prl; |
368 | p->addr = a->addr; | 367 | p->addr = a->addr; |
369 | p->flags = a->flags; | 368 | p->flags = a->flags; |
@@ -1227,15 +1226,14 @@ static int __init sit_init(void) | |||
1227 | 1226 | ||
1228 | printk(KERN_INFO "IPv6 over IPv4 tunneling driver\n"); | 1227 | printk(KERN_INFO "IPv6 over IPv4 tunneling driver\n"); |
1229 | 1228 | ||
1230 | if (xfrm4_tunnel_register(&sit_handler, AF_INET6) < 0) { | ||
1231 | printk(KERN_INFO "sit init: Can't add protocol\n"); | ||
1232 | return -EAGAIN; | ||
1233 | } | ||
1234 | |||
1235 | err = register_pernet_device(&sit_net_ops); | 1229 | err = register_pernet_device(&sit_net_ops); |
1236 | if (err < 0) | 1230 | if (err < 0) |
1237 | xfrm4_tunnel_deregister(&sit_handler, AF_INET6); | 1231 | return err; |
1238 | 1232 | err = xfrm4_tunnel_register(&sit_handler, AF_INET6); | |
1233 | if (err < 0) { | ||
1234 | unregister_pernet_device(&sit_net_ops); | ||
1235 | printk(KERN_INFO "sit init: Can't add protocol\n"); | ||
1236 | } | ||
1239 | return err; | 1237 | return err; |
1240 | } | 1238 | } |
1241 | 1239 | ||
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 34efb3589ffa..a7af9d68cd6c 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -322,7 +322,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
322 | struct ipv6_pinfo *np = inet6_sk(sk); | 322 | struct ipv6_pinfo *np = inet6_sk(sk); |
323 | struct inet_sock *inet = inet_sk(sk); | 323 | struct inet_sock *inet = inet_sk(sk); |
324 | struct sk_buff *skb; | 324 | struct sk_buff *skb; |
325 | unsigned int ulen, copied; | 325 | unsigned int ulen; |
326 | int peeked; | 326 | int peeked; |
327 | int err; | 327 | int err; |
328 | int is_udplite = IS_UDPLITE(sk); | 328 | int is_udplite = IS_UDPLITE(sk); |
@@ -341,10 +341,9 @@ try_again: | |||
341 | goto out; | 341 | goto out; |
342 | 342 | ||
343 | ulen = skb->len - sizeof(struct udphdr); | 343 | ulen = skb->len - sizeof(struct udphdr); |
344 | copied = len; | 344 | if (len > ulen) |
345 | if (copied > ulen) | 345 | len = ulen; |
346 | copied = ulen; | 346 | else if (len < ulen) |
347 | else if (copied < ulen) | ||
348 | msg->msg_flags |= MSG_TRUNC; | 347 | msg->msg_flags |= MSG_TRUNC; |
349 | 348 | ||
350 | is_udp4 = (skb->protocol == htons(ETH_P_IP)); | 349 | is_udp4 = (skb->protocol == htons(ETH_P_IP)); |
@@ -355,14 +354,14 @@ try_again: | |||
355 | * coverage checksum (UDP-Lite), do it before the copy. | 354 | * coverage checksum (UDP-Lite), do it before the copy. |
356 | */ | 355 | */ |
357 | 356 | ||
358 | if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { | 357 | if (len < ulen || UDP_SKB_CB(skb)->partial_cov) { |
359 | if (udp_lib_checksum_complete(skb)) | 358 | if (udp_lib_checksum_complete(skb)) |
360 | goto csum_copy_err; | 359 | goto csum_copy_err; |
361 | } | 360 | } |
362 | 361 | ||
363 | if (skb_csum_unnecessary(skb)) | 362 | if (skb_csum_unnecessary(skb)) |
364 | err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), | 363 | err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), |
365 | msg->msg_iov, copied ); | 364 | msg->msg_iov,len); |
366 | else { | 365 | else { |
367 | err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov); | 366 | err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov); |
368 | if (err == -EINVAL) | 367 | if (err == -EINVAL) |
@@ -411,7 +410,7 @@ try_again: | |||
411 | datagram_recv_ctl(sk, msg, skb); | 410 | datagram_recv_ctl(sk, msg, skb); |
412 | } | 411 | } |
413 | 412 | ||
414 | err = copied; | 413 | err = len; |
415 | if (flags & MSG_TRUNC) | 414 | if (flags & MSG_TRUNC) |
416 | err = ulen; | 415 | err = ulen; |
417 | 416 | ||
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index d6f9aeec69f7..fa85a7d22dc4 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c | |||
@@ -84,23 +84,6 @@ static inline unsigned xfrm6_tunnel_spi_hash_byspi(u32 spi) | |||
84 | return spi % XFRM6_TUNNEL_SPI_BYSPI_HSIZE; | 84 | return spi % XFRM6_TUNNEL_SPI_BYSPI_HSIZE; |
85 | } | 85 | } |
86 | 86 | ||
87 | |||
88 | static int __init xfrm6_tunnel_spi_init(void) | ||
89 | { | ||
90 | xfrm6_tunnel_spi_kmem = kmem_cache_create("xfrm6_tunnel_spi", | ||
91 | sizeof(struct xfrm6_tunnel_spi), | ||
92 | 0, SLAB_HWCACHE_ALIGN, | ||
93 | NULL); | ||
94 | if (!xfrm6_tunnel_spi_kmem) | ||
95 | return -ENOMEM; | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | static void xfrm6_tunnel_spi_fini(void) | ||
100 | { | ||
101 | kmem_cache_destroy(xfrm6_tunnel_spi_kmem); | ||
102 | } | ||
103 | |||
104 | static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(struct net *net, xfrm_address_t *saddr) | 87 | static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(struct net *net, xfrm_address_t *saddr) |
105 | { | 88 | { |
106 | struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net); | 89 | struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net); |
@@ -178,7 +161,6 @@ alloc_spi: | |||
178 | if (!x6spi) | 161 | if (!x6spi) |
179 | goto out; | 162 | goto out; |
180 | 163 | ||
181 | INIT_RCU_HEAD(&x6spi->rcu_head); | ||
182 | memcpy(&x6spi->addr, saddr, sizeof(x6spi->addr)); | 164 | memcpy(&x6spi->addr, saddr, sizeof(x6spi->addr)); |
183 | x6spi->spi = spi; | 165 | x6spi->spi = spi; |
184 | atomic_set(&x6spi->refcnt, 1); | 166 | atomic_set(&x6spi->refcnt, 1); |
@@ -375,42 +357,44 @@ static int __init xfrm6_tunnel_init(void) | |||
375 | { | 357 | { |
376 | int rv; | 358 | int rv; |
377 | 359 | ||
360 | xfrm6_tunnel_spi_kmem = kmem_cache_create("xfrm6_tunnel_spi", | ||
361 | sizeof(struct xfrm6_tunnel_spi), | ||
362 | 0, SLAB_HWCACHE_ALIGN, | ||
363 | NULL); | ||
364 | if (!xfrm6_tunnel_spi_kmem) | ||
365 | return -ENOMEM; | ||
366 | rv = register_pernet_subsys(&xfrm6_tunnel_net_ops); | ||
367 | if (rv < 0) | ||
368 | goto out_pernet; | ||
378 | rv = xfrm_register_type(&xfrm6_tunnel_type, AF_INET6); | 369 | rv = xfrm_register_type(&xfrm6_tunnel_type, AF_INET6); |
379 | if (rv < 0) | 370 | if (rv < 0) |
380 | goto err; | 371 | goto out_type; |
381 | rv = xfrm6_tunnel_register(&xfrm6_tunnel_handler, AF_INET6); | 372 | rv = xfrm6_tunnel_register(&xfrm6_tunnel_handler, AF_INET6); |
382 | if (rv < 0) | 373 | if (rv < 0) |
383 | goto unreg; | 374 | goto out_xfrm6; |
384 | rv = xfrm6_tunnel_register(&xfrm46_tunnel_handler, AF_INET); | 375 | rv = xfrm6_tunnel_register(&xfrm46_tunnel_handler, AF_INET); |
385 | if (rv < 0) | 376 | if (rv < 0) |
386 | goto dereg6; | 377 | goto out_xfrm46; |
387 | rv = xfrm6_tunnel_spi_init(); | ||
388 | if (rv < 0) | ||
389 | goto dereg46; | ||
390 | rv = register_pernet_subsys(&xfrm6_tunnel_net_ops); | ||
391 | if (rv < 0) | ||
392 | goto deregspi; | ||
393 | return 0; | 378 | return 0; |
394 | 379 | ||
395 | deregspi: | 380 | out_xfrm46: |
396 | xfrm6_tunnel_spi_fini(); | ||
397 | dereg46: | ||
398 | xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET); | ||
399 | dereg6: | ||
400 | xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6); | 381 | xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6); |
401 | unreg: | 382 | out_xfrm6: |
402 | xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); | 383 | xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); |
403 | err: | 384 | out_type: |
385 | unregister_pernet_subsys(&xfrm6_tunnel_net_ops); | ||
386 | out_pernet: | ||
387 | kmem_cache_destroy(xfrm6_tunnel_spi_kmem); | ||
404 | return rv; | 388 | return rv; |
405 | } | 389 | } |
406 | 390 | ||
407 | static void __exit xfrm6_tunnel_fini(void) | 391 | static void __exit xfrm6_tunnel_fini(void) |
408 | { | 392 | { |
409 | unregister_pernet_subsys(&xfrm6_tunnel_net_ops); | ||
410 | xfrm6_tunnel_spi_fini(); | ||
411 | xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET); | 393 | xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET); |
412 | xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6); | 394 | xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6); |
413 | xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); | 395 | xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); |
396 | unregister_pernet_subsys(&xfrm6_tunnel_net_ops); | ||
397 | kmem_cache_destroy(xfrm6_tunnel_spi_kmem); | ||
414 | } | 398 | } |
415 | 399 | ||
416 | module_init(xfrm6_tunnel_init); | 400 | module_init(xfrm6_tunnel_init); |
diff --git a/net/ipx/ipx_proc.c b/net/ipx/ipx_proc.c index 576178482f89..26b5bfcf1d03 100644 --- a/net/ipx/ipx_proc.c +++ b/net/ipx/ipx_proc.c | |||
@@ -13,45 +13,15 @@ | |||
13 | #include <net/tcp_states.h> | 13 | #include <net/tcp_states.h> |
14 | #include <net/ipx.h> | 14 | #include <net/ipx.h> |
15 | 15 | ||
16 | static __inline__ struct ipx_interface *ipx_get_interface_idx(loff_t pos) | ||
17 | { | ||
18 | struct ipx_interface *i; | ||
19 | |||
20 | list_for_each_entry(i, &ipx_interfaces, node) | ||
21 | if (!pos--) | ||
22 | goto out; | ||
23 | i = NULL; | ||
24 | out: | ||
25 | return i; | ||
26 | } | ||
27 | |||
28 | static struct ipx_interface *ipx_interfaces_next(struct ipx_interface *i) | ||
29 | { | ||
30 | struct ipx_interface *rc = NULL; | ||
31 | |||
32 | if (i->node.next != &ipx_interfaces) | ||
33 | rc = list_entry(i->node.next, struct ipx_interface, node); | ||
34 | return rc; | ||
35 | } | ||
36 | |||
37 | static void *ipx_seq_interface_start(struct seq_file *seq, loff_t *pos) | 16 | static void *ipx_seq_interface_start(struct seq_file *seq, loff_t *pos) |
38 | { | 17 | { |
39 | loff_t l = *pos; | ||
40 | |||
41 | spin_lock_bh(&ipx_interfaces_lock); | 18 | spin_lock_bh(&ipx_interfaces_lock); |
42 | return l ? ipx_get_interface_idx(--l) : SEQ_START_TOKEN; | 19 | return seq_list_start_head(&ipx_interfaces, *pos); |
43 | } | 20 | } |
44 | 21 | ||
45 | static void *ipx_seq_interface_next(struct seq_file *seq, void *v, loff_t *pos) | 22 | static void *ipx_seq_interface_next(struct seq_file *seq, void *v, loff_t *pos) |
46 | { | 23 | { |
47 | struct ipx_interface *i; | 24 | return seq_list_next(v, &ipx_interfaces, pos); |
48 | |||
49 | ++*pos; | ||
50 | if (v == SEQ_START_TOKEN) | ||
51 | i = ipx_interfaces_head(); | ||
52 | else | ||
53 | i = ipx_interfaces_next(v); | ||
54 | return i; | ||
55 | } | 25 | } |
56 | 26 | ||
57 | static void ipx_seq_interface_stop(struct seq_file *seq, void *v) | 27 | static void ipx_seq_interface_stop(struct seq_file *seq, void *v) |
@@ -63,7 +33,7 @@ static int ipx_seq_interface_show(struct seq_file *seq, void *v) | |||
63 | { | 33 | { |
64 | struct ipx_interface *i; | 34 | struct ipx_interface *i; |
65 | 35 | ||
66 | if (v == SEQ_START_TOKEN) { | 36 | if (v == &ipx_interfaces) { |
67 | seq_puts(seq, "Network Node_Address Primary Device " | 37 | seq_puts(seq, "Network Node_Address Primary Device " |
68 | "Frame_Type"); | 38 | "Frame_Type"); |
69 | #ifdef IPX_REFCNT_DEBUG | 39 | #ifdef IPX_REFCNT_DEBUG |
@@ -73,7 +43,7 @@ static int ipx_seq_interface_show(struct seq_file *seq, void *v) | |||
73 | goto out; | 43 | goto out; |
74 | } | 44 | } |
75 | 45 | ||
76 | i = v; | 46 | i = list_entry(v, struct ipx_interface, node); |
77 | seq_printf(seq, "%08lX ", (unsigned long int)ntohl(i->if_netnum)); | 47 | seq_printf(seq, "%08lX ", (unsigned long int)ntohl(i->if_netnum)); |
78 | seq_printf(seq, "%02X%02X%02X%02X%02X%02X ", | 48 | seq_printf(seq, "%02X%02X%02X%02X%02X%02X ", |
79 | i->if_node[0], i->if_node[1], i->if_node[2], | 49 | i->if_node[0], i->if_node[1], i->if_node[2], |
@@ -89,53 +59,15 @@ out: | |||
89 | return 0; | 59 | return 0; |
90 | } | 60 | } |
91 | 61 | ||
92 | static struct ipx_route *ipx_routes_head(void) | ||
93 | { | ||
94 | struct ipx_route *rc = NULL; | ||
95 | |||
96 | if (!list_empty(&ipx_routes)) | ||
97 | rc = list_entry(ipx_routes.next, struct ipx_route, node); | ||
98 | return rc; | ||
99 | } | ||
100 | |||
101 | static struct ipx_route *ipx_routes_next(struct ipx_route *r) | ||
102 | { | ||
103 | struct ipx_route *rc = NULL; | ||
104 | |||
105 | if (r->node.next != &ipx_routes) | ||
106 | rc = list_entry(r->node.next, struct ipx_route, node); | ||
107 | return rc; | ||
108 | } | ||
109 | |||
110 | static __inline__ struct ipx_route *ipx_get_route_idx(loff_t pos) | ||
111 | { | ||
112 | struct ipx_route *r; | ||
113 | |||
114 | list_for_each_entry(r, &ipx_routes, node) | ||
115 | if (!pos--) | ||
116 | goto out; | ||
117 | r = NULL; | ||
118 | out: | ||
119 | return r; | ||
120 | } | ||
121 | |||
122 | static void *ipx_seq_route_start(struct seq_file *seq, loff_t *pos) | 62 | static void *ipx_seq_route_start(struct seq_file *seq, loff_t *pos) |
123 | { | 63 | { |
124 | loff_t l = *pos; | ||
125 | read_lock_bh(&ipx_routes_lock); | 64 | read_lock_bh(&ipx_routes_lock); |
126 | return l ? ipx_get_route_idx(--l) : SEQ_START_TOKEN; | 65 | return seq_list_start_head(&ipx_routes, *pos); |
127 | } | 66 | } |
128 | 67 | ||
129 | static void *ipx_seq_route_next(struct seq_file *seq, void *v, loff_t *pos) | 68 | static void *ipx_seq_route_next(struct seq_file *seq, void *v, loff_t *pos) |
130 | { | 69 | { |
131 | struct ipx_route *r; | 70 | return seq_list_next(v, &ipx_routes, pos); |
132 | |||
133 | ++*pos; | ||
134 | if (v == SEQ_START_TOKEN) | ||
135 | r = ipx_routes_head(); | ||
136 | else | ||
137 | r = ipx_routes_next(v); | ||
138 | return r; | ||
139 | } | 71 | } |
140 | 72 | ||
141 | static void ipx_seq_route_stop(struct seq_file *seq, void *v) | 73 | static void ipx_seq_route_stop(struct seq_file *seq, void *v) |
@@ -147,11 +79,13 @@ static int ipx_seq_route_show(struct seq_file *seq, void *v) | |||
147 | { | 79 | { |
148 | struct ipx_route *rt; | 80 | struct ipx_route *rt; |
149 | 81 | ||
150 | if (v == SEQ_START_TOKEN) { | 82 | if (v == &ipx_routes) { |
151 | seq_puts(seq, "Network Router_Net Router_Node\n"); | 83 | seq_puts(seq, "Network Router_Net Router_Node\n"); |
152 | goto out; | 84 | goto out; |
153 | } | 85 | } |
154 | rt = v; | 86 | |
87 | rt = list_entry(v, struct ipx_route, node); | ||
88 | |||
155 | seq_printf(seq, "%08lX ", (unsigned long int)ntohl(rt->ir_net)); | 89 | seq_printf(seq, "%08lX ", (unsigned long int)ntohl(rt->ir_net)); |
156 | if (rt->ir_routed) | 90 | if (rt->ir_routed) |
157 | seq_printf(seq, "%08lX %02X%02X%02X%02X%02X%02X\n", | 91 | seq_printf(seq, "%08lX %02X%02X%02X%02X%02X%02X\n", |
@@ -226,9 +160,9 @@ static void *ipx_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos) | |||
226 | spin_unlock_bh(&i->if_sklist_lock); | 160 | spin_unlock_bh(&i->if_sklist_lock); |
227 | sk = NULL; | 161 | sk = NULL; |
228 | for (;;) { | 162 | for (;;) { |
229 | i = ipx_interfaces_next(i); | 163 | if (i->node.next == &ipx_interfaces) |
230 | if (!i) | ||
231 | break; | 164 | break; |
165 | i = list_entry(i->node.next, struct ipx_interface, node); | ||
232 | spin_lock_bh(&i->if_sklist_lock); | 166 | spin_lock_bh(&i->if_sklist_lock); |
233 | if (!hlist_empty(&i->if_sklist)) { | 167 | if (!hlist_empty(&i->if_sklist)) { |
234 | sk = sk_head(&i->if_sklist); | 168 | sk = sk_head(&i->if_sklist); |
diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c index 315ead3cb926..e486dc89ea59 100644 --- a/net/irda/irlan/irlan_common.c +++ b/net/irda/irlan/irlan_common.c | |||
@@ -1128,34 +1128,14 @@ int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len) | |||
1128 | */ | 1128 | */ |
1129 | static void *irlan_seq_start(struct seq_file *seq, loff_t *pos) | 1129 | static void *irlan_seq_start(struct seq_file *seq, loff_t *pos) |
1130 | { | 1130 | { |
1131 | int i = 1; | ||
1132 | struct irlan_cb *self; | ||
1133 | |||
1134 | rcu_read_lock(); | 1131 | rcu_read_lock(); |
1135 | if (*pos == 0) | 1132 | return seq_list_start_head(&irlans, *pos); |
1136 | return SEQ_START_TOKEN; | ||
1137 | |||
1138 | list_for_each_entry(self, &irlans, dev_list) { | ||
1139 | if (*pos == i) | ||
1140 | return self; | ||
1141 | ++i; | ||
1142 | } | ||
1143 | return NULL; | ||
1144 | } | 1133 | } |
1145 | 1134 | ||
1146 | /* Return entry after v, and increment pos */ | 1135 | /* Return entry after v, and increment pos */ |
1147 | static void *irlan_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 1136 | static void *irlan_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
1148 | { | 1137 | { |
1149 | struct list_head *nxt; | 1138 | return seq_list_next(v, &irlans, pos); |
1150 | |||
1151 | ++*pos; | ||
1152 | if (v == SEQ_START_TOKEN) | ||
1153 | nxt = irlans.next; | ||
1154 | else | ||
1155 | nxt = ((struct irlan_cb *)v)->dev_list.next; | ||
1156 | |||
1157 | return (nxt == &irlans) ? NULL | ||
1158 | : list_entry(nxt, struct irlan_cb, dev_list); | ||
1159 | } | 1139 | } |
1160 | 1140 | ||
1161 | /* End of reading /proc file */ | 1141 | /* End of reading /proc file */ |
@@ -1170,10 +1150,10 @@ static void irlan_seq_stop(struct seq_file *seq, void *v) | |||
1170 | */ | 1150 | */ |
1171 | static int irlan_seq_show(struct seq_file *seq, void *v) | 1151 | static int irlan_seq_show(struct seq_file *seq, void *v) |
1172 | { | 1152 | { |
1173 | if (v == SEQ_START_TOKEN) | 1153 | if (v == &irlans) |
1174 | seq_puts(seq, "IrLAN instances:\n"); | 1154 | seq_puts(seq, "IrLAN instances:\n"); |
1175 | else { | 1155 | else { |
1176 | struct irlan_cb *self = v; | 1156 | struct irlan_cb *self = list_entry(v, struct irlan_cb, dev_list); |
1177 | 1157 | ||
1178 | IRDA_ASSERT(self != NULL, return -1;); | 1158 | IRDA_ASSERT(self != NULL, return -1;); |
1179 | IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;); | 1159 | IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;); |
diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c index d340110f5c0c..9616c32d1076 100644 --- a/net/irda/irlan/irlan_eth.c +++ b/net/irda/irlan/irlan_eth.c | |||
@@ -321,14 +321,15 @@ static void irlan_eth_set_multicast_list(struct net_device *dev) | |||
321 | /* Enable promiscuous mode */ | 321 | /* Enable promiscuous mode */ |
322 | IRDA_WARNING("Promiscuous mode not implemented by IrLAN!\n"); | 322 | IRDA_WARNING("Promiscuous mode not implemented by IrLAN!\n"); |
323 | } | 323 | } |
324 | else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > HW_MAX_ADDRS) { | 324 | else if ((dev->flags & IFF_ALLMULTI) || |
325 | netdev_mc_count(dev) > HW_MAX_ADDRS) { | ||
325 | /* Disable promiscuous mode, use normal mode. */ | 326 | /* Disable promiscuous mode, use normal mode. */ |
326 | IRDA_DEBUG(4, "%s(), Setting multicast filter\n", __func__ ); | 327 | IRDA_DEBUG(4, "%s(), Setting multicast filter\n", __func__ ); |
327 | /* hardware_set_filter(NULL); */ | 328 | /* hardware_set_filter(NULL); */ |
328 | 329 | ||
329 | irlan_set_multicast_filter(self, TRUE); | 330 | irlan_set_multicast_filter(self, TRUE); |
330 | } | 331 | } |
331 | else if (dev->mc_count) { | 332 | else if (!netdev_mc_empty(dev)) { |
332 | IRDA_DEBUG(4, "%s(), Setting multicast filter\n", __func__ ); | 333 | IRDA_DEBUG(4, "%s(), Setting multicast filter\n", __func__ ); |
333 | /* Walk the address list, and load the filter */ | 334 | /* Walk the address list, and load the filter */ |
334 | /* hardware_set_filter(dev->mc_list); */ | 335 | /* hardware_set_filter(dev->mc_list); */ |
diff --git a/net/key/af_key.c b/net/key/af_key.c index 41dd2cb07ef3..79d2c0f3c334 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -3654,9 +3654,8 @@ static const struct net_proto_family pfkey_family_ops = { | |||
3654 | #ifdef CONFIG_PROC_FS | 3654 | #ifdef CONFIG_PROC_FS |
3655 | static int pfkey_seq_show(struct seq_file *f, void *v) | 3655 | static int pfkey_seq_show(struct seq_file *f, void *v) |
3656 | { | 3656 | { |
3657 | struct sock *s; | 3657 | struct sock *s = sk_entry(v); |
3658 | 3658 | ||
3659 | s = (struct sock *)v; | ||
3660 | if (v == SEQ_START_TOKEN) | 3659 | if (v == SEQ_START_TOKEN) |
3661 | seq_printf(f ,"sk RefCnt Rmem Wmem User Inode\n"); | 3660 | seq_printf(f ,"sk RefCnt Rmem Wmem User Inode\n"); |
3662 | else | 3661 | else |
@@ -3675,19 +3674,9 @@ static void *pfkey_seq_start(struct seq_file *f, loff_t *ppos) | |||
3675 | { | 3674 | { |
3676 | struct net *net = seq_file_net(f); | 3675 | struct net *net = seq_file_net(f); |
3677 | struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id); | 3676 | struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id); |
3678 | struct sock *s; | ||
3679 | struct hlist_node *node; | ||
3680 | loff_t pos = *ppos; | ||
3681 | 3677 | ||
3682 | read_lock(&pfkey_table_lock); | 3678 | read_lock(&pfkey_table_lock); |
3683 | if (pos == 0) | 3679 | return seq_hlist_start_head(&net_pfkey->table, *ppos); |
3684 | return SEQ_START_TOKEN; | ||
3685 | |||
3686 | sk_for_each(s, node, &net_pfkey->table) | ||
3687 | if (pos-- == 1) | ||
3688 | return s; | ||
3689 | |||
3690 | return NULL; | ||
3691 | } | 3680 | } |
3692 | 3681 | ||
3693 | static void *pfkey_seq_next(struct seq_file *f, void *v, loff_t *ppos) | 3682 | static void *pfkey_seq_next(struct seq_file *f, void *v, loff_t *ppos) |
@@ -3695,10 +3684,7 @@ static void *pfkey_seq_next(struct seq_file *f, void *v, loff_t *ppos) | |||
3695 | struct net *net = seq_file_net(f); | 3684 | struct net *net = seq_file_net(f); |
3696 | struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id); | 3685 | struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id); |
3697 | 3686 | ||
3698 | ++*ppos; | 3687 | return seq_hlist_next(v, &net_pfkey->table, ppos); |
3699 | return (v == SEQ_START_TOKEN) ? | ||
3700 | sk_head(&net_pfkey->table) : | ||
3701 | sk_next((struct sock *)v); | ||
3702 | } | 3688 | } |
3703 | 3689 | ||
3704 | static void pfkey_seq_stop(struct seq_file *f, void *v) | 3690 | static void pfkey_seq_stop(struct seq_file *f, void *v) |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 718fbcff84d2..5538e1b4a697 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -237,6 +237,14 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) | |||
237 | sdata->vif.type != NL80211_IFTYPE_AP) | 237 | sdata->vif.type != NL80211_IFTYPE_AP) |
238 | return -EINVAL; | 238 | return -EINVAL; |
239 | 239 | ||
240 | if (test_sta_flags(sta, WLAN_STA_DISASSOC)) { | ||
241 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
242 | printk(KERN_DEBUG "Disassociation is in progress. " | ||
243 | "Denying BA session request\n"); | ||
244 | #endif | ||
245 | return -EINVAL; | ||
246 | } | ||
247 | |||
240 | if (test_sta_flags(sta, WLAN_STA_SUSPEND)) { | 248 | if (test_sta_flags(sta, WLAN_STA_SUSPEND)) { |
241 | #ifdef CONFIG_MAC80211_HT_DEBUG | 249 | #ifdef CONFIG_MAC80211_HT_DEBUG |
242 | printk(KERN_DEBUG "Suspend in progress. " | 250 | printk(KERN_DEBUG "Suspend in progress. " |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index facf233843e0..e1731b7c2523 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -515,6 +515,8 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, | |||
515 | if (old) | 515 | if (old) |
516 | memcpy(new->tail, old->tail, new_tail_len); | 516 | memcpy(new->tail, old->tail, new_tail_len); |
517 | 517 | ||
518 | sdata->vif.bss_conf.dtim_period = new->dtim_period; | ||
519 | |||
518 | rcu_assign_pointer(sdata->u.ap.beacon, new); | 520 | rcu_assign_pointer(sdata->u.ap.beacon, new); |
519 | 521 | ||
520 | synchronize_rcu(); | 522 | synchronize_rcu(); |
@@ -747,9 +749,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
747 | layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN || | 749 | layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN || |
748 | sdata->vif.type == NL80211_IFTYPE_AP; | 750 | sdata->vif.type == NL80211_IFTYPE_AP; |
749 | 751 | ||
750 | rcu_read_lock(); | 752 | err = sta_info_insert_rcu(sta); |
751 | |||
752 | err = sta_info_insert(sta); | ||
753 | if (err) { | 753 | if (err) { |
754 | rcu_read_unlock(); | 754 | rcu_read_unlock(); |
755 | return err; | 755 | return err; |
@@ -768,26 +768,13 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, | |||
768 | { | 768 | { |
769 | struct ieee80211_local *local = wiphy_priv(wiphy); | 769 | struct ieee80211_local *local = wiphy_priv(wiphy); |
770 | struct ieee80211_sub_if_data *sdata; | 770 | struct ieee80211_sub_if_data *sdata; |
771 | struct sta_info *sta; | ||
772 | 771 | ||
773 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 772 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
774 | 773 | ||
775 | if (mac) { | 774 | if (mac) |
776 | rcu_read_lock(); | 775 | return sta_info_destroy_addr_bss(sdata, mac); |
777 | |||
778 | sta = sta_info_get_bss(sdata, mac); | ||
779 | if (!sta) { | ||
780 | rcu_read_unlock(); | ||
781 | return -ENOENT; | ||
782 | } | ||
783 | |||
784 | sta_info_unlink(&sta); | ||
785 | rcu_read_unlock(); | ||
786 | |||
787 | sta_info_destroy(sta); | ||
788 | } else | ||
789 | sta_info_flush(local, sdata); | ||
790 | 776 | ||
777 | sta_info_flush(local, sdata); | ||
791 | return 0; | 778 | return 0; |
792 | } | 779 | } |
793 | 780 | ||
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index b3bc32b62a5a..637929b65ccc 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -250,6 +250,38 @@ static const struct file_operations uapsd_max_sp_len_ops = { | |||
250 | .open = mac80211_open_file_generic | 250 | .open = mac80211_open_file_generic |
251 | }; | 251 | }; |
252 | 252 | ||
253 | static ssize_t channel_type_read(struct file *file, char __user *user_buf, | ||
254 | size_t count, loff_t *ppos) | ||
255 | { | ||
256 | struct ieee80211_local *local = file->private_data; | ||
257 | const char *buf; | ||
258 | |||
259 | switch (local->hw.conf.channel_type) { | ||
260 | case NL80211_CHAN_NO_HT: | ||
261 | buf = "no ht\n"; | ||
262 | break; | ||
263 | case NL80211_CHAN_HT20: | ||
264 | buf = "ht20\n"; | ||
265 | break; | ||
266 | case NL80211_CHAN_HT40MINUS: | ||
267 | buf = "ht40-\n"; | ||
268 | break; | ||
269 | case NL80211_CHAN_HT40PLUS: | ||
270 | buf = "ht40+\n"; | ||
271 | break; | ||
272 | default: | ||
273 | buf = "???"; | ||
274 | break; | ||
275 | } | ||
276 | |||
277 | return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); | ||
278 | } | ||
279 | |||
280 | static const struct file_operations channel_type_ops = { | ||
281 | .read = channel_type_read, | ||
282 | .open = mac80211_open_file_generic | ||
283 | }; | ||
284 | |||
253 | static ssize_t queues_read(struct file *file, char __user *user_buf, | 285 | static ssize_t queues_read(struct file *file, char __user *user_buf, |
254 | size_t count, loff_t *ppos) | 286 | size_t count, loff_t *ppos) |
255 | { | 287 | { |
@@ -408,6 +440,7 @@ void debugfs_hw_add(struct ieee80211_local *local) | |||
408 | DEBUGFS_ADD(noack); | 440 | DEBUGFS_ADD(noack); |
409 | DEBUGFS_ADD(uapsd_queues); | 441 | DEBUGFS_ADD(uapsd_queues); |
410 | DEBUGFS_ADD(uapsd_max_sp_len); | 442 | DEBUGFS_ADD(uapsd_max_sp_len); |
443 | DEBUGFS_ADD(channel_type); | ||
411 | 444 | ||
412 | statsd = debugfs_create_dir("statistics", phyd); | 445 | statsd = debugfs_create_dir("statistics", phyd); |
413 | 446 | ||
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 6c31f38ac7f5..c3d844093a2f 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -243,6 +243,40 @@ static inline void drv_sta_notify(struct ieee80211_local *local, | |||
243 | trace_drv_sta_notify(local, sdata, cmd, sta); | 243 | trace_drv_sta_notify(local, sdata, cmd, sta); |
244 | } | 244 | } |
245 | 245 | ||
246 | static inline int drv_sta_add(struct ieee80211_local *local, | ||
247 | struct ieee80211_sub_if_data *sdata, | ||
248 | struct ieee80211_sta *sta) | ||
249 | { | ||
250 | int ret = 0; | ||
251 | |||
252 | might_sleep(); | ||
253 | |||
254 | if (local->ops->sta_add) | ||
255 | ret = local->ops->sta_add(&local->hw, &sdata->vif, sta); | ||
256 | else if (local->ops->sta_notify) | ||
257 | local->ops->sta_notify(&local->hw, &sdata->vif, | ||
258 | STA_NOTIFY_ADD, sta); | ||
259 | |||
260 | trace_drv_sta_add(local, sdata, sta, ret); | ||
261 | |||
262 | return ret; | ||
263 | } | ||
264 | |||
265 | static inline void drv_sta_remove(struct ieee80211_local *local, | ||
266 | struct ieee80211_sub_if_data *sdata, | ||
267 | struct ieee80211_sta *sta) | ||
268 | { | ||
269 | might_sleep(); | ||
270 | |||
271 | if (local->ops->sta_remove) | ||
272 | local->ops->sta_remove(&local->hw, &sdata->vif, sta); | ||
273 | else if (local->ops->sta_notify) | ||
274 | local->ops->sta_notify(&local->hw, &sdata->vif, | ||
275 | STA_NOTIFY_REMOVE, sta); | ||
276 | |||
277 | trace_drv_sta_remove(local, sdata, sta); | ||
278 | } | ||
279 | |||
246 | static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, | 280 | static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, |
247 | const struct ieee80211_tx_queue_params *params) | 281 | const struct ieee80211_tx_queue_params *params) |
248 | { | 282 | { |
@@ -256,14 +290,6 @@ static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, | |||
256 | return ret; | 290 | return ret; |
257 | } | 291 | } |
258 | 292 | ||
259 | static inline int drv_get_tx_stats(struct ieee80211_local *local, | ||
260 | struct ieee80211_tx_queue_stats *stats) | ||
261 | { | ||
262 | int ret = local->ops->get_tx_stats(&local->hw, stats); | ||
263 | trace_drv_get_tx_stats(local, stats, ret); | ||
264 | return ret; | ||
265 | } | ||
266 | |||
267 | static inline u64 drv_get_tsf(struct ieee80211_local *local) | 293 | static inline u64 drv_get_tsf(struct ieee80211_local *local) |
268 | { | 294 | { |
269 | u64 ret = -1ULL; | 295 | u64 ret = -1ULL; |
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 502424b2538a..41baf730a5c7 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -545,59 +545,88 @@ TRACE_EVENT(drv_sta_notify, | |||
545 | ) | 545 | ) |
546 | ); | 546 | ); |
547 | 547 | ||
548 | TRACE_EVENT(drv_conf_tx, | 548 | TRACE_EVENT(drv_sta_add, |
549 | TP_PROTO(struct ieee80211_local *local, u16 queue, | 549 | TP_PROTO(struct ieee80211_local *local, |
550 | const struct ieee80211_tx_queue_params *params, | 550 | struct ieee80211_sub_if_data *sdata, |
551 | int ret), | 551 | struct ieee80211_sta *sta, int ret), |
552 | 552 | ||
553 | TP_ARGS(local, queue, params, ret), | 553 | TP_ARGS(local, sdata, sta, ret), |
554 | 554 | ||
555 | TP_STRUCT__entry( | 555 | TP_STRUCT__entry( |
556 | LOCAL_ENTRY | 556 | LOCAL_ENTRY |
557 | __field(u16, queue) | 557 | VIF_ENTRY |
558 | __field(u16, txop) | 558 | STA_ENTRY |
559 | __field(u16, cw_min) | ||
560 | __field(u16, cw_max) | ||
561 | __field(u8, aifs) | ||
562 | __field(int, ret) | 559 | __field(int, ret) |
563 | ), | 560 | ), |
564 | 561 | ||
565 | TP_fast_assign( | 562 | TP_fast_assign( |
566 | LOCAL_ASSIGN; | 563 | LOCAL_ASSIGN; |
567 | __entry->queue = queue; | 564 | VIF_ASSIGN; |
565 | STA_ASSIGN; | ||
568 | __entry->ret = ret; | 566 | __entry->ret = ret; |
569 | __entry->txop = params->txop; | ||
570 | __entry->cw_max = params->cw_max; | ||
571 | __entry->cw_min = params->cw_min; | ||
572 | __entry->aifs = params->aifs; | ||
573 | ), | 567 | ), |
574 | 568 | ||
575 | TP_printk( | 569 | TP_printk( |
576 | LOCAL_PR_FMT " queue:%d ret:%d", | 570 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " ret:%d", |
577 | LOCAL_PR_ARG, __entry->queue, __entry->ret | 571 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->ret |
578 | ) | 572 | ) |
579 | ); | 573 | ); |
580 | 574 | ||
581 | TRACE_EVENT(drv_get_tx_stats, | 575 | TRACE_EVENT(drv_sta_remove, |
582 | TP_PROTO(struct ieee80211_local *local, | 576 | TP_PROTO(struct ieee80211_local *local, |
583 | struct ieee80211_tx_queue_stats *stats, | 577 | struct ieee80211_sub_if_data *sdata, |
578 | struct ieee80211_sta *sta), | ||
579 | |||
580 | TP_ARGS(local, sdata, sta), | ||
581 | |||
582 | TP_STRUCT__entry( | ||
583 | LOCAL_ENTRY | ||
584 | VIF_ENTRY | ||
585 | STA_ENTRY | ||
586 | ), | ||
587 | |||
588 | TP_fast_assign( | ||
589 | LOCAL_ASSIGN; | ||
590 | VIF_ASSIGN; | ||
591 | STA_ASSIGN; | ||
592 | ), | ||
593 | |||
594 | TP_printk( | ||
595 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT, | ||
596 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG | ||
597 | ) | ||
598 | ); | ||
599 | |||
600 | TRACE_EVENT(drv_conf_tx, | ||
601 | TP_PROTO(struct ieee80211_local *local, u16 queue, | ||
602 | const struct ieee80211_tx_queue_params *params, | ||
584 | int ret), | 603 | int ret), |
585 | 604 | ||
586 | TP_ARGS(local, stats, ret), | 605 | TP_ARGS(local, queue, params, ret), |
587 | 606 | ||
588 | TP_STRUCT__entry( | 607 | TP_STRUCT__entry( |
589 | LOCAL_ENTRY | 608 | LOCAL_ENTRY |
609 | __field(u16, queue) | ||
610 | __field(u16, txop) | ||
611 | __field(u16, cw_min) | ||
612 | __field(u16, cw_max) | ||
613 | __field(u8, aifs) | ||
590 | __field(int, ret) | 614 | __field(int, ret) |
591 | ), | 615 | ), |
592 | 616 | ||
593 | TP_fast_assign( | 617 | TP_fast_assign( |
594 | LOCAL_ASSIGN; | 618 | LOCAL_ASSIGN; |
619 | __entry->queue = queue; | ||
595 | __entry->ret = ret; | 620 | __entry->ret = ret; |
621 | __entry->txop = params->txop; | ||
622 | __entry->cw_max = params->cw_max; | ||
623 | __entry->cw_min = params->cw_min; | ||
624 | __entry->aifs = params->aifs; | ||
596 | ), | 625 | ), |
597 | 626 | ||
598 | TP_printk( | 627 | TP_printk( |
599 | LOCAL_PR_FMT " ret:%d", | 628 | LOCAL_PR_FMT " queue:%d ret:%d", |
600 | LOCAL_PR_ARG, __entry->ret | 629 | LOCAL_PR_ARG, __entry->queue, __entry->ret |
601 | ) | 630 | ) |
602 | ); | 631 | ); |
603 | 632 | ||
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index f95750b423e3..f3e942486749 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -275,10 +275,12 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
275 | (unsigned long long) supp_rates, | 275 | (unsigned long long) supp_rates, |
276 | (unsigned long long) sta->sta.supp_rates[band]); | 276 | (unsigned long long) sta->sta.supp_rates[band]); |
277 | #endif | 277 | #endif |
278 | } else | 278 | rcu_read_unlock(); |
279 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates); | 279 | } else { |
280 | 280 | rcu_read_unlock(); | |
281 | rcu_read_unlock(); | 281 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, |
282 | supp_rates, GFP_KERNEL); | ||
283 | } | ||
282 | } | 284 | } |
283 | 285 | ||
284 | bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, | 286 | bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, |
@@ -368,7 +370,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
368 | sdata->name, mgmt->bssid); | 370 | sdata->name, mgmt->bssid); |
369 | #endif | 371 | #endif |
370 | ieee80211_sta_join_ibss(sdata, bss); | 372 | ieee80211_sta_join_ibss(sdata, bss); |
371 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates); | 373 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, |
374 | supp_rates, GFP_KERNEL); | ||
372 | } | 375 | } |
373 | 376 | ||
374 | put_bss: | 377 | put_bss: |
@@ -381,7 +384,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
381 | * must be callable in atomic context. | 384 | * must be callable in atomic context. |
382 | */ | 385 | */ |
383 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | 386 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, |
384 | u8 *bssid,u8 *addr, u32 supp_rates) | 387 | u8 *bssid,u8 *addr, u32 supp_rates, |
388 | gfp_t gfp) | ||
385 | { | 389 | { |
386 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 390 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
387 | struct ieee80211_local *local = sdata->local; | 391 | struct ieee80211_local *local = sdata->local; |
@@ -410,7 +414,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
410 | wiphy_name(local->hw.wiphy), addr, sdata->name); | 414 | wiphy_name(local->hw.wiphy), addr, sdata->name); |
411 | #endif | 415 | #endif |
412 | 416 | ||
413 | sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); | 417 | sta = sta_info_alloc(sdata, addr, gfp); |
414 | if (!sta) | 418 | if (!sta) |
415 | return NULL; | 419 | return NULL; |
416 | 420 | ||
@@ -422,9 +426,9 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
422 | 426 | ||
423 | rate_control_rate_init(sta); | 427 | rate_control_rate_init(sta); |
424 | 428 | ||
429 | /* If it fails, maybe we raced another insertion? */ | ||
425 | if (sta_info_insert(sta)) | 430 | if (sta_info_insert(sta)) |
426 | return NULL; | 431 | return sta_info_get(sdata, addr); |
427 | |||
428 | return sta; | 432 | return sta; |
429 | } | 433 | } |
430 | 434 | ||
@@ -652,7 +656,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
652 | } | 656 | } |
653 | if (pos[1] != 0 && | 657 | if (pos[1] != 0 && |
654 | (pos[1] != ifibss->ssid_len || | 658 | (pos[1] != ifibss->ssid_len || |
655 | !memcmp(pos + 2, ifibss->ssid, ifibss->ssid_len))) { | 659 | memcmp(pos + 2, ifibss->ssid, ifibss->ssid_len))) { |
656 | /* Ignore ProbeReq for foreign SSID */ | 660 | /* Ignore ProbeReq for foreign SSID */ |
657 | return; | 661 | return; |
658 | } | 662 | } |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3067fbd69d63..9dd98b674cbc 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -316,6 +316,7 @@ enum ieee80211_sta_flags { | |||
316 | IEEE80211_STA_CSA_RECEIVED = BIT(5), | 316 | IEEE80211_STA_CSA_RECEIVED = BIT(5), |
317 | IEEE80211_STA_MFP_ENABLED = BIT(6), | 317 | IEEE80211_STA_MFP_ENABLED = BIT(6), |
318 | IEEE80211_STA_UAPSD_ENABLED = BIT(7), | 318 | IEEE80211_STA_UAPSD_ENABLED = BIT(7), |
319 | IEEE80211_STA_NULLFUNC_ACKED = BIT(8), | ||
319 | }; | 320 | }; |
320 | 321 | ||
321 | struct ieee80211_if_managed { | 322 | struct ieee80211_if_managed { |
@@ -688,15 +689,18 @@ struct ieee80211_local { | |||
688 | 689 | ||
689 | /* Station data */ | 690 | /* Station data */ |
690 | /* | 691 | /* |
691 | * The lock only protects the list, hash, timer and counter | 692 | * The mutex only protects the list and counter, |
692 | * against manipulation, reads are done in RCU. Additionally, | 693 | * reads are done in RCU. |
693 | * the lock protects each BSS's TIM bitmap. | 694 | * Additionally, the lock protects the hash table, |
695 | * the pending list and each BSS's TIM bitmap. | ||
694 | */ | 696 | */ |
697 | struct mutex sta_mtx; | ||
695 | spinlock_t sta_lock; | 698 | spinlock_t sta_lock; |
696 | unsigned long num_sta; | 699 | unsigned long num_sta; |
697 | struct list_head sta_list; | 700 | struct list_head sta_list, sta_pending_list; |
698 | struct sta_info *sta_hash[STA_HASH_SIZE]; | 701 | struct sta_info *sta_hash[STA_HASH_SIZE]; |
699 | struct timer_list sta_cleanup; | 702 | struct timer_list sta_cleanup; |
703 | struct work_struct sta_finish_work; | ||
700 | int sta_generation; | 704 | int sta_generation; |
701 | 705 | ||
702 | struct sk_buff_head pending[IEEE80211_MAX_QUEUES]; | 706 | struct sk_buff_head pending[IEEE80211_MAX_QUEUES]; |
@@ -770,10 +774,6 @@ struct ieee80211_local { | |||
770 | assoc_led_name[32], radio_led_name[32]; | 774 | assoc_led_name[32], radio_led_name[32]; |
771 | #endif | 775 | #endif |
772 | 776 | ||
773 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
774 | struct work_struct sta_debugfs_add; | ||
775 | #endif | ||
776 | |||
777 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | 777 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS |
778 | /* TX/RX handler statistics */ | 778 | /* TX/RX handler statistics */ |
779 | unsigned int tx_handlers_drop; | 779 | unsigned int tx_handlers_drop; |
@@ -985,7 +985,8 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata); | |||
985 | ieee80211_rx_result | 985 | ieee80211_rx_result |
986 | ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); | 986 | ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); |
987 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | 987 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, |
988 | u8 *bssid, u8 *addr, u32 supp_rates); | 988 | u8 *bssid, u8 *addr, u32 supp_rates, |
989 | gfp_t gfp); | ||
989 | int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | 990 | int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, |
990 | struct cfg80211_ibss_params *params); | 991 | struct cfg80211_ibss_params *params); |
991 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); | 992 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 7985e5150898..bc4e20e57ff5 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -102,7 +102,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, | |||
102 | if (local->num_sta >= MESH_MAX_PLINKS) | 102 | if (local->num_sta >= MESH_MAX_PLINKS) |
103 | return NULL; | 103 | return NULL; |
104 | 104 | ||
105 | sta = sta_info_alloc(sdata, hw_addr, GFP_ATOMIC); | 105 | sta = sta_info_alloc(sdata, hw_addr, GFP_KERNEL); |
106 | if (!sta) | 106 | if (!sta) |
107 | return NULL; | 107 | return NULL; |
108 | 108 | ||
@@ -236,12 +236,12 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data | |||
236 | 236 | ||
237 | sta = sta_info_get(sdata, hw_addr); | 237 | sta = sta_info_get(sdata, hw_addr); |
238 | if (!sta) { | 238 | if (!sta) { |
239 | rcu_read_unlock(); | ||
240 | |||
239 | sta = mesh_plink_alloc(sdata, hw_addr, rates); | 241 | sta = mesh_plink_alloc(sdata, hw_addr, rates); |
240 | if (!sta) { | 242 | if (!sta) |
241 | rcu_read_unlock(); | ||
242 | return; | 243 | return; |
243 | } | 244 | if (sta_info_insert_rcu(sta)) { |
244 | if (sta_info_insert(sta)) { | ||
245 | rcu_read_unlock(); | 245 | rcu_read_unlock(); |
246 | return; | 246 | return; |
247 | } | 247 | } |
@@ -485,9 +485,11 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
485 | } else if (!sta) { | 485 | } else if (!sta) { |
486 | /* ftype == PLINK_OPEN */ | 486 | /* ftype == PLINK_OPEN */ |
487 | u32 rates; | 487 | u32 rates; |
488 | |||
489 | rcu_read_unlock(); | ||
490 | |||
488 | if (!mesh_plink_free_count(sdata)) { | 491 | if (!mesh_plink_free_count(sdata)) { |
489 | mpl_dbg("Mesh plink error: no more free plinks\n"); | 492 | mpl_dbg("Mesh plink error: no more free plinks\n"); |
490 | rcu_read_unlock(); | ||
491 | return; | 493 | return; |
492 | } | 494 | } |
493 | 495 | ||
@@ -495,10 +497,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
495 | sta = mesh_plink_alloc(sdata, mgmt->sa, rates); | 497 | sta = mesh_plink_alloc(sdata, mgmt->sa, rates); |
496 | if (!sta) { | 498 | if (!sta) { |
497 | mpl_dbg("Mesh plink error: plink table full\n"); | 499 | mpl_dbg("Mesh plink error: plink table full\n"); |
498 | rcu_read_unlock(); | ||
499 | return; | 500 | return; |
500 | } | 501 | } |
501 | if (sta_info_insert(sta)) { | 502 | if (sta_info_insert_rcu(sta)) { |
502 | rcu_read_unlock(); | 503 | rcu_read_unlock(); |
503 | return; | 504 | return; |
504 | } | 505 | } |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 86c6ad1b058d..bfc4a5070013 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -27,10 +27,6 @@ | |||
27 | #include "rate.h" | 27 | #include "rate.h" |
28 | #include "led.h" | 28 | #include "led.h" |
29 | 29 | ||
30 | #define IEEE80211_AUTH_TIMEOUT (HZ / 5) | ||
31 | #define IEEE80211_AUTH_MAX_TRIES 3 | ||
32 | #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) | ||
33 | #define IEEE80211_ASSOC_MAX_TRIES 3 | ||
34 | #define IEEE80211_MAX_PROBE_TRIES 5 | 30 | #define IEEE80211_MAX_PROBE_TRIES 5 |
35 | 31 | ||
36 | /* | 32 | /* |
@@ -438,8 +434,11 @@ static void ieee80211_enable_ps(struct ieee80211_local *local, | |||
438 | } else { | 434 | } else { |
439 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) | 435 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) |
440 | ieee80211_send_nullfunc(local, sdata, 1); | 436 | ieee80211_send_nullfunc(local, sdata, 1); |
441 | conf->flags |= IEEE80211_CONF_PS; | 437 | |
442 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | 438 | if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) { |
439 | conf->flags |= IEEE80211_CONF_PS; | ||
440 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | ||
441 | } | ||
443 | } | 442 | } |
444 | } | 443 | } |
445 | 444 | ||
@@ -545,6 +544,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | |||
545 | container_of(work, struct ieee80211_local, | 544 | container_of(work, struct ieee80211_local, |
546 | dynamic_ps_enable_work); | 545 | dynamic_ps_enable_work); |
547 | struct ieee80211_sub_if_data *sdata = local->ps_sdata; | 546 | struct ieee80211_sub_if_data *sdata = local->ps_sdata; |
547 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
548 | 548 | ||
549 | /* can only happen when PS was just disabled anyway */ | 549 | /* can only happen when PS was just disabled anyway */ |
550 | if (!sdata) | 550 | if (!sdata) |
@@ -553,11 +553,16 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | |||
553 | if (local->hw.conf.flags & IEEE80211_CONF_PS) | 553 | if (local->hw.conf.flags & IEEE80211_CONF_PS) |
554 | return; | 554 | return; |
555 | 555 | ||
556 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) | 556 | if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && |
557 | (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) | ||
557 | ieee80211_send_nullfunc(local, sdata, 1); | 558 | ieee80211_send_nullfunc(local, sdata, 1); |
558 | 559 | ||
559 | local->hw.conf.flags |= IEEE80211_CONF_PS; | 560 | if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) || |
560 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | 561 | (ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) { |
562 | ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; | ||
563 | local->hw.conf.flags |= IEEE80211_CONF_PS; | ||
564 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | ||
565 | } | ||
561 | } | 566 | } |
562 | 567 | ||
563 | void ieee80211_dynamic_ps_timer(unsigned long data) | 568 | void ieee80211_dynamic_ps_timer(unsigned long data) |
@@ -792,8 +797,10 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) | |||
792 | 797 | ||
793 | rcu_read_lock(); | 798 | rcu_read_lock(); |
794 | sta = sta_info_get(sdata, bssid); | 799 | sta = sta_info_get(sdata, bssid); |
795 | if (sta) | 800 | if (sta) { |
801 | set_sta_flags(sta, WLAN_STA_DISASSOC); | ||
796 | ieee80211_sta_tear_down_BA_sessions(sta); | 802 | ieee80211_sta_tear_down_BA_sessions(sta); |
803 | } | ||
797 | rcu_read_unlock(); | 804 | rcu_read_unlock(); |
798 | 805 | ||
799 | changed |= ieee80211_reset_erp_info(sdata); | 806 | changed |= ieee80211_reset_erp_info(sdata); |
@@ -826,19 +833,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) | |||
826 | changed |= BSS_CHANGED_BSSID; | 833 | changed |= BSS_CHANGED_BSSID; |
827 | ieee80211_bss_info_change_notify(sdata, changed); | 834 | ieee80211_bss_info_change_notify(sdata, changed); |
828 | 835 | ||
829 | rcu_read_lock(); | 836 | sta_info_destroy_addr(sdata, bssid); |
830 | |||
831 | sta = sta_info_get(sdata, bssid); | ||
832 | if (!sta) { | ||
833 | rcu_read_unlock(); | ||
834 | return; | ||
835 | } | ||
836 | |||
837 | sta_info_unlink(&sta); | ||
838 | |||
839 | rcu_read_unlock(); | ||
840 | |||
841 | sta_info_destroy(sta); | ||
842 | } | 837 | } |
843 | 838 | ||
844 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | 839 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, |
@@ -1844,7 +1839,11 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
1844 | wk->probe_auth.algorithm = auth_alg; | 1839 | wk->probe_auth.algorithm = auth_alg; |
1845 | wk->probe_auth.privacy = req->bss->capability & WLAN_CAPABILITY_PRIVACY; | 1840 | wk->probe_auth.privacy = req->bss->capability & WLAN_CAPABILITY_PRIVACY; |
1846 | 1841 | ||
1847 | wk->type = IEEE80211_WORK_DIRECT_PROBE; | 1842 | /* if we already have a probe, don't probe again */ |
1843 | if (req->bss->proberesp_ies) | ||
1844 | wk->type = IEEE80211_WORK_AUTH; | ||
1845 | else | ||
1846 | wk->type = IEEE80211_WORK_DIRECT_PROBE; | ||
1848 | wk->chan = req->bss->channel; | 1847 | wk->chan = req->bss->channel; |
1849 | wk->sdata = sdata; | 1848 | wk->sdata = sdata; |
1850 | wk->done = ieee80211_probe_auth_done; | 1849 | wk->done = ieee80211_probe_auth_done; |
@@ -1904,6 +1903,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
1904 | return -ENOMEM; | 1903 | return -ENOMEM; |
1905 | 1904 | ||
1906 | ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; | 1905 | ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; |
1906 | ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; | ||
1907 | 1907 | ||
1908 | for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) | 1908 | for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) |
1909 | if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || | 1909 | if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || |
@@ -2007,12 +2007,18 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2007 | 2007 | ||
2008 | mutex_lock(&local->work_mtx); | 2008 | mutex_lock(&local->work_mtx); |
2009 | list_for_each_entry(wk, &local->work_list, list) { | 2009 | list_for_each_entry(wk, &local->work_list, list) { |
2010 | if (wk->type != IEEE80211_WORK_DIRECT_PROBE) | 2010 | if (wk->sdata != sdata) |
2011 | continue; | ||
2012 | |||
2013 | if (wk->type != IEEE80211_WORK_DIRECT_PROBE && | ||
2014 | wk->type != IEEE80211_WORK_AUTH) | ||
2011 | continue; | 2015 | continue; |
2016 | |||
2012 | if (memcmp(req->bss->bssid, wk->filter_ta, ETH_ALEN)) | 2017 | if (memcmp(req->bss->bssid, wk->filter_ta, ETH_ALEN)) |
2013 | continue; | 2018 | continue; |
2014 | not_auth_yet = true; | 2019 | |
2015 | list_del(&wk->list); | 2020 | not_auth_yet = wk->type == IEEE80211_WORK_DIRECT_PROBE; |
2021 | list_del_rcu(&wk->list); | ||
2016 | free_work(wk); | 2022 | free_work(wk); |
2017 | break; | 2023 | break; |
2018 | } | 2024 | } |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 47f818959ad7..0e64484e861c 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -11,7 +11,6 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
11 | struct ieee80211_local *local = hw_to_local(hw); | 11 | struct ieee80211_local *local = hw_to_local(hw); |
12 | struct ieee80211_sub_if_data *sdata; | 12 | struct ieee80211_sub_if_data *sdata; |
13 | struct sta_info *sta; | 13 | struct sta_info *sta; |
14 | unsigned long flags; | ||
15 | 14 | ||
16 | ieee80211_scan_cancel(local); | 15 | ieee80211_scan_cancel(local); |
17 | 16 | ||
@@ -55,22 +54,21 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
55 | rcu_read_unlock(); | 54 | rcu_read_unlock(); |
56 | 55 | ||
57 | /* remove STAs */ | 56 | /* remove STAs */ |
58 | spin_lock_irqsave(&local->sta_lock, flags); | 57 | mutex_lock(&local->sta_mtx); |
59 | list_for_each_entry(sta, &local->sta_list, list) { | 58 | list_for_each_entry(sta, &local->sta_list, list) { |
60 | if (local->ops->sta_notify) { | 59 | if (sta->uploaded) { |
61 | sdata = sta->sdata; | 60 | sdata = sta->sdata; |
62 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 61 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
63 | sdata = container_of(sdata->bss, | 62 | sdata = container_of(sdata->bss, |
64 | struct ieee80211_sub_if_data, | 63 | struct ieee80211_sub_if_data, |
65 | u.ap); | 64 | u.ap); |
66 | 65 | ||
67 | drv_sta_notify(local, sdata, STA_NOTIFY_REMOVE, | 66 | drv_sta_remove(local, sdata, &sta->sta); |
68 | &sta->sta); | ||
69 | } | 67 | } |
70 | 68 | ||
71 | mesh_plink_quiesce(sta); | 69 | mesh_plink_quiesce(sta); |
72 | } | 70 | } |
73 | spin_unlock_irqrestore(&local->sta_lock, flags); | 71 | mutex_unlock(&local->sta_mtx); |
74 | 72 | ||
75 | /* remove all interfaces */ | 73 | /* remove all interfaces */ |
76 | list_for_each_entry(sdata, &local->interfaces, list) { | 74 | list_for_each_entry(sdata, &local->interfaces, list) { |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index c74b7c85403c..0b299d236fa1 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -145,7 +145,7 @@ static const struct file_operations rcname_ops = { | |||
145 | }; | 145 | }; |
146 | #endif | 146 | #endif |
147 | 147 | ||
148 | struct rate_control_ref *rate_control_alloc(const char *name, | 148 | static struct rate_control_ref *rate_control_alloc(const char *name, |
149 | struct ieee80211_local *local) | 149 | struct ieee80211_local *local) |
150 | { | 150 | { |
151 | struct dentry *debugfsdir = NULL; | 151 | struct dentry *debugfsdir = NULL; |
@@ -303,6 +303,9 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, | |||
303 | info->control.rates[i].count = 1; | 303 | info->control.rates[i].count = 1; |
304 | } | 304 | } |
305 | 305 | ||
306 | if (sdata->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) | ||
307 | return; | ||
308 | |||
306 | ref->ops->get_rate(ref->priv, ista, priv_sta, txrc); | 309 | ref->ops->get_rate(ref->priv, ista, priv_sta, txrc); |
307 | 310 | ||
308 | /* | 311 | /* |
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 998cf7a935b6..b6108bca96d4 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -26,10 +26,6 @@ struct rate_control_ref { | |||
26 | struct kref kref; | 26 | struct kref kref; |
27 | }; | 27 | }; |
28 | 28 | ||
29 | /* Get a reference to the rate control algorithm. If `name' is NULL, get the | ||
30 | * first available algorithm. */ | ||
31 | struct rate_control_ref *rate_control_alloc(const char *name, | ||
32 | struct ieee80211_local *local); | ||
33 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, | 29 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, |
34 | struct sta_info *sta, | 30 | struct sta_info *sta, |
35 | struct ieee80211_tx_rate_control *txrc); | 31 | struct ieee80211_tx_rate_control *txrc); |
@@ -116,7 +112,8 @@ static inline void rate_control_remove_sta_debugfs(struct sta_info *sta) | |||
116 | #endif | 112 | #endif |
117 | } | 113 | } |
118 | 114 | ||
119 | /* functions for rate control related to a device */ | 115 | /* Get a reference to the rate control algorithm. If `name' is NULL, get the |
116 | * first available algorithm. */ | ||
120 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, | 117 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, |
121 | const char *name); | 118 | const char *name); |
122 | void rate_control_deinitialize(struct ieee80211_local *local); | 119 | void rate_control_deinitialize(struct ieee80211_local *local); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 5709307fcb9b..c9755f3d986c 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1719,6 +1719,7 @@ static ieee80211_rx_result debug_noinline | |||
1719 | ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | 1719 | ieee80211_rx_h_data(struct ieee80211_rx_data *rx) |
1720 | { | 1720 | { |
1721 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 1721 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1722 | struct ieee80211_local *local = rx->local; | ||
1722 | struct net_device *dev = sdata->dev; | 1723 | struct net_device *dev = sdata->dev; |
1723 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 1724 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
1724 | __le16 fc = hdr->frame_control; | 1725 | __le16 fc = hdr->frame_control; |
@@ -1750,6 +1751,13 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | |||
1750 | dev->stats.rx_packets++; | 1751 | dev->stats.rx_packets++; |
1751 | dev->stats.rx_bytes += rx->skb->len; | 1752 | dev->stats.rx_bytes += rx->skb->len; |
1752 | 1753 | ||
1754 | if (ieee80211_is_data(hdr->frame_control) && | ||
1755 | !is_multicast_ether_addr(hdr->addr1) && | ||
1756 | local->hw.conf.dynamic_ps_timeout > 0 && local->ps_sdata) { | ||
1757 | mod_timer(&local->dynamic_ps_timer, jiffies + | ||
1758 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); | ||
1759 | } | ||
1760 | |||
1753 | ieee80211_deliver_skb(rx); | 1761 | ieee80211_deliver_skb(rx); |
1754 | 1762 | ||
1755 | return RX_QUEUED; | 1763 | return RX_QUEUED; |
@@ -2244,8 +2252,8 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
2244 | rate_idx = 0; /* TODO: HT rates */ | 2252 | rate_idx = 0; /* TODO: HT rates */ |
2245 | else | 2253 | else |
2246 | rate_idx = status->rate_idx; | 2254 | rate_idx = status->rate_idx; |
2247 | rx->sta = ieee80211_ibss_add_sta(sdata, bssid, hdr->addr2, | 2255 | rx->sta = ieee80211_ibss_add_sta(sdata, bssid, |
2248 | BIT(rate_idx)); | 2256 | hdr->addr2, BIT(rate_idx), GFP_ATOMIC); |
2249 | } | 2257 | } |
2250 | break; | 2258 | break; |
2251 | case NL80211_IFTYPE_MESH_POINT: | 2259 | case NL80211_IFTYPE_MESH_POINT: |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index bc061f629674..b822dce97867 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -345,6 +345,13 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
345 | if (local->scan_req) | 345 | if (local->scan_req) |
346 | return -EBUSY; | 346 | return -EBUSY; |
347 | 347 | ||
348 | if (!list_empty(&local->work_list)) { | ||
349 | /* wait for the work to finish/time out */ | ||
350 | local->scan_req = req; | ||
351 | local->scan_sdata = sdata; | ||
352 | return 0; | ||
353 | } | ||
354 | |||
348 | if (local->ops->hw_scan) { | 355 | if (local->ops->hw_scan) { |
349 | u8 *ies; | 356 | u8 *ies; |
350 | 357 | ||
@@ -364,29 +371,33 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
364 | local->hw_scan_req->ie = ies; | 371 | local->hw_scan_req->ie = ies; |
365 | 372 | ||
366 | local->hw_scan_band = 0; | 373 | local->hw_scan_band = 0; |
374 | |||
375 | /* | ||
376 | * After allocating local->hw_scan_req, we must | ||
377 | * go through until ieee80211_prep_hw_scan(), so | ||
378 | * anything that might be changed here and leave | ||
379 | * this function early must not go after this | ||
380 | * allocation. | ||
381 | */ | ||
367 | } | 382 | } |
368 | 383 | ||
369 | local->scan_req = req; | 384 | local->scan_req = req; |
370 | local->scan_sdata = sdata; | 385 | local->scan_sdata = sdata; |
371 | 386 | ||
372 | if (!list_empty(&local->work_list)) { | ||
373 | /* wait for the work to finish/time out */ | ||
374 | return 0; | ||
375 | } | ||
376 | |||
377 | if (local->ops->hw_scan) | 387 | if (local->ops->hw_scan) |
378 | __set_bit(SCAN_HW_SCANNING, &local->scanning); | 388 | __set_bit(SCAN_HW_SCANNING, &local->scanning); |
379 | else | 389 | else |
380 | __set_bit(SCAN_SW_SCANNING, &local->scanning); | 390 | __set_bit(SCAN_SW_SCANNING, &local->scanning); |
391 | |||
381 | /* | 392 | /* |
382 | * Kicking off the scan need not be protected, | 393 | * Kicking off the scan need not be protected, |
383 | * only the scan variable stuff, since now | 394 | * only the scan variable stuff, since now |
384 | * local->scan_req is assigned and other callers | 395 | * local->scan_req is assigned and other callers |
385 | * will abort their scan attempts. | 396 | * will abort their scan attempts. |
386 | * | 397 | * |
387 | * This avoids getting a scan_mtx -> iflist_mtx | 398 | * This avoids too many locking dependencies |
388 | * dependency, so that the scan completed calls | 399 | * so that the scan completed calls have more |
389 | * have more locking freedom. | 400 | * locking freedom. |
390 | */ | 401 | */ |
391 | 402 | ||
392 | ieee80211_recalc_idle(local); | 403 | ieee80211_recalc_idle(local); |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index f735826f055c..211c475f73c6 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -32,49 +32,33 @@ | |||
32 | * for faster lookup and a list for iteration. They are managed using | 32 | * for faster lookup and a list for iteration. They are managed using |
33 | * RCU, i.e. access to the list and hash table is protected by RCU. | 33 | * RCU, i.e. access to the list and hash table is protected by RCU. |
34 | * | 34 | * |
35 | * Upon allocating a STA info structure with sta_info_alloc(), the caller owns | 35 | * Upon allocating a STA info structure with sta_info_alloc(), the caller |
36 | * that structure. It must then either destroy it using sta_info_destroy() | 36 | * owns that structure. It must then insert it into the hash table using |
37 | * (which is pretty useless) or insert it into the hash table using | 37 | * either sta_info_insert() or sta_info_insert_rcu(); only in the latter |
38 | * sta_info_insert() which demotes the reference from ownership to a regular | 38 | * case (which acquires an rcu read section but must not be called from |
39 | * RCU-protected reference; if the function is called without protection by an | 39 | * within one) will the pointer still be valid after the call. Note that |
40 | * RCU critical section the reference is instantly invalidated. Note that the | 40 | * the caller may not do much with the STA info before inserting it, in |
41 | * caller may not do much with the STA info before inserting it, in particular, | 41 | * particular, it may not start any mesh peer link management or add |
42 | * it may not start any mesh peer link management or add encryption keys. | 42 | * encryption keys. |
43 | * | 43 | * |
44 | * When the insertion fails (sta_info_insert()) returns non-zero), the | 44 | * When the insertion fails (sta_info_insert()) returns non-zero), the |
45 | * structure will have been freed by sta_info_insert()! | 45 | * structure will have been freed by sta_info_insert()! |
46 | * | 46 | * |
47 | * sta entries are added by mac80211 when you establish a link with a | 47 | * Station entries are added by mac80211 when you establish a link with a |
48 | * peer. This means different things for the different type of interfaces | 48 | * peer. This means different things for the different type of interfaces |
49 | * we support. For a regular station this mean we add the AP sta when we | 49 | * we support. For a regular station this mean we add the AP sta when we |
50 | * receive an assocation response from the AP. For IBSS this occurs when | 50 | * receive an assocation response from the AP. For IBSS this occurs when |
51 | * we receive a probe response or a beacon from target IBSS network. For | 51 | * get to know about a peer on the same IBSS. For WDS we add the sta for |
52 | * WDS we add the sta for the peer imediately upon device open. When using | 52 | * the peer imediately upon device open. When using AP mode we add stations |
53 | * AP mode we add stations for each respective station upon request from | 53 | * for each respective station upon request from userspace through nl80211. |
54 | * userspace through nl80211. | ||
55 | * | 54 | * |
56 | * Because there are debugfs entries for each station, and adding those | 55 | * In order to remove a STA info structure, various sta_info_destroy_*() |
57 | * must be able to sleep, it is also possible to "pin" a station entry, | 56 | * calls are available. |
58 | * that means it can be removed from the hash table but not be freed. | ||
59 | * See the comment in __sta_info_unlink() for more information, this is | ||
60 | * an internal capability only. | ||
61 | * | 57 | * |
62 | * In order to remove a STA info structure, the caller needs to first | 58 | * There is no concept of ownership on a STA entry, each structure is |
63 | * unlink it (sta_info_unlink()) from the list and hash tables and | 59 | * owned by the global hash table/list until it is removed. All users of |
64 | * then destroy it; sta_info_destroy() will wait for an RCU grace period | 60 | * the structure need to be RCU protected so that the structure won't be |
65 | * to elapse before actually freeing it. Due to the pinning and the | 61 | * freed before they are done using it. |
66 | * possibility of multiple callers trying to remove the same STA info at | ||
67 | * the same time, sta_info_unlink() can clear the STA info pointer it is | ||
68 | * passed to indicate that the STA info is owned by somebody else now. | ||
69 | * | ||
70 | * If sta_info_unlink() did not clear the pointer then the caller owns | ||
71 | * the STA info structure now and is responsible of destroying it with | ||
72 | * a call to sta_info_destroy(). | ||
73 | * | ||
74 | * In all other cases, there is no concept of ownership on a STA entry, | ||
75 | * each structure is owned by the global hash table/list until it is | ||
76 | * removed. All users of the structure need to be RCU protected so that | ||
77 | * the structure won't be freed before they are done using it. | ||
78 | */ | 62 | */ |
79 | 63 | ||
80 | /* Caller must hold local->sta_lock */ | 64 | /* Caller must hold local->sta_lock */ |
@@ -185,101 +169,6 @@ static void __sta_info_free(struct ieee80211_local *local, | |||
185 | kfree(sta); | 169 | kfree(sta); |
186 | } | 170 | } |
187 | 171 | ||
188 | void sta_info_destroy(struct sta_info *sta) | ||
189 | { | ||
190 | struct ieee80211_local *local; | ||
191 | struct sk_buff *skb; | ||
192 | int i; | ||
193 | |||
194 | might_sleep(); | ||
195 | |||
196 | if (!sta) | ||
197 | return; | ||
198 | |||
199 | local = sta->local; | ||
200 | |||
201 | cancel_work_sync(&sta->drv_unblock_wk); | ||
202 | |||
203 | rate_control_remove_sta_debugfs(sta); | ||
204 | ieee80211_sta_debugfs_remove(sta); | ||
205 | |||
206 | #ifdef CONFIG_MAC80211_MESH | ||
207 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) | ||
208 | mesh_plink_deactivate(sta); | ||
209 | #endif | ||
210 | |||
211 | /* | ||
212 | * We have only unlinked the key, and actually destroying it | ||
213 | * may mean it is removed from hardware which requires that | ||
214 | * the key->sta pointer is still valid, so flush the key todo | ||
215 | * list here. | ||
216 | * | ||
217 | * ieee80211_key_todo() will synchronize_rcu() so after this | ||
218 | * nothing can reference this sta struct any more. | ||
219 | */ | ||
220 | ieee80211_key_todo(); | ||
221 | |||
222 | #ifdef CONFIG_MAC80211_MESH | ||
223 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) | ||
224 | del_timer_sync(&sta->plink_timer); | ||
225 | #endif | ||
226 | |||
227 | while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { | ||
228 | local->total_ps_buffered--; | ||
229 | dev_kfree_skb_any(skb); | ||
230 | } | ||
231 | |||
232 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) | ||
233 | dev_kfree_skb_any(skb); | ||
234 | |||
235 | for (i = 0; i < STA_TID_NUM; i++) { | ||
236 | struct tid_ampdu_rx *tid_rx; | ||
237 | struct tid_ampdu_tx *tid_tx; | ||
238 | |||
239 | spin_lock_bh(&sta->lock); | ||
240 | tid_rx = sta->ampdu_mlme.tid_rx[i]; | ||
241 | /* Make sure timer won't free the tid_rx struct, see below */ | ||
242 | if (tid_rx) | ||
243 | tid_rx->shutdown = true; | ||
244 | |||
245 | spin_unlock_bh(&sta->lock); | ||
246 | |||
247 | /* | ||
248 | * Outside spinlock - shutdown is true now so that the timer | ||
249 | * won't free tid_rx, we have to do that now. Can't let the | ||
250 | * timer do it because we have to sync the timer outside the | ||
251 | * lock that it takes itself. | ||
252 | */ | ||
253 | if (tid_rx) { | ||
254 | del_timer_sync(&tid_rx->session_timer); | ||
255 | kfree(tid_rx); | ||
256 | } | ||
257 | |||
258 | /* | ||
259 | * No need to do such complications for TX agg sessions, the | ||
260 | * path leading to freeing the tid_tx struct goes via a call | ||
261 | * from the driver, and thus needs to look up the sta struct | ||
262 | * again, which cannot be found when we get here. Hence, we | ||
263 | * just need to delete the timer and free the aggregation | ||
264 | * info; we won't be telling the peer about it then but that | ||
265 | * doesn't matter if we're not talking to it again anyway. | ||
266 | */ | ||
267 | tid_tx = sta->ampdu_mlme.tid_tx[i]; | ||
268 | if (tid_tx) { | ||
269 | del_timer_sync(&tid_tx->addba_resp_timer); | ||
270 | /* | ||
271 | * STA removed while aggregation session being | ||
272 | * started? Bit odd, but purge frames anyway. | ||
273 | */ | ||
274 | skb_queue_purge(&tid_tx->pending); | ||
275 | kfree(tid_tx); | ||
276 | } | ||
277 | } | ||
278 | |||
279 | __sta_info_free(local, sta); | ||
280 | } | ||
281 | |||
282 | |||
283 | /* Caller must hold local->sta_lock */ | 172 | /* Caller must hold local->sta_lock */ |
284 | static void sta_info_hash_add(struct ieee80211_local *local, | 173 | static void sta_info_hash_add(struct ieee80211_local *local, |
285 | struct sta_info *sta) | 174 | struct sta_info *sta) |
@@ -376,7 +265,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
376 | return sta; | 265 | return sta; |
377 | } | 266 | } |
378 | 267 | ||
379 | int sta_info_insert(struct sta_info *sta) | 268 | static int sta_info_finish_insert(struct sta_info *sta, bool async) |
380 | { | 269 | { |
381 | struct ieee80211_local *local = sta->local; | 270 | struct ieee80211_local *local = sta->local; |
382 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 271 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
@@ -384,6 +273,91 @@ int sta_info_insert(struct sta_info *sta) | |||
384 | unsigned long flags; | 273 | unsigned long flags; |
385 | int err = 0; | 274 | int err = 0; |
386 | 275 | ||
276 | WARN_ON(!mutex_is_locked(&local->sta_mtx)); | ||
277 | |||
278 | /* notify driver */ | ||
279 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
280 | sdata = container_of(sdata->bss, | ||
281 | struct ieee80211_sub_if_data, | ||
282 | u.ap); | ||
283 | err = drv_sta_add(local, sdata, &sta->sta); | ||
284 | if (err) { | ||
285 | if (!async) | ||
286 | return err; | ||
287 | printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to driver (%d)" | ||
288 | " - keeping it anyway.\n", | ||
289 | sdata->name, sta->sta.addr, err); | ||
290 | } else { | ||
291 | sta->uploaded = true; | ||
292 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
293 | if (async) | ||
294 | printk(KERN_DEBUG "%s: Finished adding IBSS STA %pM\n", | ||
295 | wiphy_name(local->hw.wiphy), sta->sta.addr); | ||
296 | #endif | ||
297 | } | ||
298 | |||
299 | sdata = sta->sdata; | ||
300 | |||
301 | if (!async) { | ||
302 | local->num_sta++; | ||
303 | local->sta_generation++; | ||
304 | smp_mb(); | ||
305 | |||
306 | /* make the station visible */ | ||
307 | spin_lock_irqsave(&local->sta_lock, flags); | ||
308 | sta_info_hash_add(local, sta); | ||
309 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
310 | } | ||
311 | |||
312 | list_add(&sta->list, &local->sta_list); | ||
313 | |||
314 | ieee80211_sta_debugfs_add(sta); | ||
315 | rate_control_add_sta_debugfs(sta); | ||
316 | |||
317 | sinfo.filled = 0; | ||
318 | sinfo.generation = local->sta_generation; | ||
319 | cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); | ||
320 | |||
321 | |||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static void sta_info_finish_pending(struct ieee80211_local *local) | ||
326 | { | ||
327 | struct sta_info *sta; | ||
328 | unsigned long flags; | ||
329 | |||
330 | spin_lock_irqsave(&local->sta_lock, flags); | ||
331 | while (!list_empty(&local->sta_pending_list)) { | ||
332 | sta = list_first_entry(&local->sta_pending_list, | ||
333 | struct sta_info, list); | ||
334 | list_del(&sta->list); | ||
335 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
336 | |||
337 | sta_info_finish_insert(sta, true); | ||
338 | |||
339 | spin_lock_irqsave(&local->sta_lock, flags); | ||
340 | } | ||
341 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
342 | } | ||
343 | |||
344 | static void sta_info_finish_work(struct work_struct *work) | ||
345 | { | ||
346 | struct ieee80211_local *local = | ||
347 | container_of(work, struct ieee80211_local, sta_finish_work); | ||
348 | |||
349 | mutex_lock(&local->sta_mtx); | ||
350 | sta_info_finish_pending(local); | ||
351 | mutex_unlock(&local->sta_mtx); | ||
352 | } | ||
353 | |||
354 | int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) | ||
355 | { | ||
356 | struct ieee80211_local *local = sta->local; | ||
357 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
358 | unsigned long flags; | ||
359 | int err = 0; | ||
360 | |||
387 | /* | 361 | /* |
388 | * Can't be a WARN_ON because it can be triggered through a race: | 362 | * Can't be a WARN_ON because it can be triggered through a race: |
389 | * something inserts a STA (on one CPU) without holding the RTNL | 363 | * something inserts a STA (on one CPU) without holding the RTNL |
@@ -391,36 +365,87 @@ int sta_info_insert(struct sta_info *sta) | |||
391 | */ | 365 | */ |
392 | if (unlikely(!ieee80211_sdata_running(sdata))) { | 366 | if (unlikely(!ieee80211_sdata_running(sdata))) { |
393 | err = -ENETDOWN; | 367 | err = -ENETDOWN; |
368 | rcu_read_lock(); | ||
394 | goto out_free; | 369 | goto out_free; |
395 | } | 370 | } |
396 | 371 | ||
397 | if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->vif.addr) == 0 || | 372 | if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->vif.addr) == 0 || |
398 | is_multicast_ether_addr(sta->sta.addr))) { | 373 | is_multicast_ether_addr(sta->sta.addr))) { |
399 | err = -EINVAL; | 374 | err = -EINVAL; |
375 | rcu_read_lock(); | ||
400 | goto out_free; | 376 | goto out_free; |
401 | } | 377 | } |
402 | 378 | ||
379 | /* | ||
380 | * In ad-hoc mode, we sometimes need to insert stations | ||
381 | * from tasklet context from the RX path. To avoid races, | ||
382 | * always do so in that case -- see the comment below. | ||
383 | */ | ||
384 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | ||
385 | spin_lock_irqsave(&local->sta_lock, flags); | ||
386 | /* check if STA exists already */ | ||
387 | if (sta_info_get_bss(sdata, sta->sta.addr)) { | ||
388 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
389 | rcu_read_lock(); | ||
390 | err = -EEXIST; | ||
391 | goto out_free; | ||
392 | } | ||
393 | |||
394 | local->num_sta++; | ||
395 | local->sta_generation++; | ||
396 | smp_mb(); | ||
397 | sta_info_hash_add(local, sta); | ||
398 | |||
399 | list_add_tail(&sta->list, &local->sta_pending_list); | ||
400 | |||
401 | rcu_read_lock(); | ||
402 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
403 | |||
404 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
405 | printk(KERN_DEBUG "%s: Added IBSS STA %pM\n", | ||
406 | wiphy_name(local->hw.wiphy), sta->sta.addr); | ||
407 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | ||
408 | |||
409 | ieee80211_queue_work(&local->hw, &local->sta_finish_work); | ||
410 | |||
411 | return 0; | ||
412 | } | ||
413 | |||
414 | /* | ||
415 | * On first glance, this will look racy, because the code | ||
416 | * below this point, which inserts a station with sleeping, | ||
417 | * unlocks the sta_lock between checking existence in the | ||
418 | * hash table and inserting into it. | ||
419 | * | ||
420 | * However, it is not racy against itself because it keeps | ||
421 | * the mutex locked. It still seems to race against the | ||
422 | * above code that atomically inserts the station... That, | ||
423 | * however, is not true because the above code can only | ||
424 | * be invoked for IBSS interfaces, and the below code will | ||
425 | * not be -- and the two do not race against each other as | ||
426 | * the hash table also keys off the interface. | ||
427 | */ | ||
428 | |||
429 | might_sleep(); | ||
430 | |||
431 | mutex_lock(&local->sta_mtx); | ||
432 | |||
403 | spin_lock_irqsave(&local->sta_lock, flags); | 433 | spin_lock_irqsave(&local->sta_lock, flags); |
404 | /* check if STA exists already */ | 434 | /* check if STA exists already */ |
405 | if (sta_info_get(sdata, sta->sta.addr)) { | 435 | if (sta_info_get_bss(sdata, sta->sta.addr)) { |
406 | spin_unlock_irqrestore(&local->sta_lock, flags); | 436 | spin_unlock_irqrestore(&local->sta_lock, flags); |
437 | rcu_read_lock(); | ||
407 | err = -EEXIST; | 438 | err = -EEXIST; |
408 | goto out_free; | 439 | goto out_free; |
409 | } | 440 | } |
410 | list_add(&sta->list, &local->sta_list); | ||
411 | local->sta_generation++; | ||
412 | local->num_sta++; | ||
413 | sta_info_hash_add(local, sta); | ||
414 | 441 | ||
415 | /* notify driver */ | 442 | spin_unlock_irqrestore(&local->sta_lock, flags); |
416 | if (local->ops->sta_notify) { | ||
417 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
418 | sdata = container_of(sdata->bss, | ||
419 | struct ieee80211_sub_if_data, | ||
420 | u.ap); | ||
421 | 443 | ||
422 | drv_sta_notify(local, sdata, STA_NOTIFY_ADD, &sta->sta); | 444 | err = sta_info_finish_insert(sta, false); |
423 | sdata = sta->sdata; | 445 | if (err) { |
446 | mutex_unlock(&local->sta_mtx); | ||
447 | rcu_read_lock(); | ||
448 | goto out_free; | ||
424 | } | 449 | } |
425 | 450 | ||
426 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 451 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
@@ -428,22 +453,9 @@ int sta_info_insert(struct sta_info *sta) | |||
428 | wiphy_name(local->hw.wiphy), sta->sta.addr); | 453 | wiphy_name(local->hw.wiphy), sta->sta.addr); |
429 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 454 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
430 | 455 | ||
431 | spin_unlock_irqrestore(&local->sta_lock, flags); | 456 | /* move reference to rcu-protected */ |
432 | 457 | rcu_read_lock(); | |
433 | sinfo.filled = 0; | 458 | mutex_unlock(&local->sta_mtx); |
434 | sinfo.generation = local->sta_generation; | ||
435 | cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_ATOMIC); | ||
436 | |||
437 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
438 | /* | ||
439 | * Debugfs entry adding might sleep, so schedule process | ||
440 | * context task for adding entry for STAs that do not yet | ||
441 | * have one. | ||
442 | * NOTE: due to auto-freeing semantics this may only be done | ||
443 | * if the insertion is successful! | ||
444 | */ | ||
445 | schedule_work(&local->sta_debugfs_add); | ||
446 | #endif | ||
447 | 459 | ||
448 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 460 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
449 | mesh_accept_plinks_update(sdata); | 461 | mesh_accept_plinks_update(sdata); |
@@ -455,6 +467,15 @@ int sta_info_insert(struct sta_info *sta) | |||
455 | return err; | 467 | return err; |
456 | } | 468 | } |
457 | 469 | ||
470 | int sta_info_insert(struct sta_info *sta) | ||
471 | { | ||
472 | int err = sta_info_insert_rcu(sta); | ||
473 | |||
474 | rcu_read_unlock(); | ||
475 | |||
476 | return err; | ||
477 | } | ||
478 | |||
458 | static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) | 479 | static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) |
459 | { | 480 | { |
460 | /* | 481 | /* |
@@ -523,108 +544,6 @@ void sta_info_clear_tim_bit(struct sta_info *sta) | |||
523 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); | 544 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); |
524 | } | 545 | } |
525 | 546 | ||
526 | static void __sta_info_unlink(struct sta_info **sta) | ||
527 | { | ||
528 | struct ieee80211_local *local = (*sta)->local; | ||
529 | struct ieee80211_sub_if_data *sdata = (*sta)->sdata; | ||
530 | /* | ||
531 | * pull caller's reference if we're already gone. | ||
532 | */ | ||
533 | if (sta_info_hash_del(local, *sta)) { | ||
534 | *sta = NULL; | ||
535 | return; | ||
536 | } | ||
537 | |||
538 | if ((*sta)->key) { | ||
539 | ieee80211_key_free((*sta)->key); | ||
540 | WARN_ON((*sta)->key); | ||
541 | } | ||
542 | |||
543 | list_del(&(*sta)->list); | ||
544 | (*sta)->dead = true; | ||
545 | |||
546 | if (test_and_clear_sta_flags(*sta, | ||
547 | WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) { | ||
548 | BUG_ON(!sdata->bss); | ||
549 | |||
550 | atomic_dec(&sdata->bss->num_sta_ps); | ||
551 | __sta_info_clear_tim_bit(sdata->bss, *sta); | ||
552 | } | ||
553 | |||
554 | local->num_sta--; | ||
555 | local->sta_generation++; | ||
556 | |||
557 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
558 | rcu_assign_pointer(sdata->u.vlan.sta, NULL); | ||
559 | |||
560 | if (local->ops->sta_notify) { | ||
561 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
562 | sdata = container_of(sdata->bss, | ||
563 | struct ieee80211_sub_if_data, | ||
564 | u.ap); | ||
565 | |||
566 | drv_sta_notify(local, sdata, STA_NOTIFY_REMOVE, | ||
567 | &(*sta)->sta); | ||
568 | sdata = (*sta)->sdata; | ||
569 | } | ||
570 | |||
571 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
572 | mesh_accept_plinks_update(sdata); | ||
573 | #ifdef CONFIG_MAC80211_MESH | ||
574 | del_timer(&(*sta)->plink_timer); | ||
575 | #endif | ||
576 | } | ||
577 | |||
578 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
579 | printk(KERN_DEBUG "%s: Removed STA %pM\n", | ||
580 | wiphy_name(local->hw.wiphy), (*sta)->sta.addr); | ||
581 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | ||
582 | |||
583 | /* | ||
584 | * Finally, pull caller's reference if the STA is pinned by the | ||
585 | * task that is adding the debugfs entries. In that case, we | ||
586 | * leave the STA "to be freed". | ||
587 | * | ||
588 | * The rules are not trivial, but not too complex either: | ||
589 | * (1) pin_status is only modified under the sta_lock | ||
590 | * (2) STAs may only be pinned under the RTNL so that | ||
591 | * sta_info_flush() is guaranteed to actually destroy | ||
592 | * all STAs that are active for a given interface, this | ||
593 | * is required for correctness because otherwise we | ||
594 | * could notify a driver that an interface is going | ||
595 | * away and only after that (!) notify it about a STA | ||
596 | * on that interface going away. | ||
597 | * (3) sta_info_debugfs_add_work() will set the status | ||
598 | * to PINNED when it found an item that needs a new | ||
599 | * debugfs directory created. In that case, that item | ||
600 | * must not be freed although all *RCU* users are done | ||
601 | * with it. Hence, we tell the caller of _unlink() | ||
602 | * that the item is already gone (as can happen when | ||
603 | * two tasks try to unlink/destroy at the same time) | ||
604 | * (4) We set the pin_status to DESTROY here when we | ||
605 | * find such an item. | ||
606 | * (5) sta_info_debugfs_add_work() will reset the pin_status | ||
607 | * from PINNED to NORMAL when it is done with the item, | ||
608 | * but will check for DESTROY before resetting it in | ||
609 | * which case it will free the item. | ||
610 | */ | ||
611 | if ((*sta)->pin_status == STA_INFO_PIN_STAT_PINNED) { | ||
612 | (*sta)->pin_status = STA_INFO_PIN_STAT_DESTROY; | ||
613 | *sta = NULL; | ||
614 | return; | ||
615 | } | ||
616 | } | ||
617 | |||
618 | void sta_info_unlink(struct sta_info **sta) | ||
619 | { | ||
620 | struct ieee80211_local *local = (*sta)->local; | ||
621 | unsigned long flags; | ||
622 | |||
623 | spin_lock_irqsave(&local->sta_lock, flags); | ||
624 | __sta_info_unlink(sta); | ||
625 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
626 | } | ||
627 | |||
628 | static int sta_info_buffer_expired(struct sta_info *sta, | 547 | static int sta_info_buffer_expired(struct sta_info *sta, |
629 | struct sk_buff *skb) | 548 | struct sk_buff *skb) |
630 | { | 549 | { |
@@ -681,109 +600,209 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | |||
681 | } | 600 | } |
682 | } | 601 | } |
683 | 602 | ||
684 | 603 | static int __must_check __sta_info_destroy(struct sta_info *sta) | |
685 | static void sta_info_cleanup(unsigned long data) | ||
686 | { | 604 | { |
687 | struct ieee80211_local *local = (struct ieee80211_local *) data; | 605 | struct ieee80211_local *local; |
688 | struct sta_info *sta; | 606 | struct ieee80211_sub_if_data *sdata; |
607 | struct sk_buff *skb; | ||
608 | unsigned long flags; | ||
609 | int ret, i; | ||
689 | 610 | ||
690 | rcu_read_lock(); | 611 | might_sleep(); |
691 | list_for_each_entry_rcu(sta, &local->sta_list, list) | ||
692 | sta_info_cleanup_expire_buffered(local, sta); | ||
693 | rcu_read_unlock(); | ||
694 | 612 | ||
695 | if (local->quiescing) | 613 | if (!sta) |
696 | return; | 614 | return -ENOENT; |
697 | 615 | ||
698 | local->sta_cleanup.expires = | 616 | local = sta->local; |
699 | round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); | 617 | sdata = sta->sdata; |
700 | add_timer(&local->sta_cleanup); | ||
701 | } | ||
702 | 618 | ||
703 | #ifdef CONFIG_MAC80211_DEBUGFS | 619 | spin_lock_irqsave(&local->sta_lock, flags); |
704 | /* | 620 | ret = sta_info_hash_del(local, sta); |
705 | * See comment in __sta_info_unlink, | 621 | /* this might still be the pending list ... which is fine */ |
706 | * caller must hold local->sta_lock. | 622 | if (!ret) |
707 | */ | 623 | list_del(&sta->list); |
708 | static void __sta_info_pin(struct sta_info *sta) | 624 | spin_unlock_irqrestore(&local->sta_lock, flags); |
709 | { | 625 | if (ret) |
710 | WARN_ON(sta->pin_status != STA_INFO_PIN_STAT_NORMAL); | 626 | return ret; |
711 | sta->pin_status = STA_INFO_PIN_STAT_PINNED; | 627 | |
628 | if (sta->key) { | ||
629 | ieee80211_key_free(sta->key); | ||
630 | /* | ||
631 | * We have only unlinked the key, and actually destroying it | ||
632 | * may mean it is removed from hardware which requires that | ||
633 | * the key->sta pointer is still valid, so flush the key todo | ||
634 | * list here. | ||
635 | * | ||
636 | * ieee80211_key_todo() will synchronize_rcu() so after this | ||
637 | * nothing can reference this sta struct any more. | ||
638 | */ | ||
639 | ieee80211_key_todo(); | ||
640 | |||
641 | WARN_ON(sta->key); | ||
642 | } | ||
643 | |||
644 | sta->dead = true; | ||
645 | |||
646 | if (test_and_clear_sta_flags(sta, | ||
647 | WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) { | ||
648 | BUG_ON(!sdata->bss); | ||
649 | |||
650 | atomic_dec(&sdata->bss->num_sta_ps); | ||
651 | __sta_info_clear_tim_bit(sdata->bss, sta); | ||
652 | } | ||
653 | |||
654 | local->num_sta--; | ||
655 | local->sta_generation++; | ||
656 | |||
657 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
658 | rcu_assign_pointer(sdata->u.vlan.sta, NULL); | ||
659 | |||
660 | if (sta->uploaded) { | ||
661 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
662 | sdata = container_of(sdata->bss, | ||
663 | struct ieee80211_sub_if_data, | ||
664 | u.ap); | ||
665 | drv_sta_remove(local, sdata, &sta->sta); | ||
666 | sdata = sta->sdata; | ||
667 | } | ||
668 | |||
669 | #ifdef CONFIG_MAC80211_MESH | ||
670 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
671 | mesh_accept_plinks_update(sdata); | ||
672 | del_timer(&sta->plink_timer); | ||
673 | } | ||
674 | #endif | ||
675 | |||
676 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
677 | printk(KERN_DEBUG "%s: Removed STA %pM\n", | ||
678 | wiphy_name(local->hw.wiphy), sta->sta.addr); | ||
679 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | ||
680 | cancel_work_sync(&sta->drv_unblock_wk); | ||
681 | |||
682 | rate_control_remove_sta_debugfs(sta); | ||
683 | ieee80211_sta_debugfs_remove(sta); | ||
684 | |||
685 | #ifdef CONFIG_MAC80211_MESH | ||
686 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) { | ||
687 | mesh_plink_deactivate(sta); | ||
688 | del_timer_sync(&sta->plink_timer); | ||
689 | } | ||
690 | #endif | ||
691 | |||
692 | while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { | ||
693 | local->total_ps_buffered--; | ||
694 | dev_kfree_skb_any(skb); | ||
695 | } | ||
696 | |||
697 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) | ||
698 | dev_kfree_skb_any(skb); | ||
699 | |||
700 | for (i = 0; i < STA_TID_NUM; i++) { | ||
701 | struct tid_ampdu_rx *tid_rx; | ||
702 | struct tid_ampdu_tx *tid_tx; | ||
703 | |||
704 | spin_lock_bh(&sta->lock); | ||
705 | tid_rx = sta->ampdu_mlme.tid_rx[i]; | ||
706 | /* Make sure timer won't free the tid_rx struct, see below */ | ||
707 | if (tid_rx) | ||
708 | tid_rx->shutdown = true; | ||
709 | |||
710 | spin_unlock_bh(&sta->lock); | ||
711 | |||
712 | /* | ||
713 | * Outside spinlock - shutdown is true now so that the timer | ||
714 | * won't free tid_rx, we have to do that now. Can't let the | ||
715 | * timer do it because we have to sync the timer outside the | ||
716 | * lock that it takes itself. | ||
717 | */ | ||
718 | if (tid_rx) { | ||
719 | del_timer_sync(&tid_rx->session_timer); | ||
720 | kfree(tid_rx); | ||
721 | } | ||
722 | |||
723 | /* | ||
724 | * No need to do such complications for TX agg sessions, the | ||
725 | * path leading to freeing the tid_tx struct goes via a call | ||
726 | * from the driver, and thus needs to look up the sta struct | ||
727 | * again, which cannot be found when we get here. Hence, we | ||
728 | * just need to delete the timer and free the aggregation | ||
729 | * info; we won't be telling the peer about it then but that | ||
730 | * doesn't matter if we're not talking to it again anyway. | ||
731 | */ | ||
732 | tid_tx = sta->ampdu_mlme.tid_tx[i]; | ||
733 | if (tid_tx) { | ||
734 | del_timer_sync(&tid_tx->addba_resp_timer); | ||
735 | /* | ||
736 | * STA removed while aggregation session being | ||
737 | * started? Bit odd, but purge frames anyway. | ||
738 | */ | ||
739 | skb_queue_purge(&tid_tx->pending); | ||
740 | kfree(tid_tx); | ||
741 | } | ||
742 | } | ||
743 | |||
744 | __sta_info_free(local, sta); | ||
745 | |||
746 | return 0; | ||
712 | } | 747 | } |
713 | 748 | ||
714 | /* | 749 | int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, const u8 *addr) |
715 | * See comment in __sta_info_unlink, returns sta if it | ||
716 | * needs to be destroyed. | ||
717 | */ | ||
718 | static struct sta_info *__sta_info_unpin(struct sta_info *sta) | ||
719 | { | 750 | { |
720 | struct sta_info *ret = NULL; | 751 | struct sta_info *sta; |
721 | unsigned long flags; | 752 | int ret; |
722 | 753 | ||
723 | spin_lock_irqsave(&sta->local->sta_lock, flags); | 754 | mutex_lock(&sdata->local->sta_mtx); |
724 | WARN_ON(sta->pin_status != STA_INFO_PIN_STAT_DESTROY && | 755 | sta = sta_info_get(sdata, addr); |
725 | sta->pin_status != STA_INFO_PIN_STAT_PINNED); | 756 | ret = __sta_info_destroy(sta); |
726 | if (sta->pin_status == STA_INFO_PIN_STAT_DESTROY) | 757 | mutex_unlock(&sdata->local->sta_mtx); |
727 | ret = sta; | ||
728 | sta->pin_status = STA_INFO_PIN_STAT_NORMAL; | ||
729 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); | ||
730 | 758 | ||
731 | return ret; | 759 | return ret; |
732 | } | 760 | } |
733 | 761 | ||
734 | static void sta_info_debugfs_add_work(struct work_struct *work) | 762 | int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata, |
763 | const u8 *addr) | ||
735 | { | 764 | { |
736 | struct ieee80211_local *local = | 765 | struct sta_info *sta; |
737 | container_of(work, struct ieee80211_local, sta_debugfs_add); | 766 | int ret; |
738 | struct sta_info *sta, *tmp; | ||
739 | unsigned long flags; | ||
740 | 767 | ||
741 | /* We need to keep the RTNL across the whole pinned status. */ | 768 | mutex_lock(&sdata->local->sta_mtx); |
742 | rtnl_lock(); | 769 | sta = sta_info_get_bss(sdata, addr); |
743 | while (1) { | 770 | ret = __sta_info_destroy(sta); |
744 | sta = NULL; | 771 | mutex_unlock(&sdata->local->sta_mtx); |
745 | 772 | ||
746 | spin_lock_irqsave(&local->sta_lock, flags); | 773 | return ret; |
747 | list_for_each_entry(tmp, &local->sta_list, list) { | 774 | } |
748 | /* | ||
749 | * debugfs.add_has_run will be set by | ||
750 | * ieee80211_sta_debugfs_add regardless | ||
751 | * of what else it does. | ||
752 | */ | ||
753 | if (!tmp->debugfs.add_has_run) { | ||
754 | sta = tmp; | ||
755 | __sta_info_pin(sta); | ||
756 | break; | ||
757 | } | ||
758 | } | ||
759 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
760 | 775 | ||
761 | if (!sta) | 776 | static void sta_info_cleanup(unsigned long data) |
762 | break; | 777 | { |
778 | struct ieee80211_local *local = (struct ieee80211_local *) data; | ||
779 | struct sta_info *sta; | ||
780 | |||
781 | rcu_read_lock(); | ||
782 | list_for_each_entry_rcu(sta, &local->sta_list, list) | ||
783 | sta_info_cleanup_expire_buffered(local, sta); | ||
784 | rcu_read_unlock(); | ||
763 | 785 | ||
764 | ieee80211_sta_debugfs_add(sta); | 786 | if (local->quiescing) |
765 | rate_control_add_sta_debugfs(sta); | 787 | return; |
766 | 788 | ||
767 | sta = __sta_info_unpin(sta); | 789 | local->sta_cleanup.expires = |
768 | sta_info_destroy(sta); | 790 | round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); |
769 | } | 791 | add_timer(&local->sta_cleanup); |
770 | rtnl_unlock(); | ||
771 | } | 792 | } |
772 | #endif | ||
773 | 793 | ||
774 | void sta_info_init(struct ieee80211_local *local) | 794 | void sta_info_init(struct ieee80211_local *local) |
775 | { | 795 | { |
776 | spin_lock_init(&local->sta_lock); | 796 | spin_lock_init(&local->sta_lock); |
797 | mutex_init(&local->sta_mtx); | ||
777 | INIT_LIST_HEAD(&local->sta_list); | 798 | INIT_LIST_HEAD(&local->sta_list); |
799 | INIT_LIST_HEAD(&local->sta_pending_list); | ||
800 | INIT_WORK(&local->sta_finish_work, sta_info_finish_work); | ||
778 | 801 | ||
779 | setup_timer(&local->sta_cleanup, sta_info_cleanup, | 802 | setup_timer(&local->sta_cleanup, sta_info_cleanup, |
780 | (unsigned long)local); | 803 | (unsigned long)local); |
781 | local->sta_cleanup.expires = | 804 | local->sta_cleanup.expires = |
782 | round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); | 805 | round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); |
783 | |||
784 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
785 | INIT_WORK(&local->sta_debugfs_add, sta_info_debugfs_add_work); | ||
786 | #endif | ||
787 | } | 806 | } |
788 | 807 | ||
789 | int sta_info_start(struct ieee80211_local *local) | 808 | int sta_info_start(struct ieee80211_local *local) |
@@ -795,16 +814,6 @@ int sta_info_start(struct ieee80211_local *local) | |||
795 | void sta_info_stop(struct ieee80211_local *local) | 814 | void sta_info_stop(struct ieee80211_local *local) |
796 | { | 815 | { |
797 | del_timer(&local->sta_cleanup); | 816 | del_timer(&local->sta_cleanup); |
798 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
799 | /* | ||
800 | * Make sure the debugfs adding work isn't pending after this | ||
801 | * because we're about to be destroyed. It doesn't matter | ||
802 | * whether it ran or not since we're going to flush all STAs | ||
803 | * anyway. | ||
804 | */ | ||
805 | cancel_work_sync(&local->sta_debugfs_add); | ||
806 | #endif | ||
807 | |||
808 | sta_info_flush(local, NULL); | 817 | sta_info_flush(local, NULL); |
809 | } | 818 | } |
810 | 819 | ||
@@ -820,26 +829,19 @@ int sta_info_flush(struct ieee80211_local *local, | |||
820 | struct ieee80211_sub_if_data *sdata) | 829 | struct ieee80211_sub_if_data *sdata) |
821 | { | 830 | { |
822 | struct sta_info *sta, *tmp; | 831 | struct sta_info *sta, *tmp; |
823 | LIST_HEAD(tmp_list); | ||
824 | int ret = 0; | 832 | int ret = 0; |
825 | unsigned long flags; | ||
826 | 833 | ||
827 | might_sleep(); | 834 | might_sleep(); |
828 | 835 | ||
829 | spin_lock_irqsave(&local->sta_lock, flags); | 836 | mutex_lock(&local->sta_mtx); |
837 | |||
838 | sta_info_finish_pending(local); | ||
839 | |||
830 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { | 840 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { |
831 | if (!sdata || sdata == sta->sdata) { | 841 | if (!sdata || sdata == sta->sdata) |
832 | __sta_info_unlink(&sta); | 842 | WARN_ON(__sta_info_destroy(sta)); |
833 | if (sta) { | ||
834 | list_add_tail(&sta->list, &tmp_list); | ||
835 | ret++; | ||
836 | } | ||
837 | } | ||
838 | } | 843 | } |
839 | spin_unlock_irqrestore(&local->sta_lock, flags); | 844 | mutex_unlock(&local->sta_mtx); |
840 | |||
841 | list_for_each_entry_safe(sta, tmp, &tmp_list, list) | ||
842 | sta_info_destroy(sta); | ||
843 | 845 | ||
844 | return ret; | 846 | return ret; |
845 | } | 847 | } |
@@ -849,24 +851,17 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | |||
849 | { | 851 | { |
850 | struct ieee80211_local *local = sdata->local; | 852 | struct ieee80211_local *local = sdata->local; |
851 | struct sta_info *sta, *tmp; | 853 | struct sta_info *sta, *tmp; |
852 | LIST_HEAD(tmp_list); | ||
853 | unsigned long flags; | ||
854 | 854 | ||
855 | spin_lock_irqsave(&local->sta_lock, flags); | 855 | mutex_lock(&local->sta_mtx); |
856 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) | 856 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) |
857 | if (time_after(jiffies, sta->last_rx + exp_time)) { | 857 | if (time_after(jiffies, sta->last_rx + exp_time)) { |
858 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 858 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
859 | printk(KERN_DEBUG "%s: expiring inactive STA %pM\n", | 859 | printk(KERN_DEBUG "%s: expiring inactive STA %pM\n", |
860 | sdata->name, sta->sta.addr); | 860 | sdata->name, sta->sta.addr); |
861 | #endif | 861 | #endif |
862 | __sta_info_unlink(&sta); | 862 | WARN_ON(__sta_info_destroy(sta)); |
863 | if (sta) | ||
864 | list_add(&sta->list, &tmp_list); | ||
865 | } | 863 | } |
866 | spin_unlock_irqrestore(&local->sta_lock, flags); | 864 | mutex_unlock(&local->sta_mtx); |
867 | |||
868 | list_for_each_entry_safe(sta, tmp, &tmp_list, list) | ||
869 | sta_info_destroy(sta); | ||
870 | } | 865 | } |
871 | 866 | ||
872 | struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw, | 867 | struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw, |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 6f79bba5706e..822d84522937 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -42,6 +42,9 @@ | |||
42 | * be in the queues | 42 | * be in the queues |
43 | * @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping | 43 | * @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping |
44 | * station in power-save mode, reply when the driver unblocks. | 44 | * station in power-save mode, reply when the driver unblocks. |
45 | * @WLAN_STA_DISASSOC: Disassociation in progress. | ||
46 | * This is used to reject TX BA session requests when disassociation | ||
47 | * is in progress. | ||
45 | */ | 48 | */ |
46 | enum ieee80211_sta_info_flags { | 49 | enum ieee80211_sta_info_flags { |
47 | WLAN_STA_AUTH = 1<<0, | 50 | WLAN_STA_AUTH = 1<<0, |
@@ -57,6 +60,7 @@ enum ieee80211_sta_info_flags { | |||
57 | WLAN_STA_SUSPEND = 1<<11, | 60 | WLAN_STA_SUSPEND = 1<<11, |
58 | WLAN_STA_PS_DRIVER = 1<<12, | 61 | WLAN_STA_PS_DRIVER = 1<<12, |
59 | WLAN_STA_PSPOLL = 1<<13, | 62 | WLAN_STA_PSPOLL = 1<<13, |
63 | WLAN_STA_DISASSOC = 1<<14, | ||
60 | }; | 64 | }; |
61 | 65 | ||
62 | #define STA_TID_NUM 16 | 66 | #define STA_TID_NUM 16 |
@@ -162,11 +166,6 @@ struct sta_ampdu_mlme { | |||
162 | }; | 166 | }; |
163 | 167 | ||
164 | 168 | ||
165 | /* see __sta_info_unlink */ | ||
166 | #define STA_INFO_PIN_STAT_NORMAL 0 | ||
167 | #define STA_INFO_PIN_STAT_PINNED 1 | ||
168 | #define STA_INFO_PIN_STAT_DESTROY 2 | ||
169 | |||
170 | /** | 169 | /** |
171 | * struct sta_info - STA information | 170 | * struct sta_info - STA information |
172 | * | 171 | * |
@@ -187,7 +186,6 @@ struct sta_ampdu_mlme { | |||
187 | * @flaglock: spinlock for flags accesses | 186 | * @flaglock: spinlock for flags accesses |
188 | * @drv_unblock_wk: used for driver PS unblocking | 187 | * @drv_unblock_wk: used for driver PS unblocking |
189 | * @listen_interval: listen interval of this station, when we're acting as AP | 188 | * @listen_interval: listen interval of this station, when we're acting as AP |
190 | * @pin_status: used internally for pinning a STA struct into memory | ||
191 | * @flags: STA flags, see &enum ieee80211_sta_info_flags | 189 | * @flags: STA flags, see &enum ieee80211_sta_info_flags |
192 | * @ps_tx_buf: buffer of frames to transmit to this station | 190 | * @ps_tx_buf: buffer of frames to transmit to this station |
193 | * when it leaves power saving state | 191 | * when it leaves power saving state |
@@ -226,6 +224,7 @@ struct sta_ampdu_mlme { | |||
226 | * @debugfs: debug filesystem info | 224 | * @debugfs: debug filesystem info |
227 | * @sta: station information we share with the driver | 225 | * @sta: station information we share with the driver |
228 | * @dead: set to true when sta is unlinked | 226 | * @dead: set to true when sta is unlinked |
227 | * @uploaded: set to true when sta is uploaded to the driver | ||
229 | */ | 228 | */ |
230 | struct sta_info { | 229 | struct sta_info { |
231 | /* General information, mostly static */ | 230 | /* General information, mostly static */ |
@@ -245,11 +244,7 @@ struct sta_info { | |||
245 | 244 | ||
246 | bool dead; | 245 | bool dead; |
247 | 246 | ||
248 | /* | 247 | bool uploaded; |
249 | * for use by the internal lifetime management, | ||
250 | * see __sta_info_unlink | ||
251 | */ | ||
252 | u8 pin_status; | ||
253 | 248 | ||
254 | /* | 249 | /* |
255 | * frequently updated, locked with own spinlock (flaglock), | 250 | * frequently updated, locked with own spinlock (flaglock), |
@@ -449,18 +444,19 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
449 | * Insert STA info into hash table/list, returns zero or a | 444 | * Insert STA info into hash table/list, returns zero or a |
450 | * -EEXIST if (if the same MAC address is already present). | 445 | * -EEXIST if (if the same MAC address is already present). |
451 | * | 446 | * |
452 | * Calling this without RCU protection makes the caller | 447 | * Calling the non-rcu version makes the caller relinquish, |
453 | * relinquish its reference to @sta. | 448 | * the _rcu version calls read_lock_rcu() and must be called |
449 | * without it held. | ||
454 | */ | 450 | */ |
455 | int sta_info_insert(struct sta_info *sta); | 451 | int sta_info_insert(struct sta_info *sta); |
456 | /* | 452 | int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); |
457 | * Unlink a STA info from the hash table/list. | 453 | int sta_info_insert_atomic(struct sta_info *sta); |
458 | * This can NULL the STA pointer if somebody else | 454 | |
459 | * has already unlinked it. | 455 | int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, |
460 | */ | 456 | const u8 *addr); |
461 | void sta_info_unlink(struct sta_info **sta); | 457 | int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata, |
458 | const u8 *addr); | ||
462 | 459 | ||
463 | void sta_info_destroy(struct sta_info *sta); | ||
464 | void sta_info_set_tim_bit(struct sta_info *sta); | 460 | void sta_info_set_tim_bit(struct sta_info *sta); |
465 | void sta_info_clear_tim_bit(struct sta_info *sta); | 461 | void sta_info_clear_tim_bit(struct sta_info *sta); |
466 | 462 | ||
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index e57ad6b1d7ea..ded98730c111 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -188,6 +188,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
188 | rcu_read_lock(); | 188 | rcu_read_lock(); |
189 | 189 | ||
190 | sband = local->hw.wiphy->bands[info->band]; | 190 | sband = local->hw.wiphy->bands[info->band]; |
191 | fc = hdr->frame_control; | ||
191 | 192 | ||
192 | for_each_sta_info(local, hdr->addr1, sta, tmp) { | 193 | for_each_sta_info(local, hdr->addr1, sta, tmp) { |
193 | /* skip wrong virtual interface */ | 194 | /* skip wrong virtual interface */ |
@@ -205,8 +206,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
205 | return; | 206 | return; |
206 | } | 207 | } |
207 | 208 | ||
208 | fc = hdr->frame_control; | ||
209 | |||
210 | if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && | 209 | if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && |
211 | (ieee80211_is_data_qos(fc))) { | 210 | (ieee80211_is_data_qos(fc))) { |
212 | u16 tid, ssn; | 211 | u16 tid, ssn; |
@@ -275,6 +274,20 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
275 | local->dot11FailedCount++; | 274 | local->dot11FailedCount++; |
276 | } | 275 | } |
277 | 276 | ||
277 | if (ieee80211_is_nullfunc(fc) && ieee80211_has_pm(fc) && | ||
278 | (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) && | ||
279 | !(info->flags & IEEE80211_TX_CTL_INJECTED) && | ||
280 | local->ps_sdata && !(local->scanning)) { | ||
281 | if (info->flags & IEEE80211_TX_STAT_ACK) { | ||
282 | local->ps_sdata->u.mgd.flags |= | ||
283 | IEEE80211_STA_NULLFUNC_ACKED; | ||
284 | ieee80211_queue_work(&local->hw, | ||
285 | &local->dynamic_ps_enable_work); | ||
286 | } else | ||
287 | mod_timer(&local->dynamic_ps_timer, jiffies + | ||
288 | msecs_to_jiffies(10)); | ||
289 | } | ||
290 | |||
278 | /* this was a transmitted frame, but now we want to reuse it */ | 291 | /* this was a transmitted frame, but now we want to reuse it */ |
279 | skb_orphan(skb); | 292 | skb_orphan(skb); |
280 | 293 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 85e382aa894e..cbe53ed4fb0b 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -571,7 +571,7 @@ ieee80211_tx_h_sta(struct ieee80211_tx_data *tx) | |||
571 | { | 571 | { |
572 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 572 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
573 | 573 | ||
574 | if (tx->sta) | 574 | if (tx->sta && tx->sta->uploaded) |
575 | info->control.sta = &tx->sta->sta; | 575 | info->control.sta = &tx->sta->sta; |
576 | 576 | ||
577 | return TX_CONTINUE; | 577 | return TX_CONTINUE; |
@@ -1010,7 +1010,8 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | |||
1010 | (struct ieee80211_radiotap_header *) skb->data; | 1010 | (struct ieee80211_radiotap_header *) skb->data; |
1011 | struct ieee80211_supported_band *sband; | 1011 | struct ieee80211_supported_band *sband; |
1012 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1012 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1013 | int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len); | 1013 | int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len, |
1014 | NULL); | ||
1014 | 1015 | ||
1015 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; | 1016 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; |
1016 | 1017 | ||
@@ -1046,7 +1047,7 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | |||
1046 | * because it will be recomputed and added | 1047 | * because it will be recomputed and added |
1047 | * on transmission | 1048 | * on transmission |
1048 | */ | 1049 | */ |
1049 | if (skb->len < (iterator.max_length + FCS_LEN)) | 1050 | if (skb->len < (iterator._max_length + FCS_LEN)) |
1050 | return false; | 1051 | return false; |
1051 | 1052 | ||
1052 | skb_trim(skb, skb->len - FCS_LEN); | 1053 | skb_trim(skb, skb->len - FCS_LEN); |
@@ -1073,10 +1074,10 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | |||
1073 | 1074 | ||
1074 | /* | 1075 | /* |
1075 | * remove the radiotap header | 1076 | * remove the radiotap header |
1076 | * iterator->max_length was sanity-checked against | 1077 | * iterator->_max_length was sanity-checked against |
1077 | * skb->len by iterator init | 1078 | * skb->len by iterator init |
1078 | */ | 1079 | */ |
1079 | skb_pull(skb, iterator.max_length); | 1080 | skb_pull(skb, iterator._max_length); |
1080 | 1081 | ||
1081 | return true; | 1082 | return true; |
1082 | } | 1083 | } |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index ca170b417da6..c453226f06b2 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1082,7 +1082,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1082 | struct ieee80211_hw *hw = &local->hw; | 1082 | struct ieee80211_hw *hw = &local->hw; |
1083 | struct ieee80211_sub_if_data *sdata; | 1083 | struct ieee80211_sub_if_data *sdata; |
1084 | struct sta_info *sta; | 1084 | struct sta_info *sta; |
1085 | unsigned long flags; | ||
1086 | int res; | 1085 | int res; |
1087 | 1086 | ||
1088 | if (local->suspended) | 1087 | if (local->suspended) |
@@ -1116,20 +1115,19 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1116 | } | 1115 | } |
1117 | 1116 | ||
1118 | /* add STAs back */ | 1117 | /* add STAs back */ |
1119 | if (local->ops->sta_notify) { | 1118 | mutex_lock(&local->sta_mtx); |
1120 | spin_lock_irqsave(&local->sta_lock, flags); | 1119 | list_for_each_entry(sta, &local->sta_list, list) { |
1121 | list_for_each_entry(sta, &local->sta_list, list) { | 1120 | if (sta->uploaded) { |
1122 | sdata = sta->sdata; | 1121 | sdata = sta->sdata; |
1123 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 1122 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
1124 | sdata = container_of(sdata->bss, | 1123 | sdata = container_of(sdata->bss, |
1125 | struct ieee80211_sub_if_data, | 1124 | struct ieee80211_sub_if_data, |
1126 | u.ap); | 1125 | u.ap); |
1127 | 1126 | ||
1128 | drv_sta_notify(local, sdata, STA_NOTIFY_ADD, | 1127 | WARN_ON(drv_sta_add(local, sdata, &sta->sta)); |
1129 | &sta->sta); | ||
1130 | } | 1128 | } |
1131 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
1132 | } | 1129 | } |
1130 | mutex_unlock(&local->sta_mtx); | ||
1133 | 1131 | ||
1134 | /* Clear Suspend state so that ADDBA requests can be processed */ | 1132 | /* Clear Suspend state so that ADDBA requests can be processed */ |
1135 | 1133 | ||
@@ -1180,6 +1178,14 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1180 | } | 1178 | } |
1181 | } | 1179 | } |
1182 | 1180 | ||
1181 | rcu_read_lock(); | ||
1182 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { | ||
1183 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | ||
1184 | ieee80211_sta_tear_down_BA_sessions(sta); | ||
1185 | } | ||
1186 | } | ||
1187 | rcu_read_unlock(); | ||
1188 | |||
1183 | /* add back keys */ | 1189 | /* add back keys */ |
1184 | list_for_each_entry(sdata, &local->interfaces, list) | 1190 | list_for_each_entry(sdata, &local->interfaces, list) |
1185 | if (ieee80211_sdata_running(sdata)) | 1191 | if (ieee80211_sdata_running(sdata)) |
@@ -1219,10 +1225,10 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1219 | 1225 | ||
1220 | add_timer(&local->sta_cleanup); | 1226 | add_timer(&local->sta_cleanup); |
1221 | 1227 | ||
1222 | spin_lock_irqsave(&local->sta_lock, flags); | 1228 | mutex_lock(&local->sta_mtx); |
1223 | list_for_each_entry(sta, &local->sta_list, list) | 1229 | list_for_each_entry(sta, &local->sta_list, list) |
1224 | mesh_plink_restart(sta); | 1230 | mesh_plink_restart(sta); |
1225 | spin_unlock_irqrestore(&local->sta_lock, flags); | 1231 | mutex_unlock(&local->sta_mtx); |
1226 | #else | 1232 | #else |
1227 | WARN_ON(1); | 1233 | WARN_ON(1); |
1228 | #endif | 1234 | #endif |
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index e47fb805ffb4..d952806b6469 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c | |||
@@ -262,9 +262,7 @@ static int htable_create_v0(struct net *net, struct xt_hashlimit_info *minfo, u_ | |||
262 | hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval); | 262 | hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval); |
263 | add_timer(&hinfo->timer); | 263 | add_timer(&hinfo->timer); |
264 | 264 | ||
265 | mutex_lock(&hashlimit_mutex); | ||
266 | hlist_add_head(&hinfo->node, &hashlimit_net->htables); | 265 | hlist_add_head(&hinfo->node, &hashlimit_net->htables); |
267 | mutex_unlock(&hashlimit_mutex); | ||
268 | 266 | ||
269 | return 0; | 267 | return 0; |
270 | } | 268 | } |
@@ -327,9 +325,7 @@ static int htable_create(struct net *net, struct xt_hashlimit_mtinfo1 *minfo, | |||
327 | hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval); | 325 | hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval); |
328 | add_timer(&hinfo->timer); | 326 | add_timer(&hinfo->timer); |
329 | 327 | ||
330 | mutex_lock(&hashlimit_mutex); | ||
331 | hlist_add_head(&hinfo->node, &hashlimit_net->htables); | 328 | hlist_add_head(&hinfo->node, &hashlimit_net->htables); |
332 | mutex_unlock(&hashlimit_mutex); | ||
333 | 329 | ||
334 | return 0; | 330 | return 0; |
335 | } | 331 | } |
diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index c5d9f97ef217..0bfeaab88ef5 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c | |||
@@ -315,7 +315,6 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, | |||
315 | entry_old = netlbl_domhsh_search_def(entry->domain); | 315 | entry_old = netlbl_domhsh_search_def(entry->domain); |
316 | if (entry_old == NULL) { | 316 | if (entry_old == NULL) { |
317 | entry->valid = 1; | 317 | entry->valid = 1; |
318 | INIT_RCU_HEAD(&entry->rcu); | ||
319 | 318 | ||
320 | if (entry->domain != NULL) { | 319 | if (entry->domain != NULL) { |
321 | u32 bkt = netlbl_domhsh_hash(entry->domain); | 320 | u32 bkt = netlbl_domhsh_hash(entry->domain); |
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 98ed22ee2ff4..852d9d7976b9 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c | |||
@@ -327,7 +327,6 @@ static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface, | |||
327 | entry->list.addr = addr->s_addr & mask->s_addr; | 327 | entry->list.addr = addr->s_addr & mask->s_addr; |
328 | entry->list.mask = mask->s_addr; | 328 | entry->list.mask = mask->s_addr; |
329 | entry->list.valid = 1; | 329 | entry->list.valid = 1; |
330 | INIT_RCU_HEAD(&entry->rcu); | ||
331 | entry->secid = secid; | 330 | entry->secid = secid; |
332 | 331 | ||
333 | spin_lock(&netlbl_unlhsh_lock); | 332 | spin_lock(&netlbl_unlhsh_lock); |
@@ -373,7 +372,6 @@ static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface, | |||
373 | entry->list.addr.s6_addr32[3] &= mask->s6_addr32[3]; | 372 | entry->list.addr.s6_addr32[3] &= mask->s6_addr32[3]; |
374 | ipv6_addr_copy(&entry->list.mask, mask); | 373 | ipv6_addr_copy(&entry->list.mask, mask); |
375 | entry->list.valid = 1; | 374 | entry->list.valid = 1; |
376 | INIT_RCU_HEAD(&entry->rcu); | ||
377 | entry->secid = secid; | 375 | entry->secid = secid; |
378 | 376 | ||
379 | spin_lock(&netlbl_unlhsh_lock); | 377 | spin_lock(&netlbl_unlhsh_lock); |
@@ -410,7 +408,6 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_add_iface(int ifindex) | |||
410 | INIT_LIST_HEAD(&iface->addr4_list); | 408 | INIT_LIST_HEAD(&iface->addr4_list); |
411 | INIT_LIST_HEAD(&iface->addr6_list); | 409 | INIT_LIST_HEAD(&iface->addr6_list); |
412 | iface->valid = 1; | 410 | iface->valid = 1; |
413 | INIT_RCU_HEAD(&iface->rcu); | ||
414 | 411 | ||
415 | spin_lock(&netlbl_unlhsh_lock); | 412 | spin_lock(&netlbl_unlhsh_lock); |
416 | if (ifindex > 0) { | 413 | if (ifindex > 0) { |
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 71604c6613b5..a249127020a5 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c | |||
@@ -1267,28 +1267,13 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1267 | 1267 | ||
1268 | static void *nr_info_start(struct seq_file *seq, loff_t *pos) | 1268 | static void *nr_info_start(struct seq_file *seq, loff_t *pos) |
1269 | { | 1269 | { |
1270 | struct sock *s; | ||
1271 | struct hlist_node *node; | ||
1272 | int i = 1; | ||
1273 | |||
1274 | spin_lock_bh(&nr_list_lock); | 1270 | spin_lock_bh(&nr_list_lock); |
1275 | if (*pos == 0) | 1271 | return seq_hlist_start_head(&nr_list, *pos); |
1276 | return SEQ_START_TOKEN; | ||
1277 | |||
1278 | sk_for_each(s, node, &nr_list) { | ||
1279 | if (i == *pos) | ||
1280 | return s; | ||
1281 | ++i; | ||
1282 | } | ||
1283 | return NULL; | ||
1284 | } | 1272 | } |
1285 | 1273 | ||
1286 | static void *nr_info_next(struct seq_file *seq, void *v, loff_t *pos) | 1274 | static void *nr_info_next(struct seq_file *seq, void *v, loff_t *pos) |
1287 | { | 1275 | { |
1288 | ++*pos; | 1276 | return seq_hlist_next(v, &nr_list, pos); |
1289 | |||
1290 | return (v == SEQ_START_TOKEN) ? sk_head(&nr_list) | ||
1291 | : sk_next((struct sock *)v); | ||
1292 | } | 1277 | } |
1293 | 1278 | ||
1294 | static void nr_info_stop(struct seq_file *seq, void *v) | 1279 | static void nr_info_stop(struct seq_file *seq, void *v) |
@@ -1298,7 +1283,7 @@ static void nr_info_stop(struct seq_file *seq, void *v) | |||
1298 | 1283 | ||
1299 | static int nr_info_show(struct seq_file *seq, void *v) | 1284 | static int nr_info_show(struct seq_file *seq, void *v) |
1300 | { | 1285 | { |
1301 | struct sock *s = v; | 1286 | struct sock *s = sk_entry(v); |
1302 | struct net_device *dev; | 1287 | struct net_device *dev; |
1303 | struct nr_sock *nr; | 1288 | struct nr_sock *nr; |
1304 | const char *devname; | 1289 | const char *devname; |
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c index e2e2d33cafdf..5cc648012f50 100644 --- a/net/netrom/nr_route.c +++ b/net/netrom/nr_route.c | |||
@@ -863,33 +863,13 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25) | |||
863 | 863 | ||
864 | static void *nr_node_start(struct seq_file *seq, loff_t *pos) | 864 | static void *nr_node_start(struct seq_file *seq, loff_t *pos) |
865 | { | 865 | { |
866 | struct nr_node *nr_node; | ||
867 | struct hlist_node *node; | ||
868 | int i = 1; | ||
869 | |||
870 | spin_lock_bh(&nr_node_list_lock); | 866 | spin_lock_bh(&nr_node_list_lock); |
871 | if (*pos == 0) | 867 | return seq_hlist_start_head(&nr_node_list, *pos); |
872 | return SEQ_START_TOKEN; | ||
873 | |||
874 | nr_node_for_each(nr_node, node, &nr_node_list) { | ||
875 | if (i == *pos) | ||
876 | return nr_node; | ||
877 | ++i; | ||
878 | } | ||
879 | |||
880 | return NULL; | ||
881 | } | 868 | } |
882 | 869 | ||
883 | static void *nr_node_next(struct seq_file *seq, void *v, loff_t *pos) | 870 | static void *nr_node_next(struct seq_file *seq, void *v, loff_t *pos) |
884 | { | 871 | { |
885 | struct hlist_node *node; | 872 | return seq_hlist_next(v, &nr_node_list, pos); |
886 | ++*pos; | ||
887 | |||
888 | node = (v == SEQ_START_TOKEN) | ||
889 | ? nr_node_list.first | ||
890 | : ((struct nr_node *)v)->node_node.next; | ||
891 | |||
892 | return hlist_entry(node, struct nr_node, node_node); | ||
893 | } | 873 | } |
894 | 874 | ||
895 | static void nr_node_stop(struct seq_file *seq, void *v) | 875 | static void nr_node_stop(struct seq_file *seq, void *v) |
@@ -906,7 +886,9 @@ static int nr_node_show(struct seq_file *seq, void *v) | |||
906 | seq_puts(seq, | 886 | seq_puts(seq, |
907 | "callsign mnemonic w n qual obs neigh qual obs neigh qual obs neigh\n"); | 887 | "callsign mnemonic w n qual obs neigh qual obs neigh qual obs neigh\n"); |
908 | else { | 888 | else { |
909 | struct nr_node *nr_node = v; | 889 | struct nr_node *nr_node = hlist_entry(v, struct nr_node, |
890 | node_node); | ||
891 | |||
910 | nr_node_lock(nr_node); | 892 | nr_node_lock(nr_node); |
911 | seq_printf(seq, "%-9s %-7s %d %d", | 893 | seq_printf(seq, "%-9s %-7s %d %d", |
912 | ax2asc(buf, &nr_node->callsign), | 894 | ax2asc(buf, &nr_node->callsign), |
@@ -949,31 +931,13 @@ const struct file_operations nr_nodes_fops = { | |||
949 | 931 | ||
950 | static void *nr_neigh_start(struct seq_file *seq, loff_t *pos) | 932 | static void *nr_neigh_start(struct seq_file *seq, loff_t *pos) |
951 | { | 933 | { |
952 | struct nr_neigh *nr_neigh; | ||
953 | struct hlist_node *node; | ||
954 | int i = 1; | ||
955 | |||
956 | spin_lock_bh(&nr_neigh_list_lock); | 934 | spin_lock_bh(&nr_neigh_list_lock); |
957 | if (*pos == 0) | 935 | return seq_hlist_start_head(&nr_neigh_list, *pos); |
958 | return SEQ_START_TOKEN; | ||
959 | |||
960 | nr_neigh_for_each(nr_neigh, node, &nr_neigh_list) { | ||
961 | if (i == *pos) | ||
962 | return nr_neigh; | ||
963 | } | ||
964 | return NULL; | ||
965 | } | 936 | } |
966 | 937 | ||
967 | static void *nr_neigh_next(struct seq_file *seq, void *v, loff_t *pos) | 938 | static void *nr_neigh_next(struct seq_file *seq, void *v, loff_t *pos) |
968 | { | 939 | { |
969 | struct hlist_node *node; | 940 | return seq_hlist_next(v, &nr_neigh_list, pos); |
970 | ++*pos; | ||
971 | |||
972 | node = (v == SEQ_START_TOKEN) | ||
973 | ? nr_neigh_list.first | ||
974 | : ((struct nr_neigh *)v)->neigh_node.next; | ||
975 | |||
976 | return hlist_entry(node, struct nr_neigh, neigh_node); | ||
977 | } | 941 | } |
978 | 942 | ||
979 | static void nr_neigh_stop(struct seq_file *seq, void *v) | 943 | static void nr_neigh_stop(struct seq_file *seq, void *v) |
@@ -989,8 +953,9 @@ static int nr_neigh_show(struct seq_file *seq, void *v) | |||
989 | if (v == SEQ_START_TOKEN) | 953 | if (v == SEQ_START_TOKEN) |
990 | seq_puts(seq, "addr callsign dev qual lock count failed digipeaters\n"); | 954 | seq_puts(seq, "addr callsign dev qual lock count failed digipeaters\n"); |
991 | else { | 955 | else { |
992 | struct nr_neigh *nr_neigh = v; | 956 | struct nr_neigh *nr_neigh; |
993 | 957 | ||
958 | nr_neigh = hlist_entry(v, struct nr_neigh, neigh_node); | ||
994 | seq_printf(seq, "%05d %-9s %-4s %3d %d %3d %3d", | 959 | seq_printf(seq, "%05d %-9s %-4s %3d %d %3d %3d", |
995 | nr_neigh->number, | 960 | nr_neigh->number, |
996 | ax2asc(buf, &nr_neigh->callsign), | 961 | ax2asc(buf, &nr_neigh->callsign), |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 6ecb426bc0cf..10f7295bcefb 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -2510,33 +2510,19 @@ static struct notifier_block packet_netdev_notifier = { | |||
2510 | }; | 2510 | }; |
2511 | 2511 | ||
2512 | #ifdef CONFIG_PROC_FS | 2512 | #ifdef CONFIG_PROC_FS |
2513 | static inline struct sock *packet_seq_idx(struct net *net, loff_t off) | ||
2514 | { | ||
2515 | struct sock *s; | ||
2516 | struct hlist_node *node; | ||
2517 | |||
2518 | sk_for_each(s, node, &net->packet.sklist) { | ||
2519 | if (!off--) | ||
2520 | return s; | ||
2521 | } | ||
2522 | return NULL; | ||
2523 | } | ||
2524 | 2513 | ||
2525 | static void *packet_seq_start(struct seq_file *seq, loff_t *pos) | 2514 | static void *packet_seq_start(struct seq_file *seq, loff_t *pos) |
2526 | __acquires(seq_file_net(seq)->packet.sklist_lock) | 2515 | __acquires(seq_file_net(seq)->packet.sklist_lock) |
2527 | { | 2516 | { |
2528 | struct net *net = seq_file_net(seq); | 2517 | struct net *net = seq_file_net(seq); |
2529 | read_lock(&net->packet.sklist_lock); | 2518 | read_lock(&net->packet.sklist_lock); |
2530 | return *pos ? packet_seq_idx(net, *pos - 1) : SEQ_START_TOKEN; | 2519 | return seq_hlist_start_head(&net->packet.sklist, *pos); |
2531 | } | 2520 | } |
2532 | 2521 | ||
2533 | static void *packet_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 2522 | static void *packet_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
2534 | { | 2523 | { |
2535 | struct net *net = seq_file_net(seq); | 2524 | struct net *net = seq_file_net(seq); |
2536 | ++*pos; | 2525 | return seq_hlist_next(v, &net->packet.sklist, pos); |
2537 | return (v == SEQ_START_TOKEN) | ||
2538 | ? sk_head(&net->packet.sklist) | ||
2539 | : sk_next((struct sock *)v) ; | ||
2540 | } | 2526 | } |
2541 | 2527 | ||
2542 | static void packet_seq_stop(struct seq_file *seq, void *v) | 2528 | static void packet_seq_stop(struct seq_file *seq, void *v) |
@@ -2551,7 +2537,7 @@ static int packet_seq_show(struct seq_file *seq, void *v) | |||
2551 | if (v == SEQ_START_TOKEN) | 2537 | if (v == SEQ_START_TOKEN) |
2552 | seq_puts(seq, "sk RefCnt Type Proto Iface R Rmem User Inode\n"); | 2538 | seq_puts(seq, "sk RefCnt Type Proto Iface R Rmem User Inode\n"); |
2553 | else { | 2539 | else { |
2554 | struct sock *s = v; | 2540 | struct sock *s = sk_entry(v); |
2555 | const struct packet_sock *po = pkt_sk(s); | 2541 | const struct packet_sock *po = pkt_sk(s); |
2556 | 2542 | ||
2557 | seq_printf(seq, | 2543 | seq_printf(seq, |
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 8feb9e5d6623..e90b9b6c16ae 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c | |||
@@ -1404,29 +1404,13 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1404 | static void *rose_info_start(struct seq_file *seq, loff_t *pos) | 1404 | static void *rose_info_start(struct seq_file *seq, loff_t *pos) |
1405 | __acquires(rose_list_lock) | 1405 | __acquires(rose_list_lock) |
1406 | { | 1406 | { |
1407 | int i; | ||
1408 | struct sock *s; | ||
1409 | struct hlist_node *node; | ||
1410 | |||
1411 | spin_lock_bh(&rose_list_lock); | 1407 | spin_lock_bh(&rose_list_lock); |
1412 | if (*pos == 0) | 1408 | return seq_hlist_start_head(&rose_list, *pos); |
1413 | return SEQ_START_TOKEN; | ||
1414 | |||
1415 | i = 1; | ||
1416 | sk_for_each(s, node, &rose_list) { | ||
1417 | if (i == *pos) | ||
1418 | return s; | ||
1419 | ++i; | ||
1420 | } | ||
1421 | return NULL; | ||
1422 | } | 1409 | } |
1423 | 1410 | ||
1424 | static void *rose_info_next(struct seq_file *seq, void *v, loff_t *pos) | 1411 | static void *rose_info_next(struct seq_file *seq, void *v, loff_t *pos) |
1425 | { | 1412 | { |
1426 | ++*pos; | 1413 | return seq_hlist_next(v, &rose_list, pos); |
1427 | |||
1428 | return (v == SEQ_START_TOKEN) ? sk_head(&rose_list) | ||
1429 | : sk_next((struct sock *)v); | ||
1430 | } | 1414 | } |
1431 | 1415 | ||
1432 | static void rose_info_stop(struct seq_file *seq, void *v) | 1416 | static void rose_info_stop(struct seq_file *seq, void *v) |
@@ -1444,7 +1428,7 @@ static int rose_info_show(struct seq_file *seq, void *v) | |||
1444 | "dest_addr dest_call src_addr src_call dev lci neigh st vs vr va t t1 t2 t3 hb idle Snd-Q Rcv-Q inode\n"); | 1428 | "dest_addr dest_call src_addr src_call dev lci neigh st vs vr va t t1 t2 t3 hb idle Snd-Q Rcv-Q inode\n"); |
1445 | 1429 | ||
1446 | else { | 1430 | else { |
1447 | struct sock *s = v; | 1431 | struct sock *s = sk_entry(v); |
1448 | struct rose_sock *rose = rose_sk(s); | 1432 | struct rose_sock *rose = rose_sk(s); |
1449 | const char *devname, *callsign; | 1433 | const char *devname, *callsign; |
1450 | const struct net_device *dev = rose->device; | 1434 | const struct net_device *dev = rose->device; |
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index 13a6fba41077..bef133731683 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c | |||
@@ -186,7 +186,6 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new, | |||
186 | addr->valid = 1; | 186 | addr->valid = 1; |
187 | 187 | ||
188 | INIT_LIST_HEAD(&addr->list); | 188 | INIT_LIST_HEAD(&addr->list); |
189 | INIT_RCU_HEAD(&addr->rcu); | ||
190 | 189 | ||
191 | /* We always hold a socket lock when calling this function, | 190 | /* We always hold a socket lock when calling this function, |
192 | * and that acts as a writer synchronizing lock. | 191 | * and that acts as a writer synchronizing lock. |
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index cc50fbe99291..1d7ac70ba39f 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -381,7 +381,6 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist, | |||
381 | addr->a.v6.sin6_scope_id = dev->ifindex; | 381 | addr->a.v6.sin6_scope_id = dev->ifindex; |
382 | addr->valid = 1; | 382 | addr->valid = 1; |
383 | INIT_LIST_HEAD(&addr->list); | 383 | INIT_LIST_HEAD(&addr->list); |
384 | INIT_RCU_HEAD(&addr->rcu); | ||
385 | list_add_tail(&addr->list, addrlist); | 384 | list_add_tail(&addr->list, addrlist); |
386 | } | 385 | } |
387 | } | 386 | } |
diff --git a/net/sctp/proc.c b/net/sctp/proc.c index a5ac6e0a8d9c..784bcc9a979d 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c | |||
@@ -83,7 +83,7 @@ static int sctp_snmp_seq_show(struct seq_file *seq, void *v) | |||
83 | 83 | ||
84 | for (i = 0; sctp_snmp_list[i].name != NULL; i++) | 84 | for (i = 0; sctp_snmp_list[i].name != NULL; i++) |
85 | seq_printf(seq, "%-32s\t%ld\n", sctp_snmp_list[i].name, | 85 | seq_printf(seq, "%-32s\t%ld\n", sctp_snmp_list[i].name, |
86 | snmp_fold_field((void **)sctp_statistics, | 86 | snmp_fold_field((void __percpu **)sctp_statistics, |
87 | sctp_snmp_list[i].entry)); | 87 | sctp_snmp_list[i].entry)); |
88 | 88 | ||
89 | return 0; | 89 | return 0; |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index a3c8988758b1..e771690f6d5d 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -188,7 +188,6 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist, | |||
188 | addr->a.v4.sin_addr.s_addr = ifa->ifa_local; | 188 | addr->a.v4.sin_addr.s_addr = ifa->ifa_local; |
189 | addr->valid = 1; | 189 | addr->valid = 1; |
190 | INIT_LIST_HEAD(&addr->list); | 190 | INIT_LIST_HEAD(&addr->list); |
191 | INIT_RCU_HEAD(&addr->rcu); | ||
192 | list_add_tail(&addr->list, addrlist); | 191 | list_add_tail(&addr->list, addrlist); |
193 | } | 192 | } |
194 | } | 193 | } |
@@ -996,12 +995,13 @@ int sctp_register_pf(struct sctp_pf *pf, sa_family_t family) | |||
996 | 995 | ||
997 | static inline int init_sctp_mibs(void) | 996 | static inline int init_sctp_mibs(void) |
998 | { | 997 | { |
999 | return snmp_mib_init((void**)sctp_statistics, sizeof(struct sctp_mib)); | 998 | return snmp_mib_init((void __percpu **)sctp_statistics, |
999 | sizeof(struct sctp_mib)); | ||
1000 | } | 1000 | } |
1001 | 1001 | ||
1002 | static inline void cleanup_sctp_mibs(void) | 1002 | static inline void cleanup_sctp_mibs(void) |
1003 | { | 1003 | { |
1004 | snmp_mib_free((void**)sctp_statistics); | 1004 | snmp_mib_free((void __percpu **)sctp_statistics); |
1005 | } | 1005 | } |
1006 | 1006 | ||
1007 | static void sctp_v4_pf_init(void) | 1007 | static void sctp_v4_pf_init(void) |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 49278f830367..9ea45383480e 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -78,7 +78,7 @@ rpc_timeout_upcall_queue(struct work_struct *work) | |||
78 | } | 78 | } |
79 | 79 | ||
80 | /** | 80 | /** |
81 | * rpc_queue_upcall | 81 | * rpc_queue_upcall - queue an upcall message to userspace |
82 | * @inode: inode of upcall pipe on which to queue given message | 82 | * @inode: inode of upcall pipe on which to queue given message |
83 | * @msg: message to queue | 83 | * @msg: message to queue |
84 | * | 84 | * |
diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c index f591871a7b4f..1332c445d1c7 100644 --- a/net/wireless/radiotap.c +++ b/net/wireless/radiotap.c | |||
@@ -2,6 +2,16 @@ | |||
2 | * Radiotap parser | 2 | * Radiotap parser |
3 | * | 3 | * |
4 | * Copyright 2007 Andy Green <andy@warmcat.com> | 4 | * Copyright 2007 Andy Green <andy@warmcat.com> |
5 | * Copyright 2009 Johannes Berg <johannes@sipsolutions.net> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * Alternatively, this software may be distributed under the terms of BSD | ||
12 | * license. | ||
13 | * | ||
14 | * See COPYING for more details. | ||
5 | */ | 15 | */ |
6 | 16 | ||
7 | #include <net/cfg80211.h> | 17 | #include <net/cfg80211.h> |
@@ -10,6 +20,35 @@ | |||
10 | 20 | ||
11 | /* function prototypes and related defs are in include/net/cfg80211.h */ | 21 | /* function prototypes and related defs are in include/net/cfg80211.h */ |
12 | 22 | ||
23 | static const struct radiotap_align_size rtap_namespace_sizes[] = { | ||
24 | [IEEE80211_RADIOTAP_TSFT] = { .align = 8, .size = 8, }, | ||
25 | [IEEE80211_RADIOTAP_FLAGS] = { .align = 1, .size = 1, }, | ||
26 | [IEEE80211_RADIOTAP_RATE] = { .align = 1, .size = 1, }, | ||
27 | [IEEE80211_RADIOTAP_CHANNEL] = { .align = 2, .size = 4, }, | ||
28 | [IEEE80211_RADIOTAP_FHSS] = { .align = 2, .size = 2, }, | ||
29 | [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = { .align = 1, .size = 1, }, | ||
30 | [IEEE80211_RADIOTAP_DBM_ANTNOISE] = { .align = 1, .size = 1, }, | ||
31 | [IEEE80211_RADIOTAP_LOCK_QUALITY] = { .align = 2, .size = 2, }, | ||
32 | [IEEE80211_RADIOTAP_TX_ATTENUATION] = { .align = 2, .size = 2, }, | ||
33 | [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = { .align = 2, .size = 2, }, | ||
34 | [IEEE80211_RADIOTAP_DBM_TX_POWER] = { .align = 1, .size = 1, }, | ||
35 | [IEEE80211_RADIOTAP_ANTENNA] = { .align = 1, .size = 1, }, | ||
36 | [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = { .align = 1, .size = 1, }, | ||
37 | [IEEE80211_RADIOTAP_DB_ANTNOISE] = { .align = 1, .size = 1, }, | ||
38 | [IEEE80211_RADIOTAP_RX_FLAGS] = { .align = 2, .size = 2, }, | ||
39 | [IEEE80211_RADIOTAP_TX_FLAGS] = { .align = 2, .size = 2, }, | ||
40 | [IEEE80211_RADIOTAP_RTS_RETRIES] = { .align = 1, .size = 1, }, | ||
41 | [IEEE80211_RADIOTAP_DATA_RETRIES] = { .align = 1, .size = 1, }, | ||
42 | /* | ||
43 | * add more here as they are defined in radiotap.h | ||
44 | */ | ||
45 | }; | ||
46 | |||
47 | static const struct ieee80211_radiotap_namespace radiotap_ns = { | ||
48 | .n_bits = sizeof(rtap_namespace_sizes) / sizeof(rtap_namespace_sizes[0]), | ||
49 | .align_size = rtap_namespace_sizes, | ||
50 | }; | ||
51 | |||
13 | /** | 52 | /** |
14 | * ieee80211_radiotap_iterator_init - radiotap parser iterator initialization | 53 | * ieee80211_radiotap_iterator_init - radiotap parser iterator initialization |
15 | * @iterator: radiotap_iterator to initialize | 54 | * @iterator: radiotap_iterator to initialize |
@@ -50,9 +89,9 @@ | |||
50 | */ | 89 | */ |
51 | 90 | ||
52 | int ieee80211_radiotap_iterator_init( | 91 | int ieee80211_radiotap_iterator_init( |
53 | struct ieee80211_radiotap_iterator *iterator, | 92 | struct ieee80211_radiotap_iterator *iterator, |
54 | struct ieee80211_radiotap_header *radiotap_header, | 93 | struct ieee80211_radiotap_header *radiotap_header, |
55 | int max_length) | 94 | int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns) |
56 | { | 95 | { |
57 | /* Linux only supports version 0 radiotap format */ | 96 | /* Linux only supports version 0 radiotap format */ |
58 | if (radiotap_header->it_version) | 97 | if (radiotap_header->it_version) |
@@ -62,19 +101,24 @@ int ieee80211_radiotap_iterator_init( | |||
62 | if (max_length < get_unaligned_le16(&radiotap_header->it_len)) | 101 | if (max_length < get_unaligned_le16(&radiotap_header->it_len)) |
63 | return -EINVAL; | 102 | return -EINVAL; |
64 | 103 | ||
65 | iterator->rtheader = radiotap_header; | 104 | iterator->_rtheader = radiotap_header; |
66 | iterator->max_length = get_unaligned_le16(&radiotap_header->it_len); | 105 | iterator->_max_length = get_unaligned_le16(&radiotap_header->it_len); |
67 | iterator->arg_index = 0; | 106 | iterator->_arg_index = 0; |
68 | iterator->bitmap_shifter = get_unaligned_le32(&radiotap_header->it_present); | 107 | iterator->_bitmap_shifter = get_unaligned_le32(&radiotap_header->it_present); |
69 | iterator->arg = (u8 *)radiotap_header + sizeof(*radiotap_header); | 108 | iterator->_arg = (uint8_t *)radiotap_header + sizeof(*radiotap_header); |
70 | iterator->this_arg = NULL; | 109 | iterator->_reset_on_ext = 0; |
110 | iterator->_next_bitmap = &radiotap_header->it_present; | ||
111 | iterator->_next_bitmap++; | ||
112 | iterator->_vns = vns; | ||
113 | iterator->current_namespace = &radiotap_ns; | ||
114 | iterator->is_radiotap_ns = 1; | ||
71 | 115 | ||
72 | /* find payload start allowing for extended bitmap(s) */ | 116 | /* find payload start allowing for extended bitmap(s) */ |
73 | 117 | ||
74 | if (unlikely(iterator->bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT))) { | 118 | if (iterator->_bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT)) { |
75 | while (get_unaligned_le32(iterator->arg) & | 119 | while (get_unaligned_le32(iterator->_arg) & |
76 | (1 << IEEE80211_RADIOTAP_EXT)) { | 120 | (1 << IEEE80211_RADIOTAP_EXT)) { |
77 | iterator->arg += sizeof(u32); | 121 | iterator->_arg += sizeof(uint32_t); |
78 | 122 | ||
79 | /* | 123 | /* |
80 | * check for insanity where the present bitmaps | 124 | * check for insanity where the present bitmaps |
@@ -82,12 +126,13 @@ int ieee80211_radiotap_iterator_init( | |||
82 | * stated radiotap header length | 126 | * stated radiotap header length |
83 | */ | 127 | */ |
84 | 128 | ||
85 | if (((ulong)iterator->arg - | 129 | if ((unsigned long)iterator->_arg - |
86 | (ulong)iterator->rtheader) > iterator->max_length) | 130 | (unsigned long)iterator->_rtheader > |
131 | (unsigned long)iterator->_max_length) | ||
87 | return -EINVAL; | 132 | return -EINVAL; |
88 | } | 133 | } |
89 | 134 | ||
90 | iterator->arg += sizeof(u32); | 135 | iterator->_arg += sizeof(uint32_t); |
91 | 136 | ||
92 | /* | 137 | /* |
93 | * no need to check again for blowing past stated radiotap | 138 | * no need to check again for blowing past stated radiotap |
@@ -96,12 +141,36 @@ int ieee80211_radiotap_iterator_init( | |||
96 | */ | 141 | */ |
97 | } | 142 | } |
98 | 143 | ||
144 | iterator->this_arg = iterator->_arg; | ||
145 | |||
99 | /* we are all initialized happily */ | 146 | /* we are all initialized happily */ |
100 | 147 | ||
101 | return 0; | 148 | return 0; |
102 | } | 149 | } |
103 | EXPORT_SYMBOL(ieee80211_radiotap_iterator_init); | 150 | EXPORT_SYMBOL(ieee80211_radiotap_iterator_init); |
104 | 151 | ||
152 | static void find_ns(struct ieee80211_radiotap_iterator *iterator, | ||
153 | uint32_t oui, uint8_t subns) | ||
154 | { | ||
155 | int i; | ||
156 | |||
157 | iterator->current_namespace = NULL; | ||
158 | |||
159 | if (!iterator->_vns) | ||
160 | return; | ||
161 | |||
162 | for (i = 0; i < iterator->_vns->n_ns; i++) { | ||
163 | if (iterator->_vns->ns[i].oui != oui) | ||
164 | continue; | ||
165 | if (iterator->_vns->ns[i].subns != subns) | ||
166 | continue; | ||
167 | |||
168 | iterator->current_namespace = &iterator->_vns->ns[i]; | ||
169 | break; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | |||
105 | 174 | ||
106 | /** | 175 | /** |
107 | * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg | 176 | * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg |
@@ -127,99 +196,80 @@ EXPORT_SYMBOL(ieee80211_radiotap_iterator_init); | |||
127 | */ | 196 | */ |
128 | 197 | ||
129 | int ieee80211_radiotap_iterator_next( | 198 | int ieee80211_radiotap_iterator_next( |
130 | struct ieee80211_radiotap_iterator *iterator) | 199 | struct ieee80211_radiotap_iterator *iterator) |
131 | { | 200 | { |
132 | 201 | while (1) { | |
133 | /* | ||
134 | * small length lookup table for all radiotap types we heard of | ||
135 | * starting from b0 in the bitmap, so we can walk the payload | ||
136 | * area of the radiotap header | ||
137 | * | ||
138 | * There is a requirement to pad args, so that args | ||
139 | * of a given length must begin at a boundary of that length | ||
140 | * -- but note that compound args are allowed (eg, 2 x u16 | ||
141 | * for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not | ||
142 | * a reliable indicator of alignment requirement. | ||
143 | * | ||
144 | * upper nybble: content alignment for arg | ||
145 | * lower nybble: content length for arg | ||
146 | */ | ||
147 | |||
148 | static const u8 rt_sizes[] = { | ||
149 | [IEEE80211_RADIOTAP_TSFT] = 0x88, | ||
150 | [IEEE80211_RADIOTAP_FLAGS] = 0x11, | ||
151 | [IEEE80211_RADIOTAP_RATE] = 0x11, | ||
152 | [IEEE80211_RADIOTAP_CHANNEL] = 0x24, | ||
153 | [IEEE80211_RADIOTAP_FHSS] = 0x22, | ||
154 | [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 0x11, | ||
155 | [IEEE80211_RADIOTAP_DBM_ANTNOISE] = 0x11, | ||
156 | [IEEE80211_RADIOTAP_LOCK_QUALITY] = 0x22, | ||
157 | [IEEE80211_RADIOTAP_TX_ATTENUATION] = 0x22, | ||
158 | [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 0x22, | ||
159 | [IEEE80211_RADIOTAP_DBM_TX_POWER] = 0x11, | ||
160 | [IEEE80211_RADIOTAP_ANTENNA] = 0x11, | ||
161 | [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 0x11, | ||
162 | [IEEE80211_RADIOTAP_DB_ANTNOISE] = 0x11, | ||
163 | [IEEE80211_RADIOTAP_RX_FLAGS] = 0x22, | ||
164 | [IEEE80211_RADIOTAP_TX_FLAGS] = 0x22, | ||
165 | [IEEE80211_RADIOTAP_RTS_RETRIES] = 0x11, | ||
166 | [IEEE80211_RADIOTAP_DATA_RETRIES] = 0x11, | ||
167 | /* | ||
168 | * add more here as they are defined in | ||
169 | * include/net/ieee80211_radiotap.h | ||
170 | */ | ||
171 | }; | ||
172 | |||
173 | /* | ||
174 | * for every radiotap entry we can at | ||
175 | * least skip (by knowing the length)... | ||
176 | */ | ||
177 | |||
178 | while (iterator->arg_index < sizeof(rt_sizes)) { | ||
179 | int hit = 0; | 202 | int hit = 0; |
180 | int pad; | 203 | int pad, align, size, subns, vnslen; |
204 | uint32_t oui; | ||
181 | 205 | ||
182 | if (!(iterator->bitmap_shifter & 1)) | 206 | /* if no more EXT bits, that's it */ |
207 | if ((iterator->_arg_index % 32) == IEEE80211_RADIOTAP_EXT && | ||
208 | !(iterator->_bitmap_shifter & 1)) | ||
209 | return -ENOENT; | ||
210 | |||
211 | if (!(iterator->_bitmap_shifter & 1)) | ||
183 | goto next_entry; /* arg not present */ | 212 | goto next_entry; /* arg not present */ |
184 | 213 | ||
214 | /* get alignment/size of data */ | ||
215 | switch (iterator->_arg_index % 32) { | ||
216 | case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE: | ||
217 | case IEEE80211_RADIOTAP_EXT: | ||
218 | align = 1; | ||
219 | size = 0; | ||
220 | break; | ||
221 | case IEEE80211_RADIOTAP_VENDOR_NAMESPACE: | ||
222 | align = 2; | ||
223 | size = 6; | ||
224 | break; | ||
225 | default: | ||
226 | if (!iterator->current_namespace || | ||
227 | iterator->_arg_index >= iterator->current_namespace->n_bits) { | ||
228 | if (iterator->current_namespace == &radiotap_ns) | ||
229 | return -ENOENT; | ||
230 | align = 0; | ||
231 | } else { | ||
232 | align = iterator->current_namespace->align_size[iterator->_arg_index].align; | ||
233 | size = iterator->current_namespace->align_size[iterator->_arg_index].size; | ||
234 | } | ||
235 | if (!align) { | ||
236 | /* skip all subsequent data */ | ||
237 | iterator->_arg = iterator->_next_ns_data; | ||
238 | /* give up on this namespace */ | ||
239 | iterator->current_namespace = NULL; | ||
240 | goto next_entry; | ||
241 | } | ||
242 | break; | ||
243 | } | ||
244 | |||
185 | /* | 245 | /* |
186 | * arg is present, account for alignment padding | 246 | * arg is present, account for alignment padding |
187 | * 8-bit args can be at any alignment | ||
188 | * 16-bit args must start on 16-bit boundary | ||
189 | * 32-bit args must start on 32-bit boundary | ||
190 | * 64-bit args must start on 64-bit boundary | ||
191 | * | 247 | * |
192 | * note that total arg size can differ from alignment of | 248 | * Note that these alignments are relative to the start |
193 | * elements inside arg, so we use upper nybble of length | 249 | * of the radiotap header. There is no guarantee |
194 | * table to base alignment on | ||
195 | * | ||
196 | * also note: these alignments are ** relative to the | ||
197 | * start of the radiotap header **. There is no guarantee | ||
198 | * that the radiotap header itself is aligned on any | 250 | * that the radiotap header itself is aligned on any |
199 | * kind of boundary. | 251 | * kind of boundary. |
200 | * | 252 | * |
201 | * the above is why get_unaligned() is used to dereference | 253 | * The above is why get_unaligned() is used to dereference |
202 | * multibyte elements from the radiotap area | 254 | * multibyte elements from the radiotap area. |
203 | */ | 255 | */ |
204 | 256 | ||
205 | pad = (((ulong)iterator->arg) - | 257 | pad = ((unsigned long)iterator->_arg - |
206 | ((ulong)iterator->rtheader)) & | 258 | (unsigned long)iterator->_rtheader) & (align - 1); |
207 | ((rt_sizes[iterator->arg_index] >> 4) - 1); | ||
208 | 259 | ||
209 | if (pad) | 260 | if (pad) |
210 | iterator->arg += | 261 | iterator->_arg += align - pad; |
211 | (rt_sizes[iterator->arg_index] >> 4) - pad; | ||
212 | 262 | ||
213 | /* | 263 | /* |
214 | * this is what we will return to user, but we need to | 264 | * this is what we will return to user, but we need to |
215 | * move on first so next call has something fresh to test | 265 | * move on first so next call has something fresh to test |
216 | */ | 266 | */ |
217 | iterator->this_arg_index = iterator->arg_index; | 267 | iterator->this_arg_index = iterator->_arg_index; |
218 | iterator->this_arg = iterator->arg; | 268 | iterator->this_arg = iterator->_arg; |
219 | hit = 1; | 269 | iterator->this_arg_size = size; |
220 | 270 | ||
221 | /* internally move on the size of this arg */ | 271 | /* internally move on the size of this arg */ |
222 | iterator->arg += rt_sizes[iterator->arg_index] & 0x0f; | 272 | iterator->_arg += size; |
223 | 273 | ||
224 | /* | 274 | /* |
225 | * check for insanity where we are given a bitmap that | 275 | * check for insanity where we are given a bitmap that |
@@ -228,32 +278,73 @@ int ieee80211_radiotap_iterator_next( | |||
228 | * max_length on the last arg, never exceeding it. | 278 | * max_length on the last arg, never exceeding it. |
229 | */ | 279 | */ |
230 | 280 | ||
231 | if (((ulong)iterator->arg - (ulong)iterator->rtheader) > | 281 | if ((unsigned long)iterator->_arg - |
232 | iterator->max_length) | 282 | (unsigned long)iterator->_rtheader > |
283 | (unsigned long)iterator->_max_length) | ||
233 | return -EINVAL; | 284 | return -EINVAL; |
234 | 285 | ||
235 | next_entry: | 286 | /* these special ones are valid in each bitmap word */ |
236 | iterator->arg_index++; | 287 | switch (iterator->_arg_index % 32) { |
237 | if (unlikely((iterator->arg_index & 31) == 0)) { | 288 | case IEEE80211_RADIOTAP_VENDOR_NAMESPACE: |
238 | /* completed current u32 bitmap */ | 289 | iterator->_bitmap_shifter >>= 1; |
239 | if (iterator->bitmap_shifter & 1) { | 290 | iterator->_arg_index++; |
240 | /* b31 was set, there is more */ | 291 | |
241 | /* move to next u32 bitmap */ | 292 | iterator->_reset_on_ext = 1; |
242 | iterator->bitmap_shifter = | 293 | |
243 | get_unaligned_le32(iterator->next_bitmap); | 294 | vnslen = get_unaligned_le16(iterator->this_arg + 4); |
244 | iterator->next_bitmap++; | 295 | iterator->_next_ns_data = iterator->_arg + vnslen; |
245 | } else | 296 | oui = (*iterator->this_arg << 16) | |
246 | /* no more bitmaps: end */ | 297 | (*(iterator->this_arg + 1) << 8) | |
247 | iterator->arg_index = sizeof(rt_sizes); | 298 | *(iterator->this_arg + 2); |
248 | } else /* just try the next bit */ | 299 | subns = *(iterator->this_arg + 3); |
249 | iterator->bitmap_shifter >>= 1; | 300 | |
301 | find_ns(iterator, oui, subns); | ||
302 | |||
303 | iterator->is_radiotap_ns = 0; | ||
304 | /* allow parsers to show this information */ | ||
305 | iterator->this_arg_index = | ||
306 | IEEE80211_RADIOTAP_VENDOR_NAMESPACE; | ||
307 | iterator->this_arg_size += vnslen; | ||
308 | if ((unsigned long)iterator->this_arg + | ||
309 | iterator->this_arg_size - | ||
310 | (unsigned long)iterator->_rtheader > | ||
311 | (unsigned long)(unsigned long)iterator->_max_length) | ||
312 | return -EINVAL; | ||
313 | hit = 1; | ||
314 | break; | ||
315 | case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE: | ||
316 | iterator->_bitmap_shifter >>= 1; | ||
317 | iterator->_arg_index++; | ||
318 | |||
319 | iterator->_reset_on_ext = 1; | ||
320 | iterator->current_namespace = &radiotap_ns; | ||
321 | iterator->is_radiotap_ns = 1; | ||
322 | break; | ||
323 | case IEEE80211_RADIOTAP_EXT: | ||
324 | /* | ||
325 | * bit 31 was set, there is more | ||
326 | * -- move to next u32 bitmap | ||
327 | */ | ||
328 | iterator->_bitmap_shifter = | ||
329 | get_unaligned_le32(iterator->_next_bitmap); | ||
330 | iterator->_next_bitmap++; | ||
331 | if (iterator->_reset_on_ext) | ||
332 | iterator->_arg_index = 0; | ||
333 | else | ||
334 | iterator->_arg_index++; | ||
335 | iterator->_reset_on_ext = 0; | ||
336 | break; | ||
337 | default: | ||
338 | /* we've got a hit! */ | ||
339 | hit = 1; | ||
340 | next_entry: | ||
341 | iterator->_bitmap_shifter >>= 1; | ||
342 | iterator->_arg_index++; | ||
343 | } | ||
250 | 344 | ||
251 | /* if we found a valid arg earlier, return it now */ | 345 | /* if we found a valid arg earlier, return it now */ |
252 | if (hit) | 346 | if (hit) |
253 | return 0; | 347 | return 0; |
254 | } | 348 | } |
255 | |||
256 | /* we don't know how to handle any more args, we're done */ | ||
257 | return -ENOENT; | ||
258 | } | 349 | } |
259 | EXPORT_SYMBOL(ieee80211_radiotap_iterator_next); | 350 | EXPORT_SYMBOL(ieee80211_radiotap_iterator_next); |
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index e3219e4cd044..9796f3ed1edb 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
@@ -55,6 +55,7 @@ | |||
55 | #include <linux/notifier.h> | 55 | #include <linux/notifier.h> |
56 | #include <linux/init.h> | 56 | #include <linux/init.h> |
57 | #include <linux/compat.h> | 57 | #include <linux/compat.h> |
58 | #include <linux/ctype.h> | ||
58 | 59 | ||
59 | #include <net/x25.h> | 60 | #include <net/x25.h> |
60 | #include <net/compat.h> | 61 | #include <net/compat.h> |
@@ -512,15 +513,20 @@ static int x25_create(struct net *net, struct socket *sock, int protocol, | |||
512 | { | 513 | { |
513 | struct sock *sk; | 514 | struct sock *sk; |
514 | struct x25_sock *x25; | 515 | struct x25_sock *x25; |
515 | int rc = -ESOCKTNOSUPPORT; | 516 | int rc = -EAFNOSUPPORT; |
516 | 517 | ||
517 | if (!net_eq(net, &init_net)) | 518 | if (!net_eq(net, &init_net)) |
518 | return -EAFNOSUPPORT; | 519 | goto out; |
519 | 520 | ||
520 | if (sock->type != SOCK_SEQPACKET || protocol) | 521 | rc = -ESOCKTNOSUPPORT; |
522 | if (sock->type != SOCK_SEQPACKET) | ||
521 | goto out; | 523 | goto out; |
522 | 524 | ||
523 | rc = -ENOMEM; | 525 | rc = -EINVAL; |
526 | if (protocol) | ||
527 | goto out; | ||
528 | |||
529 | rc = -ENOBUFS; | ||
524 | if ((sk = x25_alloc_socket(net)) == NULL) | 530 | if ((sk = x25_alloc_socket(net)) == NULL) |
525 | goto out; | 531 | goto out; |
526 | 532 | ||
@@ -643,7 +649,7 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
643 | { | 649 | { |
644 | struct sock *sk = sock->sk; | 650 | struct sock *sk = sock->sk; |
645 | struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr; | 651 | struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr; |
646 | int rc = 0; | 652 | int len, i, rc = 0; |
647 | 653 | ||
648 | lock_kernel(); | 654 | lock_kernel(); |
649 | if (!sock_flag(sk, SOCK_ZAPPED) || | 655 | if (!sock_flag(sk, SOCK_ZAPPED) || |
@@ -653,6 +659,14 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
653 | goto out; | 659 | goto out; |
654 | } | 660 | } |
655 | 661 | ||
662 | len = strlen(addr->sx25_addr.x25_addr); | ||
663 | for (i = 0; i < len; i++) { | ||
664 | if (!isdigit(addr->sx25_addr.x25_addr[i])) { | ||
665 | rc = -EINVAL; | ||
666 | goto out; | ||
667 | } | ||
668 | } | ||
669 | |||
656 | x25_sk(sk)->source_addr = addr->sx25_addr; | 670 | x25_sk(sk)->source_addr = addr->sx25_addr; |
657 | x25_insert_socket(sk); | 671 | x25_insert_socket(sk); |
658 | sock_reset_flag(sk, SOCK_ZAPPED); | 672 | sock_reset_flag(sk, SOCK_ZAPPED); |
diff --git a/net/x25/x25_proc.c b/net/x25/x25_proc.c index 0a04e62e0e18..7ff373792324 100644 --- a/net/x25/x25_proc.c +++ b/net/x25/x25_proc.c | |||
@@ -25,49 +25,17 @@ | |||
25 | #include <net/x25.h> | 25 | #include <net/x25.h> |
26 | 26 | ||
27 | #ifdef CONFIG_PROC_FS | 27 | #ifdef CONFIG_PROC_FS |
28 | static __inline__ struct x25_route *x25_get_route_idx(loff_t pos) | ||
29 | { | ||
30 | struct list_head *route_entry; | ||
31 | struct x25_route *rt = NULL; | ||
32 | |||
33 | list_for_each(route_entry, &x25_route_list) { | ||
34 | rt = list_entry(route_entry, struct x25_route, node); | ||
35 | if (!pos--) | ||
36 | goto found; | ||
37 | } | ||
38 | rt = NULL; | ||
39 | found: | ||
40 | return rt; | ||
41 | } | ||
42 | 28 | ||
43 | static void *x25_seq_route_start(struct seq_file *seq, loff_t *pos) | 29 | static void *x25_seq_route_start(struct seq_file *seq, loff_t *pos) |
44 | __acquires(x25_route_list_lock) | 30 | __acquires(x25_route_list_lock) |
45 | { | 31 | { |
46 | loff_t l = *pos; | ||
47 | |||
48 | read_lock_bh(&x25_route_list_lock); | 32 | read_lock_bh(&x25_route_list_lock); |
49 | return l ? x25_get_route_idx(--l) : SEQ_START_TOKEN; | 33 | return seq_list_start_head(&x25_route_list, *pos); |
50 | } | 34 | } |
51 | 35 | ||
52 | static void *x25_seq_route_next(struct seq_file *seq, void *v, loff_t *pos) | 36 | static void *x25_seq_route_next(struct seq_file *seq, void *v, loff_t *pos) |
53 | { | 37 | { |
54 | struct x25_route *rt; | 38 | return seq_list_next(v, &x25_route_list, pos); |
55 | |||
56 | ++*pos; | ||
57 | if (v == SEQ_START_TOKEN) { | ||
58 | rt = NULL; | ||
59 | if (!list_empty(&x25_route_list)) | ||
60 | rt = list_entry(x25_route_list.next, | ||
61 | struct x25_route, node); | ||
62 | goto out; | ||
63 | } | ||
64 | rt = v; | ||
65 | if (rt->node.next != &x25_route_list) | ||
66 | rt = list_entry(rt->node.next, struct x25_route, node); | ||
67 | else | ||
68 | rt = NULL; | ||
69 | out: | ||
70 | return rt; | ||
71 | } | 39 | } |
72 | 40 | ||
73 | static void x25_seq_route_stop(struct seq_file *seq, void *v) | 41 | static void x25_seq_route_stop(struct seq_file *seq, void *v) |
@@ -78,9 +46,9 @@ static void x25_seq_route_stop(struct seq_file *seq, void *v) | |||
78 | 46 | ||
79 | static int x25_seq_route_show(struct seq_file *seq, void *v) | 47 | static int x25_seq_route_show(struct seq_file *seq, void *v) |
80 | { | 48 | { |
81 | struct x25_route *rt; | 49 | struct x25_route *rt = list_entry(v, struct x25_route, node); |
82 | 50 | ||
83 | if (v == SEQ_START_TOKEN) { | 51 | if (v == &x25_route_list) { |
84 | seq_puts(seq, "Address Digits Device\n"); | 52 | seq_puts(seq, "Address Digits Device\n"); |
85 | goto out; | 53 | goto out; |
86 | } | 54 | } |
@@ -93,40 +61,16 @@ out: | |||
93 | return 0; | 61 | return 0; |
94 | } | 62 | } |
95 | 63 | ||
96 | static __inline__ struct sock *x25_get_socket_idx(loff_t pos) | ||
97 | { | ||
98 | struct sock *s; | ||
99 | struct hlist_node *node; | ||
100 | |||
101 | sk_for_each(s, node, &x25_list) | ||
102 | if (!pos--) | ||
103 | goto found; | ||
104 | s = NULL; | ||
105 | found: | ||
106 | return s; | ||
107 | } | ||
108 | |||
109 | static void *x25_seq_socket_start(struct seq_file *seq, loff_t *pos) | 64 | static void *x25_seq_socket_start(struct seq_file *seq, loff_t *pos) |
110 | __acquires(x25_list_lock) | 65 | __acquires(x25_list_lock) |
111 | { | 66 | { |
112 | loff_t l = *pos; | ||
113 | |||
114 | read_lock_bh(&x25_list_lock); | 67 | read_lock_bh(&x25_list_lock); |
115 | return l ? x25_get_socket_idx(--l) : SEQ_START_TOKEN; | 68 | return seq_hlist_start_head(&x25_list, *pos); |
116 | } | 69 | } |
117 | 70 | ||
118 | static void *x25_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos) | 71 | static void *x25_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos) |
119 | { | 72 | { |
120 | struct sock *s; | 73 | return seq_hlist_next(v, &x25_list, pos); |
121 | |||
122 | ++*pos; | ||
123 | if (v == SEQ_START_TOKEN) { | ||
124 | s = sk_head(&x25_list); | ||
125 | goto out; | ||
126 | } | ||
127 | s = sk_next(v); | ||
128 | out: | ||
129 | return s; | ||
130 | } | 74 | } |
131 | 75 | ||
132 | static void x25_seq_socket_stop(struct seq_file *seq, void *v) | 76 | static void x25_seq_socket_stop(struct seq_file *seq, void *v) |
@@ -148,7 +92,7 @@ static int x25_seq_socket_show(struct seq_file *seq, void *v) | |||
148 | goto out; | 92 | goto out; |
149 | } | 93 | } |
150 | 94 | ||
151 | s = v; | 95 | s = sk_entry(v); |
152 | x25 = x25_sk(s); | 96 | x25 = x25_sk(s); |
153 | 97 | ||
154 | if (!x25->neighbour || (dev = x25->neighbour->dev) == NULL) | 98 | if (!x25->neighbour || (dev = x25->neighbour->dev) == NULL) |
@@ -170,51 +114,16 @@ out: | |||
170 | return 0; | 114 | return 0; |
171 | } | 115 | } |
172 | 116 | ||
173 | static __inline__ struct x25_forward *x25_get_forward_idx(loff_t pos) | ||
174 | { | ||
175 | struct x25_forward *f; | ||
176 | struct list_head *entry; | ||
177 | |||
178 | list_for_each(entry, &x25_forward_list) { | ||
179 | f = list_entry(entry, struct x25_forward, node); | ||
180 | if (!pos--) | ||
181 | goto found; | ||
182 | } | ||
183 | |||
184 | f = NULL; | ||
185 | found: | ||
186 | return f; | ||
187 | } | ||
188 | |||
189 | static void *x25_seq_forward_start(struct seq_file *seq, loff_t *pos) | 117 | static void *x25_seq_forward_start(struct seq_file *seq, loff_t *pos) |
190 | __acquires(x25_forward_list_lock) | 118 | __acquires(x25_forward_list_lock) |
191 | { | 119 | { |
192 | loff_t l = *pos; | ||
193 | |||
194 | read_lock_bh(&x25_forward_list_lock); | 120 | read_lock_bh(&x25_forward_list_lock); |
195 | return l ? x25_get_forward_idx(--l) : SEQ_START_TOKEN; | 121 | return seq_list_start_head(&x25_forward_list, *pos); |
196 | } | 122 | } |
197 | 123 | ||
198 | static void *x25_seq_forward_next(struct seq_file *seq, void *v, loff_t *pos) | 124 | static void *x25_seq_forward_next(struct seq_file *seq, void *v, loff_t *pos) |
199 | { | 125 | { |
200 | struct x25_forward *f; | 126 | return seq_list_next(v, &x25_forward_list, pos); |
201 | |||
202 | ++*pos; | ||
203 | if (v == SEQ_START_TOKEN) { | ||
204 | f = NULL; | ||
205 | if (!list_empty(&x25_forward_list)) | ||
206 | f = list_entry(x25_forward_list.next, | ||
207 | struct x25_forward, node); | ||
208 | goto out; | ||
209 | } | ||
210 | f = v; | ||
211 | if (f->node.next != &x25_forward_list) | ||
212 | f = list_entry(f->node.next, struct x25_forward, node); | ||
213 | else | ||
214 | f = NULL; | ||
215 | out: | ||
216 | return f; | ||
217 | |||
218 | } | 127 | } |
219 | 128 | ||
220 | static void x25_seq_forward_stop(struct seq_file *seq, void *v) | 129 | static void x25_seq_forward_stop(struct seq_file *seq, void *v) |
@@ -225,9 +134,9 @@ static void x25_seq_forward_stop(struct seq_file *seq, void *v) | |||
225 | 134 | ||
226 | static int x25_seq_forward_show(struct seq_file *seq, void *v) | 135 | static int x25_seq_forward_show(struct seq_file *seq, void *v) |
227 | { | 136 | { |
228 | struct x25_forward *f; | 137 | struct x25_forward *f = list_entry(v, struct x25_forward, node); |
229 | 138 | ||
230 | if (v == SEQ_START_TOKEN) { | 139 | if (v == &x25_forward_list) { |
231 | seq_printf(seq, "lci dev1 dev2\n"); | 140 | seq_printf(seq, "lci dev1 dev2\n"); |
232 | goto out; | 141 | goto out; |
233 | } | 142 | } |
@@ -236,7 +145,6 @@ static int x25_seq_forward_show(struct seq_file *seq, void *v) | |||
236 | 145 | ||
237 | seq_printf(seq, "%d %-10s %-10s\n", | 146 | seq_printf(seq, "%d %-10s %-10s\n", |
238 | f->lci, f->dev1->name, f->dev2->name); | 147 | f->lci, f->dev1->name, f->dev2->name); |
239 | |||
240 | out: | 148 | out: |
241 | return 0; | 149 | return 0; |
242 | } | 150 | } |
diff --git a/net/xfrm/xfrm_ipcomp.c b/net/xfrm/xfrm_ipcomp.c index 42cd18391f46..0fc5ff66d1fa 100644 --- a/net/xfrm/xfrm_ipcomp.c +++ b/net/xfrm/xfrm_ipcomp.c | |||
@@ -30,12 +30,12 @@ | |||
30 | 30 | ||
31 | struct ipcomp_tfms { | 31 | struct ipcomp_tfms { |
32 | struct list_head list; | 32 | struct list_head list; |
33 | struct crypto_comp **tfms; | 33 | struct crypto_comp * __percpu *tfms; |
34 | int users; | 34 | int users; |
35 | }; | 35 | }; |
36 | 36 | ||
37 | static DEFINE_MUTEX(ipcomp_resource_mutex); | 37 | static DEFINE_MUTEX(ipcomp_resource_mutex); |
38 | static void **ipcomp_scratches; | 38 | static void * __percpu *ipcomp_scratches; |
39 | static int ipcomp_scratch_users; | 39 | static int ipcomp_scratch_users; |
40 | static LIST_HEAD(ipcomp_tfms_list); | 40 | static LIST_HEAD(ipcomp_tfms_list); |
41 | 41 | ||
@@ -200,7 +200,7 @@ EXPORT_SYMBOL_GPL(ipcomp_output); | |||
200 | static void ipcomp_free_scratches(void) | 200 | static void ipcomp_free_scratches(void) |
201 | { | 201 | { |
202 | int i; | 202 | int i; |
203 | void **scratches; | 203 | void * __percpu *scratches; |
204 | 204 | ||
205 | if (--ipcomp_scratch_users) | 205 | if (--ipcomp_scratch_users) |
206 | return; | 206 | return; |
@@ -215,10 +215,10 @@ static void ipcomp_free_scratches(void) | |||
215 | free_percpu(scratches); | 215 | free_percpu(scratches); |
216 | } | 216 | } |
217 | 217 | ||
218 | static void **ipcomp_alloc_scratches(void) | 218 | static void * __percpu *ipcomp_alloc_scratches(void) |
219 | { | 219 | { |
220 | int i; | 220 | int i; |
221 | void **scratches; | 221 | void * __percpu *scratches; |
222 | 222 | ||
223 | if (ipcomp_scratch_users++) | 223 | if (ipcomp_scratch_users++) |
224 | return ipcomp_scratches; | 224 | return ipcomp_scratches; |
@@ -239,7 +239,7 @@ static void **ipcomp_alloc_scratches(void) | |||
239 | return scratches; | 239 | return scratches; |
240 | } | 240 | } |
241 | 241 | ||
242 | static void ipcomp_free_tfms(struct crypto_comp **tfms) | 242 | static void ipcomp_free_tfms(struct crypto_comp * __percpu *tfms) |
243 | { | 243 | { |
244 | struct ipcomp_tfms *pos; | 244 | struct ipcomp_tfms *pos; |
245 | int cpu; | 245 | int cpu; |
@@ -267,10 +267,10 @@ static void ipcomp_free_tfms(struct crypto_comp **tfms) | |||
267 | free_percpu(tfms); | 267 | free_percpu(tfms); |
268 | } | 268 | } |
269 | 269 | ||
270 | static struct crypto_comp **ipcomp_alloc_tfms(const char *alg_name) | 270 | static struct crypto_comp * __percpu *ipcomp_alloc_tfms(const char *alg_name) |
271 | { | 271 | { |
272 | struct ipcomp_tfms *pos; | 272 | struct ipcomp_tfms *pos; |
273 | struct crypto_comp **tfms; | 273 | struct crypto_comp * __percpu *tfms; |
274 | int cpu; | 274 | int cpu; |
275 | 275 | ||
276 | /* This can be any valid CPU ID so we don't need locking. */ | 276 | /* This can be any valid CPU ID so we don't need locking. */ |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 0ecb16a9a883..2c5d93181f13 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -2421,19 +2421,19 @@ static int __net_init xfrm_statistics_init(struct net *net) | |||
2421 | { | 2421 | { |
2422 | int rv; | 2422 | int rv; |
2423 | 2423 | ||
2424 | if (snmp_mib_init((void **)net->mib.xfrm_statistics, | 2424 | if (snmp_mib_init((void __percpu **)net->mib.xfrm_statistics, |
2425 | sizeof(struct linux_xfrm_mib)) < 0) | 2425 | sizeof(struct linux_xfrm_mib)) < 0) |
2426 | return -ENOMEM; | 2426 | return -ENOMEM; |
2427 | rv = xfrm_proc_init(net); | 2427 | rv = xfrm_proc_init(net); |
2428 | if (rv < 0) | 2428 | if (rv < 0) |
2429 | snmp_mib_free((void **)net->mib.xfrm_statistics); | 2429 | snmp_mib_free((void __percpu **)net->mib.xfrm_statistics); |
2430 | return rv; | 2430 | return rv; |
2431 | } | 2431 | } |
2432 | 2432 | ||
2433 | static void xfrm_statistics_fini(struct net *net) | 2433 | static void xfrm_statistics_fini(struct net *net) |
2434 | { | 2434 | { |
2435 | xfrm_proc_fini(net); | 2435 | xfrm_proc_fini(net); |
2436 | snmp_mib_free((void **)net->mib.xfrm_statistics); | 2436 | snmp_mib_free((void __percpu **)net->mib.xfrm_statistics); |
2437 | } | 2437 | } |
2438 | #else | 2438 | #else |
2439 | static int __net_init xfrm_statistics_init(struct net *net) | 2439 | static int __net_init xfrm_statistics_init(struct net *net) |
diff --git a/net/xfrm/xfrm_proc.c b/net/xfrm/xfrm_proc.c index c083a4e4e796..003f2c437ac3 100644 --- a/net/xfrm/xfrm_proc.c +++ b/net/xfrm/xfrm_proc.c | |||
@@ -50,7 +50,8 @@ static int xfrm_statistics_seq_show(struct seq_file *seq, void *v) | |||
50 | int i; | 50 | int i; |
51 | for (i=0; xfrm_mib_list[i].name; i++) | 51 | for (i=0; xfrm_mib_list[i].name; i++) |
52 | seq_printf(seq, "%-24s\t%lu\n", xfrm_mib_list[i].name, | 52 | seq_printf(seq, "%-24s\t%lu\n", xfrm_mib_list[i].name, |
53 | snmp_fold_field((void **)net->mib.xfrm_statistics, | 53 | snmp_fold_field((void __percpu **) |
54 | net->mib.xfrm_statistics, | ||
54 | xfrm_mib_list[i].entry)); | 55 | xfrm_mib_list[i].entry)); |
55 | return 0; | 56 | return 0; |
56 | } | 57 | } |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index b36cc344474b..c9d6a5f1348d 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -1102,7 +1102,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp) | |||
1102 | int err = -ENOMEM; | 1102 | int err = -ENOMEM; |
1103 | struct xfrm_state *x = xfrm_state_alloc(net); | 1103 | struct xfrm_state *x = xfrm_state_alloc(net); |
1104 | if (!x) | 1104 | if (!x) |
1105 | goto error; | 1105 | goto out; |
1106 | 1106 | ||
1107 | memcpy(&x->id, &orig->id, sizeof(x->id)); | 1107 | memcpy(&x->id, &orig->id, sizeof(x->id)); |
1108 | memcpy(&x->sel, &orig->sel, sizeof(x->sel)); | 1108 | memcpy(&x->sel, &orig->sel, sizeof(x->sel)); |
@@ -1160,16 +1160,10 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp) | |||
1160 | return x; | 1160 | return x; |
1161 | 1161 | ||
1162 | error: | 1162 | error: |
1163 | xfrm_state_put(x); | ||
1164 | out: | ||
1163 | if (errp) | 1165 | if (errp) |
1164 | *errp = err; | 1166 | *errp = err; |
1165 | if (x) { | ||
1166 | kfree(x->aalg); | ||
1167 | kfree(x->ealg); | ||
1168 | kfree(x->calg); | ||
1169 | kfree(x->encap); | ||
1170 | kfree(x->coaddr); | ||
1171 | } | ||
1172 | kfree(x); | ||
1173 | return NULL; | 1167 | return NULL; |
1174 | } | 1168 | } |
1175 | 1169 | ||
@@ -1458,12 +1452,12 @@ EXPORT_SYMBOL(xfrm_find_acq_byseq); | |||
1458 | u32 xfrm_get_acqseq(void) | 1452 | u32 xfrm_get_acqseq(void) |
1459 | { | 1453 | { |
1460 | u32 res; | 1454 | u32 res; |
1461 | static u32 acqseq; | 1455 | static atomic_t acqseq; |
1462 | static DEFINE_SPINLOCK(acqseq_lock); | 1456 | |
1457 | do { | ||
1458 | res = atomic_inc_return(&acqseq); | ||
1459 | } while (!res); | ||
1463 | 1460 | ||
1464 | spin_lock_bh(&acqseq_lock); | ||
1465 | res = (++acqseq ? : ++acqseq); | ||
1466 | spin_unlock_bh(&acqseq_lock); | ||
1467 | return res; | 1461 | return res; |
1468 | } | 1462 | } |
1469 | EXPORT_SYMBOL(xfrm_get_acqseq); | 1463 | EXPORT_SYMBOL(xfrm_get_acqseq); |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index d5a712976004..943c8712bd97 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -2054,6 +2054,10 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { | |||
2054 | #undef XMSGSIZE | 2054 | #undef XMSGSIZE |
2055 | 2055 | ||
2056 | static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { | 2056 | static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { |
2057 | [XFRMA_SA] = { .len = sizeof(struct xfrm_usersa_info)}, | ||
2058 | [XFRMA_POLICY] = { .len = sizeof(struct xfrm_userpolicy_info)}, | ||
2059 | [XFRMA_LASTUSED] = { .type = NLA_U64}, | ||
2060 | [XFRMA_ALG_AUTH_TRUNC] = { .len = sizeof(struct xfrm_algo_auth)}, | ||
2057 | [XFRMA_ALG_AEAD] = { .len = sizeof(struct xfrm_algo_aead) }, | 2061 | [XFRMA_ALG_AEAD] = { .len = sizeof(struct xfrm_algo_aead) }, |
2058 | [XFRMA_ALG_AUTH] = { .len = sizeof(struct xfrm_algo) }, | 2062 | [XFRMA_ALG_AUTH] = { .len = sizeof(struct xfrm_algo) }, |
2059 | [XFRMA_ALG_CRYPT] = { .len = sizeof(struct xfrm_algo) }, | 2063 | [XFRMA_ALG_CRYPT] = { .len = sizeof(struct xfrm_algo) }, |