diff --git a/drivers/net/wireless/iwl7000/iwlwifi/iwl-vendor-cmd.h b/drivers/net/wireless/iwl7000/iwlwifi/iwl-vendor-cmd.h index 6f30a866042b..86b7fb308b9f 100644 --- a/drivers/net/wireless/iwl7000/iwlwifi/iwl-vendor-cmd.h +++ b/drivers/net/wireless/iwl7000/iwlwifi/iwl-vendor-cmd.h @@ -135,6 +135,8 @@ * @IWL_MVM_VENDOR_CMD_GEO_SAR_GET_TABLE: retrieves the full GEO SAR table. * Contains a &IWL_MVM_VENDOR_ATTR_SAR_TABLE and a * &IWL_MVM_VENDOR_ATTR_GEO_SAR_VER attributes. + * @IWL_MVM_VENDOR_CMD_GET_FW_VERSION: Driver version + * @IWL_MVM_VENDOR_CMD_GET_FW_VERSION: Firmware version */ enum iwl_mvm_vendor_cmd { @@ -192,6 +194,8 @@ enum iwl_mvm_vendor_cmd { IWL_MVM_VENDOR_CMD_PPAG_GET_TABLE = 0x33, IWL_MVM_VENDOR_CMD_SAR_GET_TABLE = 0x34, IWL_MVM_VENDOR_CMD_GEO_SAR_GET_TABLE = 0x35, + IWL_MVM_VENDOR_CMD_GET_FW_VERSION = 0x36, + IWL_MVM_VENDOR_CMD_GET_DRV_VERSION = 0x37, }; /** @@ -895,10 +899,11 @@ enum iwl_vendor_sw_rfkill_state { * iwl_vendor_sar_per_chain_geo_table. * @IWL_MVM_VNDOR_ATTR_GEO_SAR_VER: u32 attribute. Contains the GEO SAR * table version + * @IWL_MVM_VENDOR_ATTR_DRV_VER: string attribute. Driver Version + * @IWL_MVM_VENDOR_ATTR_FW_VER: string attribute. Firmware Version * * @NUM_IWL_MVM_VENDOR_ATTR: number of vendor attributes * @MAX_IWL_MVM_VENDOR_ATTR: highest vendor attribute number - */ enum iwl_mvm_vendor_attr { __IWL_MVM_VENDOR_ATTR_INVALID = 0x00, @@ -1015,6 +1020,8 @@ enum iwl_mvm_vendor_attr { IWL_MVM_VENDOR_ATTR_SAR_VER = 0x75, IWL_MVM_VENDOR_ATTR_GEO_SAR_TABLE = 0x76, IWL_MVM_VENDOR_ATTR_GEO_SAR_VER = 0x77, + IWL_MVM_VENDOR_ATTR_FW_VER = 0x78, + IWL_MVM_VENDOR_ATTR_DRV_VER = 0x79, NUM_IWL_MVM_VENDOR_ATTR, MAX_IWL_MVM_VENDOR_ATTR = NUM_IWL_MVM_VENDOR_ATTR - 1, diff --git a/drivers/net/wireless/iwl7000/iwlwifi/mvm/Makefile b/drivers/net/wireless/iwl7000/iwlwifi/mvm/Makefile index 297fd32fc223..cec6b5518ed3 100644 --- a/drivers/net/wireless/iwl7000/iwlwifi/mvm/Makefile +++ b/drivers/net/wireless/iwl7000/iwlwifi/mvm/Makefile @@ -8,6 +8,7 @@ iwlmvm-y += tt.o offloading.o tdls.o iwlmvm-y += ftm-responder.o ftm-initiator.o iwlmvm-y += rfi.o iwlmvm-y += nan.o +iwlmvm-y += vendor-cmd.o iwlmvm-$(CPTCFG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o iwlmvm-$(CPTCFG_IWLWIFI_LEDS) += led.o iwlmvm-$(CONFIG_PM) += d3.o diff --git a/drivers/net/wireless/iwl7000/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwl7000/iwlwifi/mvm/mac80211.c index 71df3d75d29b..c9b5f775c1d7 100644 --- a/drivers/net/wireless/iwl7000/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwl7000/iwlwifi/mvm/mac80211.c @@ -899,6 +899,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *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); + iwl_mvm_set_wiphy_vendor_commands(hw->wiphy); + ret = ieee80211_register_hw(mvm->hw); if (ret) { #ifdef CPTCFG_IWLMVM_VENDOR_CMDS diff --git a/drivers/net/wireless/iwl7000/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwl7000/iwlwifi/mvm/mvm.h index c659f98f0c09..23799edbb25b 100644 --- a/drivers/net/wireless/iwl7000/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwl7000/iwlwifi/mvm/mvm.h @@ -2155,6 +2155,7 @@ void iwl_mvm_reorder_timer_expired(struct timer_list *t); struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm); struct ieee80211_vif *iwl_mvm_get_vif_by_macid(struct iwl_mvm *mvm, u32 macid); bool iwl_mvm_is_vif_assoc(struct iwl_mvm *mvm); +void iwl_mvm_set_wiphy_vendor_commands(struct wiphy *wiphy); #define MVM_TCM_PERIOD_MSEC 500 #define MVM_TCM_PERIOD (HZ * MVM_TCM_PERIOD_MSEC / 1000) diff --git a/drivers/net/wireless/iwl7000/iwlwifi/mvm/vendor-cmd.c b/drivers/net/wireless/iwl7000/iwlwifi/mvm/vendor-cmd.c index 54ad61507040..622f438fe18a 100644 --- a/drivers/net/wireless/iwl7000/iwlwifi/mvm/vendor-cmd.c +++ b/drivers/net/wireless/iwl7000/iwlwifi/mvm/vendor-cmd.c @@ -5,6 +5,8 @@ * Copyright (C) 2016-2017 Intel Deutschland GmbH */ #include +#include +#include #include #include #include "mvm.h" @@ -111,6 +113,8 @@ iwl_mvm_vendor_attr_policy[NUM_IWL_MVM_VENDOR_ATTR] = { [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 }, + [IWL_MVM_VENDOR_ATTR_FW_VER] = { .type = NLA_STRING, .len = 50 }, + [IWL_MVM_VENDOR_ATTR_DRV_VER] = { .type = NLA_STRING, .len = 50 }, }; static struct nlattr **iwl_mvm_parse_vendor_data(const void *data, int data_len) @@ -135,6 +139,57 @@ static struct nlattr **iwl_mvm_parse_vendor_data(const void *data, int data_len) return tb; } +static int iwl_mvm_vendor_get_fw_version(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int err = 0; + struct sk_buff *skb; + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + const struct iwl_fw *fw = mvm->fw; + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fw->fw_version)); + if (!skb) + return -ENOMEM; + if (nla_put_string(skb, IWL_MVM_VENDOR_ATTR_FW_VER, fw->fw_version)) { + kfree_skb(skb); + return -ENOBUFS; + } + + return cfg80211_vendor_cmd_reply(skb); +} + + +static int iwl_mvm_vendor_get_drv_version(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int err = 0; + struct sk_buff *skb; + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + const struct iwl_fw *fw = mvm->fw; + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(utsname()->release)); + if (!skb) + return -ENOMEM; + if (nla_put_string(skb, IWL_MVM_VENDOR_ATTR_DRV_VER, utsname()->release)) { + kfree_skb(skb); + return -ENOBUFS; + } + + return cfg80211_vendor_cmd_reply(skb); +} + +void iwl_mvm_set_wiphy_vendor_commands(struct wiphy *wiphy) +{ + wiphy->vendor_commands = iwl_mvm_vendor_commands; + wiphy->n_vendor_commands = ARRAY_SIZE(iwl_mvm_vendor_commands); + wiphy->vendor_events = NULL;; + wiphy->n_vendor_events = 0; +} + static int iwl_mvm_set_low_latency(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) @@ -1811,6 +1866,32 @@ static int iwl_mvm_vendor_set_sw_rfkill_state(struct wiphy *wiphy, } static const struct wiphy_vendor_command iwl_mvm_vendor_commands[] = { + { + .info = { + .vendor_id = INTEL_OUI, + .subcmd = IWL_MVM_VENDOR_CMD_GET_FW_VERSION, + }, + .flags = WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = iwl_mvm_vendor_get_fw_version, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,3,0) + .policy = iwl_mvm_vendor_attr_policy, + .maxattr = MAX_IWL_MVM_VENDOR_ATTR, +#endif + }, + { + .info = { + .vendor_id = INTEL_OUI, + .subcmd = IWL_MVM_VENDOR_CMD_GET_DRV_VERSION, + }, + .flags = WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = iwl_mvm_vendor_get_drv_version, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,3,0) + .policy = iwl_mvm_vendor_attr_policy, + .maxattr = MAX_IWL_MVM_VENDOR_ATTR, +#endif + }, { .info = { .vendor_id = INTEL_OUI,