3fbc217dbdccbf9c6f83a34440a7ff6f0dcb335a
[cascardo/linux.git] / net / mac802154 / mib.c
1 /*
2  * Copyright 2007-2012 Siemens AG
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2
6  * as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * Written by:
14  * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
15  * Sergey Lapin <slapin@ossfans.org>
16  * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
17  * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
18  */
19
20 #include <linux/if_arp.h>
21
22 #include <net/mac802154.h>
23 #include <net/ieee802154_netdev.h>
24 #include <net/cfg802154.h>
25
26 #include "ieee802154_i.h"
27 #include "driver-ops.h"
28
29 struct phy_chan_notify_work {
30         struct work_struct work;
31         struct net_device *dev;
32 };
33
34 struct hw_addr_filt_notify_work {
35         struct work_struct work;
36         struct net_device *dev;
37         unsigned long changed;
38 };
39
40 static struct ieee802154_local *mac802154_slave_get_priv(struct net_device *dev)
41 {
42         struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
43
44         BUG_ON(dev->type != ARPHRD_IEEE802154);
45
46         return sdata->local;
47 }
48
49 static void hw_addr_notify(struct work_struct *work)
50 {
51         struct hw_addr_filt_notify_work *nw = container_of(work,
52                         struct hw_addr_filt_notify_work, work);
53         struct ieee802154_local *local = mac802154_slave_get_priv(nw->dev);
54         int res;
55
56         res = local->ops->set_hw_addr_filt(&local->hw, &local->hw.hw_filt,
57                                            nw->changed);
58         if (res)
59                 pr_debug("failed changed mask %lx\n", nw->changed);
60
61         kfree(nw);
62 }
63
64 static void set_hw_addr_filt(struct net_device *dev, unsigned long changed)
65 {
66         struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
67         struct hw_addr_filt_notify_work *work;
68
69         work = kzalloc(sizeof(*work), GFP_ATOMIC);
70         if (!work)
71                 return;
72
73         INIT_WORK(&work->work, hw_addr_notify);
74         work->dev = dev;
75         work->changed = changed;
76         queue_work(sdata->local->workqueue, &work->work);
77 }
78
79 void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val)
80 {
81         struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
82
83         BUG_ON(dev->type != ARPHRD_IEEE802154);
84
85         spin_lock_bh(&sdata->mib_lock);
86         sdata->short_addr = val;
87         spin_unlock_bh(&sdata->mib_lock);
88
89         if ((sdata->local->ops->set_hw_addr_filt) &&
90             (sdata->local->hw.hw_filt.short_addr != sdata->short_addr)) {
91                 sdata->local->hw.hw_filt.short_addr = sdata->short_addr;
92                 set_hw_addr_filt(dev, IEEE802154_AFILT_SADDR_CHANGED);
93         }
94 }
95
96 __le16 mac802154_dev_get_short_addr(const struct net_device *dev)
97 {
98         struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
99         __le16 ret;
100
101         BUG_ON(dev->type != ARPHRD_IEEE802154);
102
103         spin_lock_bh(&sdata->mib_lock);
104         ret = sdata->short_addr;
105         spin_unlock_bh(&sdata->mib_lock);
106
107         return ret;
108 }
109
110 void mac802154_dev_set_ieee_addr(struct net_device *dev)
111 {
112         struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
113         struct ieee802154_local *local = sdata->local;
114
115         sdata->extended_addr = ieee802154_devaddr_from_raw(dev->dev_addr);
116
117         if (local->ops->set_hw_addr_filt &&
118             local->hw.hw_filt.ieee_addr != sdata->extended_addr) {
119                 local->hw.hw_filt.ieee_addr = sdata->extended_addr;
120                 set_hw_addr_filt(dev, IEEE802154_AFILT_IEEEADDR_CHANGED);
121         }
122 }
123
124 __le16 mac802154_dev_get_pan_id(const struct net_device *dev)
125 {
126         struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
127         __le16 ret;
128
129         BUG_ON(dev->type != ARPHRD_IEEE802154);
130
131         spin_lock_bh(&sdata->mib_lock);
132         ret = sdata->pan_id;
133         spin_unlock_bh(&sdata->mib_lock);
134
135         return ret;
136 }
137
138 void mac802154_dev_set_pan_id(struct net_device *dev, __le16 val)
139 {
140         struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
141
142         BUG_ON(dev->type != ARPHRD_IEEE802154);
143
144         spin_lock_bh(&sdata->mib_lock);
145         sdata->pan_id = val;
146         spin_unlock_bh(&sdata->mib_lock);
147
148         if ((sdata->local->ops->set_hw_addr_filt) &&
149             (sdata->local->hw.hw_filt.pan_id != sdata->pan_id)) {
150                 sdata->local->hw.hw_filt.pan_id = sdata->pan_id;
151                 set_hw_addr_filt(dev, IEEE802154_AFILT_PANID_CHANGED);
152         }
153 }
154
155 u8 mac802154_dev_get_dsn(const struct net_device *dev)
156 {
157         struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
158
159         BUG_ON(dev->type != ARPHRD_IEEE802154);
160
161         return sdata->dsn++;
162 }
163
164 static void phy_chan_notify(struct work_struct *work)
165 {
166         struct phy_chan_notify_work *nw = container_of(work,
167                                           struct phy_chan_notify_work, work);
168         struct net_device *dev = nw->dev;
169         struct ieee802154_local *local = mac802154_slave_get_priv(dev);
170         struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
171         int res;
172
173         mutex_lock(&sdata->local->phy->pib_lock);
174         res = drv_set_channel(local, sdata->page, sdata->chan);
175         if (res) {
176                 pr_debug("set_channel failed\n");
177         } else {
178                 sdata->local->phy->current_channel = sdata->chan;
179                 sdata->local->phy->current_page = sdata->page;
180         }
181         mutex_unlock(&sdata->local->phy->pib_lock);
182
183         kfree(nw);
184 }
185
186 void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan)
187 {
188         struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
189         struct phy_chan_notify_work *work;
190
191         BUG_ON(dev->type != ARPHRD_IEEE802154);
192
193         spin_lock_bh(&sdata->mib_lock);
194         sdata->page = page;
195         sdata->chan = chan;
196         spin_unlock_bh(&sdata->mib_lock);
197
198         mutex_lock(&sdata->local->phy->pib_lock);
199         if (sdata->local->phy->current_channel != sdata->chan ||
200             sdata->local->phy->current_page != sdata->page) {
201                 mutex_unlock(&sdata->local->phy->pib_lock);
202
203                 work = kzalloc(sizeof(*work), GFP_ATOMIC);
204                 if (!work)
205                         return;
206
207                 INIT_WORK(&work->work, phy_chan_notify);
208                 work->dev = dev;
209                 queue_work(sdata->local->workqueue, &work->work);
210         } else {
211                 mutex_unlock(&sdata->local->phy->pib_lock);
212         }
213 }
214
215
216 int mac802154_get_params(struct net_device *dev,
217                          struct ieee802154_llsec_params *params)
218 {
219         struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
220         int res;
221
222         BUG_ON(dev->type != ARPHRD_IEEE802154);
223
224         mutex_lock(&sdata->sec_mtx);
225         res = mac802154_llsec_get_params(&sdata->sec, params);
226         mutex_unlock(&sdata->sec_mtx);
227
228         return res;
229 }
230
231 int mac802154_set_params(struct net_device *dev,
232                          const struct ieee802154_llsec_params *params,
233                          int changed)
234 {
235         struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
236         int res;
237
238         BUG_ON(dev->type != ARPHRD_IEEE802154);
239
240         mutex_lock(&sdata->sec_mtx);
241         res = mac802154_llsec_set_params(&sdata->sec, params, changed);
242         mutex_unlock(&sdata->sec_mtx);
243
244         return res;
245 }
246
247
248 int mac802154_add_key(struct net_device *dev,
249                       const struct ieee802154_llsec_key_id *id,
250                       const struct ieee802154_llsec_key *key)
251 {
252         struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
253         int res;
254
255         BUG_ON(dev->type != ARPHRD_IEEE802154);
256
257         mutex_lock(&sdata->sec_mtx);
258         res = mac802154_llsec_key_add(&sdata->sec, id, key);
259         mutex_unlock(&sdata->sec_mtx);
260
261         return res;
262 }
263
264 int mac802154_del_key(struct net_device *dev,
265                       const struct ieee802154_llsec_key_id *id)
266 {
267         struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
268         int res;
269
270         BUG_ON(dev->type != ARPHRD_IEEE802154);
271
272         mutex_lock(&sdata->sec_mtx);
273         res = mac802154_llsec_key_del(&sdata->sec, id);
274         mutex_unlock(&sdata->sec_mtx);
275
276         return res;
277 }
278
279
280 int mac802154_add_dev(struct net_device *dev,
281                       const struct ieee802154_llsec_device *llsec_dev)
282 {
283         struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
284         int res;
285
286         BUG_ON(dev->type != ARPHRD_IEEE802154);
287
288         mutex_lock(&sdata->sec_mtx);
289         res = mac802154_llsec_dev_add(&sdata->sec, llsec_dev);
290         mutex_unlock(&sdata->sec_mtx);
291
292         return res;
293 }
294
295 int mac802154_del_dev(struct net_device *dev, __le64 dev_addr)
296 {
297         struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
298         int res;
299
300         BUG_ON(dev->type != ARPHRD_IEEE802154);
301
302         mutex_lock(&sdata->sec_mtx);
303         res = mac802154_llsec_dev_del(&sdata->sec, dev_addr);
304         mutex_unlock(&sdata->sec_mtx);
305
306         return res;
307 }
308
309
310 int mac802154_add_devkey(struct net_device *dev,
311                          __le64 device_addr,
312                          const struct ieee802154_llsec_device_key *key)
313 {
314         struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
315         int res;
316
317         BUG_ON(dev->type != ARPHRD_IEEE802154);
318
319         mutex_lock(&sdata->sec_mtx);
320         res = mac802154_llsec_devkey_add(&sdata->sec, device_addr, key);
321         mutex_unlock(&sdata->sec_mtx);
322
323         return res;
324 }
325
326 int mac802154_del_devkey(struct net_device *dev,
327                          __le64 device_addr,
328                          const struct ieee802154_llsec_device_key *key)
329 {
330         struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
331         int res;
332
333         BUG_ON(dev->type != ARPHRD_IEEE802154);
334
335         mutex_lock(&sdata->sec_mtx);
336         res = mac802154_llsec_devkey_del(&sdata->sec, device_addr, key);
337         mutex_unlock(&sdata->sec_mtx);
338
339         return res;
340 }
341
342
343 int mac802154_add_seclevel(struct net_device *dev,
344                            const struct ieee802154_llsec_seclevel *sl)
345 {
346         struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
347         int res;
348
349         BUG_ON(dev->type != ARPHRD_IEEE802154);
350
351         mutex_lock(&sdata->sec_mtx);
352         res = mac802154_llsec_seclevel_add(&sdata->sec, sl);
353         mutex_unlock(&sdata->sec_mtx);
354
355         return res;
356 }
357
358 int mac802154_del_seclevel(struct net_device *dev,
359                            const struct ieee802154_llsec_seclevel *sl)
360 {
361         struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
362         int res;
363
364         BUG_ON(dev->type != ARPHRD_IEEE802154);
365
366         mutex_lock(&sdata->sec_mtx);
367         res = mac802154_llsec_seclevel_del(&sdata->sec, sl);
368         mutex_unlock(&sdata->sec_mtx);
369
370         return res;
371 }
372
373
374 void mac802154_lock_table(struct net_device *dev)
375 {
376         struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
377
378         BUG_ON(dev->type != ARPHRD_IEEE802154);
379
380         mutex_lock(&sdata->sec_mtx);
381 }
382
383 void mac802154_get_table(struct net_device *dev,
384                          struct ieee802154_llsec_table **t)
385 {
386         struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
387
388         BUG_ON(dev->type != ARPHRD_IEEE802154);
389
390         *t = &sdata->sec.table;
391 }
392
393 void mac802154_unlock_table(struct net_device *dev)
394 {
395         struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
396
397         BUG_ON(dev->type != ARPHRD_IEEE802154);
398
399         mutex_unlock(&sdata->sec_mtx);
400 }