blob: 0184fced2f62372aed120c8e248dfefa6079a53e [file] [log] [blame]
alex.bluesman.smirnov@gmail.comef2486f2012-05-15 20:50:26 +00001/*
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 *
alex.bluesman.smirnov@gmail.comef2486f2012-05-15 20:50:26 +000013 * 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>
Phoebe Buckheisterb70ab2e2014-03-14 21:23:59 +010023#include <net/ieee802154_netdev.h>
Alexander Aring5ad60d32014-10-25 09:41:02 +020024#include <net/cfg802154.h>
alex.bluesman.smirnov@gmail.comef2486f2012-05-15 20:50:26 +000025
Alexander Aring0f1556b2014-10-25 09:41:00 +020026#include "ieee802154_i.h"
Alexander Aring59cb3002014-10-28 18:21:21 +010027#include "driver-ops.h"
alex.bluesman.smirnov@gmail.comef2486f2012-05-15 20:50:26 +000028
29struct hw_addr_filt_notify_work {
30 struct work_struct work;
31 struct net_device *dev;
32 unsigned long changed;
33};
34
Alexander Aringa5e1ec52014-10-25 17:16:35 +020035static struct ieee802154_local *mac802154_slave_get_priv(struct net_device *dev)
alex.bluesman.smirnov@gmail.comef2486f2012-05-15 20:50:26 +000036{
Alexander Aring59d19cd2014-10-25 17:16:40 +020037 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
alex.bluesman.smirnov@gmail.comef2486f2012-05-15 20:50:26 +000038
39 BUG_ON(dev->type != ARPHRD_IEEE802154);
40
Alexander Aring04e850f2014-10-25 17:16:37 +020041 return sdata->local;
alex.bluesman.smirnov@gmail.comef2486f2012-05-15 20:50:26 +000042}
43
44static void hw_addr_notify(struct work_struct *work)
45{
46 struct hw_addr_filt_notify_work *nw = container_of(work,
47 struct hw_addr_filt_notify_work, work);
Alexander Aringa5e1ec52014-10-25 17:16:35 +020048 struct ieee802154_local *local = mac802154_slave_get_priv(nw->dev);
alex.bluesman.smirnov@gmail.comef2486f2012-05-15 20:50:26 +000049 int res;
50
Alexander Aringa5e1ec52014-10-25 17:16:35 +020051 res = local->ops->set_hw_addr_filt(&local->hw, &local->hw.hw_filt,
52 nw->changed);
alex.bluesman.smirnov@gmail.comef2486f2012-05-15 20:50:26 +000053 if (res)
54 pr_debug("failed changed mask %lx\n", nw->changed);
55
56 kfree(nw);
alex.bluesman.smirnov@gmail.comef2486f2012-05-15 20:50:26 +000057}
58
59static void set_hw_addr_filt(struct net_device *dev, unsigned long changed)
60{
Alexander Aring59d19cd2014-10-25 17:16:40 +020061 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
alex.bluesman.smirnov@gmail.comef2486f2012-05-15 20:50:26 +000062 struct hw_addr_filt_notify_work *work;
63
64 work = kzalloc(sizeof(*work), GFP_ATOMIC);
65 if (!work)
66 return;
67
68 INIT_WORK(&work->work, hw_addr_notify);
69 work->dev = dev;
70 work->changed = changed;
Alexander Aringf7730542014-10-25 17:16:41 +020071 queue_work(sdata->local->workqueue, &work->work);
alex.bluesman.smirnov@gmail.comef2486f2012-05-15 20:50:26 +000072}
73
Phoebe Buckheisterb70ab2e2014-03-14 21:23:59 +010074void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val)
alex.bluesman.smirnov@gmail.com48e44d52012-06-25 23:24:50 +000075{
Alexander Aring59d19cd2014-10-25 17:16:40 +020076 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
alex.bluesman.smirnov@gmail.com48e44d52012-06-25 23:24:50 +000077
78 BUG_ON(dev->type != ARPHRD_IEEE802154);
79
Alexander Aring036562f2014-10-25 17:16:36 +020080 spin_lock_bh(&sdata->mib_lock);
81 sdata->short_addr = val;
82 spin_unlock_bh(&sdata->mib_lock);
alex.bluesman.smirnov@gmail.com48e44d52012-06-25 23:24:50 +000083
Alexander Aring04e850f2014-10-25 17:16:37 +020084 if ((sdata->local->ops->set_hw_addr_filt) &&
85 (sdata->local->hw.hw_filt.short_addr != sdata->short_addr)) {
86 sdata->local->hw.hw_filt.short_addr = sdata->short_addr;
Alexander Aring57205c12014-10-25 05:25:09 +020087 set_hw_addr_filt(dev, IEEE802154_AFILT_SADDR_CHANGED);
alex.bluesman.smirnov@gmail.com48e44d52012-06-25 23:24:50 +000088 }
89}
90
Phoebe Buckheisterb70ab2e2014-03-14 21:23:59 +010091__le16 mac802154_dev_get_short_addr(const struct net_device *dev)
alex.bluesman.smirnov@gmail.come885a472012-07-10 21:22:44 +000092{
Alexander Aring59d19cd2014-10-25 17:16:40 +020093 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
Phoebe Buckheisterb70ab2e2014-03-14 21:23:59 +010094 __le16 ret;
alex.bluesman.smirnov@gmail.come885a472012-07-10 21:22:44 +000095
96 BUG_ON(dev->type != ARPHRD_IEEE802154);
97
Alexander Aring036562f2014-10-25 17:16:36 +020098 spin_lock_bh(&sdata->mib_lock);
99 ret = sdata->short_addr;
100 spin_unlock_bh(&sdata->mib_lock);
alex.bluesman.smirnov@gmail.come885a472012-07-10 21:22:44 +0000101
102 return ret;
103}
104
alex.bluesman.smirnov@gmail.comef2486f2012-05-15 20:50:26 +0000105void mac802154_dev_set_ieee_addr(struct net_device *dev)
106{
Alexander Aring59d19cd2014-10-25 17:16:40 +0200107 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
Alexander Aring04e850f2014-10-25 17:16:37 +0200108 struct ieee802154_local *local = sdata->local;
alex.bluesman.smirnov@gmail.comef2486f2012-05-15 20:50:26 +0000109
Alexander Aring036562f2014-10-25 17:16:36 +0200110 sdata->extended_addr = ieee802154_devaddr_from_raw(dev->dev_addr);
Phoebe Buckheisterb70ab2e2014-03-14 21:23:59 +0100111
Alexander Aringa5e1ec52014-10-25 17:16:35 +0200112 if (local->ops->set_hw_addr_filt &&
Alexander Aring036562f2014-10-25 17:16:36 +0200113 local->hw.hw_filt.ieee_addr != sdata->extended_addr) {
114 local->hw.hw_filt.ieee_addr = sdata->extended_addr;
Alexander Aring57205c12014-10-25 05:25:09 +0200115 set_hw_addr_filt(dev, IEEE802154_AFILT_IEEEADDR_CHANGED);
alex.bluesman.smirnov@gmail.comef2486f2012-05-15 20:50:26 +0000116 }
117}
alex.bluesman.smirnov@gmail.comdcbe4f92012-06-25 23:24:49 +0000118
Phoebe Buckheisterb70ab2e2014-03-14 21:23:59 +0100119__le16 mac802154_dev_get_pan_id(const struct net_device *dev)
alex.bluesman.smirnov@gmail.comdcbe4f92012-06-25 23:24:49 +0000120{
Alexander Aring59d19cd2014-10-25 17:16:40 +0200121 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
Phoebe Buckheisterb70ab2e2014-03-14 21:23:59 +0100122 __le16 ret;
alex.bluesman.smirnov@gmail.comdcbe4f92012-06-25 23:24:49 +0000123
124 BUG_ON(dev->type != ARPHRD_IEEE802154);
125
Alexander Aring036562f2014-10-25 17:16:36 +0200126 spin_lock_bh(&sdata->mib_lock);
127 ret = sdata->pan_id;
128 spin_unlock_bh(&sdata->mib_lock);
alex.bluesman.smirnov@gmail.comdcbe4f92012-06-25 23:24:49 +0000129
130 return ret;
131}
132
Phoebe Buckheisterb70ab2e2014-03-14 21:23:59 +0100133void mac802154_dev_set_pan_id(struct net_device *dev, __le16 val)
alex.bluesman.smirnov@gmail.comdcbe4f92012-06-25 23:24:49 +0000134{
Alexander Aring59d19cd2014-10-25 17:16:40 +0200135 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
alex.bluesman.smirnov@gmail.comdcbe4f92012-06-25 23:24:49 +0000136
137 BUG_ON(dev->type != ARPHRD_IEEE802154);
138
Alexander Aring036562f2014-10-25 17:16:36 +0200139 spin_lock_bh(&sdata->mib_lock);
140 sdata->pan_id = val;
141 spin_unlock_bh(&sdata->mib_lock);
alex.bluesman.smirnov@gmail.comdcbe4f92012-06-25 23:24:49 +0000142
Alexander Aring04e850f2014-10-25 17:16:37 +0200143 if ((sdata->local->ops->set_hw_addr_filt) &&
144 (sdata->local->hw.hw_filt.pan_id != sdata->pan_id)) {
145 sdata->local->hw.hw_filt.pan_id = sdata->pan_id;
Alexander Aring57205c12014-10-25 05:25:09 +0200146 set_hw_addr_filt(dev, IEEE802154_AFILT_PANID_CHANGED);
alex.bluesman.smirnov@gmail.comdcbe4f92012-06-25 23:24:49 +0000147 }
148}
alex.bluesman.smirnov@gmail.com66b69d42012-06-25 23:24:51 +0000149
Tony Cheneau04835462013-03-25 17:59:29 +0000150u8 mac802154_dev_get_dsn(const struct net_device *dev)
151{
Alexander Aring59d19cd2014-10-25 17:16:40 +0200152 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
Tony Cheneau04835462013-03-25 17:59:29 +0000153
154 BUG_ON(dev->type != ARPHRD_IEEE802154);
155
Alexander Aring036562f2014-10-25 17:16:36 +0200156 return sdata->dsn++;
Tony Cheneau04835462013-03-25 17:59:29 +0000157}
158
alex.bluesman.smirnov@gmail.com66b69d42012-06-25 23:24:51 +0000159void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan)
160{
Alexander Aring59d19cd2014-10-25 17:16:40 +0200161 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
Alexander Aring12439a52014-10-28 18:21:29 +0100162 struct ieee802154_local *local = sdata->local;
163 int res;
alex.bluesman.smirnov@gmail.com66b69d42012-06-25 23:24:51 +0000164
165 BUG_ON(dev->type != ARPHRD_IEEE802154);
166
Alexander Aring12439a52014-10-28 18:21:29 +0100167 res = drv_set_channel(local, page, chan);
168 if (res) {
169 pr_debug("set_channel failed\n");
Varka Bhadram4710d802014-07-02 09:01:09 +0530170 } else {
Alexander Aring12439a52014-10-28 18:21:29 +0100171 mutex_lock(&local->phy->pib_lock);
172 local->phy->current_channel = chan;
173 local->phy->current_page = page;
174 mutex_unlock(&local->phy->pib_lock);
Varka Bhadram4710d802014-07-02 09:01:09 +0530175 }
alex.bluesman.smirnov@gmail.com66b69d42012-06-25 23:24:51 +0000176}
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200177
178
179int mac802154_get_params(struct net_device *dev,
180 struct ieee802154_llsec_params *params)
181{
Alexander Aring59d19cd2014-10-25 17:16:40 +0200182 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200183 int res;
184
185 BUG_ON(dev->type != ARPHRD_IEEE802154);
186
Alexander Aring036562f2014-10-25 17:16:36 +0200187 mutex_lock(&sdata->sec_mtx);
188 res = mac802154_llsec_get_params(&sdata->sec, params);
189 mutex_unlock(&sdata->sec_mtx);
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200190
191 return res;
192}
193
194int mac802154_set_params(struct net_device *dev,
195 const struct ieee802154_llsec_params *params,
196 int changed)
197{
Alexander Aring59d19cd2014-10-25 17:16:40 +0200198 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200199 int res;
200
201 BUG_ON(dev->type != ARPHRD_IEEE802154);
202
Alexander Aring036562f2014-10-25 17:16:36 +0200203 mutex_lock(&sdata->sec_mtx);
204 res = mac802154_llsec_set_params(&sdata->sec, params, changed);
205 mutex_unlock(&sdata->sec_mtx);
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200206
207 return res;
208}
209
210
211int mac802154_add_key(struct net_device *dev,
212 const struct ieee802154_llsec_key_id *id,
213 const struct ieee802154_llsec_key *key)
214{
Alexander Aring59d19cd2014-10-25 17:16:40 +0200215 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200216 int res;
217
218 BUG_ON(dev->type != ARPHRD_IEEE802154);
219
Alexander Aring036562f2014-10-25 17:16:36 +0200220 mutex_lock(&sdata->sec_mtx);
221 res = mac802154_llsec_key_add(&sdata->sec, id, key);
222 mutex_unlock(&sdata->sec_mtx);
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200223
224 return res;
225}
226
227int mac802154_del_key(struct net_device *dev,
228 const struct ieee802154_llsec_key_id *id)
229{
Alexander Aring59d19cd2014-10-25 17:16:40 +0200230 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200231 int res;
232
233 BUG_ON(dev->type != ARPHRD_IEEE802154);
234
Alexander Aring036562f2014-10-25 17:16:36 +0200235 mutex_lock(&sdata->sec_mtx);
236 res = mac802154_llsec_key_del(&sdata->sec, id);
237 mutex_unlock(&sdata->sec_mtx);
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200238
239 return res;
240}
241
242
243int mac802154_add_dev(struct net_device *dev,
244 const struct ieee802154_llsec_device *llsec_dev)
245{
Alexander Aring59d19cd2014-10-25 17:16:40 +0200246 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200247 int res;
248
249 BUG_ON(dev->type != ARPHRD_IEEE802154);
250
Alexander Aring036562f2014-10-25 17:16:36 +0200251 mutex_lock(&sdata->sec_mtx);
252 res = mac802154_llsec_dev_add(&sdata->sec, llsec_dev);
253 mutex_unlock(&sdata->sec_mtx);
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200254
255 return res;
256}
257
258int mac802154_del_dev(struct net_device *dev, __le64 dev_addr)
259{
Alexander Aring59d19cd2014-10-25 17:16:40 +0200260 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200261 int res;
262
263 BUG_ON(dev->type != ARPHRD_IEEE802154);
264
Alexander Aring036562f2014-10-25 17:16:36 +0200265 mutex_lock(&sdata->sec_mtx);
266 res = mac802154_llsec_dev_del(&sdata->sec, dev_addr);
267 mutex_unlock(&sdata->sec_mtx);
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200268
269 return res;
270}
271
272
273int mac802154_add_devkey(struct net_device *dev,
274 __le64 device_addr,
275 const struct ieee802154_llsec_device_key *key)
276{
Alexander Aring59d19cd2014-10-25 17:16:40 +0200277 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200278 int res;
279
280 BUG_ON(dev->type != ARPHRD_IEEE802154);
281
Alexander Aring036562f2014-10-25 17:16:36 +0200282 mutex_lock(&sdata->sec_mtx);
283 res = mac802154_llsec_devkey_add(&sdata->sec, device_addr, key);
284 mutex_unlock(&sdata->sec_mtx);
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200285
286 return res;
287}
288
289int mac802154_del_devkey(struct net_device *dev,
290 __le64 device_addr,
291 const struct ieee802154_llsec_device_key *key)
292{
Alexander Aring59d19cd2014-10-25 17:16:40 +0200293 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200294 int res;
295
296 BUG_ON(dev->type != ARPHRD_IEEE802154);
297
Alexander Aring036562f2014-10-25 17:16:36 +0200298 mutex_lock(&sdata->sec_mtx);
299 res = mac802154_llsec_devkey_del(&sdata->sec, device_addr, key);
300 mutex_unlock(&sdata->sec_mtx);
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200301
302 return res;
303}
304
305
306int mac802154_add_seclevel(struct net_device *dev,
307 const struct ieee802154_llsec_seclevel *sl)
308{
Alexander Aring59d19cd2014-10-25 17:16:40 +0200309 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200310 int res;
311
312 BUG_ON(dev->type != ARPHRD_IEEE802154);
313
Alexander Aring036562f2014-10-25 17:16:36 +0200314 mutex_lock(&sdata->sec_mtx);
315 res = mac802154_llsec_seclevel_add(&sdata->sec, sl);
316 mutex_unlock(&sdata->sec_mtx);
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200317
318 return res;
319}
320
321int mac802154_del_seclevel(struct net_device *dev,
322 const struct ieee802154_llsec_seclevel *sl)
323{
Alexander Aring59d19cd2014-10-25 17:16:40 +0200324 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200325 int res;
326
327 BUG_ON(dev->type != ARPHRD_IEEE802154);
328
Alexander Aring036562f2014-10-25 17:16:36 +0200329 mutex_lock(&sdata->sec_mtx);
330 res = mac802154_llsec_seclevel_del(&sdata->sec, sl);
331 mutex_unlock(&sdata->sec_mtx);
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200332
333 return res;
334}
335
336
337void mac802154_lock_table(struct net_device *dev)
338{
Alexander Aring59d19cd2014-10-25 17:16:40 +0200339 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200340
341 BUG_ON(dev->type != ARPHRD_IEEE802154);
342
Alexander Aring036562f2014-10-25 17:16:36 +0200343 mutex_lock(&sdata->sec_mtx);
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200344}
345
346void mac802154_get_table(struct net_device *dev,
347 struct ieee802154_llsec_table **t)
348{
Alexander Aring59d19cd2014-10-25 17:16:40 +0200349 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200350
351 BUG_ON(dev->type != ARPHRD_IEEE802154);
352
Alexander Aring036562f2014-10-25 17:16:36 +0200353 *t = &sdata->sec.table;
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200354}
355
356void mac802154_unlock_table(struct net_device *dev)
357{
Alexander Aring59d19cd2014-10-25 17:16:40 +0200358 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200359
360 BUG_ON(dev->type != ARPHRD_IEEE802154);
361
Alexander Aring036562f2014-10-25 17:16:36 +0200362 mutex_unlock(&sdata->sec_mtx);
Phoebe Buckheister29e02372014-05-16 17:46:42 +0200363}