static int nl80211_set_pmk(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	struct cfg80211_pmk_conf pmk_conf = {};
	int ret;

	if (wdev->iftype != NL80211_IFTYPE_STATION &&
	    wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
		return -EOPNOTSUPP;

	if (!wiphy_ext_feature_isset(&rdev->wiphy,
				     NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
		return -EOPNOTSUPP;

	if (!info->attrs[NL80211_ATTR_MAC] || !info->attrs[NL80211_ATTR_PMK])
		return -EINVAL;

	wdev_lock(wdev);
	if (!wdev->current_bss) {
		ret = -ENOTCONN;
		goto out;
	}

	pmk_conf.aa = nla_data(info->attrs[NL80211_ATTR_MAC]);
	if (memcmp(pmk_conf.aa, wdev->current_bss->pub.bssid, ETH_ALEN)) {
		ret = -EINVAL;
		goto out;
	}

	pmk_conf.pmk = nla_data(info->attrs[NL80211_ATTR_PMK]);
	pmk_conf.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]);
	if (pmk_conf.pmk_len != WLAN_PMK_LEN &&
	    pmk_conf.pmk_len != WLAN_PMK_LEN_SUITE_B_192) {
		ret = -EINVAL;
		goto out;
	}

	if (info->attrs[NL80211_ATTR_PMKR0_NAME]) {
		int r0_name_len = nla_len(info->attrs[NL80211_ATTR_PMKR0_NAME]);

		if (r0_name_len != WLAN_PMK_NAME_LEN) {
			ret = -EINVAL;
			goto out;
		}

		pmk_conf.pmk_r0_name =
			nla_data(info->attrs[NL80211_ATTR_PMKR0_NAME]);
	}

	ret = rdev_set_pmk(rdev, dev, &pmk_conf);
out:
	wdev_unlock(wdev);
	return ret;
}
static int nl80211_set_pmk(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	struct cfg80211_pmk_conf pmk_conf = {};
	int ret;

	if (wdev->iftype != NL80211_IFTYPE_STATION &&
	    wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
		return -EOPNOTSUPP;

	if (!wiphy_ext_feature_isset(&rdev->wiphy,
				     NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
		return -EOPNOTSUPP;

	if (!info->attrs[NL80211_ATTR_MAC] || !info->attrs[NL80211_ATTR_PMK])
		return -EINVAL;

	wdev_lock(wdev);
	if (!wdev->current_bss) {
		ret = -ENOTCONN;
		goto out;
	}

	pmk_conf.aa = nla_data(info->attrs[NL80211_ATTR_MAC]);
	if (memcmp(pmk_conf.aa, wdev->current_bss->pub.bssid, ETH_ALEN)) {
		ret = -EINVAL;
		goto out;
	}

	pmk_conf.pmk = nla_data(info->attrs[NL80211_ATTR_PMK]);
	pmk_conf.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]);
	if (pmk_conf.pmk_len != WLAN_PMK_LEN &&
	    pmk_conf.pmk_len != WLAN_PMK_LEN_SUITE_B_192) {
		ret = -EINVAL;
		goto out;
	}

	if (info->attrs[NL80211_ATTR_PMKR0_NAME]) {
		int r0_name_len = nla_len(info->attrs[NL80211_ATTR_PMKR0_NAME]);

		if (r0_name_len != WLAN_PMK_NAME_LEN) {
			ret = -EINVAL;
			goto out;
		}

		pmk_conf.pmk_r0_name =
			nla_data(info->attrs[NL80211_ATTR_PMKR0_NAME]);
	}

	ret = rdev_set_pmk(rdev, dev, &pmk_conf);
out:
	wdev_unlock(wdev);
	return ret;
}