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