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 int mac802154_get_params(struct net_device *dev, 219 struct ieee802154_llsec_params *params) 220 { 221 struct mac802154_sub_if_data *priv = netdev_priv(dev); 222 int res; 223 224 BUG_ON(dev->type != ARPHRD_IEEE802154); 225 226 mutex_lock(&priv->sec_mtx); 227 res = mac802154_llsec_get_params(&priv->sec, params); 228 mutex_unlock(&priv->sec_mtx); 229 230 return res; 231 } 232 233 int mac802154_set_params(struct net_device *dev, 234 const struct ieee802154_llsec_params *params, 235 int changed) 236 { 237 struct mac802154_sub_if_data *priv = netdev_priv(dev); 238 int res; 239 240 BUG_ON(dev->type != ARPHRD_IEEE802154); 241 242 mutex_lock(&priv->sec_mtx); 243 res = mac802154_llsec_set_params(&priv->sec, params, changed); 244 mutex_unlock(&priv->sec_mtx); 245 246 return res; 247 } 248 249 250 int mac802154_add_key(struct net_device *dev, 251 const struct ieee802154_llsec_key_id *id, 252 const struct ieee802154_llsec_key *key) 253 { 254 struct mac802154_sub_if_data *priv = netdev_priv(dev); 255 int res; 256 257 BUG_ON(dev->type != ARPHRD_IEEE802154); 258 259 mutex_lock(&priv->sec_mtx); 260 res = mac802154_llsec_key_add(&priv->sec, id, key); 261 mutex_unlock(&priv->sec_mtx); 262 263 return res; 264 } 265 266 int mac802154_del_key(struct net_device *dev, 267 const struct ieee802154_llsec_key_id *id) 268 { 269 struct mac802154_sub_if_data *priv = netdev_priv(dev); 270 int res; 271 272 BUG_ON(dev->type != ARPHRD_IEEE802154); 273 274 mutex_lock(&priv->sec_mtx); 275 res = mac802154_llsec_key_del(&priv->sec, id); 276 mutex_unlock(&priv->sec_mtx); 277 278 return res; 279 } 280 281 282 int mac802154_add_dev(struct net_device *dev, 283 const struct ieee802154_llsec_device *llsec_dev) 284 { 285 struct mac802154_sub_if_data *priv = netdev_priv(dev); 286 int res; 287 288 BUG_ON(dev->type != ARPHRD_IEEE802154); 289 290 mutex_lock(&priv->sec_mtx); 291 res = mac802154_llsec_dev_add(&priv->sec, llsec_dev); 292 mutex_unlock(&priv->sec_mtx); 293 294 return res; 295 } 296 297 int mac802154_del_dev(struct net_device *dev, __le64 dev_addr) 298 { 299 struct mac802154_sub_if_data *priv = netdev_priv(dev); 300 int res; 301 302 BUG_ON(dev->type != ARPHRD_IEEE802154); 303 304 mutex_lock(&priv->sec_mtx); 305 res = mac802154_llsec_dev_del(&priv->sec, dev_addr); 306 mutex_unlock(&priv->sec_mtx); 307 308 return res; 309 } 310 311 312 int mac802154_add_devkey(struct net_device *dev, 313 __le64 device_addr, 314 const struct ieee802154_llsec_device_key *key) 315 { 316 struct mac802154_sub_if_data *priv = netdev_priv(dev); 317 int res; 318 319 BUG_ON(dev->type != ARPHRD_IEEE802154); 320 321 mutex_lock(&priv->sec_mtx); 322 res = mac802154_llsec_devkey_add(&priv->sec, device_addr, key); 323 mutex_unlock(&priv->sec_mtx); 324 325 return res; 326 } 327 328 int mac802154_del_devkey(struct net_device *dev, 329 __le64 device_addr, 330 const struct ieee802154_llsec_device_key *key) 331 { 332 struct mac802154_sub_if_data *priv = netdev_priv(dev); 333 int res; 334 335 BUG_ON(dev->type != ARPHRD_IEEE802154); 336 337 mutex_lock(&priv->sec_mtx); 338 res = mac802154_llsec_devkey_del(&priv->sec, device_addr, key); 339 mutex_unlock(&priv->sec_mtx); 340 341 return res; 342 } 343 344 345 int mac802154_add_seclevel(struct net_device *dev, 346 const struct ieee802154_llsec_seclevel *sl) 347 { 348 struct mac802154_sub_if_data *priv = netdev_priv(dev); 349 int res; 350 351 BUG_ON(dev->type != ARPHRD_IEEE802154); 352 353 mutex_lock(&priv->sec_mtx); 354 res = mac802154_llsec_seclevel_add(&priv->sec, sl); 355 mutex_unlock(&priv->sec_mtx); 356 357 return res; 358 } 359 360 int mac802154_del_seclevel(struct net_device *dev, 361 const struct ieee802154_llsec_seclevel *sl) 362 { 363 struct mac802154_sub_if_data *priv = netdev_priv(dev); 364 int res; 365 366 BUG_ON(dev->type != ARPHRD_IEEE802154); 367 368 mutex_lock(&priv->sec_mtx); 369 res = mac802154_llsec_seclevel_del(&priv->sec, sl); 370 mutex_unlock(&priv->sec_mtx); 371 372 return res; 373 } 374 375 376 void mac802154_lock_table(struct net_device *dev) 377 { 378 struct mac802154_sub_if_data *priv = netdev_priv(dev); 379 380 BUG_ON(dev->type != ARPHRD_IEEE802154); 381 382 mutex_lock(&priv->sec_mtx); 383 } 384 385 void mac802154_get_table(struct net_device *dev, 386 struct ieee802154_llsec_table **t) 387 { 388 struct mac802154_sub_if_data *priv = netdev_priv(dev); 389 390 BUG_ON(dev->type != ARPHRD_IEEE802154); 391 392 *t = &priv->sec.table; 393 } 394 395 void mac802154_unlock_table(struct net_device *dev) 396 { 397 struct mac802154_sub_if_data *priv = netdev_priv(dev); 398 399 BUG_ON(dev->type != ARPHRD_IEEE802154); 400 401 mutex_unlock(&priv->sec_mtx); 402 } 403