Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eb64dca0 authored by Wey-Yi Guy's avatar Wey-Yi Guy
Browse files

iwlagn: add dumpit support for testmode trace function



For testmode trace function, huge amout of data need to pass to userspace.
Use the build-in nl80211 dumpt it function

Require nl80211 testmode dumpit support patch.

Signed-off-by: default avatarWey-Yi Guy <wey-yi.w.guy@intel.com>
parent 49b72100
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -3352,6 +3352,7 @@ struct ieee80211_ops iwlagn_hw_ops = {
	.offchannel_tx = iwl_mac_offchannel_tx,
	.offchannel_tx_cancel_wait = iwl_mac_offchannel_tx_cancel_wait,
	CFG80211_TESTMODE_CMD(iwl_testmode_cmd)
	CFG80211_TESTMODE_DUMP(iwl_testmode_dump)
};

static u32 iwl_hw_detect(struct iwl_priv *priv)
+10 −0
Original line number Diff line number Diff line
@@ -343,6 +343,9 @@ extern int iwl_alive_start(struct iwl_priv *priv);
/* svtool */
#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
extern int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len);
extern int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
			     struct netlink_callback *cb,
			     void *data, int len);
extern void iwl_testmode_init(struct iwl_priv *priv);
extern void iwl_testmode_cleanup(struct iwl_priv *priv);
#else
@@ -352,6 +355,13 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
	return -ENOSYS;
}
static inline
int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
		      struct netlink_callback *cb,
		      void *data, int len)
{
	return -ENOSYS;
}
static inline
void iwl_testmode_init(struct iwl_priv *priv)
{
}
+1 −0
Original line number Diff line number Diff line
@@ -1172,6 +1172,7 @@ enum iwl_scan_type {
struct iwl_testmode_trace {
	u32 buff_size;
	u32 total_size;
	u32 num_chunks;
	u8 *cpu_addr;
	u8 *trace_addr;
	dma_addr_t dma_addr;
+82 −24
Original line number Diff line number Diff line
@@ -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 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
	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;
}
+2 −2
Original line number Diff line number Diff line
@@ -166,8 +166,8 @@ enum iwl_tm_attr_t {
	 * IWL_TM_ATTR_MEM_TRACE_ADDR for the trace address
	 */
	IWL_TM_ATTR_TRACE_ADDR,
	IWL_TM_ATTR_TRACE_DATA,
	IWL_TM_ATTR_TRACE_SIZE,
	IWL_TM_ATTR_TRACE_DUMP,

	/* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_FIXRATE_REQ,
	 * The mandatory fields are:
@@ -182,7 +182,7 @@ enum iwl_tm_attr_t {
#define TRACE_BUFF_SIZE_MAX	0x200000
#define TRACE_BUFF_SIZE_MIN	0x20000
#define TRACE_BUFF_SIZE_DEF	TRACE_BUFF_SIZE_MIN

#define TRACE_BUFF_PADD		0x2000
#define TRACE_CHUNK_SIZE	(PAGE_SIZE - 1024)

#endif