Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *
0004  * Authors:
0005  * Alexander Aring <aar@pengutronix.de>
0006  *
0007  * Based on: net/mac80211/cfg.c
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     /* stop hardware - this must stop RX */
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     /* nothing to do if HW shouldn't run */
0066     if (!local->open_count)
0067         goto wake_up;
0068 
0069     /* restart hardware */
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 /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
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     /* TODO above */
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 /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
0487 };