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

Commit 937a5045 authored by Xinming Hu's avatar Xinming Hu Committed by John W. Linville
Browse files

mwifiex: add hscfg to debugfs



Some SDIO controllers do not support MMC_PM_KEEP_POWER properly.
To test host sleep feature without putting the system into sleep
we need to simulate host sleep configuration & handshake between
driver and firmware using customized parameters.
This patch adds hscfg debugfs item, with which user could change
host sleep parameters for debugging.

Signed-off-by: default avatarXinming Hu <huxm@marvell.com>
Signed-off-by: default avatarBing Zhao <bzhao@marvell.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 54881c6b
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -194,6 +194,36 @@ rdeeprom
	Example:
		echo "0 20" > rdeeprom      : Read 20 bytes of EEPROM data from offset 0

hscfg
	This command is used to debug/simulate host sleep feature using
	different configuration parameters.

	Usage:
		echo "<condition> [GPIO# [gap]]]" > hscfg
		cat hscfg

	where the parameters are,
		<condition>: bit 0 = 1   -- broadcast data
			     bit 1 = 1   -- unicast data
			     bit 2 = 1   -- mac event
			     bit 3 = 1   -- multicast data
		[GPIO#]: pin number of GPIO used to wakeup the host.
			 GPIO pin# (e.g. 0-7) or 0xff (interface, e.g. SDIO
			 will be used instead).
		[gap]:   the gap in milliseconds between wakeup signal and
			 wakeup event or 0xff for special setting (host
			 acknowledge required) when GPIO is used to wakeup host.

	Examples:
		echo "-1" > hscfg        : Cancel host sleep mode
		echo "3" > hscfg         : Broadcast and unicast data;
					   Use GPIO and gap set previously
		echo "2 3" > hscfg       : Unicast data and GPIO 3;
					   Use gap set previously
		echo "2 1 160" > hscfg   : Unicast data, GPIO 1 and gap 160 ms
		echo "2 1 0xff" > hscfg  : Unicast data, GPIO 1; Wait for host
					   to ack before sending wakeup event

getlog
        This command is used to get the statistics available in the station.
	Usage:
+93 −0
Original line number Diff line number Diff line
@@ -692,6 +692,97 @@ mwifiex_rdeeprom_read(struct file *file, char __user *ubuf,
	return ret;
}

/* Proc hscfg file write handler
 * This function can be used to configure the host sleep parameters.
 */
static ssize_t
mwifiex_hscfg_write(struct file *file, const char __user *ubuf,
		    size_t count, loff_t *ppos)
{
	struct mwifiex_private *priv = (void *)file->private_data;
	unsigned long addr = get_zeroed_page(GFP_KERNEL);
	char *buf = (char *)addr;
	size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
	int ret, arg_num;
	struct mwifiex_ds_hs_cfg hscfg;
	int conditions = HS_CFG_COND_DEF;
	u32 gpio = HS_CFG_GPIO_DEF, gap = HS_CFG_GAP_DEF;

	if (!buf)
		return -ENOMEM;

	if (copy_from_user(buf, ubuf, buf_size)) {
		ret = -EFAULT;
		goto done;
	}

	arg_num = sscanf(buf, "%d %x %x", &conditions, &gpio, &gap);

	memset(&hscfg, 0, sizeof(struct mwifiex_ds_hs_cfg));

	if (arg_num > 3) {
		dev_err(priv->adapter->dev, "Too many arguments\n");
		ret = -EINVAL;
		goto done;
	}

	if (arg_num >= 1 && arg_num < 3)
		mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_GET,
				      MWIFIEX_SYNC_CMD, &hscfg);

	if (arg_num) {
		if (conditions == HS_CFG_CANCEL) {
			mwifiex_cancel_hs(priv, MWIFIEX_ASYNC_CMD);
			ret = count;
			goto done;
		}
		hscfg.conditions = conditions;
	}
	if (arg_num >= 2)
		hscfg.gpio = gpio;
	if (arg_num == 3)
		hscfg.gap = gap;

	hscfg.is_invoke_hostcmd = false;
	mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET,
			      MWIFIEX_SYNC_CMD, &hscfg);

	mwifiex_enable_hs(priv->adapter);
	priv->adapter->hs_enabling = false;
	ret = count;
done:
	free_page(addr);
	return ret;
}

/* Proc hscfg file read handler
 * This function can be used to read host sleep configuration
 * parameters from driver.
 */
static ssize_t
mwifiex_hscfg_read(struct file *file, char __user *ubuf,
		   size_t count, loff_t *ppos)
{
	struct mwifiex_private *priv = (void *)file->private_data;
	unsigned long addr = get_zeroed_page(GFP_KERNEL);
	char *buf = (char *)addr;
	int pos, ret;
	struct mwifiex_ds_hs_cfg hscfg;

	if (!buf)
		return -ENOMEM;

	mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_GET,
			      MWIFIEX_SYNC_CMD, &hscfg);

	pos = snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", hscfg.conditions,
		       hscfg.gpio, hscfg.gap);

	ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);

	free_page(addr);
	return ret;
}

#define MWIFIEX_DFS_ADD_FILE(name) do {                                 \
	if (!debugfs_create_file(#name, 0644, priv->dfs_dev_dir,        \
@@ -725,6 +816,7 @@ MWIFIEX_DFS_FILE_READ_OPS(getlog);
MWIFIEX_DFS_FILE_READ_OPS(fw_dump);
MWIFIEX_DFS_FILE_OPS(regrdwr);
MWIFIEX_DFS_FILE_OPS(rdeeprom);
MWIFIEX_DFS_FILE_OPS(hscfg);

/*
 * This function creates the debug FS directory structure and the files.
@@ -747,6 +839,7 @@ mwifiex_dev_debugfs_init(struct mwifiex_private *priv)
	MWIFIEX_DFS_ADD_FILE(regrdwr);
	MWIFIEX_DFS_ADD_FILE(rdeeprom);
	MWIFIEX_DFS_ADD_FILE(fw_dump);
	MWIFIEX_DFS_ADD_FILE(hscfg);
}

/*
+2 −0
Original line number Diff line number Diff line
@@ -920,6 +920,8 @@ int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,
void mwifiex_process_hs_config(struct mwifiex_adapter *adapter);
void mwifiex_hs_activated_event(struct mwifiex_private *priv,
					u8 activated);
int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
			  int cmd_type, struct mwifiex_ds_hs_cfg *hs_cfg);
int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv,
			      struct host_cmd_ds_command *resp);
int mwifiex_process_rx_packet(struct mwifiex_private *priv,
+2 −2
Original line number Diff line number Diff line
@@ -389,7 +389,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
 * This function prepares the correct firmware command and
 * issues it.
 */
static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
			  int cmd_type, struct mwifiex_ds_hs_cfg *hs_cfg)

{