linux/net/mac802154/cfg.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *
   4 * Authors:
   5 * Alexander Aring <aar@pengutronix.de>
   6 *
   7 * Based on: net/mac80211/cfg.c
   8 */
   9
  10#include <net/rtnetlink.h>
  11#include <net/cfg802154.h>
  12
  13#include "ieee802154_i.h"
  14#include "driver-ops.h"
  15#include "cfg.h"
  16
  17static struct net_device *
  18ieee802154_add_iface_deprecated(struct wpan_phy *wpan_phy,
  19                                const char *name,
  20                                unsigned char name_assign_type, int type)
  21{
  22        struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
  23        struct net_device *dev;
  24
  25        rtnl_lock();
  26        dev = ieee802154_if_add(local, name, name_assign_type, type,
  27                                cpu_to_le64(0x0000000000000000ULL));
  28        rtnl_unlock();
  29
  30        return dev;
  31}
  32
  33static void ieee802154_del_iface_deprecated(struct wpan_phy *wpan_phy,
  34                                            struct net_device *dev)
  35{
  36        struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
  37
  38        ieee802154_if_remove(sdata);
  39}
  40
  41#ifdef CONFIG_PM
  42static int ieee802154_suspend(struct wpan_phy *wpan_phy)
  43{
  44        struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
  45
  46        if (!local->open_count)
  47                goto suspend;
  48
  49        ieee802154_stop_queue(&local->hw);
  50        synchronize_net();
  51
  52        /* stop hardware - this must stop RX */
  53        ieee802154_stop_device(local);
  54
  55suspend:
  56        local->suspended = true;
  57        return 0;
  58}
  59
  60static int ieee802154_resume(struct wpan_phy *wpan_phy)
  61{
  62        struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
  63        int ret;
  64
  65        /* nothing to do if HW shouldn't run */
  66        if (!local->open_count)
  67                goto wake_up;
  68
  69        /* restart hardware */
  70        ret = drv_start(local);
  71        if (ret)
  72                return ret;
  73
  74wake_up:
  75        ieee802154_wake_queue(&local->hw);
  76        local->suspended = false;
  77        return 0;
  78}
  79#else
  80#define ieee802154_suspend NULL
  81#define ieee802154_resume NULL
  82#endif
  83
  84static int
  85ieee802154_add_iface(struct wpan_phy *phy, const char *name,
  86                     unsigned char name_assign_type,
  87                     enum nl802154_iftype type, __le64 extended_addr)
  88{
  89        struct ieee802154_local *local = wpan_phy_priv(phy);
  90        struct net_device *err;
  91
  92        err = ieee802154_if_add(local, name, name_assign_type, type,
  93                                extended_addr);
  94        return PTR_ERR_OR_ZERO(err);
  95}
  96
  97static int
  98ieee802154_del_iface(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev)
  99{
 100        ieee802154_if_remove(IEEE802154_WPAN_DEV_TO_SUB_IF(wpan_dev));
 101
 102        return 0;
 103}
 104
 105static int
 106ieee802154_set_channel(struct wpan_phy *wpan_phy, u8 page, u8 channel)
 107{
 108        struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
 109        int ret;
 110
 111        ASSERT_RTNL();
 112
 113        if (wpan_phy->current_page == page &&
 114            wpan_phy->current_channel == channel)
 115                return 0;
 116
 117        ret = drv_set_channel(local, page, channel);
 118        if (!ret) {
 119                wpan_phy->current_page = page;
 120                wpan_phy->current_channel = channel;
 121        }
 122
 123        return ret;
 124}
 125
 126static int
 127ieee802154_set_cca_mode(struct wpan_phy *wpan_phy,
 128                        const struct wpan_phy_cca *cca)
 129{
 130        struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
 131        int ret;
 132
 133        ASSERT_RTNL();
 134
 135        if (wpan_phy_cca_cmp(&wpan_phy->cca, cca))
 136                return 0;
 137
 138        ret = drv_set_cca_mode(local, cca);
 139        if (!ret)
 140                wpan_phy->cca = *cca;
 141
 142        return ret;
 143}
 144
 145static int
 146ieee802154_set_cca_ed_level(struct wpan_phy *wpan_phy, s32 ed_level)
 147{
 148        struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
 149        int ret;
 150
 151        ASSERT_RTNL();
 152
 153        if (wpan_phy->cca_ed_level == ed_level)
 154                return 0;
 155
 156        ret = drv_set_cca_ed_level(local, ed_level);
 157        if (!ret)
 158                wpan_phy->cca_ed_level = ed_level;
 159
 160        return ret;
 161}
 162
 163static int
 164ieee802154_set_tx_power(struct wpan_phy *wpan_phy, s32 power)
 165{
 166        struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
 167        int ret;
 168
 169        ASSERT_RTNL();
 170
 171        if (wpan_phy->transmit_power == power)
 172                return 0;
 173
 174        ret = drv_set_tx_power(local, power);
 175        if (!ret)
 176                wpan_phy->transmit_power = power;
 177
 178        return ret;
 179}
 180
 181static int
 182ieee802154_set_pan_id(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
 183                      __le16 pan_id)
 184{
 185        int ret;
 186
 187        ASSERT_RTNL();
 188
 189        if (wpan_dev->pan_id == pan_id)
 190                return 0;
 191
 192        ret = mac802154_wpan_update_llsec(wpan_dev->netdev);
 193        if (!ret)
 194                wpan_dev->pan_id = pan_id;
 195
 196        return ret;
 197}
 198
 199static int
 200ieee802154_set_backoff_exponent(struct wpan_phy *wpan_phy,
 201                                struct wpan_dev *wpan_dev,
 202                                u8 min_be, u8 max_be)
 203{
 204        ASSERT_RTNL();
 205
 206        wpan_dev->min_be = min_be;
 207        wpan_dev->max_be = max_be;
 208        return 0;
 209}
 210
 211static int
 212ieee802154_set_short_addr(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
 213                          __le16 short_addr)
 214{
 215        ASSERT_RTNL();
 216
 217        wpan_dev->short_addr = short_addr;
 218        return 0;
 219}
 220
 221static int
 222ieee802154_set_max_csma_backoffs(struct wpan_phy *wpan_phy,
 223                                 struct wpan_dev *wpan_dev,
 224                                 u8 max_csma_backoffs)
 225{
 226        ASSERT_RTNL();
 227
 228        wpan_dev->csma_retries = max_csma_backoffs;
 229        return 0;
 230}
 231
 232static int
 233ieee802154_set_max_frame_retries(struct wpan_phy *wpan_phy,
 234                                 struct wpan_dev *wpan_dev,
 235                                 s8 max_frame_retries)
 236{
 237        ASSERT_RTNL();
 238
 239        wpan_dev->frame_retries = max_frame_retries;
 240        return 0;
 241}
 242
 243static int
 244ieee802154_set_lbt_mode(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
 245                        bool mode)
 246{
 247        ASSERT_RTNL();
 248
 249        wpan_dev->lbt = mode;
 250        return 0;
 251}
 252
 253static int
 254ieee802154_set_ackreq_default(struct wpan_phy *wpan_phy,
 255                              struct wpan_dev *wpan_dev, bool ackreq)
 256{
 257        ASSERT_RTNL();
 258
 259        wpan_dev->ackreq = ackreq;
 260        return 0;
 261}
 262
 263#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 264static void
 265ieee802154_get_llsec_table(struct wpan_phy *wpan_phy,
 266                           struct wpan_dev *wpan_dev,
 267                           struct ieee802154_llsec_table **table)
 268{
 269        struct net_device *dev = wpan_dev->netdev;
 270        struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
 271
 272        *table = &sdata->sec.table;
 273}
 274
 275static void
 276ieee802154_lock_llsec_table(struct wpan_phy *wpan_phy,
 277                            struct wpan_dev *wpan_dev)
 278{
 279        struct net_device *dev = wpan_dev->netdev;
 280        struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
 281
 282        mutex_lock(&sdata->sec_mtx);
 283}
 284
 285static void
 286ieee802154_unlock_llsec_table(struct wpan_phy *wpan_phy,
 287                              struct wpan_dev *wpan_dev)
 288{
 289        struct net_device *dev = wpan_dev->netdev;
 290        struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
 291
 292        mutex_unlock(&sdata->sec_mtx);
 293}
 294
 295static int
 296ieee802154_set_llsec_params(struct wpan_phy *wpan_phy,
 297                            struct wpan_dev *wpan_dev,
 298                            const struct ieee802154_llsec_params *params,
 299                            int changed)
 300{
 301        struct net_device *dev = wpan_dev->netdev;
 302        struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
 303        int res;
 304
 305        mutex_lock(&sdata->sec_mtx);
 306        res = mac802154_llsec_set_params(&sdata->sec, params, changed);
 307        mutex_unlock(&sdata->sec_mtx);
 308
 309        return res;
 310}
 311
 312static int
 313ieee802154_get_llsec_params(struct wpan_phy *wpan_phy,
 314                            struct wpan_dev *wpan_dev,
 315                            struct ieee802154_llsec_params *params)
 316{
 317        struct net_device *dev = wpan_dev->netdev;
 318        struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
 319        int res;
 320
 321        mutex_lock(&sdata->sec_mtx);
 322        res = mac802154_llsec_get_params(&sdata->sec, params);
 323        mutex_unlock(&sdata->sec_mtx);
 324
 325        return res;
 326}
 327
 328static int
 329ieee802154_add_llsec_key(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
 330                         const struct ieee802154_llsec_key_id *id,
 331                         const struct ieee802154_llsec_key *key)
 332{
 333        struct net_device *dev = wpan_dev->netdev;
 334        struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
 335        int res;
 336
 337        mutex_lock(&sdata->sec_mtx);
 338        res = mac802154_llsec_key_add(&sdata->sec, id, key);
 339        mutex_unlock(&sdata->sec_mtx);
 340
 341        return res;
 342}
 343
 344static int
 345ieee802154_del_llsec_key(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
 346                         const struct ieee802154_llsec_key_id *id)
 347{
 348        struct net_device *dev = wpan_dev->netdev;
 349        struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
 350        int res;
 351
 352        mutex_lock(&sdata->sec_mtx);
 353        res = mac802154_llsec_key_del(&sdata->sec, id);
 354        mutex_unlock(&sdata->sec_mtx);
 355
 356        return res;
 357}
 358
 359static int
 360ieee802154_add_seclevel(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
 361                        const struct ieee802154_llsec_seclevel *sl)
 362{
 363        struct net_device *dev = wpan_dev->netdev;
 364        struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
 365        int res;
 366
 367        mutex_lock(&sdata->sec_mtx);
 368        res = mac802154_llsec_seclevel_add(&sdata->sec, sl);
 369        mutex_unlock(&sdata->sec_mtx);
 370
 371        return res;
 372}
 373
 374static int
 375ieee802154_del_seclevel(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
 376                        const struct ieee802154_llsec_seclevel *sl)
 377{
 378        struct net_device *dev = wpan_dev->netdev;
 379        struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
 380        int res;
 381
 382        mutex_lock(&sdata->sec_mtx);
 383        res = mac802154_llsec_seclevel_del(&sdata->sec, sl);
 384        mutex_unlock(&sdata->sec_mtx);
 385
 386        return res;
 387}
 388
 389static int
 390ieee802154_add_device(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
 391                      const struct ieee802154_llsec_device *dev_desc)
 392{
 393        struct net_device *dev = wpan_dev->netdev;
 394        struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
 395        int res;
 396
 397        mutex_lock(&sdata->sec_mtx);
 398        res = mac802154_llsec_dev_add(&sdata->sec, dev_desc);
 399        mutex_unlock(&sdata->sec_mtx);
 400
 401        return res;
 402}
 403
 404static int
 405ieee802154_del_device(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
 406                      __le64 extended_addr)
 407{
 408        struct net_device *dev = wpan_dev->netdev;
 409        struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
 410        int res;
 411
 412        mutex_lock(&sdata->sec_mtx);
 413        res = mac802154_llsec_dev_del(&sdata->sec, extended_addr);
 414        mutex_unlock(&sdata->sec_mtx);
 415
 416        return res;
 417}
 418
 419static int
 420ieee802154_add_devkey(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
 421                      __le64 extended_addr,
 422                      const struct ieee802154_llsec_device_key *key)
 423{
 424        struct net_device *dev = wpan_dev->netdev;
 425        struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
 426        int res;
 427
 428        mutex_lock(&sdata->sec_mtx);
 429        res = mac802154_llsec_devkey_add(&sdata->sec, extended_addr, key);
 430        mutex_unlock(&sdata->sec_mtx);
 431
 432        return res;
 433}
 434
 435static int
 436ieee802154_del_devkey(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
 437                      __le64 extended_addr,
 438                      const struct ieee802154_llsec_device_key *key)
 439{
 440        struct net_device *dev = wpan_dev->netdev;
 441        struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
 442        int res;
 443
 444        mutex_lock(&sdata->sec_mtx);
 445        res = mac802154_llsec_devkey_del(&sdata->sec, extended_addr, key);
 446        mutex_unlock(&sdata->sec_mtx);
 447
 448        return res;
 449}
 450#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
 451
 452const struct cfg802154_ops mac802154_config_ops = {
 453        .add_virtual_intf_deprecated = ieee802154_add_iface_deprecated,
 454        .del_virtual_intf_deprecated = ieee802154_del_iface_deprecated,
 455        .suspend = ieee802154_suspend,
 456        .resume = ieee802154_resume,
 457        .add_virtual_intf = ieee802154_add_iface,
 458        .del_virtual_intf = ieee802154_del_iface,
 459        .set_channel = ieee802154_set_channel,
 460        .set_cca_mode = ieee802154_set_cca_mode,
 461        .set_cca_ed_level = ieee802154_set_cca_ed_level,
 462        .set_tx_power = ieee802154_set_tx_power,
 463        .set_pan_id = ieee802154_set_pan_id,
 464        .set_short_addr = ieee802154_set_short_addr,
 465        .set_backoff_exponent = ieee802154_set_backoff_exponent,
 466        .set_max_csma_backoffs = ieee802154_set_max_csma_backoffs,
 467        .set_max_frame_retries = ieee802154_set_max_frame_retries,
 468        .set_lbt_mode = ieee802154_set_lbt_mode,
 469        .set_ackreq_default = ieee802154_set_ackreq_default,
 470#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 471        .get_llsec_table = ieee802154_get_llsec_table,
 472        .lock_llsec_table = ieee802154_lock_llsec_table,
 473        .unlock_llsec_table = ieee802154_unlock_llsec_table,
 474        /* TODO above */
 475        .set_llsec_params = ieee802154_set_llsec_params,
 476        .get_llsec_params = ieee802154_get_llsec_params,
 477        .add_llsec_key = ieee802154_add_llsec_key,
 478        .del_llsec_key = ieee802154_del_llsec_key,
 479        .add_seclevel = ieee802154_add_seclevel,
 480        .del_seclevel = ieee802154_del_seclevel,
 481        .add_device = ieee802154_add_device,
 482        .del_device = ieee802154_del_device,
 483        .add_devkey = ieee802154_add_devkey,
 484        .del_devkey = ieee802154_del_devkey,
 485#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
 486};
 487