diff options
author | Jukka Rissanen <jukka.rissanen@linux.intel.com> | 2014-10-09 08:27:51 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2014-10-09 10:13:01 -0400 |
commit | e9ed49bf4c2c2bd4d57667f14d595864d7596ded (patch) | |
tree | c0e437c99c70f78ab3fb06e40162fe1b847dc4f6 | |
parent | 0f791eb47f8222fd594e6f8a090632344ef23924 (diff) |
mac80211-hwsim: Add support for HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE
Add support for new attribute HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE
which can be set by the user space component. The attribute
will cause the kernel to destroy all those radios that were
created by a process if that process dies. The old behaviour
i.e., radios are persistent is still the default.
Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r-- | drivers/net/wireless/mac80211_hwsim.c | 40 | ||||
-rw-r--r-- | drivers/net/wireless/mac80211_hwsim.h | 3 |
2 files changed, 40 insertions, 3 deletions
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index f1a0794b33f3..6ffe07323e6e 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -412,6 +412,9 @@ struct mac80211_hwsim_data { | |||
412 | struct mac_address addresses[2]; | 412 | struct mac_address addresses[2]; |
413 | int channels, idx; | 413 | int channels, idx; |
414 | bool use_chanctx; | 414 | bool use_chanctx; |
415 | bool destroy_on_close; | ||
416 | struct work_struct destroy_work; | ||
417 | u32 portid; | ||
415 | 418 | ||
416 | struct ieee80211_channel *tmp_chan; | 419 | struct ieee80211_channel *tmp_chan; |
417 | struct delayed_work roc_done; | 420 | struct delayed_work roc_done; |
@@ -496,6 +499,7 @@ static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { | |||
496 | [HWSIM_ATTR_REG_CUSTOM_REG] = { .type = NLA_U32 }, | 499 | [HWSIM_ATTR_REG_CUSTOM_REG] = { .type = NLA_U32 }, |
497 | [HWSIM_ATTR_REG_STRICT_REG] = { .type = NLA_FLAG }, | 500 | [HWSIM_ATTR_REG_STRICT_REG] = { .type = NLA_FLAG }, |
498 | [HWSIM_ATTR_SUPPORT_P2P_DEVICE] = { .type = NLA_FLAG }, | 501 | [HWSIM_ATTR_SUPPORT_P2P_DEVICE] = { .type = NLA_FLAG }, |
502 | [HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE] = { .type = NLA_FLAG }, | ||
499 | }; | 503 | }; |
500 | 504 | ||
501 | static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, | 505 | static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, |
@@ -1947,7 +1951,8 @@ static struct ieee80211_ops mac80211_hwsim_mchan_ops; | |||
1947 | static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | 1951 | static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, |
1948 | const struct ieee80211_regdomain *regd, | 1952 | const struct ieee80211_regdomain *regd, |
1949 | bool reg_strict, bool p2p_device, | 1953 | bool reg_strict, bool p2p_device, |
1950 | bool use_chanctx) | 1954 | bool use_chanctx, bool destroy_on_close, |
1955 | u32 portid) | ||
1951 | { | 1956 | { |
1952 | int err; | 1957 | int err; |
1953 | u8 addr[ETH_ALEN]; | 1958 | u8 addr[ETH_ALEN]; |
@@ -2007,6 +2012,8 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | |||
2007 | data->channels = channels; | 2012 | data->channels = channels; |
2008 | data->use_chanctx = use_chanctx; | 2013 | data->use_chanctx = use_chanctx; |
2009 | data->idx = idx; | 2014 | data->idx = idx; |
2015 | data->destroy_on_close = destroy_on_close; | ||
2016 | data->portid = portid; | ||
2010 | 2017 | ||
2011 | if (data->use_chanctx) { | 2018 | if (data->use_chanctx) { |
2012 | hw->wiphy->max_scan_ssids = 255; | 2019 | hw->wiphy->max_scan_ssids = 255; |
@@ -2434,6 +2441,7 @@ static int hwsim_create_radio_nl(struct sk_buff *msg, struct genl_info *info) | |||
2434 | const struct ieee80211_regdomain *regd = NULL; | 2441 | const struct ieee80211_regdomain *regd = NULL; |
2435 | bool reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG]; | 2442 | bool reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG]; |
2436 | bool p2p_device = info->attrs[HWSIM_ATTR_SUPPORT_P2P_DEVICE]; | 2443 | bool p2p_device = info->attrs[HWSIM_ATTR_SUPPORT_P2P_DEVICE]; |
2444 | bool destroy_on_close = info->attrs[HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE]; | ||
2437 | bool use_chanctx; | 2445 | bool use_chanctx; |
2438 | 2446 | ||
2439 | if (info->attrs[HWSIM_ATTR_CHANNELS]) | 2447 | if (info->attrs[HWSIM_ATTR_CHANNELS]) |
@@ -2456,7 +2464,8 @@ static int hwsim_create_radio_nl(struct sk_buff *msg, struct genl_info *info) | |||
2456 | } | 2464 | } |
2457 | 2465 | ||
2458 | return mac80211_hwsim_create_radio(chans, alpha2, regd, reg_strict, | 2466 | return mac80211_hwsim_create_radio(chans, alpha2, regd, reg_strict, |
2459 | p2p_device, use_chanctx); | 2467 | p2p_device, use_chanctx, |
2468 | destroy_on_close, info->snd_portid); | ||
2460 | } | 2469 | } |
2461 | 2470 | ||
2462 | static int hwsim_destroy_radio_nl(struct sk_buff *msg, struct genl_info *info) | 2471 | static int hwsim_destroy_radio_nl(struct sk_buff *msg, struct genl_info *info) |
@@ -2514,6 +2523,29 @@ static const struct genl_ops hwsim_ops[] = { | |||
2514 | }, | 2523 | }, |
2515 | }; | 2524 | }; |
2516 | 2525 | ||
2526 | static void destroy_radio(struct work_struct *work) | ||
2527 | { | ||
2528 | struct mac80211_hwsim_data *data = | ||
2529 | container_of(work, struct mac80211_hwsim_data, destroy_work); | ||
2530 | |||
2531 | mac80211_hwsim_destroy_radio(data); | ||
2532 | } | ||
2533 | |||
2534 | static void remove_user_radios(u32 portid) | ||
2535 | { | ||
2536 | struct mac80211_hwsim_data *entry, *tmp; | ||
2537 | |||
2538 | spin_lock_bh(&hwsim_radio_lock); | ||
2539 | list_for_each_entry_safe(entry, tmp, &hwsim_radios, list) { | ||
2540 | if (entry->destroy_on_close && entry->portid == portid) { | ||
2541 | list_del(&entry->list); | ||
2542 | INIT_WORK(&entry->destroy_work, destroy_radio); | ||
2543 | schedule_work(&entry->destroy_work); | ||
2544 | } | ||
2545 | } | ||
2546 | spin_unlock_bh(&hwsim_radio_lock); | ||
2547 | } | ||
2548 | |||
2517 | static int mac80211_hwsim_netlink_notify(struct notifier_block *nb, | 2549 | static int mac80211_hwsim_netlink_notify(struct notifier_block *nb, |
2518 | unsigned long state, | 2550 | unsigned long state, |
2519 | void *_notify) | 2551 | void *_notify) |
@@ -2523,6 +2555,8 @@ static int mac80211_hwsim_netlink_notify(struct notifier_block *nb, | |||
2523 | if (state != NETLINK_URELEASE) | 2555 | if (state != NETLINK_URELEASE) |
2524 | return NOTIFY_DONE; | 2556 | return NOTIFY_DONE; |
2525 | 2557 | ||
2558 | remove_user_radios(notify->portid); | ||
2559 | |||
2526 | if (notify->portid == wmediumd_portid) { | 2560 | if (notify->portid == wmediumd_portid) { |
2527 | printk(KERN_INFO "mac80211_hwsim: wmediumd released netlink" | 2561 | printk(KERN_INFO "mac80211_hwsim: wmediumd released netlink" |
2528 | " socket, switching to perfect channel medium\n"); | 2562 | " socket, switching to perfect channel medium\n"); |
@@ -2676,7 +2710,7 @@ static int __init init_mac80211_hwsim(void) | |||
2676 | err = mac80211_hwsim_create_radio(channels, reg_alpha2, | 2710 | err = mac80211_hwsim_create_radio(channels, reg_alpha2, |
2677 | regd, reg_strict, | 2711 | regd, reg_strict, |
2678 | support_p2p_device, | 2712 | support_p2p_device, |
2679 | channels > 1); | 2713 | channels > 1, false, 0); |
2680 | if (err < 0) | 2714 | if (err < 0) |
2681 | goto out_free_radios; | 2715 | goto out_free_radios; |
2682 | } | 2716 | } |
diff --git a/drivers/net/wireless/mac80211_hwsim.h b/drivers/net/wireless/mac80211_hwsim.h index c9d0315575ba..b96d8670a703 100644 --- a/drivers/net/wireless/mac80211_hwsim.h +++ b/drivers/net/wireless/mac80211_hwsim.h | |||
@@ -111,6 +111,8 @@ enum { | |||
111 | * @HWSIM_ATTR_USE_CHANCTX: used with the %HWSIM_CMD_CREATE_RADIO | 111 | * @HWSIM_ATTR_USE_CHANCTX: used with the %HWSIM_CMD_CREATE_RADIO |
112 | * command to force use of channel contexts even when only a | 112 | * command to force use of channel contexts even when only a |
113 | * single channel is supported | 113 | * single channel is supported |
114 | * @HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE: used with the %HWSIM_CMD_CREATE_RADIO | ||
115 | * command to force radio removal when process that created the radio dies | ||
114 | * @__HWSIM_ATTR_MAX: enum limit | 116 | * @__HWSIM_ATTR_MAX: enum limit |
115 | */ | 117 | */ |
116 | 118 | ||
@@ -132,6 +134,7 @@ enum { | |||
132 | HWSIM_ATTR_REG_STRICT_REG, | 134 | HWSIM_ATTR_REG_STRICT_REG, |
133 | HWSIM_ATTR_SUPPORT_P2P_DEVICE, | 135 | HWSIM_ATTR_SUPPORT_P2P_DEVICE, |
134 | HWSIM_ATTR_USE_CHANCTX, | 136 | HWSIM_ATTR_USE_CHANCTX, |
137 | HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE, | ||
135 | __HWSIM_ATTR_MAX, | 138 | __HWSIM_ATTR_MAX, |
136 | }; | 139 | }; |
137 | #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1) | 140 | #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1) |