aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorLuciano Coelho <luciano.coelho@intel.com>2014-11-21 02:32:23 -0500
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2014-12-01 05:04:42 -0500
commitd9718da82f595eeac0cd42d849f7c3adc02da5e3 (patch)
treeb6827feb0968b338123c648b1b2f06969cde712d /drivers/net
parent804d4c5a811c616a111938bd04b41df83a753c74 (diff)
iwlwifi: mvm: add SSID match information for net-detect
Add SSID information to the net-detect indication to userspace. Fetch the matched profiles from the firmware in order to find the correct SSIDs in the profiles that matched. Since the net-detect information is stored in cfg80211, and in theory it could change while we are waking up and reading the matched profiles, we need to save it when we enter D3 so it is available during resume. Signed-off-by: Luciano Coelho <luciano.coelho@intel.com> Reviewed-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/d3.c71
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h2
2 files changed, 68 insertions, 5 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c
index c7297c581488..c20d8de40fcd 100644
--- a/drivers/net/wireless/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/iwlwifi/mvm/d3.c
@@ -979,8 +979,30 @@ iwl_mvm_netdetect_config(struct iwl_mvm *mvm,
979 return ret; 979 return ret;
980 980
981 ret = iwl_mvm_scan_offload_start(mvm, vif, nd_config, &mvm->nd_ies); 981 ret = iwl_mvm_scan_offload_start(mvm, vif, nd_config, &mvm->nd_ies);
982 if (ret)
983 return ret;
982 984
983 return ret; 985 if (WARN_ON(mvm->nd_match_sets))
986 return -EBUSY;
987
988 /* save the sched scan matchsets for later reporting */
989 if (nd_config->n_match_sets) {
990 mvm->nd_match_sets = kmemdup(nd_config->match_sets,
991 sizeof(*nd_config->match_sets) *
992 nd_config->n_match_sets,
993 GFP_KERNEL);
994 if (mvm->nd_match_sets)
995 mvm->n_nd_match_sets = nd_config->n_match_sets;
996 }
997
998 return 0;
999}
1000
1001static void iwl_mvm_free_nd(struct iwl_mvm *mvm)
1002{
1003 kfree(mvm->nd_match_sets);
1004 mvm->nd_match_sets = NULL;
1005 mvm->n_nd_match_sets = 0;
984} 1006}
985 1007
986static int __iwl_mvm_suspend(struct ieee80211_hw *hw, 1008static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
@@ -1094,8 +1116,10 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
1094 1116
1095 iwl_trans_d3_suspend(mvm->trans, test); 1117 iwl_trans_d3_suspend(mvm->trans, test);
1096 out: 1118 out:
1097 if (ret < 0) 1119 if (ret < 0) {
1098 ieee80211_restart_hw(mvm->hw); 1120 ieee80211_restart_hw(mvm->hw);
1121 iwl_mvm_free_nd(mvm);
1122 }
1099 out_noreset: 1123 out_noreset:
1100 mutex_unlock(&mvm->mutex); 1124 mutex_unlock(&mvm->mutex);
1101 1125
@@ -1653,14 +1677,15 @@ out_free_resp:
1653static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm, 1677static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
1654 struct ieee80211_vif *vif) 1678 struct ieee80211_vif *vif)
1655{ 1679{
1656 struct cfg80211_wowlan_nd_info net_detect = {}; 1680 struct cfg80211_wowlan_nd_info *net_detect = NULL;
1657 struct cfg80211_wowlan_wakeup wakeup = { 1681 struct cfg80211_wowlan_wakeup wakeup = {
1658 .pattern_idx = -1, 1682 .pattern_idx = -1,
1659 }; 1683 };
1660 struct cfg80211_wowlan_wakeup *wakeup_report = &wakeup; 1684 struct cfg80211_wowlan_wakeup *wakeup_report = &wakeup;
1661 struct iwl_wowlan_status *fw_status; 1685 struct iwl_wowlan_status *fw_status;
1662 u32 matched_profiles; 1686 unsigned long matched_profiles;
1663 u32 reasons = 0; 1687 u32 reasons = 0;
1688 int i, n_matches;
1664 1689
1665 fw_status = iwl_mvm_get_wakeup_status(mvm, vif); 1690 fw_status = iwl_mvm_get_wakeup_status(mvm, vif);
1666 if (!IS_ERR_OR_NULL(fw_status)) 1691 if (!IS_ERR_OR_NULL(fw_status))
@@ -1678,10 +1703,46 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
1678 goto out; 1703 goto out;
1679 } 1704 }
1680 1705
1681 wakeup.net_detect = &net_detect; 1706 if (mvm->n_nd_match_sets) {
1707 n_matches = hweight_long(matched_profiles);
1708 } else {
1709 IWL_ERR(mvm, "no net detect match information available\n");
1710 n_matches = 0;
1711 }
1712
1713 net_detect = kzalloc(sizeof(*net_detect) +
1714 (n_matches * sizeof(net_detect->matches[0])),
1715 GFP_KERNEL);
1716 if (!net_detect || !n_matches)
1717 goto out_report_nd;
1718
1719 for_each_set_bit(i, &matched_profiles, mvm->n_nd_match_sets) {
1720 struct cfg80211_wowlan_nd_match *match;
1721
1722 match = kzalloc(sizeof(*match), GFP_KERNEL);
1723 if (!match)
1724 goto out_report_nd;
1725
1726 match->ssid.ssid_len = mvm->nd_match_sets[i].ssid.ssid_len;
1727 memcpy(match->ssid.ssid, mvm->nd_match_sets[i].ssid.ssid,
1728 match->ssid.ssid_len);
1729
1730 net_detect->matches[net_detect->n_matches++] = match;
1731 }
1732
1733out_report_nd:
1734 wakeup.net_detect = net_detect;
1682out: 1735out:
1736 iwl_mvm_free_nd(mvm);
1737
1683 mutex_unlock(&mvm->mutex); 1738 mutex_unlock(&mvm->mutex);
1684 ieee80211_report_wowlan_wakeup(vif, wakeup_report, GFP_KERNEL); 1739 ieee80211_report_wowlan_wakeup(vif, wakeup_report, GFP_KERNEL);
1740
1741 if (net_detect) {
1742 for (i = 0; i < net_detect->n_matches; i++)
1743 kfree(net_detect->matches[i]);
1744 kfree(net_detect);
1745 }
1685} 1746}
1686 1747
1687static void iwl_mvm_read_d3_sram(struct iwl_mvm *mvm) 1748static void iwl_mvm_read_d3_sram(struct iwl_mvm *mvm)
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 09d48333d35a..d69cc862234a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -685,6 +685,8 @@ struct iwl_mvm {
685 /* sched scan settings for net detect */ 685 /* sched scan settings for net detect */
686 struct cfg80211_sched_scan_request *nd_config; 686 struct cfg80211_sched_scan_request *nd_config;
687 struct ieee80211_scan_ies nd_ies; 687 struct ieee80211_scan_ies nd_ies;
688 struct cfg80211_match_set *nd_match_sets;
689 int n_nd_match_sets;
688 bool net_detect; 690 bool net_detect;
689#ifdef CONFIG_IWLWIFI_DEBUGFS 691#ifdef CONFIG_IWLWIFI_DEBUGFS
690 u32 d3_wake_sysassert; /* must be u32 for debugfs_create_bool */ 692 u32 d3_wake_sysassert; /* must be u32 for debugfs_create_bool */