From: Maya Erez <merez@codeaurora.org>
To: Kalle Valo <kvalo@codeaurora.org>
Cc: Lior David <liord@codeaurora.org>,
linux-wireless@vger.kernel.org, wil6210@qti.qualcomm.com,
Maya Erez <merez@codeaurora.org>
Subject: [PATCH v2 2/8] wil6210: support concurrency record in FW file
Date: Mon, 26 Feb 2018 20:12:12 +0200 [thread overview]
Message-ID: <1519668738-16912-3-git-send-email-merez@codeaurora.org> (raw)
In-Reply-To: <1519668738-16912-1-git-send-email-merez@codeaurora.org>
From: Lior David <liord@codeaurora.org>
New FW which supports multiple virtual interfaces, reports
its allowed interface combinations using a special comment
record in the FW file. The format of the interface combinations
is similar to the kernel wiphy->iface_combinations.
When parsing FW file during module initialization, also parse
and validate the concurrency record, and initialize
wiphy->n_iface_combinations and wiphy->iface_combinations
accordingly.
Signed-off-by: Lior David <liord@codeaurora.org>
Signed-off-by: Maya Erez <merez@codeaurora.org>
---
drivers/net/wireless/ath/wil6210/cfg80211.c | 69 +++++++++++++++++++++++++++++
drivers/net/wireless/ath/wil6210/fw.h | 38 +++++++++++++++-
drivers/net/wireless/ath/wil6210/fw_inc.c | 52 ++++++++++++++++++++--
drivers/net/wireless/ath/wil6210/wil6210.h | 4 ++
4 files changed, 158 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index eeed85c..c959f15 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -20,6 +20,7 @@
#include <net/netlink.h>
#include "wil6210.h"
#include "wmi.h"
+#include "fw.h"
#define WIL_MAX_ROC_DURATION_MS 5000
@@ -1896,6 +1897,71 @@ static void wil_wiphy_init(struct wiphy *wiphy)
#endif
}
+int wil_cfg80211_iface_combinations_from_fw(
+ struct wil6210_priv *wil, const struct wil_fw_record_concurrency *conc)
+{
+ struct wiphy *wiphy = wil_to_wiphy(wil);
+ u32 total_limits = 0;
+ u16 n_combos;
+ const struct wil_fw_concurrency_combo *combo;
+ const struct wil_fw_concurrency_limit *limit;
+ struct ieee80211_iface_combination *iface_combinations;
+ struct ieee80211_iface_limit *iface_limit;
+ int i, j;
+
+ if (wiphy->iface_combinations) {
+ wil_dbg_misc(wil, "iface_combinations already set, skipping\n");
+ return 0;
+ }
+
+ combo = conc->combos;
+ n_combos = le16_to_cpu(conc->n_combos);
+ for (i = 0; i < n_combos; i++) {
+ total_limits += combo->n_limits;
+ limit = combo->limits + combo->n_limits;
+ combo = (struct wil_fw_concurrency_combo *)limit;
+ }
+
+ iface_combinations =
+ kzalloc(n_combos * sizeof(struct ieee80211_iface_combination) +
+ total_limits * sizeof(struct ieee80211_iface_limit),
+ GFP_KERNEL);
+ if (!iface_combinations)
+ return -ENOMEM;
+ iface_limit = (struct ieee80211_iface_limit *)(iface_combinations +
+ n_combos);
+ combo = conc->combos;
+ for (i = 0; i < n_combos; i++) {
+ iface_combinations[i].max_interfaces = combo->max_interfaces;
+ iface_combinations[i].num_different_channels =
+ combo->n_diff_channels;
+ iface_combinations[i].beacon_int_infra_match =
+ combo->same_bi;
+ iface_combinations[i].n_limits = combo->n_limits;
+ wil_dbg_misc(wil,
+ "iface_combination %d: max_if %d, num_ch %d, bi_match %d\n",
+ i, iface_combinations[i].max_interfaces,
+ iface_combinations[i].num_different_channels,
+ iface_combinations[i].beacon_int_infra_match);
+ limit = combo->limits;
+ for (j = 0; j < combo->n_limits; j++) {
+ iface_limit[j].max = le16_to_cpu(limit[j].max);
+ iface_limit[j].types = le16_to_cpu(limit[j].types);
+ wil_dbg_misc(wil,
+ "limit %d: max %d types 0x%x\n", j,
+ iface_limit[j].max, iface_limit[j].types);
+ }
+ iface_combinations[i].limits = iface_limit;
+ iface_limit += combo->n_limits;
+ limit += combo->n_limits;
+ combo = (struct wil_fw_concurrency_combo *)limit;
+ }
+
+ wiphy->n_iface_combinations = n_combos;
+ wiphy->iface_combinations = iface_combinations;
+ return 0;
+}
+
struct wil6210_priv *wil_cfg80211_init(struct device *dev)
{
struct wiphy *wiphy;
@@ -1934,6 +2000,9 @@ void wil_cfg80211_deinit(struct wil6210_priv *wil)
if (!wiphy)
return;
+ kfree(wiphy->iface_combinations);
+ wiphy->iface_combinations = NULL;
+
wiphy_free(wiphy);
/* do not access wil6210_priv after returning from here */
}
diff --git a/drivers/net/wireless/ath/wil6210/fw.h b/drivers/net/wireless/ath/wil6210/fw.h
index 2c7b24f..3e7a280 100644
--- a/drivers/net/wireless/ath/wil6210/fw.h
+++ b/drivers/net/wireless/ath/wil6210/fw.h
@@ -14,6 +14,8 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#ifndef __WIL_FW_H__
+#define __WIL_FW_H__
#define WIL_FW_SIGNATURE (0x36323130) /* '0126' */
#define WIL_FW_FMT_VERSION (1) /* format version driver supports */
@@ -71,7 +73,39 @@ struct wil_fw_record_capabilities { /* type == wil_fw_type_comment */
struct wil_fw_record_comment_hdr hdr;
/* capabilities (variable size), see enum wmi_fw_capability */
u8 capabilities[0];
-};
+} __packed;
+
+/* FW VIF concurrency encoded inside a comment record
+ * Format is similar to wiphy->iface_combinations
+ */
+#define WIL_FW_CONCURRENCY_MAGIC (0xfedccdef)
+#define WIL_FW_CONCURRENCY_REC_VER 1
+struct wil_fw_concurrency_limit {
+ __le16 max; /* maximum number of interfaces of these types */
+ __le16 types; /* interface types (bit mask of enum nl80211_iftype) */
+} __packed;
+
+struct wil_fw_concurrency_combo {
+ u8 n_limits; /* number of wil_fw_concurrency_limit entries */
+ u8 max_interfaces; /* max number of concurrent interfaces allowed */
+ u8 n_diff_channels; /* total number of different channels allowed */
+ u8 same_bi; /* for APs, 1 if all APs must have same BI */
+ /* keep last - concurrency limits, variable size by n_limits */
+ struct wil_fw_concurrency_limit limits[0];
+} __packed;
+
+struct wil_fw_record_concurrency { /* type == wil_fw_type_comment */
+ /* identifies concurrency record */
+ __le32 magic;
+ /* structure version, currently always 1 */
+ u8 version;
+ /* maximum number of supported MIDs _in addition_ to MID 0 */
+ u8 n_mids;
+ /* number of concurrency combinations that follow */
+ __le16 n_combos;
+ /* keep last - combinations, variable size by n_combos */
+ struct wil_fw_concurrency_combo combos[0];
+} __packed;
/* brd file info encoded inside a comment record */
#define WIL_BRD_FILE_MAGIC (0xabcddcbb)
@@ -175,3 +209,5 @@ struct wil_fw_record_gateway_data4 { /* type == wil_fw_type_gateway_data4 */
__le32 command;
struct wil_fw_data_gw4 data[0]; /* total size [data_size], see above */
} __packed;
+
+#endif /* __WIL_FW_H__ */
diff --git a/drivers/net/wireless/ath/wil6210/fw_inc.c b/drivers/net/wireless/ath/wil6210/fw_inc.c
index 914c010..718161b 100644
--- a/drivers/net/wireless/ath/wil6210/fw_inc.c
+++ b/drivers/net/wireless/ath/wil6210/fw_inc.c
@@ -136,8 +136,8 @@ static int fw_ignore_section(struct wil6210_priv *wil, const void *data,
size_t capa_size;
if (size < sizeof(*rec)) {
- wil_hex_dump_fw("", DUMP_PREFIX_OFFSET, 16, 1,
- data, size, true);
+ wil_err_fw(wil, "capabilities record too short: %zu\n", size);
+ /* let the FW load anyway */
return 0;
}
@@ -158,8 +158,7 @@ static int fw_ignore_section(struct wil6210_priv *wil, const void *data,
const struct wil_fw_record_brd_file *rec = data;
if (size < sizeof(*rec)) {
- wil_hex_dump_fw("", DUMP_PREFIX_OFFSET, 16, 1,
- data, size, true);
+ wil_err_fw(wil, "brd_file record too short: %zu\n", size);
return 0;
}
@@ -173,6 +172,44 @@ static int fw_ignore_section(struct wil6210_priv *wil, const void *data,
}
static int
+fw_handle_concurrency(struct wil6210_priv *wil, const void *data,
+ size_t size)
+{
+ const struct wil_fw_record_concurrency *rec = data;
+ const struct wil_fw_concurrency_combo *combo;
+ const struct wil_fw_concurrency_limit *limit;
+ size_t remain, lsize;
+ int i, n_combos;
+
+ if (size < sizeof(*rec)) {
+ wil_err_fw(wil, "concurrency record too short: %zu\n", size);
+ /* continue, let the FW load anyway */
+ return 0;
+ }
+
+ n_combos = le16_to_cpu(rec->n_combos);
+ remain = size - offsetof(struct wil_fw_record_concurrency, combos);
+ combo = rec->combos;
+ for (i = 0; i < n_combos; i++) {
+ if (remain < sizeof(*combo))
+ goto out_short;
+ remain -= sizeof(*combo);
+ limit = combo->limits;
+ lsize = combo->n_limits * sizeof(*limit);
+ if (remain < lsize)
+ goto out_short;
+ remain -= lsize;
+ limit += combo->n_limits;
+ combo = (struct wil_fw_concurrency_combo *)limit;
+ }
+
+ return wil_cfg80211_iface_combinations_from_fw(wil, rec);
+out_short:
+ wil_err_fw(wil, "concurrency record truncated\n");
+ return 0;
+}
+
+static int
fw_handle_comment(struct wil6210_priv *wil, const void *data,
size_t size)
{
@@ -194,6 +231,13 @@ static int fw_ignore_section(struct wil6210_priv *wil, const void *data,
wil_dbg_fw(wil, "magic is WIL_BRD_FILE_MAGIC\n");
rc = fw_handle_brd_file(wil, data, size);
break;
+ case WIL_FW_CONCURRENCY_MAGIC:
+ wil_dbg_fw(wil, "magic is WIL_FW_CONCURRENCY_MAGIC\n");
+ rc = fw_handle_concurrency(wil, data, size);
+ break;
+ default:
+ wil_hex_dump_fw("", DUMP_PREFIX_OFFSET, 16, 1,
+ data, size, true);
}
return rc;
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index b33aa7d..81cb27a 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -26,6 +26,7 @@
#include <linux/types.h>
#include "wmi.h"
#include "wil_platform.h"
+#include "fw.h"
extern bool no_fw_recovery;
extern unsigned int mtu_max;
@@ -1012,6 +1013,9 @@ int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev,
int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
struct cfg80211_mgmt_tx_params *params,
u64 *cookie);
+int wil_cfg80211_iface_combinations_from_fw(
+ struct wil6210_priv *wil,
+ const struct wil_fw_record_concurrency *conc);
#if defined(CONFIG_WIL6210_DEBUGFS)
int wil6210_debugfs_init(struct wil6210_priv *wil);
--
1.9.1
next prev parent reply other threads:[~2018-02-26 18:13 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-02-26 18:12 [PATCH v2 0/8] wil6210 patches Maya Erez
2018-02-26 18:12 ` [PATCH v2 1/8] wil6210: add wil6210_vif structure for per-VIF data Maya Erez
2018-02-27 16:52 ` [v2,1/8] " Kalle Valo
2018-02-26 18:12 ` Maya Erez [this message]
2018-02-26 18:12 ` [PATCH v2 3/8] wil6210: infrastructure for multiple virtual interfaces Maya Erez
2018-02-26 18:12 ` [PATCH v2 4/8] wil6210: add support for adding and removing " Maya Erez
2018-02-26 18:12 ` [PATCH v2 5/8] wil6210: multiple VIFs support for start/stop AP Maya Erez
2018-02-26 18:12 ` [PATCH v2 6/8] wil6210: rename p2p_wdev_mutex to vif_mutex Maya Erez
2018-02-26 18:12 ` [PATCH v2 7/8] wil6210: multiple VIFs support for connections and data path Maya Erez
2018-02-26 18:12 ` [PATCH v2 8/8] wil6210: add debugfs 'mids' file Maya Erez
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1519668738-16912-3-git-send-email-merez@codeaurora.org \
--to=merez@codeaurora.org \
--cc=kvalo@codeaurora.org \
--cc=linux-wireless@vger.kernel.org \
--cc=liord@codeaurora.org \
--cc=wil6210@qti.qualcomm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).