mac802154: introduce driver-ops header
[deliverable/linux.git] / net / mac802154 / mib.c
CommitLineData
ef2486f5 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 *
ef2486f5 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>
b70ab2e8 23#include <net/ieee802154_netdev.h>
5ad60d36 24#include <net/cfg802154.h>
ef2486f5 25
0f1556bc 26#include "ieee802154_i.h"
ef2486f5 27
66b69d4d 28struct phy_chan_notify_work {
29 struct work_struct work;
30 struct net_device *dev;
31};
32
ef2486f5 33struct hw_addr_filt_notify_work {
34 struct work_struct work;
35 struct net_device *dev;
36 unsigned long changed;
37};
38
a5e1ec53 39static struct ieee802154_local *mac802154_slave_get_priv(struct net_device *dev)
ef2486f5 40{
59d19cd7 41 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
ef2486f5 42
43 BUG_ON(dev->type != ARPHRD_IEEE802154);
44
04e850fe 45 return sdata->local;
ef2486f5 46}
47
48static void hw_addr_notify(struct work_struct *work)
49{
50 struct hw_addr_filt_notify_work *nw = container_of(work,
51 struct hw_addr_filt_notify_work, work);
a5e1ec53 52 struct ieee802154_local *local = mac802154_slave_get_priv(nw->dev);
ef2486f5 53 int res;
54
a5e1ec53
AA
55 res = local->ops->set_hw_addr_filt(&local->hw, &local->hw.hw_filt,
56 nw->changed);
ef2486f5 57 if (res)
58 pr_debug("failed changed mask %lx\n", nw->changed);
59
60 kfree(nw);
ef2486f5 61}
62
63static void set_hw_addr_filt(struct net_device *dev, unsigned long changed)
64{
59d19cd7 65 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
ef2486f5 66 struct hw_addr_filt_notify_work *work;
67
68 work = kzalloc(sizeof(*work), GFP_ATOMIC);
69 if (!work)
70 return;
71
72 INIT_WORK(&work->work, hw_addr_notify);
73 work->dev = dev;
74 work->changed = changed;
f7730542 75 queue_work(sdata->local->workqueue, &work->work);
ef2486f5 76}
77
b70ab2e8 78void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val)
48e44d50 79{
59d19cd7 80 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
48e44d50 81
82 BUG_ON(dev->type != ARPHRD_IEEE802154);
83
036562f9
AA
84 spin_lock_bh(&sdata->mib_lock);
85 sdata->short_addr = val;
86 spin_unlock_bh(&sdata->mib_lock);
48e44d50 87
04e850fe
AA
88 if ((sdata->local->ops->set_hw_addr_filt) &&
89 (sdata->local->hw.hw_filt.short_addr != sdata->short_addr)) {
90 sdata->local->hw.hw_filt.short_addr = sdata->short_addr;
57205c14 91 set_hw_addr_filt(dev, IEEE802154_AFILT_SADDR_CHANGED);
48e44d50 92 }
93}
94
b70ab2e8 95__le16 mac802154_dev_get_short_addr(const struct net_device *dev)
e885a47a 96{
59d19cd7 97 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
b70ab2e8 98 __le16 ret;
e885a47a 99
100 BUG_ON(dev->type != ARPHRD_IEEE802154);
101
036562f9
AA
102 spin_lock_bh(&sdata->mib_lock);
103 ret = sdata->short_addr;
104 spin_unlock_bh(&sdata->mib_lock);
e885a47a 105
106 return ret;
107}
108
ef2486f5 109void mac802154_dev_set_ieee_addr(struct net_device *dev)
110{
59d19cd7 111 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
04e850fe 112 struct ieee802154_local *local = sdata->local;
ef2486f5 113
036562f9 114 sdata->extended_addr = ieee802154_devaddr_from_raw(dev->dev_addr);
b70ab2e8 115
a5e1ec53 116 if (local->ops->set_hw_addr_filt &&
036562f9
AA
117 local->hw.hw_filt.ieee_addr != sdata->extended_addr) {
118 local->hw.hw_filt.ieee_addr = sdata->extended_addr;
57205c14 119 set_hw_addr_filt(dev, IEEE802154_AFILT_IEEEADDR_CHANGED);
ef2486f5 120 }
121}
dcbe4f93 122
b70ab2e8 123__le16 mac802154_dev_get_pan_id(const struct net_device *dev)
dcbe4f93 124{
59d19cd7 125 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
b70ab2e8 126 __le16 ret;
dcbe4f93 127
128 BUG_ON(dev->type != ARPHRD_IEEE802154);
129
036562f9
AA
130 spin_lock_bh(&sdata->mib_lock);
131 ret = sdata->pan_id;
132 spin_unlock_bh(&sdata->mib_lock);
dcbe4f93 133
134 return ret;
135}
136
b70ab2e8 137void mac802154_dev_set_pan_id(struct net_device *dev, __le16 val)
dcbe4f93 138{
59d19cd7 139 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
dcbe4f93 140
141 BUG_ON(dev->type != ARPHRD_IEEE802154);
142
036562f9
AA
143 spin_lock_bh(&sdata->mib_lock);
144 sdata->pan_id = val;
145 spin_unlock_bh(&sdata->mib_lock);
dcbe4f93 146
04e850fe
AA
147 if ((sdata->local->ops->set_hw_addr_filt) &&
148 (sdata->local->hw.hw_filt.pan_id != sdata->pan_id)) {
149 sdata->local->hw.hw_filt.pan_id = sdata->pan_id;
57205c14 150 set_hw_addr_filt(dev, IEEE802154_AFILT_PANID_CHANGED);
dcbe4f93 151 }
152}
66b69d4d 153
0483546a
TC
154u8 mac802154_dev_get_dsn(const struct net_device *dev)
155{
59d19cd7 156 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
0483546a
TC
157
158 BUG_ON(dev->type != ARPHRD_IEEE802154);
159
036562f9 160 return sdata->dsn++;
0483546a
TC
161}
162
66b69d4d 163static void phy_chan_notify(struct work_struct *work)
164{
165 struct phy_chan_notify_work *nw = container_of(work,
166 struct phy_chan_notify_work, work);
59d19cd7
AA
167 struct net_device *dev = nw->dev;
168 struct ieee802154_local *local = mac802154_slave_get_priv(dev);
169 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
66b69d4d 170 int res;
171
04e850fe 172 mutex_lock(&sdata->local->phy->pib_lock);
036562f9 173 res = local->ops->set_channel(&local->hw, sdata->page, sdata->chan);
4710d806 174 if (res) {
66b69d4d 175 pr_debug("set_channel failed\n");
4710d806 176 } else {
04e850fe
AA
177 sdata->local->phy->current_channel = sdata->chan;
178 sdata->local->phy->current_page = sdata->page;
9f7f78b4 179 }
04e850fe 180 mutex_unlock(&sdata->local->phy->pib_lock);
66b69d4d 181
182 kfree(nw);
183}
184
185void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan)
186{
59d19cd7 187 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
66b69d4d 188 struct phy_chan_notify_work *work;
189
190 BUG_ON(dev->type != ARPHRD_IEEE802154);
191
036562f9
AA
192 spin_lock_bh(&sdata->mib_lock);
193 sdata->page = page;
194 sdata->chan = chan;
195 spin_unlock_bh(&sdata->mib_lock);
66b69d4d 196
04e850fe
AA
197 mutex_lock(&sdata->local->phy->pib_lock);
198 if (sdata->local->phy->current_channel != sdata->chan ||
199 sdata->local->phy->current_page != sdata->page) {
200 mutex_unlock(&sdata->local->phy->pib_lock);
9f7f78b4 201
66b69d4d 202 work = kzalloc(sizeof(*work), GFP_ATOMIC);
203 if (!work)
204 return;
205
206 INIT_WORK(&work->work, phy_chan_notify);
207 work->dev = dev;
f7730542 208 queue_work(sdata->local->workqueue, &work->work);
4710d806 209 } else {
04e850fe 210 mutex_unlock(&sdata->local->phy->pib_lock);
4710d806 211 }
66b69d4d 212}
29e02374
PB
213
214
215int mac802154_get_params(struct net_device *dev,
216 struct ieee802154_llsec_params *params)
217{
59d19cd7 218 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
29e02374
PB
219 int res;
220
221 BUG_ON(dev->type != ARPHRD_IEEE802154);
222
036562f9
AA
223 mutex_lock(&sdata->sec_mtx);
224 res = mac802154_llsec_get_params(&sdata->sec, params);
225 mutex_unlock(&sdata->sec_mtx);
29e02374
PB
226
227 return res;
228}
229
230int mac802154_set_params(struct net_device *dev,
231 const struct ieee802154_llsec_params *params,
232 int changed)
233{
59d19cd7 234 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
29e02374
PB
235 int res;
236
237 BUG_ON(dev->type != ARPHRD_IEEE802154);
238
036562f9
AA
239 mutex_lock(&sdata->sec_mtx);
240 res = mac802154_llsec_set_params(&sdata->sec, params, changed);
241 mutex_unlock(&sdata->sec_mtx);
29e02374
PB
242
243 return res;
244}
245
246
247int mac802154_add_key(struct net_device *dev,
248 const struct ieee802154_llsec_key_id *id,
249 const struct ieee802154_llsec_key *key)
250{
59d19cd7 251 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
29e02374
PB
252 int res;
253
254 BUG_ON(dev->type != ARPHRD_IEEE802154);
255
036562f9
AA
256 mutex_lock(&sdata->sec_mtx);
257 res = mac802154_llsec_key_add(&sdata->sec, id, key);
258 mutex_unlock(&sdata->sec_mtx);
29e02374
PB
259
260 return res;
261}
262
263int mac802154_del_key(struct net_device *dev,
264 const struct ieee802154_llsec_key_id *id)
265{
59d19cd7 266 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
29e02374
PB
267 int res;
268
269 BUG_ON(dev->type != ARPHRD_IEEE802154);
270
036562f9
AA
271 mutex_lock(&sdata->sec_mtx);
272 res = mac802154_llsec_key_del(&sdata->sec, id);
273 mutex_unlock(&sdata->sec_mtx);
29e02374
PB
274
275 return res;
276}
277
278
279int mac802154_add_dev(struct net_device *dev,
280 const struct ieee802154_llsec_device *llsec_dev)
281{
59d19cd7 282 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
29e02374
PB
283 int res;
284
285 BUG_ON(dev->type != ARPHRD_IEEE802154);
286
036562f9
AA
287 mutex_lock(&sdata->sec_mtx);
288 res = mac802154_llsec_dev_add(&sdata->sec, llsec_dev);
289 mutex_unlock(&sdata->sec_mtx);
29e02374
PB
290
291 return res;
292}
293
294int mac802154_del_dev(struct net_device *dev, __le64 dev_addr)
295{
59d19cd7 296 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
29e02374
PB
297 int res;
298
299 BUG_ON(dev->type != ARPHRD_IEEE802154);
300
036562f9
AA
301 mutex_lock(&sdata->sec_mtx);
302 res = mac802154_llsec_dev_del(&sdata->sec, dev_addr);
303 mutex_unlock(&sdata->sec_mtx);
29e02374
PB
304
305 return res;
306}
307
308
309int mac802154_add_devkey(struct net_device *dev,
310 __le64 device_addr,
311 const struct ieee802154_llsec_device_key *key)
312{
59d19cd7 313 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
29e02374
PB
314 int res;
315
316 BUG_ON(dev->type != ARPHRD_IEEE802154);
317
036562f9
AA
318 mutex_lock(&sdata->sec_mtx);
319 res = mac802154_llsec_devkey_add(&sdata->sec, device_addr, key);
320 mutex_unlock(&sdata->sec_mtx);
29e02374
PB
321
322 return res;
323}
324
325int mac802154_del_devkey(struct net_device *dev,
326 __le64 device_addr,
327 const struct ieee802154_llsec_device_key *key)
328{
59d19cd7 329 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
29e02374
PB
330 int res;
331
332 BUG_ON(dev->type != ARPHRD_IEEE802154);
333
036562f9
AA
334 mutex_lock(&sdata->sec_mtx);
335 res = mac802154_llsec_devkey_del(&sdata->sec, device_addr, key);
336 mutex_unlock(&sdata->sec_mtx);
29e02374
PB
337
338 return res;
339}
340
341
342int mac802154_add_seclevel(struct net_device *dev,
343 const struct ieee802154_llsec_seclevel *sl)
344{
59d19cd7 345 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
29e02374
PB
346 int res;
347
348 BUG_ON(dev->type != ARPHRD_IEEE802154);
349
036562f9
AA
350 mutex_lock(&sdata->sec_mtx);
351 res = mac802154_llsec_seclevel_add(&sdata->sec, sl);
352 mutex_unlock(&sdata->sec_mtx);
29e02374
PB
353
354 return res;
355}
356
357int mac802154_del_seclevel(struct net_device *dev,
358 const struct ieee802154_llsec_seclevel *sl)
359{
59d19cd7 360 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
29e02374
PB
361 int res;
362
363 BUG_ON(dev->type != ARPHRD_IEEE802154);
364
036562f9
AA
365 mutex_lock(&sdata->sec_mtx);
366 res = mac802154_llsec_seclevel_del(&sdata->sec, sl);
367 mutex_unlock(&sdata->sec_mtx);
29e02374
PB
368
369 return res;
370}
371
372
373void mac802154_lock_table(struct net_device *dev)
374{
59d19cd7 375 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
29e02374
PB
376
377 BUG_ON(dev->type != ARPHRD_IEEE802154);
378
036562f9 379 mutex_lock(&sdata->sec_mtx);
29e02374
PB
380}
381
382void mac802154_get_table(struct net_device *dev,
383 struct ieee802154_llsec_table **t)
384{
59d19cd7 385 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
29e02374
PB
386
387 BUG_ON(dev->type != ARPHRD_IEEE802154);
388
036562f9 389 *t = &sdata->sec.table;
29e02374
PB
390}
391
392void mac802154_unlock_table(struct net_device *dev)
393{
59d19cd7 394 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
29e02374
PB
395
396 BUG_ON(dev->type != ARPHRD_IEEE802154);
397
036562f9 398 mutex_unlock(&sdata->sec_mtx);
29e02374 399}
This page took 0.231264 seconds and 5 git commands to generate.