Skip to content

Commit

Permalink
iwlwifi: mvm: add vendor commands needed for iwlmei
Browse files Browse the repository at this point in the history
Add the vendor commands that must be used by the network manager
to allow proper operation of iwlmei.

* Send information on the AP CSME is connected to
* Notify the userspace when roaming is forbidden
* Allow the userspace to require ownership

Co-Developed-by: Ayala Beker <ayala.beker@intel.com>
Signed-off-by: Ayala Beker <ayala.beker@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>

v6: remove the VENDOR_CMDS Kconfig option and make the whole infra
    depend on IWLMEI directly
v7: remove // comments
    remove an unneeded function
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20211112062814.7502-5-emmanuel.grumbach@intel.com
  • Loading branch information
Emmanuel Grumbach authored and Kalle Valo committed Nov 26, 2021
1 parent 6d19a5e commit bfcfdb5
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 6 deletions.
1 change: 1 addition & 0 deletions drivers/net/wireless/intel/iwlwifi/mvm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ iwlmvm-y += rfi.o
iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o
iwlmvm-$(CONFIG_IWLWIFI_LEDS) += led.o
iwlmvm-$(CONFIG_PM) += d3.o
iwlmvm-$(CONFIG_IWLMEI) += vendor-cmd.o

ccflags-y += -I $(srctree)/$(src)/../
2 changes: 2 additions & 0 deletions drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
wiphy_ext_feature_set(hw->wiphy,
NL80211_EXT_FEATURE_PROTECTED_TWT);

iwl_mvm_vendor_cmds_register(mvm);

hw->wiphy->available_antennas_tx = iwl_mvm_get_valid_tx_ant(mvm);
hw->wiphy->available_antennas_rx = iwl_mvm_get_valid_rx_ant(mvm);

Expand Down
20 changes: 14 additions & 6 deletions drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1959,6 +1959,17 @@ void iwl_mvm_enter_ctkill(struct iwl_mvm *mvm);
int iwl_mvm_send_temp_report_ths_cmd(struct iwl_mvm *mvm);
int iwl_mvm_ctdp_command(struct iwl_mvm *mvm, u32 op, u32 budget);

#if IS_ENABLED(CONFIG_IWLMEI)

/* vendor commands */
void iwl_mvm_vendor_cmds_register(struct iwl_mvm *mvm);

#else

static inline void iwl_mvm_vendor_cmds_register(struct iwl_mvm *mvm) {}

#endif

/* Location Aware Regulatory */
struct iwl_mcc_update_resp *
iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
Expand Down Expand Up @@ -2213,11 +2224,8 @@ static inline void iwl_mvm_mei_set_sw_rfkill_state(struct iwl_mvm *mvm, bool sw_
iwl_mei_set_rfkill_state(iwl_mvm_is_radio_killed(mvm), sw_rfkill);
}

static inline void iwl_mvm_send_roaming_forbidden_event(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
bool forbidden)
{
/* TODO */
}
void iwl_mvm_send_roaming_forbidden_event(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
bool forbidden);

#endif /* __IWL_MVM_H__ */
151 changes: 151 additions & 0 deletions drivers/net/wireless/intel/iwlwifi/mvm/vendor-cmd.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2021 Intel Corporation
*/
#include "mvm.h"
#include <linux/nl80211-vnd-intel.h>

static const struct nla_policy
iwl_mvm_vendor_attr_policy[NUM_IWL_MVM_VENDOR_ATTR] = {
[IWL_MVM_VENDOR_ATTR_ROAMING_FORBIDDEN] = { .type = NLA_U8 },
[IWL_MVM_VENDOR_ATTR_AUTH_MODE] = { .type = NLA_U32 },
[IWL_MVM_VENDOR_ATTR_CHANNEL_NUM] = { .type = NLA_U8 },
[IWL_MVM_VENDOR_ATTR_SSID] = { .type = NLA_BINARY,
.len = IEEE80211_MAX_SSID_LEN },
[IWL_MVM_VENDOR_ATTR_BAND] = { .type = NLA_U8 },
[IWL_MVM_VENDOR_ATTR_COLLOC_CHANNEL] = { .type = NLA_U8 },
[IWL_MVM_VENDOR_ATTR_COLLOC_ADDR] = { .type = NLA_BINARY, .len = ETH_ALEN },
};

static int iwl_mvm_vendor_get_csme_conn_info(struct wiphy *wiphy,
struct wireless_dev *wdev,
const void *data, int data_len)
{
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_csme_conn_info *csme_conn_info;
struct sk_buff *skb;
int err = 0;

mutex_lock(&mvm->mutex);
csme_conn_info = iwl_mvm_get_csme_conn_info(mvm);

if (!csme_conn_info) {
err = -EINVAL;
goto out_unlock;
}

skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 200);
if (!skb) {
err = -ENOMEM;
goto out_unlock;
}

