diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx/debugfs.c')
| -rw-r--r-- | drivers/net/wireless/wl12xx/debugfs.c | 241 | 
1 files changed, 239 insertions, 2 deletions
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index 15eb3a9c30c..e1cf7276596 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -113,7 +113,7 @@ static void wl1271_debugfs_update_stats(struct wl1271 *wl)  	if (ret < 0)  		goto out; -	if (wl->state == WL1271_STATE_ON && +	if (wl->state == WL1271_STATE_ON && !wl->plt &&  	    time_after(jiffies, wl->stats.fw_stats_update +  		       msecs_to_jiffies(WL1271_DEBUGFS_STATS_LIFETIME))) {  		wl1271_acx_statistics(wl, wl->stats.fw_stats); @@ -312,6 +312,181 @@ static const struct file_operations start_recovery_ops = {  	.llseek = default_llseek,  }; +static ssize_t dynamic_ps_timeout_read(struct file *file, char __user *user_buf, +			  size_t count, loff_t *ppos) +{ +	struct wl1271 *wl = file->private_data; + +	return wl1271_format_buffer(user_buf, count, +				    ppos, "%d\n", +				    wl->conf.conn.dynamic_ps_timeout); +} + +static ssize_t dynamic_ps_timeout_write(struct file *file, +				    const char __user *user_buf, +				    size_t count, loff_t *ppos) +{ +	struct wl1271 *wl = file->private_data; +	struct wl12xx_vif *wlvif; +	unsigned long value; +	int ret; + +	ret = kstrtoul_from_user(user_buf, count, 10, &value); +	if (ret < 0) { +		wl1271_warning("illegal value in dynamic_ps"); +		return -EINVAL; +	} + +	if (value < 1 || value > 65535) { +		wl1271_warning("dyanmic_ps_timeout is not in valid range"); +		return -ERANGE; +	} + +	mutex_lock(&wl->mutex); + +	wl->conf.conn.dynamic_ps_timeout = value; + +	if (wl->state == WL1271_STATE_OFF) +		goto out; + +	ret = wl1271_ps_elp_wakeup(wl); +	if (ret < 0) +		goto out; + +	/* In case we're already in PSM, trigger it again to set new timeout +	 * immediately without waiting for re-association +	 */ + +	wl12xx_for_each_wlvif_sta(wl, wlvif) { +		if (test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags)) +			wl1271_ps_set_mode(wl, wlvif, STATION_AUTO_PS_MODE); +	} + +	wl1271_ps_elp_sleep(wl); + +out: +	mutex_unlock(&wl->mutex); +	return count; +} + +static const struct file_operations dynamic_ps_timeout_ops = { +	.read = dynamic_ps_timeout_read, +	.write = dynamic_ps_timeout_write, +	.open = wl1271_open_file_generic, +	.llseek = default_llseek, +}; + +static ssize_t forced_ps_read(struct file *file, char __user *user_buf, +			  size_t count, loff_t *ppos) +{ +	struct wl1271 *wl = file->private_data; + +	return wl1271_format_buffer(user_buf, count, +				    ppos, "%d\n", +				    wl->conf.conn.forced_ps); +} + +static ssize_t forced_ps_write(struct file *file, +				    const char __user *user_buf, +				    size_t count, loff_t *ppos) +{ +	struct wl1271 *wl = file->private_data; +	struct wl12xx_vif *wlvif; +	unsigned long value; +	int ret, ps_mode; + +	ret = kstrtoul_from_user(user_buf, count, 10, &value); +	if (ret < 0) { +		wl1271_warning("illegal value in forced_ps"); +		return -EINVAL; +	} + +	if (value != 1 && value != 0) { +		wl1271_warning("forced_ps should be either 0 or 1"); +		return -ERANGE; +	} + +	mutex_lock(&wl->mutex); + +	if (wl->conf.conn.forced_ps == value) +		goto out; + +	wl->conf.conn.forced_ps = value; + +	if (wl->state == WL1271_STATE_OFF) +		goto out; + +	ret = wl1271_ps_elp_wakeup(wl); +	if (ret < 0) +		goto out; + +	/* In case we're already in PSM, trigger it again to switch mode +	 * immediately without waiting for re-association +	 */ + +	ps_mode = value ? STATION_POWER_SAVE_MODE : STATION_AUTO_PS_MODE; + +	wl12xx_for_each_wlvif_sta(wl, wlvif) { +		if (test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags)) +			wl1271_ps_set_mode(wl, wlvif, ps_mode); +	} + +	wl1271_ps_elp_sleep(wl); + +out: +	mutex_unlock(&wl->mutex); +	return count; +} + +static const struct file_operations forced_ps_ops = { +	.read = forced_ps_read, +	.write = forced_ps_write, +	.open = wl1271_open_file_generic, +	.llseek = default_llseek, +}; + +static ssize_t split_scan_timeout_read(struct file *file, char __user *user_buf, +			  size_t count, loff_t *ppos) +{ +	struct wl1271 *wl = file->private_data; + +	return wl1271_format_buffer(user_buf, count, +				    ppos, "%d\n", +				    wl->conf.scan.split_scan_timeout / 1000); +} + +static ssize_t split_scan_timeout_write(struct file *file, +				    const char __user *user_buf, +				    size_t count, loff_t *ppos) +{ +	struct wl1271 *wl = file->private_data; +	unsigned long value; +	int ret; + +	ret = kstrtoul_from_user(user_buf, count, 10, &value); +	if (ret < 0) { +		wl1271_warning("illegal value in split_scan_timeout"); +		return -EINVAL; +	} + +	if (value == 0) +		wl1271_info("split scan will be disabled"); + +	mutex_lock(&wl->mutex); + +	wl->conf.scan.split_scan_timeout = value * 1000; + +	mutex_unlock(&wl->mutex); +	return count; +} + +static const struct file_operations split_scan_timeout_ops = { +	.read = split_scan_timeout_read, +	.write = split_scan_timeout_write, +	.open = wl1271_open_file_generic, +	.llseek = default_llseek, +}; +  static ssize_t driver_state_read(struct file *file, char __user *user_buf,  				 size_t count, loff_t *ppos)  { @@ -446,6 +621,7 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf,  			VIF_STATE_PRINT_INT(sta.basic_rate_idx);  			VIF_STATE_PRINT_INT(sta.ap_rate_idx);  			VIF_STATE_PRINT_INT(sta.p2p_rate_idx); +			VIF_STATE_PRINT_INT(sta.qos);  		} else {  			VIF_STATE_PRINT_INT(ap.global_hlid);  			VIF_STATE_PRINT_INT(ap.bcast_hlid); @@ -471,7 +647,6 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf,  		VIF_STATE_PRINT_INT(default_key);  		VIF_STATE_PRINT_INT(aid);  		VIF_STATE_PRINT_INT(session_counter); -		VIF_STATE_PRINT_INT(ps_poll_failures);  		VIF_STATE_PRINT_INT(psm_entry_retry);  		VIF_STATE_PRINT_INT(power_level);  		VIF_STATE_PRINT_INT(rssi_thold); @@ -562,6 +737,64 @@ static const struct file_operations dtim_interval_ops = {  	.llseek = default_llseek,  }; + + +static ssize_t suspend_dtim_interval_read(struct file *file, +					  char __user *user_buf, +					  size_t count, loff_t *ppos) +{ +	struct wl1271 *wl = file->private_data; +	u8 value; + +	if (wl->conf.conn.suspend_wake_up_event == CONF_WAKE_UP_EVENT_DTIM || +	    wl->conf.conn.suspend_wake_up_event == CONF_WAKE_UP_EVENT_N_DTIM) +		value = wl->conf.conn.suspend_listen_interval; +	else +		value = 0; + +	return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value); +} + +static ssize_t suspend_dtim_interval_write(struct file *file, +					   const char __user *user_buf, +					   size_t count, loff_t *ppos) +{ +	struct wl1271 *wl = file->private_data; +	unsigned long value; +	int ret; + +	ret = kstrtoul_from_user(user_buf, count, 10, &value); +	if (ret < 0) { +		wl1271_warning("illegal value for suspend_dtim_interval"); +		return -EINVAL; +	} + +	if (value < 1 || value > 10) { +		wl1271_warning("suspend_dtim value is not in valid range"); +		return -ERANGE; +	} + +	mutex_lock(&wl->mutex); + +	wl->conf.conn.suspend_listen_interval = value; +	/* for some reason there are different event types for 1 and >1 */ +	if (value == 1) +		wl->conf.conn.suspend_wake_up_event = CONF_WAKE_UP_EVENT_DTIM; +	else +		wl->conf.conn.suspend_wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM; + +	mutex_unlock(&wl->mutex); +	return count; +} + + +static const struct file_operations suspend_dtim_interval_ops = { +	.read = suspend_dtim_interval_read, +	.write = suspend_dtim_interval_write, +	.open = wl1271_open_file_generic, +	.llseek = default_llseek, +}; +  static ssize_t beacon_interval_read(struct file *file, char __user *user_buf,  				    size_t count, loff_t *ppos)  { @@ -886,8 +1119,12 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl,  	DEBUGFS_ADD(driver_state, rootdir);  	DEBUGFS_ADD(vifs_state, rootdir);  	DEBUGFS_ADD(dtim_interval, rootdir); +	DEBUGFS_ADD(suspend_dtim_interval, rootdir);  	DEBUGFS_ADD(beacon_interval, rootdir);  	DEBUGFS_ADD(beacon_filtering, rootdir); +	DEBUGFS_ADD(dynamic_ps_timeout, rootdir); +	DEBUGFS_ADD(forced_ps, rootdir); +	DEBUGFS_ADD(split_scan_timeout, rootdir);  	streaming = debugfs_create_dir("rx_streaming", rootdir);  	if (!streaming || IS_ERR(streaming))  |