diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-sv-open.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-sv-open.c | 106 |
1 files changed, 82 insertions, 24 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c index 135c1b5f25ae..038c6961c46a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -100,7 +100,7 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { [IWL_TM_ATTR_EEPROM] = { .type = NLA_UNSPEC, }, [IWL_TM_ATTR_TRACE_ADDR] = { .type = NLA_UNSPEC, }, - [IWL_TM_ATTR_TRACE_DATA] = { .type = NLA_UNSPEC, }, + [IWL_TM_ATTR_TRACE_DUMP] = { .type = NLA_UNSPEC, }, [IWL_TM_ATTR_TRACE_SIZE] = { .type = NLA_U32, }, [IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, }, @@ -534,34 +534,14 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb) "Error sending msg : %d\n", status); } + priv->testmode_trace.num_chunks = + DIV_ROUND_UP(priv->testmode_trace.buff_size, + TRACE_CHUNK_SIZE); break; case IWL_TM_CMD_APP2DEV_END_TRACE: iwl_trace_cleanup(priv); break; - - case IWL_TM_CMD_APP2DEV_READ_TRACE: - if (priv->testmode_trace.trace_enabled && - priv->testmode_trace.trace_addr) { - skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, - 20 + priv->testmode_trace.buff_size); - if (skb == NULL) { - IWL_DEBUG_INFO(priv, - "Error allocating memory\n"); - return -ENOMEM; - } - NLA_PUT(skb, IWL_TM_ATTR_TRACE_DATA, - priv->testmode_trace.buff_size, - priv->testmode_trace.trace_addr); - status = cfg80211_testmode_reply(skb); - if (status < 0) { - IWL_DEBUG_INFO(priv, - "Error sending msg : %d\n", status); - } - } else - return -EFAULT; - break; - default: IWL_DEBUG_INFO(priv, "Unknown testmode mem command ID\n"); return -ENOSYS; @@ -576,6 +556,37 @@ nla_put_failure: return -EMSGSIZE; } +static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct nlattr **tb, + struct sk_buff *skb, + struct netlink_callback *cb) +{ + struct iwl_priv *priv = hw->priv; + int idx, length; + + if (priv->testmode_trace.trace_enabled && + priv->testmode_trace.trace_addr) { + idx = cb->args[4]; + if (idx >= priv->testmode_trace.num_chunks) + return -ENOENT; + length = TRACE_CHUNK_SIZE; + if (((idx + 1) == priv->testmode_trace.num_chunks) && + (priv->testmode_trace.buff_size % TRACE_CHUNK_SIZE)) + length = priv->testmode_trace.buff_size % + TRACE_CHUNK_SIZE; + + NLA_PUT(skb, IWL_TM_ATTR_TRACE_DUMP, length, + priv->testmode_trace.trace_addr + + (TRACE_CHUNK_SIZE * idx)); + idx++; + cb->args[4] = idx; + return 0; + } else + return -EFAULT; + + nla_put_failure: + return -ENOBUFS; +} + /* The testmode gnl message handler that takes the gnl message from the * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then * invoke the corresponding handlers. @@ -654,3 +665,50 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) mutex_unlock(&priv->mutex); return result; } + +int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, + struct netlink_callback *cb, + void *data, int len) +{ + struct nlattr *tb[IWL_TM_ATTR_MAX]; + struct iwl_priv *priv = hw->priv; + int result; + u32 cmd; + + if (cb->args[3]) { + /* offset by 1 since commands start at 0 */ + cmd = cb->args[3] - 1; + } else { + result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len, + iwl_testmode_gnl_msg_policy); + if (result) { + IWL_DEBUG_INFO(priv, + "Error parsing the gnl message : %d\n", result); + return result; + } + + /* IWL_TM_ATTR_COMMAND is absolutely mandatory */ + if (!tb[IWL_TM_ATTR_COMMAND]) { + IWL_DEBUG_INFO(priv, + "Error finding testmode command type\n"); + return -ENOMSG; + } + cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]); + cb->args[3] = cmd + 1; + } + + /* in case multiple accesses to the device happens */ + mutex_lock(&priv->mutex); + switch (cmd) { + case IWL_TM_CMD_APP2DEV_READ_TRACE: + IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n"); + result = iwl_testmode_trace_dump(hw, tb, skb, cb); + break; + default: + result = -EINVAL; + break; + } + + mutex_unlock(&priv->mutex); + return result; +} |