if (nla_put_u32(skb, IWL_MVM_VENDOR_ATTR_AUTH_MODE,
csme_conn_info->conn_info.auth_mode) ||
nla_put(skb, IWL_MVM_VENDOR_ATTR_SSID,
csme_conn_info->conn_info.ssid_len,
csme_conn_info->conn_info.ssid) ||
nla_put_u32(skb, IWL_MVM_VENDOR_ATTR_STA_CIPHER,
csme_conn_info->conn_info.pairwise_cipher) ||
nla_put_u8(skb, IWL_MVM_VENDOR_ATTR_CHANNEL_NUM,
csme_conn_info->conn_info.channel) ||
nla_put(skb, IWL_MVM_VENDOR_ATTR_ADDR, ETH_ALEN,
csme_conn_info->conn_info.bssid)) {
kfree_skb(skb);
err = -ENOBUFS;
}

out_unlock:
mutex_unlock(&mvm->mutex);
if (err)
return err;

return cfg80211_vendor_cmd_reply(skb);
}

static int iwl_mvm_vendor_host_get_ownership(struct wiphy *wiphy,
struct wireless_dev *wdev,
const void *data, int data_len)
{
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);

mutex_lock(&mvm->mutex);
iwl_mvm_mei_get_ownership(mvm);
mutex_unlock(&mvm->mutex);

return 0;
}

static const struct wiphy_vendor_command iwl_mvm_vendor_commands[] = {
{
.info = {
.vendor_id = INTEL_OUI,
.subcmd = IWL_MVM_VENDOR_CMD_GET_CSME_CONN_INFO,
},
.doit = iwl_mvm_vendor_get_csme_conn_info,
.flags = WIPHY_VENDOR_CMD_NEED_WDEV,
.policy = iwl_mvm_vendor_attr_policy,
.maxattr = MAX_IWL_MVM_VENDOR_ATTR,
},
{
.info = {
.vendor_id = INTEL_OUI,
.subcmd = IWL_MVM_VENDOR_CMD_HOST_GET_OWNERSHIP,
},
.doit = iwl_mvm_vendor_host_get_ownership,
.flags = WIPHY_VENDOR_CMD_NEED_WDEV,
.policy = iwl_mvm_vendor_attr_policy,
.maxattr = MAX_IWL_MVM_VENDOR_ATTR,
},
};

enum iwl_mvm_vendor_events_idx {
/* 0x0 - 0x3 are deprecated */
IWL_MVM_VENDOR_EVENT_IDX_ROAMING_FORBIDDEN = 4,
NUM_IWL_MVM_VENDOR_EVENT_IDX
};

static const struct nl80211_vendor_cmd_info
iwl_mvm_vendor_events[NUM_IWL_MVM_VENDOR_EVENT_IDX] = {
[IWL_MVM_VENDOR_EVENT_IDX_ROAMING_FORBIDDEN] = {
.vendor_id = INTEL_OUI,
.subcmd = IWL_MVM_VENDOR_CMD_ROAMING_FORBIDDEN_EVENT,
},
};

void iwl_mvm_vendor_cmds_register(struct iwl_mvm *mvm)
{
mvm->hw->wiphy->vendor_commands = iwl_mvm_vendor_commands;
mvm->hw->wiphy->n_vendor_commands = ARRAY_SIZE(iwl_mvm_vendor_commands);
mvm->hw->wiphy->vendor_events = iwl_mvm_vendor_events;
mvm->hw->wiphy->n_vendor_events = ARRAY_SIZE(iwl_mvm_vendor_events);
}

void iwl_mvm_send_roaming_forbidden_event(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
bool forbidden)
{
struct sk_buff *msg =
cfg80211_vendor_event_alloc(mvm->hw->wiphy,
ieee80211_vif_to_wdev(vif),
200, IWL_MVM_VENDOR_EVENT_IDX_ROAMING_FORBIDDEN,
GFP_ATOMIC);
if (!msg)
return;

if (WARN_ON(!vif))
return;

if (nla_put(msg, IWL_MVM_VENDOR_ATTR_VIF_ADDR,
ETH_ALEN, vif->addr) ||
nla_put_u8(msg, IWL_MVM_VENDOR_ATTR_ROAMING_FORBIDDEN, forbidden))
goto nla_put_failure;

cfg80211_vendor_event(msg, GFP_ATOMIC);
return;

nla_put_failure:
kfree_skb(msg);
}

0 comments on commit bfcfdb5

Please sign in to comment.