Commit 9b2777d6089bcd (ieee802154: add TX power control to wpan_phy) and following erroneously added CSMA and CCA parameters for 802.15.4 devices as PHY parameters, while they are actually MAC parameters and can differ for any two WPAN instances. Since it is now sensible to have multiple WPAN devices with differing CSMA/CCA parameters, make these parameters MAC parameters instead.
Unified · Split
| @@ -132,7 +132,7 @@ enum { · 131 unmodified lines | |||
| 132 | IEEE802154_ADD_IFACE, | 132 | IEEE802154_ADD_IFACE, |
| 133 | IEEE802154_DEL_IFACE, | 133 | IEEE802154_DEL_IFACE, |
| 134 | 134 | ||
| 135 | IEEE802154_SET_PHYPARAMS, | 135 | IEEE802154_SET_MACPARAMS, |
| 136 | 136 | ||
| 137 | __IEEE802154_CMD_MAX, | 137 | __IEEE802154_CMD_MAX, |
| 138 | }; | 138 | }; |
| @@ -229,6 +229,18 @@ static inline int mac_cb_type(struct sk_buff *skb) · 228 unmodified lines | |||
| 229 | #define IEEE802154_MAC_SCAN_PASSIVE 2 | 229 | #define IEEE802154_MAC_SCAN_PASSIVE 2 |
| 230 | #define IEEE802154_MAC_SCAN_ORPHAN 3 | 230 | #define IEEE802154_MAC_SCAN_ORPHAN 3 |
| 231 | 231 | ||
| 232 | struct ieee802154_mac_params { | ||
| 233 | s8 transmit_power; | ||
| 234 | u8 min_be; | ||
| 235 | u8 max_be; | ||
| 236 | u8 csma_retries; | ||
| 237 | s8 frame_retries; | ||
| 238 | |||
| 239 | bool lbt; | ||
| 240 | u8 cca_mode; | ||
| 241 | s32 cca_ed_level; | ||
| 242 | }; | ||
| 243 | |||
| 232 | struct wpan_phy; | 244 | struct wpan_phy; |
| 233 | /* | 245 | /* |
| 234 | * This should be located at net_device->ml_priv | 246 | * This should be located at net_device->ml_priv |
| @@ -255,6 +267,11 @@ struct ieee802154_mlme_ops { · 20 unmodified lines | |||
| 255 | int (*scan_req)(struct net_device *dev, | 267 | int (*scan_req)(struct net_device *dev, |
| 256 | u8 type, u32 channels, u8 page, u8 duration); | 268 | u8 type, u32 channels, u8 page, u8 duration); |
| 257 | 269 | ||
| 270 | int (*set_mac_params)(struct net_device *dev, | ||
| 271 | const struct ieee802154_mac_params *params); | ||
| 272 | void (*get_mac_params)(struct net_device *dev, | ||
| 273 | struct ieee802154_mac_params *params); | ||
| 274 | |||
| 258 | /* The fields below are required. */ | 275 | /* The fields below are required. */ |
| 259 | 276 | ||
| 260 | struct wpan_phy *(*get_phy)(const struct net_device *dev); | 277 | struct wpan_phy *(*get_phy)(const struct net_device *dev); |
| @@ -53,7 +53,6 @@ int ieee802154_list_phy(struct sk_buff *skb, struct genl_info *info); · 52 unmodified lines | |||
| 53 | int ieee802154_dump_phy(struct sk_buff *skb, struct netlink_callback *cb); | 53 | int ieee802154_dump_phy(struct sk_buff *skb, struct netlink_callback *cb); |
| 54 | int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info); | 54 | int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info); |
| 55 | int ieee802154_del_iface(struct sk_buff *skb, struct genl_info *info); | 55 | int ieee802154_del_iface(struct sk_buff *skb, struct genl_info *info); |
| 56 | int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info); | ||
| 57 | 56 | ||
| 58 | enum ieee802154_mcgrp_ids { | 57 | enum ieee802154_mcgrp_ids { |
| 59 | IEEE802154_COORD_MCGRP, | 58 | IEEE802154_COORD_MCGRP, |
| @@ -67,5 +66,6 @@ int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info); · 7 unmodified lines | |||
| 67 | int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info); | 66 | int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info); |
| 68 | int ieee802154_list_iface(struct sk_buff *skb, struct genl_info *info); | 67 | int ieee802154_list_iface(struct sk_buff *skb, struct genl_info *info); |
| 69 | int ieee802154_dump_iface(struct sk_buff *skb, struct netlink_callback *cb); | 68 | int ieee802154_dump_iface(struct sk_buff *skb, struct netlink_callback *cb); |
| 69 | int ieee802154_set_macparams(struct sk_buff *skb, struct genl_info *info); | ||
| 70 | 70 | ||
| 71 | #endif | 71 | #endif |
| @@ -115,7 +115,6 @@ static const struct genl_ops ieee8021154_ops[] = { · 114 unmodified lines | |||
| 115 | ieee802154_dump_phy), | 115 | ieee802154_dump_phy), |
| 116 | IEEE802154_OP(IEEE802154_ADD_IFACE, ieee802154_add_iface), | 116 | IEEE802154_OP(IEEE802154_ADD_IFACE, ieee802154_add_iface), |
| 117 | IEEE802154_OP(IEEE802154_DEL_IFACE, ieee802154_del_iface), | 117 | IEEE802154_OP(IEEE802154_DEL_IFACE, ieee802154_del_iface), |
| 118 | IEEE802154_OP(IEEE802154_SET_PHYPARAMS, ieee802154_set_phyparams), | ||
| 119 | /* see nl-mac.c */ | 118 | /* see nl-mac.c */ |
| 120 | IEEE802154_OP(IEEE802154_ASSOCIATE_REQ, ieee802154_associate_req), | 119 | IEEE802154_OP(IEEE802154_ASSOCIATE_REQ, ieee802154_associate_req), |
| 121 | IEEE802154_OP(IEEE802154_ASSOCIATE_RESP, ieee802154_associate_resp), | 120 | IEEE802154_OP(IEEE802154_ASSOCIATE_RESP, ieee802154_associate_resp), |
| @@ -124,6 +123,7 @@ static const struct genl_ops ieee8021154_ops[] = { · 2 unmodified lines | |||
| 124 | IEEE802154_OP(IEEE802154_START_REQ, ieee802154_start_req), | 123 | IEEE802154_OP(IEEE802154_START_REQ, ieee802154_start_req), |
| 125 | IEEE802154_DUMP(IEEE802154_LIST_IFACE, ieee802154_list_iface, | 124 | IEEE802154_DUMP(IEEE802154_LIST_IFACE, ieee802154_list_iface, |
| 126 | ieee802154_dump_iface), | 125 | ieee802154_dump_iface), |
| 126 | IEEE802154_OP(IEEE802154_SET_MACPARAMS, ieee802154_set_macparams), | ||
| 127 | }; | 127 | }; |
| 128 | 128 | ||
| 129 | static const struct genl_multicast_group ieee802154_mcgrps[] = { | 129 | static const struct genl_multicast_group ieee802154_mcgrps[] = { |
| @@ -264,6 +264,7 @@ static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid, · 263 unmodified lines | |||
| 264 | { | 264 | { |
| 265 | void *hdr; | 265 | void *hdr; |
| 266 | struct wpan_phy *phy; | 266 | struct wpan_phy *phy; |
| 267 | struct ieee802154_mlme_ops *ops; | ||
| 267 | __le16 short_addr, pan_id; | 268 | __le16 short_addr, pan_id; |
| 268 | 269 | ||
| 269 | pr_debug("%s\n", __func__); | 270 | pr_debug("%s\n", __func__); |
| @@ -273,11 +274,12 @@ static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid, · 3 unmodified lines | |||
| 273 | if (!hdr) | 274 | if (!hdr) |
| 274 | goto out; | 275 | goto out; |
| 275 | 276 | ||
| 276 | phy = ieee802154_mlme_ops(dev)->get_phy(dev); | 277 | ops = ieee802154_mlme_ops(dev); |
| 278 | phy = ops->get_phy(dev); | ||
| 277 | BUG_ON(!phy); | 279 | BUG_ON(!phy); |
| 278 | 280 | ||
| 279 | short_addr = ieee802154_mlme_ops(dev)->get_short_addr(dev); | 281 | short_addr = ops->get_short_addr(dev); |
| 280 | pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); | 282 | pan_id = ops->get_pan_id(dev); |
| 281 | 283 | ||
| 282 | if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || | 284 | if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || |
| 283 | nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) || | 285 | nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) || |
| @@ -287,6 +289,30 @@ static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid, · 3 unmodified lines | |||
| 287 | nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) || | 289 | nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) || |
| 288 | nla_put_shortaddr(msg, IEEE802154_ATTR_PAN_ID, pan_id)) | 290 | nla_put_shortaddr(msg, IEEE802154_ATTR_PAN_ID, pan_id)) |
| 289 | goto nla_put_failure; | 291 | goto nla_put_failure; |
| 292 | |||
| 293 | if (ops->get_mac_params) { | ||
| 294 | struct ieee802154_mac_params params; | ||
| 295 | |||
| 296 | ops->get_mac_params(dev, ¶ms); | ||
| 297 | |||
| 298 | if (nla_put_s8(msg, IEEE802154_ATTR_TXPOWER, | ||
| 299 | params.transmit_power) || | ||
| 300 | nla_put_u8(msg, IEEE802154_ATTR_LBT_ENABLED, params.lbt) || | ||
| 301 | nla_put_u8(msg, IEEE802154_ATTR_CCA_MODE, | ||
| 302 | params.cca_mode) || | ||
| 303 | nla_put_s32(msg, IEEE802154_ATTR_CCA_ED_LEVEL, | ||
| 304 | params.cca_ed_level) || | ||
| 305 | nla_put_u8(msg, IEEE802154_ATTR_CSMA_RETRIES, | ||
| 306 | params.csma_retries) || | ||
| 307 | nla_put_u8(msg, IEEE802154_ATTR_CSMA_MIN_BE, | ||
| 308 | params.min_be) || | ||
| 309 | nla_put_u8(msg, IEEE802154_ATTR_CSMA_MAX_BE, | ||
| 310 | params.max_be) || | ||
| 311 | nla_put_s8(msg, IEEE802154_ATTR_FRAME_RETRIES, | ||
| 312 | params.frame_retries)) | ||
| 313 | goto nla_put_failure; | ||
| 314 | } | ||
| 315 | |||
| 290 | wpan_phy_put(phy); | 316 | wpan_phy_put(phy); |
| 291 | return genlmsg_end(msg, hdr); | 317 | return genlmsg_end(msg, hdr); |
| 292 | 318 | ||
| @@ -599,3 +625,93 @@ cont: · 306 unmodified lines | |||
| 599 | 625 | ||
| 600 | return skb->len; | 626 | return skb->len; |
| 601 | } | 627 | } |
| 628 | |||
| 629 | int ieee802154_set_macparams(struct sk_buff *skb, struct genl_info *info) | ||
| 630 | { | ||
| 631 | struct net_device *dev = NULL; | ||
| 632 | struct ieee802154_mlme_ops *ops; | ||
| 633 | struct ieee802154_mac_params params; | ||
| 634 | struct wpan_phy *phy; | ||
| 635 | int rc = -EINVAL; | ||
| 636 | |||
| 637 | pr_debug("%s\n", __func__); | ||
| 638 | |||
| 639 | dev = ieee802154_nl_get_dev(info); | ||
| 640 | if (!dev) | ||
| 641 | return -ENODEV; | ||
| 642 | |||
| 643 | ops = ieee802154_mlme_ops(dev); | ||
| 644 | |||
| 645 | if (!ops->get_mac_params || !ops->set_mac_params) { | ||
| 646 | rc = -EOPNOTSUPP; | ||
| 647 | goto out; | ||
| 648 | } | ||
| 649 | |||
| 650 | if (netif_running(dev)) { | ||
| 651 | rc = -EBUSY; | ||
| 652 | goto out; | ||
| 653 | } | ||
| 654 | |||
| 655 | if (!info->attrs[IEEE802154_ATTR_LBT_ENABLED] && | ||
| 656 | !info->attrs[IEEE802154_ATTR_CCA_MODE] && | ||
| 657 | !info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL] && | ||
| 658 | !info->attrs[IEEE802154_ATTR_CSMA_RETRIES] && | ||
| 659 | !info->attrs[IEEE802154_ATTR_CSMA_MIN_BE] && | ||
| 660 | !info->attrs[IEEE802154_ATTR_CSMA_MAX_BE] && | ||
| 661 | !info->attrs[IEEE802154_ATTR_FRAME_RETRIES]) | ||
| 662 | goto out; | ||
| 663 | |||
| 664 | phy = ops->get_phy(dev); | ||
| 665 | |||
| 666 | if ((!phy->set_lbt && info->attrs[IEEE802154_ATTR_LBT_ENABLED]) || | ||
| 667 | (!phy->set_cca_mode && info->attrs[IEEE802154_ATTR_CCA_MODE]) || | ||
| 668 | (!phy->set_cca_ed_level && | ||
| 669 | info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]) || | ||
| 670 | (!phy->set_csma_params && | ||
| 671 | (info->attrs[IEEE802154_ATTR_CSMA_RETRIES] || | ||
| 672 | info->attrs[IEEE802154_ATTR_CSMA_MIN_BE] || | ||
| 673 | info->attrs[IEEE802154_ATTR_CSMA_MAX_BE])) || | ||
| 674 | (!phy->set_frame_retries && | ||
| 675 | info->attrs[IEEE802154_ATTR_FRAME_RETRIES])) { | ||
| 676 | rc = -EOPNOTSUPP; | ||
| 677 | goto out_phy; | ||
| 678 | } | ||
| 679 | |||
| 680 | ops->get_mac_params(dev, ¶ms); | ||
| 681 | |||
| 682 | if (info->attrs[IEEE802154_ATTR_TXPOWER]) | ||
| 683 | params.transmit_power = nla_get_s8(info->attrs[IEEE802154_ATTR_TXPOWER]); | ||
| 684 | |||
| 685 | if (info->attrs[IEEE802154_ATTR_LBT_ENABLED]) | ||
| 686 | params.lbt = nla_get_u8(info->attrs[IEEE802154_ATTR_LBT_ENABLED]); | ||
| 687 | |||
| 688 | if (info->attrs[IEEE802154_ATTR_CCA_MODE]) | ||
| 689 | params.cca_mode = nla_get_u8(info->attrs[IEEE802154_ATTR_CCA_MODE]); | ||
| 690 | |||
| 691 | if (info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]) | ||
| 692 | params.cca_ed_level = nla_get_s32(info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]); | ||
| 693 | |||
| 694 | if (info->attrs[IEEE802154_ATTR_CSMA_RETRIES]) | ||
| 695 | params.csma_retries = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_RETRIES]); | ||
| 696 | |||
| 697 | if (info->attrs[IEEE802154_ATTR_CSMA_MIN_BE]) | ||
| 698 | params.min_be = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_MIN_BE]); | ||
| 699 | |||
| 700 | if (info->attrs[IEEE802154_ATTR_CSMA_MAX_BE]) | ||
| 701 | params.max_be = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_MAX_BE]); | ||
| 702 | |||
| 703 | if (info->attrs[IEEE802154_ATTR_FRAME_RETRIES]) | ||
| 704 | params.frame_retries = nla_get_s8(info->attrs[IEEE802154_ATTR_FRAME_RETRIES]); | ||
| 705 | |||
| 706 | rc = ops->set_mac_params(dev, ¶ms); | ||
| 707 | |||
| 708 | wpan_phy_put(phy); | ||
| 709 | dev_put(dev); | ||
| 710 | return rc; | ||
| 711 | |||
| 712 | out_phy: | ||
| 713 | wpan_phy_put(phy); | ||
| 714 | out: | ||
| 715 | dev_put(dev); | ||
| 716 | return rc; | ||
| 717 | } | ||
| @@ -55,15 +55,7 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid, · 54 unmodified lines | |||
| 55 | mutex_lock(&phy->pib_lock); | 55 | mutex_lock(&phy->pib_lock); |
| 56 | if (nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) || | 56 | if (nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) || |
| 57 | nla_put_u8(msg, IEEE802154_ATTR_PAGE, phy->current_page) || | 57 | nla_put_u8(msg, IEEE802154_ATTR_PAGE, phy->current_page) || |
| 58 | nla_put_u8(msg, IEEE802154_ATTR_CHANNEL, phy->current_channel) || | 58 | nla_put_u8(msg, IEEE802154_ATTR_CHANNEL, phy->current_channel)) |
| 59 | nla_put_s8(msg, IEEE802154_ATTR_TXPOWER, phy->transmit_power) || | ||
| 60 | nla_put_u8(msg, IEEE802154_ATTR_LBT_ENABLED, phy->lbt) || | ||
| 61 | nla_put_u8(msg, IEEE802154_ATTR_CCA_MODE, phy->cca_mode) || | ||
| 62 | nla_put_s32(msg, IEEE802154_ATTR_CCA_ED_LEVEL, phy->cca_ed_level) || | ||
| 63 | nla_put_u8(msg, IEEE802154_ATTR_CSMA_RETRIES, phy->csma_retries) || | ||
| 64 | nla_put_u8(msg, IEEE802154_ATTR_CSMA_MIN_BE, phy->min_be) || | ||
| 65 | nla_put_u8(msg, IEEE802154_ATTR_CSMA_MAX_BE, phy->max_be) || | ||
| 66 | nla_put_s8(msg, IEEE802154_ATTR_FRAME_RETRIES, phy->frame_retries)) | ||
| 67 | goto nla_put_failure; | 59 | goto nla_put_failure; |
| 68 | for (i = 0; i < 32; i++) { | 60 | for (i = 0; i < 32; i++) { |
| 69 | if (phy->channels_supported[i]) | 61 | if (phy->channels_supported[i]) |
| @@ -362,193 +354,3 @@ out_dev: · 292 unmodified lines | |||
| 362 | 354 | ||
| 363 | return rc; | 355 | return rc; |
| 364 | } | 356 | } |
| 365 | |||
| 366 | static int phy_set_txpower(struct wpan_phy *phy, struct genl_info *info) | ||
| 367 | { | ||
| 368 | int txpower = nla_get_s8(info->attrs[IEEE802154_ATTR_TXPOWER]); | ||
| 369 | int rc; | ||
| 370 | |||
| 371 | rc = phy->set_txpower(phy, txpower); | ||
| 372 | if (rc < 0) | ||
| 373 | return rc; | ||
| 374 | |||
| 375 | phy->transmit_power = txpower; | ||
| 376 | |||
| 377 | return 0; | ||
| 378 | } | ||
| 379 | |||
| 380 | static int phy_set_lbt(struct wpan_phy *phy, struct genl_info *info) | ||
| 381 | { | ||
| 382 | u8 on = !!nla_get_u8(info->attrs[IEEE802154_ATTR_LBT_ENABLED]); | ||
| 383 | int rc; | ||
| 384 | |||
| 385 | rc = phy->set_lbt(phy, on); | ||
| 386 | if (rc < 0) | ||
| 387 | return rc; | ||
| 388 | |||
| 389 | phy->lbt = on; | ||
| 390 | |||
| 391 | return 0; | ||
| 392 | } | ||
| 393 | |||
| 394 | static int phy_set_cca_mode(struct wpan_phy *phy, struct genl_info *info) | ||
| 395 | { | ||
| 396 | u8 mode = nla_get_u8(info->attrs[IEEE802154_ATTR_CCA_MODE]); | ||
| 397 | int rc; | ||
| 398 | |||
| 399 | if (mode > 3) | ||
| 400 | return -EINVAL; | ||
| 401 | |||
| 402 | rc = phy->set_cca_mode(phy, mode); | ||
| 403 | if (rc < 0) | ||
| 404 | return rc; | ||
| 405 | |||
| 406 | phy->cca_mode = mode; | ||
| 407 | |||
| 408 | return 0; | ||
| 409 | } | ||
| 410 | |||
| 411 | static int phy_set_cca_ed_level(struct wpan_phy *phy, struct genl_info *info) | ||
| 412 | { | ||
| 413 | s32 level = nla_get_s32(info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]); | ||
| 414 | int rc; | ||
| 415 | |||
| 416 | rc = phy->set_cca_ed_level(phy, level); | ||
| 417 | if (rc < 0) | ||
| 418 | return rc; | ||
| 419 | |||
| 420 | phy->cca_ed_level = level; | ||
| 421 | |||
| 422 | return 0; | ||
| 423 | } | ||
| 424 | |||
| 425 | static int phy_set_csma_params(struct wpan_phy *phy, struct genl_info *info) | ||
| 426 | { | ||
| 427 | int rc; | ||
| 428 | u8 min_be = phy->min_be; | ||
| 429 | u8 max_be = phy->max_be; | ||
| 430 | u8 retries = phy->csma_retries; | ||
| 431 | |||
| 432 | if (info->attrs[IEEE802154_ATTR_CSMA_RETRIES]) | ||
| 433 | retries = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_RETRIES]); | ||
| 434 | if (info->attrs[IEEE802154_ATTR_CSMA_MIN_BE]) | ||
| 435 | min_be = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_MIN_BE]); | ||
| 436 | if (info->attrs[IEEE802154_ATTR_CSMA_MAX_BE]) | ||
| 437 | max_be = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_MAX_BE]); | ||
| 438 | |||
| 439 | if (retries > 5 || max_be < 3 || max_be > 8 || min_be > max_be) | ||
| 440 | return -EINVAL; | ||
| 441 | |||
| 442 | rc = phy->set_csma_params(phy, min_be, max_be, retries); | ||
| 443 | if (rc < 0) | ||
| 444 | return rc; | ||
| 445 | |||
| 446 | phy->min_be = min_be; | ||
| 447 | phy->max_be = max_be; | ||
| 448 | phy->csma_retries = retries; | ||
| 449 | |||
| 450 | return 0; | ||
| 451 | } | ||
| 452 | |||
| 453 | static int phy_set_frame_retries(struct wpan_phy *phy, struct genl_info *info) | ||
| 454 | { | ||
| 455 | s8 retries = nla_get_s8(info->attrs[IEEE802154_ATTR_FRAME_RETRIES]); | ||
| 456 | int rc; | ||
| 457 | |||
| 458 | if (retries < -1 || retries > 7) | ||
| 459 | return -EINVAL; | ||
| 460 | |||
| 461 | rc = phy->set_frame_retries(phy, retries); | ||
| 462 | if (rc < 0) | ||
| 463 | return rc; | ||
| 464 | |||
| 465 | phy->frame_retries = retries; | ||
| 466 | |||
| 467 | return 0; | ||
| 468 | } | ||
| 469 | |||
| 470 | int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info) | ||
| 471 | { | ||
| 472 | struct wpan_phy *phy; | ||
| 473 | const char *name; | ||
| 474 | int rc = -ENOTSUPP; | ||
| 475 | |||
| 476 | pr_debug("%s\n", __func__); | ||
| 477 | |||
| 478 | if (!info->attrs[IEEE802154_ATTR_PHY_NAME] && | ||
| 479 | !info->attrs[IEEE802154_ATTR_LBT_ENABLED] && | ||
| 480 | !info->attrs[IEEE802154_ATTR_CCA_MODE] && | ||
| 481 | !info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL] && | ||
| 482 | !info->attrs[IEEE802154_ATTR_CSMA_RETRIES] && | ||
| 483 | !info->attrs[IEEE802154_ATTR_CSMA_MIN_BE] && | ||
| 484 | !info->attrs[IEEE802154_ATTR_CSMA_MAX_BE] && | ||
| 485 | !info->attrs[IEEE802154_ATTR_FRAME_RETRIES]) | ||
| 486 | return -EINVAL; | ||
| 487 | |||
| 488 | name = nla_data(info->attrs[IEEE802154_ATTR_PHY_NAME]); | ||
| 489 | if (name[nla_len(info->attrs[IEEE802154_ATTR_PHY_NAME]) - 1] != '\0') | ||
| 490 | return -EINVAL; /* phy name should be null-terminated */ | ||
| 491 | |||
| 492 | phy = wpan_phy_find(name); | ||
| 493 | if (!phy) | ||
| 494 | return -ENODEV; | ||
| 495 | |||
| 496 | if ((!phy->set_txpower && info->attrs[IEEE802154_ATTR_TXPOWER]) || | ||
| 497 | (!phy->set_lbt && info->attrs[IEEE802154_ATTR_LBT_ENABLED]) || | ||
| 498 | (!phy->set_cca_mode && info->attrs[IEEE802154_ATTR_CCA_MODE]) || | ||
| 499 | (!phy->set_cca_ed_level && | ||
| 500 | info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL])) | ||
| 501 | goto out; | ||
| 502 | |||
| 503 | mutex_lock(&phy->pib_lock); | ||
| 504 | |||
| 505 | if (info->attrs[IEEE802154_ATTR_TXPOWER]) { | ||
| 506 | rc = phy_set_txpower(phy, info); | ||
| 507 | if (rc < 0) | ||
| 508 | goto error; | ||
| 509 | } | ||
| 510 | |||
| 511 | if (info->attrs[IEEE802154_ATTR_LBT_ENABLED]) { | ||
| 512 | rc = phy_set_lbt(phy, info); | ||
| 513 | if (rc < 0) | ||
| 514 | goto error; | ||
| 515 | } | ||
| 516 | |||
| 517 | if (info->attrs[IEEE802154_ATTR_CCA_MODE]) { | ||
| 518 | rc = phy_set_cca_mode(phy, info); | ||
| 519 | if (rc < 0) | ||
| 520 | goto error; | ||
| 521 | } | ||
| 522 | |||
| 523 | if (info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]) { | ||
| 524 | rc = phy_set_cca_ed_level(phy, info); | ||
| 525 | if (rc < 0) | ||
| 526 | goto error; | ||
| 527 | } | ||
| 528 | |||
| 529 | if (info->attrs[IEEE802154_ATTR_CSMA_RETRIES] || | ||
| 530 | info->attrs[IEEE802154_ATTR_CSMA_MIN_BE] || | ||
| 531 | info->attrs[IEEE802154_ATTR_CSMA_MAX_BE]) { | ||
| 532 | rc = phy_set_csma_params(phy, info); | ||
| 533 | if (rc < 0) | ||
| 534 | goto error; | ||
| 535 | } | ||
| 536 | |||
| 537 | if (info->attrs[IEEE802154_ATTR_FRAME_RETRIES]) { | ||
| 538 | rc = phy_set_frame_retries(phy, info); | ||
| 539 | if (rc < 0) | ||
| 540 | goto error; | ||
| 541 | } | ||
| 542 | |||
| 543 | mutex_unlock(&phy->pib_lock); | ||
| 544 | |||
| 545 | wpan_phy_put(phy); | ||
| 546 | |||
| 547 | return 0; | ||
| 548 | |||
| 549 | error: | ||
| 550 | mutex_unlock(&phy->pib_lock); | ||
| 551 | out: | ||
| 552 | wpan_phy_put(phy); | ||
| 553 | return rc; | ||
| 554 | } | ||
| @@ -169,12 +169,6 @@ struct wpan_phy *wpan_phy_alloc(size_t priv_size) · 168 unmodified lines | |||
| 169 | phy->current_channel = -1; /* not initialised */ | 169 | phy->current_channel = -1; /* not initialised */ |
| 170 | phy->current_page = 0; /* for compatibility */ | 170 | phy->current_page = 0; /* for compatibility */ |
| 171 | 171 | ||
| 172 | /* defaults per 802.15.4-2011 */ | ||
| 173 | phy->min_be = 3; | ||
| 174 | phy->max_be = 5; | ||
| 175 | phy->csma_retries = 4; | ||
| 176 | phy->frame_retries = -1; /* for compatibility, actual default is 3 */ | ||
| 177 | |||
| 178 | return phy; | 172 | return phy; |
| 179 | 173 | ||
| 180 | out: | 174 | out: |
| @@ -197,9 +197,6 @@ static int mac802154_set_txpower(struct wpan_phy *phy, int db) · 196 unmodified lines | |||
| 197 | { | 197 | { |
| 198 | struct mac802154_priv *priv = wpan_phy_priv(phy); | 198 | struct mac802154_priv *priv = wpan_phy_priv(phy); |
| 199 | 199 | ||
| 200 | if (!priv->ops->set_txpower) | ||
| 201 | return -ENOTSUPP; | ||
| 202 | |||
| 203 | return priv->ops->set_txpower(&priv->hw, db); | 200 | return priv->ops->set_txpower(&priv->hw, db); |
| 204 | } | 201 | } |
| 205 | 202 | ||
| @@ -207,9 +204,6 @@ static int mac802154_set_lbt(struct wpan_phy *phy, bool on) · 1 unmodified line | |||
| 207 | { | 204 | { |
| 208 | struct mac802154_priv *priv = wpan_phy_priv(phy); | 205 | struct mac802154_priv *priv = wpan_phy_priv(phy); |
| 209 | 206 | ||
| 210 | if (!priv->ops->set_lbt) | ||
| 211 | return -ENOTSUPP; | ||
| 212 | |||
| 213 | return priv->ops->set_lbt(&priv->hw, on); | 207 | return priv->ops->set_lbt(&priv->hw, on); |
| 214 | } | 208 | } |
| 215 | 209 | ||
| @@ -217,9 +211,6 @@ static int mac802154_set_cca_mode(struct wpan_phy *phy, u8 mode) · 1 unmodified line | |||
| 217 | { | 211 | { |
| 218 | struct mac802154_priv *priv = wpan_phy_priv(phy); | 212 | struct mac802154_priv *priv = wpan_phy_priv(phy); |
| 219 | 213 | ||
| 220 | if (!priv->ops->set_cca_mode) | ||
| 221 | return -ENOTSUPP; | ||
| 222 | |||
| 223 | return priv->ops->set_cca_mode(&priv->hw, mode); | 214 | return priv->ops->set_cca_mode(&priv->hw, mode); |
| 224 | } | 215 | } |
| 225 | 216 | ||
| @@ -227,9 +218,6 @@ static int mac802154_set_cca_ed_level(struct wpan_phy *phy, s32 level) · 1 unmodified line | |||
| 227 | { | 218 | { |
| 228 | struct mac802154_priv *priv = wpan_phy_priv(phy); | 219 | struct mac802154_priv *priv = wpan_phy_priv(phy); |
| 229 | 220 | ||
| 230 | if (!priv->ops->set_cca_ed_level) | ||
| 231 | return -ENOTSUPP; | ||
| 232 | |||
| 233 | return priv->ops->set_cca_ed_level(&priv->hw, level); | 221 | return priv->ops->set_cca_ed_level(&priv->hw, level); |
| 234 | } | 222 | } |
| 235 | 223 | ||
| @@ -238,9 +226,6 @@ static int mac802154_set_csma_params(struct wpan_phy *phy, u8 min_be, · 2 unmodified lines | |||
| 238 | { | 226 | { |
| 239 | struct mac802154_priv *priv = wpan_phy_priv(phy); | 227 | struct mac802154_priv *priv = wpan_phy_priv(phy); |
| 240 | 228 | ||
| 241 | if (!priv->ops->set_csma_params) | ||
| 242 | return -ENOTSUPP; | ||
| 243 | |||
| 244 | return priv->ops->set_csma_params(&priv->hw, min_be, max_be, retries); | 229 | return priv->ops->set_csma_params(&priv->hw, min_be, max_be, retries); |
| 245 | } | 230 | } |
| 246 | 231 | ||
| @@ -248,9 +233,6 @@ static int mac802154_set_frame_retries(struct wpan_phy *phy, s8 retries) · 1 unmodified line | |||
| 248 | { | 233 | { |
| 249 | struct mac802154_priv *priv = wpan_phy_priv(phy); | 234 | struct mac802154_priv *priv = wpan_phy_priv(phy); |
| 250 | 235 | ||
| 251 | if (!priv->ops->set_frame_retries) | ||
| 252 | return -ENOTSUPP; | ||
| 253 | |||
| 254 | return priv->ops->set_frame_retries(&priv->hw, retries); | 236 | return priv->ops->set_frame_retries(&priv->hw, retries); |
| 255 | } | 237 | } |
| 256 | 238 | ||
| @@ -331,12 +313,18 @@ int ieee802154_register_device(struct ieee802154_dev *dev) · 74 unmodified lines | |||
| 331 | 313 | ||
| 332 | priv->phy->add_iface = mac802154_add_iface; | 314 | priv->phy->add_iface = mac802154_add_iface; |
| 333 | priv->phy->del_iface = mac802154_del_iface; | 315 | priv->phy->del_iface = mac802154_del_iface; |
| 334 | priv->phy->set_txpower = mac802154_set_txpower; | 316 | if (priv->ops->set_txpower) |
| 335 | priv->phy->set_lbt = mac802154_set_lbt; | 317 | priv->phy->set_txpower = mac802154_set_txpower; |
| 336 | priv->phy->set_cca_mode = mac802154_set_cca_mode; | 318 | if (priv->ops->set_lbt) |
| 337 | priv->phy->set_cca_ed_level = mac802154_set_cca_ed_level; | 319 | priv->phy->set_lbt = mac802154_set_lbt; |
| 338 | priv->phy->set_csma_params = mac802154_set_csma_params; | 320 | if (priv->ops->set_cca_mode) |
| 339 | priv->phy->set_frame_retries = mac802154_set_frame_retries; | 321 | priv->phy->set_cca_mode = mac802154_set_cca_mode; |
| 322 | if (priv->ops->set_cca_ed_level) | ||
| 323 | priv->phy->set_cca_ed_level = mac802154_set_cca_ed_level; | ||
| 324 | if (priv->ops->set_csma_params) | ||
| 325 | priv->phy->set_csma_params = mac802154_set_csma_params; | ||
| 326 | if (priv->ops->set_frame_retries) | ||
| 327 | priv->phy->set_frame_retries = mac802154_set_frame_retries; | ||
| 340 | 328 | ||
| 341 | rc = wpan_phy_register(priv->phy); | 329 | rc = wpan_phy_register(priv->phy); |
| 342 | if (rc < 0) | 330 | if (rc < 0) |
| @@ -23,6 +23,8 @@ · 22 unmodified lines | |||
| 23 | #ifndef MAC802154_H | 23 | #ifndef MAC802154_H |
| 24 | #define MAC802154_H | 24 | #define MAC802154_H |
| 25 | 25 | ||
| 26 | #include <net/ieee802154_netdev.h> | ||
| 27 | |||
| 26 | /* mac802154 device private data */ | 28 | /* mac802154 device private data */ |
| 27 | struct mac802154_priv { | 29 | struct mac802154_priv { |
| 28 | struct ieee802154_dev hw; | 30 | struct ieee802154_dev hw; |
| @@ -82,6 +84,8 @@ struct mac802154_sub_if_data { · 53 unmodified lines | |||
| 82 | u8 chan; | 84 | u8 chan; |
| 83 | u8 page; | 85 | u8 page; |
| 84 | 86 | ||
| 87 | struct ieee802154_mac_params mac_params; | ||
| 88 | |||
| 85 | /* MAC BSN field */ | 89 | /* MAC BSN field */ |
| 86 | u8 bsn; | 90 | u8 bsn; |
| 87 | /* MAC DSN field */ | 91 | /* MAC DSN field */ |
| @@ -116,4 +120,9 @@ void mac802154_dev_set_pan_id(struct net_device *dev, __le16 val); · 28 unmodified lines | |||
| 116 | void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan); | 120 | void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan); |
| 117 | u8 mac802154_dev_get_dsn(const struct net_device *dev); | 121 | u8 mac802154_dev_get_dsn(const struct net_device *dev); |
| 118 | 122 | ||
| 123 | int mac802154_set_mac_params(struct net_device *dev, | ||
| 124 | const struct ieee802154_mac_params *params); | ||
| 125 | void mac802154_get_mac_params(struct net_device *dev, | ||
| 126 | struct ieee802154_mac_params *params); | ||
| 127 | |||
| 119 | #endif /* MAC802154_H */ | 128 | #endif /* MAC802154_H */ |
| @@ -74,4 +74,7 @@ struct ieee802154_mlme_ops mac802154_mlme_wpan = { · 73 unmodified lines | |||
| 74 | .get_pan_id = mac802154_dev_get_pan_id, | 74 | .get_pan_id = mac802154_dev_get_pan_id, |
| 75 | .get_short_addr = mac802154_dev_get_short_addr, | 75 | .get_short_addr = mac802154_dev_get_short_addr, |
| 76 | .get_dsn = mac802154_dev_get_dsn, | 76 | .get_dsn = mac802154_dev_get_dsn, |
| 77 | |||
| 78 | .set_mac_params = mac802154_set_mac_params, | ||
| 79 | .get_mac_params = mac802154_get_mac_params, | ||
| 77 | }; | 80 | }; |
| @@ -102,6 +102,87 @@ static int mac802154_wpan_mac_addr(struct net_device *dev, void *p) · 101 unmodified lines | |||
| 102 | return 0; | 102 | return 0; |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | int mac802154_set_mac_params(struct net_device *dev, | ||
| 106 | const struct ieee802154_mac_params *params) | ||
| 107 | { | ||
| 108 | struct mac802154_sub_if_data *priv = netdev_priv(dev); | ||
| 109 | |||
| 110 | mutex_lock(&priv->hw->slaves_mtx); | ||
| 111 | priv->mac_params = *params; | ||
| 112 | mutex_unlock(&priv->hw->slaves_mtx); | ||
| 113 | |||
| 114 | return 0; | ||
| 115 | } | ||
| 116 | |||
| 117 | void mac802154_get_mac_params(struct net_device *dev, | ||
| 118 | struct ieee802154_mac_params *params) | ||
| 119 | { | ||
| 120 | struct mac802154_sub_if_data *priv = netdev_priv(dev); | ||
| 121 | |||
| 122 | mutex_lock(&priv->hw->slaves_mtx); | ||
| 123 | *params = priv->mac_params; | ||
| 124 | mutex_unlock(&priv->hw->slaves_mtx); | ||
| 125 | } | ||
| 126 | |||
| 127 | int mac802154_wpan_open(struct net_device *dev) | ||
| 128 | { | ||
| 129 | int rc; | ||
| 130 | struct mac802154_sub_if_data *priv = netdev_priv(dev); | ||
| 131 | struct wpan_phy *phy = priv->hw->phy; | ||
| 132 | |||
| 133 | rc = mac802154_slave_open(dev); | ||
| 134 | if (rc < 0) | ||
| 135 | return rc; | ||
| 136 | |||
| 137 | mutex_lock(&phy->pib_lock); | ||
| 138 | |||
| 139 | if (phy->set_txpower) { | ||
| 140 | rc = phy->set_txpower(phy, priv->mac_params.transmit_power); | ||
| 141 | if (rc < 0) | ||
| 142 | goto out; | ||
| 143 | } | ||
| 144 | |||
| 145 | if (phy->set_lbt) { | ||
| 146 | rc = phy->set_lbt(phy, priv->mac_params.lbt); | ||
| 147 | if (rc < 0) | ||
| 148 | goto out; | ||
| 149 | } | ||
| 150 | |||
| 151 | if (phy->set_cca_mode) { | ||
| 152 | rc = phy->set_cca_mode(phy, priv->mac_params.cca_mode); | ||
| 153 | if (rc < 0) | ||
| 154 | goto out; | ||
| 155 | } | ||
| 156 | |||
| 157 | if (phy->set_cca_ed_level) { | ||
| 158 | rc = phy->set_cca_ed_level(phy, priv->mac_params.cca_ed_level); | ||
| 159 | if (rc < 0) | ||
| 160 | goto out; | ||
| 161 | } | ||
| 162 | |||
| 163 | if (phy->set_csma_params) { | ||
| 164 | rc = phy->set_csma_params(phy, priv->mac_params.min_be, | ||
| 165 | priv->mac_params.max_be, | ||
| 166 | priv->mac_params.csma_retries); | ||
| 167 | if (rc < 0) | ||
| 168 | goto out; | ||
| 169 | } | ||
| 170 | |||
| 171 | if (phy->set_frame_retries) { | ||
| 172 | rc = phy->set_frame_retries(phy, | ||
| 173 | priv->mac_params.frame_retries); | ||
| 174 | if (rc < 0) | ||
| 175 | goto out; | ||
| 176 | } | ||
| 177 | |||
| 178 | mutex_unlock(&phy->pib_lock); | ||
| 179 | return 0; | ||
| 180 | |||
| 181 | out: | ||
| 182 | mutex_unlock(&phy->pib_lock); | ||
| 183 | return rc; | ||
| 184 | } | ||
| 185 | |||
| 105 | static int mac802154_header_create(struct sk_buff *skb, | 186 | static int mac802154_header_create(struct sk_buff *skb, |
| 106 | struct net_device *dev, | 187 | struct net_device *dev, |
| 107 | unsigned short type, | 188 | unsigned short type, |
| @@ -204,7 +285,7 @@ static struct header_ops mac802154_header_ops = { · 96 unmodified lines | |||
| 204 | }; | 285 | }; |
| 205 | 286 | ||
| 206 | static const struct net_device_ops mac802154_wpan_ops = { | 287 | static const struct net_device_ops mac802154_wpan_ops = { |
| 207 | .ndo_open = mac802154_slave_open, | 288 | .ndo_open = mac802154_wpan_open, |
| 208 | .ndo_stop = mac802154_slave_close, | 289 | .ndo_stop = mac802154_slave_close, |
| 209 | .ndo_start_xmit = mac802154_wpan_xmit, | 290 | .ndo_start_xmit = mac802154_wpan_xmit, |
| 210 | .ndo_do_ioctl = mac802154_wpan_ioctl, | 291 | .ndo_do_ioctl = mac802154_wpan_ioctl, |
| @@ -242,6 +323,12 @@ void mac802154_wpan_setup(struct net_device *dev) · 31 unmodified lines | |||
| 242 | get_random_bytes(&priv->bsn, 1); | 323 | get_random_bytes(&priv->bsn, 1); |
| 243 | get_random_bytes(&priv->dsn, 1); | 324 | get_random_bytes(&priv->dsn, 1); |
| 244 | 325 | ||
| 326 | /* defaults per 802.15.4-2011 */ | ||
| 327 | priv->mac_params.min_be = 3; | ||
| 328 | priv->mac_params.max_be = 5; | ||
| 329 | priv->mac_params.csma_retries = 4; | ||
| 330 | priv->mac_params.frame_retries = -1; /* for compatibility, actual default is 3 */ | ||
| 331 | |||
| 245 | priv->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST); | 332 | priv->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST); |
| 246 | priv->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST); | 333 | priv->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST); |
| 247 | } | 334 | } |