* [PATCH v3] *** Add wmi-tlv support in test mode *** @ 2015-08-31 17:44 Kuei Hao Liu 2015-08-31 17:44 ` [PATCH v3] Add wmi-tlv support in test mode Kuei Hao Liu 2015-08-31 17:49 ` [PATCH v3] *** Add wmi-tlv support in test mode *** Arend van Spriel 0 siblings, 2 replies; 5+ messages in thread From: Kuei Hao Liu @ 2015-08-31 17:44 UTC (permalink / raw) To: kvalo; +Cc: ath6kl-devel, linux-wireless *** BLURB HERE *** alanliu (1): Add wmi-tlv support in test mode drivers/net/wireless/ath/ath10k/core.c | 4 +- drivers/net/wireless/ath/ath10k/core.h | 5 +- drivers/net/wireless/ath/ath10k/testmode.c | 123 ++++++++++++++++++++++++++--- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 15 +++- 4 files changed, 131 insertions(+), 16 deletions(-) -- 1.9.1 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v3] Add wmi-tlv support in test mode 2015-08-31 17:44 [PATCH v3] *** Add wmi-tlv support in test mode *** Kuei Hao Liu @ 2015-08-31 17:44 ` Kuei Hao Liu 2015-08-31 18:03 ` Arend van Spriel 2015-08-31 17:49 ` [PATCH v3] *** Add wmi-tlv support in test mode *** Arend van Spriel 1 sibling, 1 reply; 5+ messages in thread From: Kuei Hao Liu @ 2015-08-31 17:44 UTC (permalink / raw) To: kvalo; +Cc: ath6kl-devel, linux-wireless From: alanliu <alanliu@qca.qualcomm.com> Add WMI-TLV and FW API support in ath10k testmode. Ath10k can get right wmi command format from UTF image to communicate UTF firmware. Signed-off-by: Kuei Hao Liu <alanliu@qca.qualcomm.com> --- drivers/net/wireless/ath/ath10k/core.c | 4 +- drivers/net/wireless/ath/ath10k/core.h | 5 +- drivers/net/wireless/ath/ath10k/testmode.c | 123 ++++++++++++++++++++++++++--- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 15 +++- 4 files changed, 131 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 2551067..b2210b9 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -489,8 +489,8 @@ static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode) } break; case ATH10K_FIRMWARE_MODE_UTF: - data = ar->testmode.utf->data; - data_len = ar->testmode.utf->size; + data = ar->testmode.utf_firmware_data; + data_len = ar->testmode.utf_firmware_len; mode_name = "utf"; break; default: diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 6a387ba..6b11a5c 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -768,9 +768,12 @@ struct ath10k { struct { /* protected by conf_mutex */ const struct firmware *utf; + char fw_version[32]; + const void *utf_firmware_data; + size_t utf_firmware_len; DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT); enum ath10k_fw_wmi_op_version orig_wmi_op_version; - + enum ath10k_fw_wmi_op_version op_version; /* protected by data_lock */ bool utf_monitor; } testmode; diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c index b084f88..a94c30c 100644 --- a/drivers/net/wireless/ath/ath10k/testmode.c +++ b/drivers/net/wireless/ath/ath10k/testmode.c @@ -35,6 +35,100 @@ static const struct nla_policy ath10k_tm_policy[ATH10K_TM_ATTR_MAX + 1] = { [ATH10K_TM_ATTR_VERSION_MINOR] = { .type = NLA_U32 }, }; +bool ath10k_tm_fetch_utf_firmware_api(struct ath10k *ar, const u8 *fw_data, size_t fw_len) +{ + size_t magic_len, ie_len; + int ie_id; + struct ath10k_fw_ie *hdr; + __le32 *version; + const u8 *data = fw_data; + size_t len = fw_len; + bool ret = false; + + if(!data || len <= 0) + goto err; + /* magic also includes the null byte, check that as well */ + magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1; + + if (len < magic_len) { + ath10k_err(ar, "utf firmware file is too small to contain magic\n"); + goto err; + } + if (memcmp(data, ATH10K_FIRMWARE_MAGIC, magic_len) != 0) { + ath10k_err(ar, "invalid firmware magic\n"); + goto err; + } + /* jump over the padding */ + magic_len = ALIGN(magic_len, 4); + + len -= magic_len; + data += magic_len; + + /* loop elements */ + while (len > sizeof(struct ath10k_fw_ie)) { + hdr = (struct ath10k_fw_ie *)data; + + ie_id = le32_to_cpu(hdr->id); + ie_len = le32_to_cpu(hdr->len); + + len -= sizeof(*hdr); + data += sizeof(*hdr); + + if (len < ie_len) { + ath10k_err(ar, "invalid length for FW IE %d (%zu < %zu)\n", ie_id, len, ie_len); + ret = -EINVAL; + goto err; + } + + switch (ie_id) { + case ATH10K_FW_IE_FW_VERSION: + if (ie_len > sizeof(ar->testmode.fw_version) - 1) + break; + + memcpy(ar->testmode.fw_version, data, ie_len); + ar->testmode.fw_version[ie_len] = '\0'; + + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, + "found fw version %s\n", + ar->testmode.fw_version); + break; + case ATH10K_FW_IE_FW_IMAGE: + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, + "found fw image ie (%zd B)\n", + ie_len); + + ar->testmode.utf_firmware_data = data; + ar->testmode.utf_firmware_len = ie_len; + break; + case ATH10K_FW_IE_WMI_OP_VERSION: + if (ie_len != sizeof(u32)) + break; + version = (__le32 *)data; + ar->testmode.op_version = le32_to_cpup(version); + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "found fw ie wmi op version %d\n", + ar->testmode.op_version); + break; + default: + ath10k_warn(ar, "Unknown FW IE: %u\n", + le32_to_cpu(hdr->id)); + break; + } + /* jump over the padding */ + ie_len = ALIGN(ie_len, 4); + + len -= ie_len; + data += ie_len; + } + if (!ar->testmode.utf_firmware_data || !ar->testmode.utf_firmware_len) { + ath10k_warn(ar, "No ATH10K_FW_IE_FW_IMAGE found\n"); + goto err; + } + return true; +err: + return ret; +} + + /* Returns true if callee consumes the skb and the skb should be discarded. * Returns false if skb is not used. Does not sleep. */ @@ -143,7 +237,6 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) { char filename[100]; int ret; - ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf start\n"); mutex_lock(&ar->conf_mutex); @@ -166,36 +259,42 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) } snprintf(filename, sizeof(filename), "%s/%s", - ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE); + ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE); /* load utf firmware image */ ret = request_firmware(&ar->testmode.utf, filename, ar->dev); if (ret) { ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n", - filename, ret); + filename, ret); goto err; } spin_lock_bh(&ar->data_lock); - ar->testmode.utf_monitor = true; - spin_unlock_bh(&ar->data_lock); - BUILD_BUG_ON(sizeof(ar->fw_features) != sizeof(ar->testmode.orig_fw_features)); memcpy(ar->testmode.orig_fw_features, ar->fw_features, sizeof(ar->fw_features)); ar->testmode.orig_wmi_op_version = ar->wmi.op_version; - - /* utf.bin firmware image does not advertise firmware features. Do - * an ugly hack where we force the firmware features so that wmi.c - * will use the correct WMI interface. - */ memset(ar->fw_features, 0, sizeof(ar->fw_features)); - ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1; + if(ath10k_tm_fetch_utf_firmware_api(ar,ar->testmode.utf->data, ar->testmode.utf->size)){ + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "utf firmware %s advertise firmware feature\n",filename); + ar->wmi.op_version = ar->testmode.op_version; + }else{ + /* for utf.bin firmware image does not advertise firmware features. Do + * an ugly hack where we force the firmware features so that wmi.c + * will use the correct WMI interface. + */ + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "utf firmware %s doesn't advertise firmware feature\n",filename); + ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1; + ar->testmode.utf_firmware_data = ar->testmode.utf->data; + ar->testmode.utf_firmware_len = ar->testmode.utf->size; + } + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode wmi version %d\n", + ar->wmi.op_version); ret = ath10k_hif_power_up(ar); if (ret) { ath10k_err(ar, "failed to power up hif (testmode): %d\n", ret); diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 567b797..cc3d993 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -23,6 +23,7 @@ #include "wmi-ops.h" #include "wmi-tlv.h" #include "p2p.h" +#include "testmode.h" /***************/ /* TLV helpers */ @@ -419,7 +420,7 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb) { struct wmi_cmd_hdr *cmd_hdr; enum wmi_tlv_event_id id; - + bool consumed; cmd_hdr = (struct wmi_cmd_hdr *)skb->data; id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); @@ -428,6 +429,18 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb) trace_ath10k_wmi_event(ar, id, skb->data, skb->len); + consumed = ath10k_tm_event_wmi(ar, id, skb); + + /* Ready event must be handled normally also in UTF mode so that we + * know the UTF firmware has booted, others we are just bypass WMI + * events to testmode. + */ + if (consumed && id != WMI_TLV_READY_EVENTID) { + ath10k_dbg(ar, ATH10K_DBG_WMI, + "wmi tlv testmode consumed 0x%x\n", id); + goto out; + } + switch (id) { case WMI_TLV_MGMT_RX_EVENTID: ath10k_wmi_event_mgmt_rx(ar, skb); -- 1.9.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v3] Add wmi-tlv support in test mode 2015-08-31 17:44 ` [PATCH v3] Add wmi-tlv support in test mode Kuei Hao Liu @ 2015-08-31 18:03 ` Arend van Spriel 0 siblings, 0 replies; 5+ messages in thread From: Arend van Spriel @ 2015-08-31 18:03 UTC (permalink / raw) To: Kuei Hao Liu, kvalo; +Cc: ath6kl-devel, linux-wireless On 31-08-15 19:44, Kuei Hao Liu wrote: > From: alanliu <alanliu@qca.qualcomm.com> Would be good to start subject with driver name, ie.: ath10k: Add wmi-tlv support in test mode Regards, Arend > Add WMI-TLV and FW API support in ath10k testmode. > Ath10k can get right wmi command format from UTF image > to communicate UTF firmware. > > Signed-off-by: Kuei Hao Liu <alanliu@qca.qualcomm.com> > --- > drivers/net/wireless/ath/ath10k/core.c | 4 +- > drivers/net/wireless/ath/ath10k/core.h | 5 +- > drivers/net/wireless/ath/ath10k/testmode.c | 123 ++++++++++++++++++++++++++--- > drivers/net/wireless/ath/ath10k/wmi-tlv.c | 15 +++- > 4 files changed, 131 insertions(+), 16 deletions(-) > > diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c > index 2551067..b2210b9 100644 > --- a/drivers/net/wireless/ath/ath10k/core.c > +++ b/drivers/net/wireless/ath/ath10k/core.c > @@ -489,8 +489,8 @@ static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode) > } > break; > case ATH10K_FIRMWARE_MODE_UTF: > - data = ar->testmode.utf->data; > - data_len = ar->testmode.utf->size; > + data = ar->testmode.utf_firmware_data; > + data_len = ar->testmode.utf_firmware_len; > mode_name = "utf"; > break; > default: > diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h > index 6a387ba..6b11a5c 100644 > --- a/drivers/net/wireless/ath/ath10k/core.h > +++ b/drivers/net/wireless/ath/ath10k/core.h > @@ -768,9 +768,12 @@ struct ath10k { > struct { > /* protected by conf_mutex */ > const struct firmware *utf; > + char fw_version[32]; > + const void *utf_firmware_data; > + size_t utf_firmware_len; > DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT); > enum ath10k_fw_wmi_op_version orig_wmi_op_version; > - > + enum ath10k_fw_wmi_op_version op_version; > /* protected by data_lock */ > bool utf_monitor; > } testmode; > diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c > index b084f88..a94c30c 100644 > --- a/drivers/net/wireless/ath/ath10k/testmode.c > +++ b/drivers/net/wireless/ath/ath10k/testmode.c > @@ -35,6 +35,100 @@ static const struct nla_policy ath10k_tm_policy[ATH10K_TM_ATTR_MAX + 1] = { > [ATH10K_TM_ATTR_VERSION_MINOR] = { .type = NLA_U32 }, > }; > > +bool ath10k_tm_fetch_utf_firmware_api(struct ath10k *ar, const u8 *fw_data, size_t fw_len) > +{ > + size_t magic_len, ie_len; > + int ie_id; > + struct ath10k_fw_ie *hdr; > + __le32 *version; > + const u8 *data = fw_data; > + size_t len = fw_len; > + bool ret = false; > + > + if(!data || len <= 0) > + goto err; > + /* magic also includes the null byte, check that as well */ > + magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1; > + > + if (len < magic_len) { > + ath10k_err(ar, "utf firmware file is too small to contain magic\n"); > + goto err; > + } > + if (memcmp(data, ATH10K_FIRMWARE_MAGIC, magic_len) != 0) { > + ath10k_err(ar, "invalid firmware magic\n"); > + goto err; > + } > + /* jump over the padding */ > + magic_len = ALIGN(magic_len, 4); > + > + len -= magic_len; > + data += magic_len; > + > + /* loop elements */ > + while (len > sizeof(struct ath10k_fw_ie)) { > + hdr = (struct ath10k_fw_ie *)data; > + > + ie_id = le32_to_cpu(hdr->id); > + ie_len = le32_to_cpu(hdr->len); > + > + len -= sizeof(*hdr); > + data += sizeof(*hdr); > + > + if (len < ie_len) { > + ath10k_err(ar, "invalid length for FW IE %d (%zu < %zu)\n", ie_id, len, ie_len); > + ret = -EINVAL; > + goto err; > + } > + > + switch (ie_id) { > + case ATH10K_FW_IE_FW_VERSION: > + if (ie_len > sizeof(ar->testmode.fw_version) - 1) > + break; > + > + memcpy(ar->testmode.fw_version, data, ie_len); > + ar->testmode.fw_version[ie_len] = '\0'; > + > + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, > + "found fw version %s\n", > + ar->testmode.fw_version); > + break; > + case ATH10K_FW_IE_FW_IMAGE: > + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, > + "found fw image ie (%zd B)\n", > + ie_len); > + > + ar->testmode.utf_firmware_data = data; > + ar->testmode.utf_firmware_len = ie_len; > + break; > + case ATH10K_FW_IE_WMI_OP_VERSION: > + if (ie_len != sizeof(u32)) > + break; > + version = (__le32 *)data; > + ar->testmode.op_version = le32_to_cpup(version); > + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "found fw ie wmi op version %d\n", > + ar->testmode.op_version); > + break; > + default: > + ath10k_warn(ar, "Unknown FW IE: %u\n", > + le32_to_cpu(hdr->id)); > + break; > + } > + /* jump over the padding */ > + ie_len = ALIGN(ie_len, 4); > + > + len -= ie_len; > + data += ie_len; > + } > + if (!ar->testmode.utf_firmware_data || !ar->testmode.utf_firmware_len) { > + ath10k_warn(ar, "No ATH10K_FW_IE_FW_IMAGE found\n"); > + goto err; > + } > + return true; > +err: > + return ret; > +} > + > + > /* Returns true if callee consumes the skb and the skb should be discarded. > * Returns false if skb is not used. Does not sleep. > */ > @@ -143,7 +237,6 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) > { > char filename[100]; > int ret; > - > ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf start\n"); > > mutex_lock(&ar->conf_mutex); > @@ -166,36 +259,42 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) > } > > snprintf(filename, sizeof(filename), "%s/%s", > - ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE); > + ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE); > > /* load utf firmware image */ > ret = request_firmware(&ar->testmode.utf, filename, ar->dev); > if (ret) { > ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n", > - filename, ret); > + filename, ret); > goto err; > } > > spin_lock_bh(&ar->data_lock); > - > ar->testmode.utf_monitor = true; > - > spin_unlock_bh(&ar->data_lock); > - > BUILD_BUG_ON(sizeof(ar->fw_features) != > sizeof(ar->testmode.orig_fw_features)); > > memcpy(ar->testmode.orig_fw_features, ar->fw_features, > sizeof(ar->fw_features)); > ar->testmode.orig_wmi_op_version = ar->wmi.op_version; > - > - /* utf.bin firmware image does not advertise firmware features. Do > - * an ugly hack where we force the firmware features so that wmi.c > - * will use the correct WMI interface. > - */ > memset(ar->fw_features, 0, sizeof(ar->fw_features)); > - ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1; > > + if(ath10k_tm_fetch_utf_firmware_api(ar,ar->testmode.utf->data, ar->testmode.utf->size)){ > + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "utf firmware %s advertise firmware feature\n",filename); > + ar->wmi.op_version = ar->testmode.op_version; > + }else{ > + /* for utf.bin firmware image does not advertise firmware features. Do > + * an ugly hack where we force the firmware features so that wmi.c > + * will use the correct WMI interface. > + */ > + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "utf firmware %s doesn't advertise firmware feature\n",filename); > + ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1; > + ar->testmode.utf_firmware_data = ar->testmode.utf->data; > + ar->testmode.utf_firmware_len = ar->testmode.utf->size; > + } > + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode wmi version %d\n", > + ar->wmi.op_version); > ret = ath10k_hif_power_up(ar); > if (ret) { > ath10k_err(ar, "failed to power up hif (testmode): %d\n", ret); > diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c > index 567b797..cc3d993 100644 > --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c > +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c > @@ -23,6 +23,7 @@ > #include "wmi-ops.h" > #include "wmi-tlv.h" > #include "p2p.h" > +#include "testmode.h" > > /***************/ > /* TLV helpers */ > @@ -419,7 +420,7 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb) > { > struct wmi_cmd_hdr *cmd_hdr; > enum wmi_tlv_event_id id; > - > + bool consumed; > cmd_hdr = (struct wmi_cmd_hdr *)skb->data; > id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); > > @@ -428,6 +429,18 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb) > > trace_ath10k_wmi_event(ar, id, skb->data, skb->len); > > + consumed = ath10k_tm_event_wmi(ar, id, skb); > + > + /* Ready event must be handled normally also in UTF mode so that we > + * know the UTF firmware has booted, others we are just bypass WMI > + * events to testmode. > + */ > + if (consumed && id != WMI_TLV_READY_EVENTID) { > + ath10k_dbg(ar, ATH10K_DBG_WMI, > + "wmi tlv testmode consumed 0x%x\n", id); > + goto out; > + } > + > switch (id) { > case WMI_TLV_MGMT_RX_EVENTID: > ath10k_wmi_event_mgmt_rx(ar, skb); > ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v3] *** Add wmi-tlv support in test mode *** 2015-08-31 17:44 [PATCH v3] *** Add wmi-tlv support in test mode *** Kuei Hao Liu 2015-08-31 17:44 ` [PATCH v3] Add wmi-tlv support in test mode Kuei Hao Liu @ 2015-08-31 17:49 ` Arend van Spriel 1 sibling, 0 replies; 5+ messages in thread From: Arend van Spriel @ 2015-08-31 17:49 UTC (permalink / raw) To: Kuei Hao Liu, kvalo; +Cc: ath6kl-devel, linux-wireless On 31-08-15 19:44, Kuei Hao Liu wrote: > *** BLURB HERE *** For a single patch I would not bother adding cover letter. Regards, Arend > alanliu (1): > Add wmi-tlv support in test mode > > drivers/net/wireless/ath/ath10k/core.c | 4 +- > drivers/net/wireless/ath/ath10k/core.h | 5 +- > drivers/net/wireless/ath/ath10k/testmode.c | 123 ++++++++++++++++++++++++++--- > drivers/net/wireless/ath/ath10k/wmi-tlv.c | 15 +++- > 4 files changed, 131 insertions(+), 16 deletions(-) > ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v3] *** Add wmi-tlv support in test mode *** @ 2015-08-31 17:53 Kuei Hao Liu 2015-08-31 17:53 ` [PATCH v3] Add wmi-tlv support in test mode Kuei Hao Liu 0 siblings, 1 reply; 5+ messages in thread From: Kuei Hao Liu @ 2015-08-31 17:53 UTC (permalink / raw) To: kvalo; +Cc: ath10k-devel, ath10k-tieto.external, linux-wireless *** BLURB HERE *** alanliu (1): Add wmi-tlv support in test mode drivers/net/wireless/ath/ath10k/core.c | 4 +- drivers/net/wireless/ath/ath10k/core.h | 5 +- drivers/net/wireless/ath/ath10k/testmode.c | 123 ++++++++++++++++++++++++++--- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 15 +++- 4 files changed, 131 insertions(+), 16 deletions(-) -- 1.9.1 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v3] Add wmi-tlv support in test mode 2015-08-31 17:53 Kuei Hao Liu @ 2015-08-31 17:53 ` Kuei Hao Liu 0 siblings, 0 replies; 5+ messages in thread From: Kuei Hao Liu @ 2015-08-31 17:53 UTC (permalink / raw) To: kvalo; +Cc: ath10k-devel, ath10k-tieto.external, linux-wireless From: alanliu <alanliu@qca.qualcomm.com> Add WMI-TLV and FW API support in ath10k testmode. Ath10k can get right wmi command format from UTF image to communicate UTF firmware. Signed-off-by: Kuei Hao Liu <alanliu@qca.qualcomm.com> --- drivers/net/wireless/ath/ath10k/core.c | 4 +- drivers/net/wireless/ath/ath10k/core.h | 5 +- drivers/net/wireless/ath/ath10k/testmode.c | 123 ++++++++++++++++++++++++++--- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 15 +++- 4 files changed, 131 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 2551067..b2210b9 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -489,8 +489,8 @@ static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode) } break; case ATH10K_FIRMWARE_MODE_UTF: - data = ar->testmode.utf->data; - data_len = ar->testmode.utf->size; + data = ar->testmode.utf_firmware_data; + data_len = ar->testmode.utf_firmware_len; mode_name = "utf"; break; default: diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 6a387ba..6b11a5c 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -768,9 +768,12 @@ struct ath10k { struct { /* protected by conf_mutex */ const struct firmware *utf; + char fw_version[32]; + const void *utf_firmware_data; + size_t utf_firmware_len; DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT); enum ath10k_fw_wmi_op_version orig_wmi_op_version; - + enum ath10k_fw_wmi_op_version op_version; /* protected by data_lock */ bool utf_monitor; } testmode; diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c index b084f88..a94c30c 100644 --- a/drivers/net/wireless/ath/ath10k/testmode.c +++ b/drivers/net/wireless/ath/ath10k/testmode.c @@ -35,6 +35,100 @@ static const struct nla_policy ath10k_tm_policy[ATH10K_TM_ATTR_MAX + 1] = { [ATH10K_TM_ATTR_VERSION_MINOR] = { .type = NLA_U32 }, }; +bool ath10k_tm_fetch_utf_firmware_api(struct ath10k *ar, const u8 *fw_data, size_t fw_len) +{ + size_t magic_len, ie_len; + int ie_id; + struct ath10k_fw_ie *hdr; + __le32 *version; + const u8 *data = fw_data; + size_t len = fw_len; + bool ret = false; + + if(!data || len <= 0) + goto err; + /* magic also includes the null byte, check that as well */ + magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1; + + if (len < magic_len) { + ath10k_err(ar, "utf firmware file is too small to contain magic\n"); + goto err; + } + if (memcmp(data, ATH10K_FIRMWARE_MAGIC, magic_len) != 0) { + ath10k_err(ar, "invalid firmware magic\n"); + goto err; + } + /* jump over the padding */ + magic_len = ALIGN(magic_len, 4); + + len -= magic_len; + data += magic_len; + + /* loop elements */ + while (len > sizeof(struct ath10k_fw_ie)) { + hdr = (struct ath10k_fw_ie *)data; + + ie_id = le32_to_cpu(hdr->id); + ie_len = le32_to_cpu(hdr->len); + + len -= sizeof(*hdr); + data += sizeof(*hdr); + + if (len < ie_len) { + ath10k_err(ar, "invalid length for FW IE %d (%zu < %zu)\n", ie_id, len, ie_len); + ret = -EINVAL; + goto err; + } + + switch (ie_id) { + case ATH10K_FW_IE_FW_VERSION: + if (ie_len > sizeof(ar->testmode.fw_version) - 1) + break; + + memcpy(ar->testmode.fw_version, data, ie_len); + ar->testmode.fw_version[ie_len] = '\0'; + + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, + "found fw version %s\n", + ar->testmode.fw_version); + break; + case ATH10K_FW_IE_FW_IMAGE: + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, + "found fw image ie (%zd B)\n", + ie_len); + + ar->testmode.utf_firmware_data = data; + ar->testmode.utf_firmware_len = ie_len; + break; + case ATH10K_FW_IE_WMI_OP_VERSION: + if (ie_len != sizeof(u32)) + break; + version = (__le32 *)data; + ar->testmode.op_version = le32_to_cpup(version); + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "found fw ie wmi op version %d\n", + ar->testmode.op_version); + break; + default: + ath10k_warn(ar, "Unknown FW IE: %u\n", + le32_to_cpu(hdr->id)); + break; + } + /* jump over the padding */ + ie_len = ALIGN(ie_len, 4); + + len -= ie_len; + data += ie_len; + } + if (!ar->testmode.utf_firmware_data || !ar->testmode.utf_firmware_len) { + ath10k_warn(ar, "No ATH10K_FW_IE_FW_IMAGE found\n"); + goto err; + } + return true; +err: + return ret; +} + + /* Returns true if callee consumes the skb and the skb should be discarded. * Returns false if skb is not used. Does not sleep. */ @@ -143,7 +237,6 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) { char filename[100]; int ret; - ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf start\n"); mutex_lock(&ar->conf_mutex); @@ -166,36 +259,42 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) } snprintf(filename, sizeof(filename), "%s/%s", - ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE); + ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE); /* load utf firmware image */ ret = request_firmware(&ar->testmode.utf, filename, ar->dev); if (ret) { ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n", - filename, ret); + filename, ret); goto err; } spin_lock_bh(&ar->data_lock); - ar->testmode.utf_monitor = true; - spin_unlock_bh(&ar->data_lock); - BUILD_BUG_ON(sizeof(ar->fw_features) != sizeof(ar->testmode.orig_fw_features)); memcpy(ar->testmode.orig_fw_features, ar->fw_features, sizeof(ar->fw_features)); ar->testmode.orig_wmi_op_version = ar->wmi.op_version; - - /* utf.bin firmware image does not advertise firmware features. Do - * an ugly hack where we force the firmware features so that wmi.c - * will use the correct WMI interface. - */ memset(ar->fw_features, 0, sizeof(ar->fw_features)); - ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1; + if(ath10k_tm_fetch_utf_firmware_api(ar,ar->testmode.utf->data, ar->testmode.utf->size)){ + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "utf firmware %s advertise firmware feature\n",filename); + ar->wmi.op_version = ar->testmode.op_version; + }else{ + /* for utf.bin firmware image does not advertise firmware features. Do + * an ugly hack where we force the firmware features so that wmi.c + * will use the correct WMI interface. + */ + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "utf firmware %s doesn't advertise firmware feature\n",filename); + ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1; + ar->testmode.utf_firmware_data = ar->testmode.utf->data; + ar->testmode.utf_firmware_len = ar->testmode.utf->size; + } + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode wmi version %d\n", + ar->wmi.op_version); ret = ath10k_hif_power_up(ar); if (ret) { ath10k_err(ar, "failed to power up hif (testmode): %d\n", ret); diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 567b797..cc3d993 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -23,6 +23,7 @@ #include "wmi-ops.h" #include "wmi-tlv.h" #include "p2p.h" +#include "testmode.h" /***************/ /* TLV helpers */ @@ -419,7 +420,7 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb) { struct wmi_cmd_hdr *cmd_hdr; enum wmi_tlv_event_id id; - + bool consumed; cmd_hdr = (struct wmi_cmd_hdr *)skb->data; id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); @@ -428,6 +429,18 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb) trace_ath10k_wmi_event(ar, id, skb->data, skb->len); + consumed = ath10k_tm_event_wmi(ar, id, skb); + + /* Ready event must be handled normally also in UTF mode so that we + * know the UTF firmware has booted, others we are just bypass WMI + * events to testmode. + */ + if (consumed && id != WMI_TLV_READY_EVENTID) { + ath10k_dbg(ar, ATH10K_DBG_WMI, + "wmi tlv testmode consumed 0x%x\n", id); + goto out; + } + switch (id) { case WMI_TLV_MGMT_RX_EVENTID: ath10k_wmi_event_mgmt_rx(ar, skb); -- 1.9.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2015-08-31 18:03 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-08-31 17:44 [PATCH v3] *** Add wmi-tlv support in test mode *** Kuei Hao Liu 2015-08-31 17:44 ` [PATCH v3] Add wmi-tlv support in test mode Kuei Hao Liu 2015-08-31 18:03 ` Arend van Spriel 2015-08-31 17:49 ` [PATCH v3] *** Add wmi-tlv support in test mode *** Arend van Spriel -- strict thread matches above, loose matches on Subject: below -- 2015-08-31 17:53 Kuei Hao Liu 2015-08-31 17:53 ` [PATCH v3] Add wmi-tlv support in test mode Kuei Hao Liu
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.