0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <net/rtnetlink.h>
0011 #include <net/cfg802154.h>
0012
0013 #include "ieee802154_i.h"
0014 #include "driver-ops.h"
0015 #include "cfg.h"
0016
0017 static struct net_device *
0018 ieee802154_add_iface_deprecated(struct wpan_phy *wpan_phy,
0019 const char *name,
0020 unsigned char name_assign_type, int type)
0021 {
0022 struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
0023 struct net_device *dev;
0024
0025 rtnl_lock();
0026 dev = ieee802154_if_add(local, name, name_assign_type, type,
0027 cpu_to_le64(0x0000000000000000ULL));
0028 rtnl_unlock();
0029
0030 return dev;
0031 }
0032
0033 static void ieee802154_del_iface_deprecated(struct wpan_phy *wpan_phy,
0034 struct net_device *dev)
0035 {
0036 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
0037
0038 ieee802154_if_remove(sdata);
0039 }
0040
0041 #ifdef CONFIG_PM
0042 static int ieee802154_suspend(struct wpan_phy *wpan_phy)
0043 {
0044 struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
0045
0046 if (!local->open_count)
0047 goto suspend;
0048
0049 ieee802154_stop_queue(&local->hw);
0050 synchronize_net();
0051
0052
0053 ieee802154_stop_device(local);
0054
0055 suspend:
0056 local->suspended = true;
0057 return 0;
0058 }
0059
0060 static int ieee802154_resume(struct wpan_phy *wpan_phy)
0061 {
0062 struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
0063 int ret;
0064
0065
0066 if (!local->open_count)
0067 goto wake_up;
0068
0069
0070 ret = drv_start(local);
0071 if (ret)
0072 return ret;
0073
0074 wake_up:
0075 ieee802154_wake_queue(&local->hw);
0076 local->suspended = false;
0077 return 0;
0078 }
0079 #else
0080 #define ieee802154_suspend NULL
0081 #define ieee802154_resume NULL
0082 #endif
0083
0084 static int
0085 ieee802154_add_iface(struct wpan_phy *phy, const char *name,
0086 unsigned char name_assign_type,
0087 enum nl802154_iftype type, __le64 extended_addr)
0088 {
0089 struct ieee802154_local *local = wpan_phy_priv(phy);
0090 struct net_device *err;
0091
0092 err = ieee802154_if_add(local, name, name_assign_type, type,
0093 extended_addr);
0094 return PTR_ERR_OR_ZERO(err);
0095 }
0096
0097 static int
0098 ieee802154_del_iface(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev)
0099 {
0100 ieee802154_if_remove(IEEE802154_WPAN_DEV_TO_SUB_IF(wpan_dev));
0101
0102 return 0;
0103 }
0104
0105 static int
0106 ieee802154_set_channel(struct wpan_phy *wpan_phy, u8 page, u8 channel)
0107 {
0108 struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
0109 int ret;
0110
0111 ASSERT_RTNL();
0112
0113 if (wpan_phy->current_page == page &&
0114 wpan_phy->current_channel == channel)
0115 return 0;
0116
0117 ret = drv_set_channel(local, page, channel);
0118 if (!ret) {
0119 wpan_phy->current_page = page;
0120 wpan_phy->current_channel = channel;
0121 ieee802154_configure_durations(wpan_phy);
0122 }
0123
0124 return ret;
0125 }
0126
0127 static int
0128 ieee802154_set_cca_mode(struct wpan_phy *wpan_phy,
0129 const struct wpan_phy_cca *cca)
0130 {
0131 struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
0132 int ret;
0133
0134 ASSERT_RTNL();
0135
0136 if (wpan_phy_cca_cmp(&wpan_phy->cca, cca))
0137 return 0;
0138
0139 ret = drv_set_cca_mode(local, cca);
0140 if (!ret)
0141 wpan_phy->cca = *cca;
0142
0143 return ret;
0144 }
0145
0146 static int
0147 ieee802154_set_cca_ed_level(struct wpan_phy *wpan_phy, s32 ed_level)
0148 {
0149 struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
0150 int ret;
0151
0152 ASSERT_RTNL();
0153
0154 if (wpan_phy->cca_ed_level == ed_level)
0155 return 0;
0156
0157 ret = drv_set_cca_ed_level(local, ed_level);
0158 if (!ret)
0159 wpan_phy->cca_ed_level = ed_level;
0160
0161 return ret;
0162 }
0163
0164 static int
0165 ieee802154_set_tx_power(struct wpan_phy *wpan_phy, s32 power)
0166 {
0167 struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
0168 int ret;
0169
0170 ASSERT_RTNL();
0171
0172 if (wpan_phy->transmit_power == power)
0173 return 0;
0174
0175 ret = drv_set_tx_power(local, power);
0176 if (!ret)
0177 wpan_phy->transmit_power = power;
0178
0179 return ret;
0180 }
0181
0182 static int
0183 ieee802154_set_pan_id(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
0184 __le16 pan_id)
0185 {
0186 int ret;
0187
0188 ASSERT_RTNL();
0189
0190 if (wpan_dev->pan_id == pan_id)
0191 return 0;
0192
0193 ret = mac802154_wpan_update_llsec(wpan_dev->netdev);
0194 if (!ret)
0195 wpan_dev->pan_id = pan_id;
0196
0197 return ret;
0198 }
0199
0200 static int
0201 ieee802154_set_backoff_exponent(struct wpan_phy *wpan_phy,
0202 struct wpan_dev *wpan_dev,
0203 u8 min_be, u8 max_be)
0204 {
0205 ASSERT_RTNL();
0206
0207 wpan_dev->min_be = min_be;
0208 wpan_dev->max_be = max_be;
0209 return 0;
0210 }
0211
0212 static int
0213 ieee802154_set_short_addr(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
0214 __le16 short_addr)
0215 {
0216 ASSERT_RTNL();
0217
0218 wpan_dev->short_addr = short_addr;
0219 return 0;
0220 }
0221
0222 static int
0223 ieee802154_set_max_csma_backoffs(struct wpan_phy *wpan_phy,
0224 struct wpan_dev *wpan_dev,
0225 u8 max_csma_backoffs)
0226 {
0227 ASSERT_RTNL();
0228
0229 wpan_dev->csma_retries = max_csma_backoffs;
0230 return 0;
0231 }
0232
0233 static int
0234 ieee802154_set_max_frame_retries(struct wpan_phy *wpan_phy,
0235 struct wpan_dev *wpan_dev,
0236 s8 max_frame_retries)
0237 {
0238 ASSERT_RTNL();
0239
0240 wpan_dev->frame_retries = max_frame_retries;
0241 return 0;
0242 }
0243
0244 static int
0245 ieee802154_set_lbt_mode(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
0246 bool mode)
0247 {
0248 ASSERT_RTNL();
0249
0250 wpan_dev->lbt = mode;
0251 return 0;
0252 }
0253
0254 static int
0255 ieee802154_set_ackreq_default(struct wpan_phy *wpan_phy,
0256 struct wpan_dev *wpan_dev, bool ackreq)
0257 {
0258 ASSERT_RTNL();
0259
0260 wpan_dev->ackreq = ackreq;
0261 return 0;
0262 }
0263
0264 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
0265 static void
0266 ieee802154_get_llsec_table(struct wpan_phy *wpan_phy,
0267 struct wpan_dev *wpan_dev,
0268 struct ieee802154_llsec_table **table)
0269 {
0270 struct net_device *dev = wpan_dev->netdev;
0271 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
0272
0273 *table = &sdata->sec.table;
0274 }
0275
0276 static void
0277 ieee802154_lock_llsec_table(struct wpan_phy *wpan_phy,
0278 struct wpan_dev *wpan_dev)
0279 {
0280 struct net_device *dev = wpan_dev->netdev;
0281 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
0282
0283 mutex_lock(&sdata->sec_mtx);
0284 }
0285
0286 static void
0287 ieee802154_unlock_llsec_table(struct wpan_phy *wpan_phy,
0288 struct wpan_dev *wpan_dev)
0289 {
0290 struct net_device *dev = wpan_dev->netdev;
0291 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
0292
0293 mutex_unlock(&sdata->sec_mtx);
0294 }
0295
0296 static int
0297 ieee802154_set_llsec_params(struct wpan_phy *wpan_phy,
0298 struct wpan_dev *wpan_dev,
0299 const struct ieee802154_llsec_params *params,
0300 int changed)
0301 {
0302 struct net_device *dev = wpan_dev->netdev;
0303 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
0304 int res;
0305
0306 mutex_lock(&sdata->sec_mtx);
0307 res = mac802154_llsec_set_params(&sdata->sec, params, changed);
0308 mutex_unlock(&sdata->sec_mtx);
0309
0310 return res;
0311 }
0312
0313 static int
0314 ieee802154_get_llsec_params(struct wpan_phy *wpan_phy,
0315 struct wpan_dev *wpan_dev,
0316 struct ieee802154_llsec_params *params)
0317 {
0318 struct net_device *dev = wpan_dev->netdev;
0319 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
0320 int res;
0321
0322 mutex_lock(&sdata->sec_mtx);
0323 res = mac802154_llsec_get_params(&sdata->sec, params);
0324 mutex_unlock(&sdata->sec_mtx);
0325
0326 return res;
0327 }
0328
0329 static int
0330 ieee802154_add_llsec_key(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
0331 const struct ieee802154_llsec_key_id *id,
0332 const struct ieee802154_llsec_key *key)
0333 {
0334 struct net_device *dev = wpan_dev->netdev;
0335 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
0336 int res;
0337
0338 mutex_lock(&sdata->sec_mtx);
0339 res = mac802154_llsec_key_add(&sdata->sec, id, key);
0340 mutex_unlock(&sdata->sec_mtx);
0341
0342 return res;
0343 }
0344
0345 static int
0346 ieee802154_del_llsec_key(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
0347 const struct ieee802154_llsec_key_id *id)
0348 {
0349 struct net_device *dev = wpan_dev->netdev;
0350 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
0351 int res;
0352
0353 mutex_lock(&sdata->sec_mtx);
0354 res = mac802154_llsec_key_del(&sdata->sec, id);
0355 mutex_unlock(&sdata->sec_mtx);
0356
0357 return res;
0358 }
0359
0360 static int
0361 ieee802154_add_seclevel(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
0362 const struct ieee802154_llsec_seclevel *sl)
0363 {
0364 struct net_device *dev = wpan_dev->netdev;
0365 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
0366 int res;
0367
0368 mutex_lock(&sdata->sec_mtx);
0369 res = mac802154_llsec_seclevel_add(&sdata->sec, sl);
0370 mutex_unlock(&sdata->sec_mtx);
0371
0372 return res;
0373 }
0374
0375 static int
0376 ieee802154_del_seclevel(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
0377 const struct ieee802154_llsec_seclevel *sl)
0378 {
0379 struct net_device *dev = wpan_dev->netdev;
0380 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
0381 int res;
0382
0383 mutex_lock(&sdata->sec_mtx);
0384 res = mac802154_llsec_seclevel_del(&sdata->sec, sl);
0385 mutex_unlock(&sdata->sec_mtx);
0386
0387 return res;
0388 }
0389
0390 static int
0391 ieee802154_add_device(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
0392 const struct ieee802154_llsec_device *dev_desc)
0393 {
0394 struct net_device *dev = wpan_dev->netdev;
0395 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
0396 int res;
0397
0398 mutex_lock(&sdata->sec_mtx);
0399 res = mac802154_llsec_dev_add(&sdata->sec, dev_desc);
0400 mutex_unlock(&sdata->sec_mtx);
0401
0402 return res;
0403 }
0404
0405 static int
0406 ieee802154_del_device(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
0407 __le64 extended_addr)
0408 {
0409 struct net_device *dev = wpan_dev->netdev;
0410 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
0411 int res;
0412
0413 mutex_lock(&sdata->sec_mtx);
0414 res = mac802154_llsec_dev_del(&sdata->sec, extended_addr);
0415 mutex_unlock(&sdata->sec_mtx);
0416
0417 return res;
0418 }
0419
0420 static int
0421 ieee802154_add_devkey(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
0422 __le64 extended_addr,
0423 const struct ieee802154_llsec_device_key *key)
0424 {
0425 struct net_device *dev = wpan_dev->netdev;
0426 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
0427 int res;
0428
0429 mutex_lock(&sdata->sec_mtx);
0430 res = mac802154_llsec_devkey_add(&sdata->sec, extended_addr, key);
0431 mutex_unlock(&sdata->sec_mtx);
0432
0433 return res;
0434 }
0435
0436 static int
0437 ieee802154_del_devkey(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
0438 __le64 extended_addr,
0439 const struct ieee802154_llsec_device_key *key)
0440 {
0441 struct net_device *dev = wpan_dev->netdev;
0442 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
0443 int res;
0444
0445 mutex_lock(&sdata->sec_mtx);
0446 res = mac802154_llsec_devkey_del(&sdata->sec, extended_addr, key);
0447 mutex_unlock(&sdata->sec_mtx);
0448
0449 return res;
0450 }
0451 #endif
0452
0453 const struct cfg802154_ops mac802154_config_ops = {
0454 .add_virtual_intf_deprecated = ieee802154_add_iface_deprecated,
0455 .del_virtual_intf_deprecated = ieee802154_del_iface_deprecated,
0456 .suspend = ieee802154_suspend,
0457 .resume = ieee802154_resume,
0458 .add_virtual_intf = ieee802154_add_iface,
0459 .del_virtual_intf = ieee802154_del_iface,
0460 .set_channel = ieee802154_set_channel,
0461 .set_cca_mode = ieee802154_set_cca_mode,
0462 .set_cca_ed_level = ieee802154_set_cca_ed_level,
0463 .set_tx_power = ieee802154_set_tx_power,
0464 .set_pan_id = ieee802154_set_pan_id,
0465 .set_short_addr = ieee802154_set_short_addr,
0466 .set_backoff_exponent = ieee802154_set_backoff_exponent,
0467 .set_max_csma_backoffs = ieee802154_set_max_csma_backoffs,
0468 .set_max_frame_retries = ieee802154_set_max_frame_retries,
0469 .set_lbt_mode = ieee802154_set_lbt_mode,
0470 .set_ackreq_default = ieee802154_set_ackreq_default,
0471 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
0472 .get_llsec_table = ieee802154_get_llsec_table,
0473 .lock_llsec_table = ieee802154_lock_llsec_table,
0474 .unlock_llsec_table = ieee802154_unlock_llsec_table,
0475
0476 .set_llsec_params = ieee802154_set_llsec_params,
0477 .get_llsec_params = ieee802154_get_llsec_params,
0478 .add_llsec_key = ieee802154_add_llsec_key,
0479 .del_llsec_key = ieee802154_del_llsec_key,
0480 .add_seclevel = ieee802154_add_seclevel,
0481 .del_seclevel = ieee802154_del_seclevel,
0482 .add_device = ieee802154_add_device,
0483 .del_device = ieee802154_del_device,
0484 .add_devkey = ieee802154_add_devkey,
0485 .del_devkey = ieee802154_del_devkey,
0486 #endif
0487 };