xref: /linux/drivers/net/wireless/ti/wlcore/sysfs.c (revision 621cde16e49b3ecf7d59a8106a20aaebfb4a59a9)
12b27bdccSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
233cab57aSLuciano Coelho /*
333cab57aSLuciano Coelho  * This file is part of wlcore
433cab57aSLuciano Coelho  *
533cab57aSLuciano Coelho  * Copyright (C) 2013 Texas Instruments Inc.
633cab57aSLuciano Coelho  */
733cab57aSLuciano Coelho 
8fa2648a3STony Lindgren #include <linux/pm_runtime.h>
9fa2648a3STony Lindgren 
10fa2648a3STony Lindgren #include "acx.h"
1133cab57aSLuciano Coelho #include "wlcore.h"
1233cab57aSLuciano Coelho #include "debug.h"
1333cab57aSLuciano Coelho #include "sysfs.h"
1433cab57aSLuciano Coelho 
bt_coex_state_show(struct device * dev,struct device_attribute * attr,char * buf)1586f1ea9dSYueHaibing static ssize_t bt_coex_state_show(struct device *dev,
1633cab57aSLuciano Coelho 				  struct device_attribute *attr,
1733cab57aSLuciano Coelho 				  char *buf)
1833cab57aSLuciano Coelho {
1933cab57aSLuciano Coelho 	struct wl1271 *wl = dev_get_drvdata(dev);
2033cab57aSLuciano Coelho 	ssize_t len;
2133cab57aSLuciano Coelho 
2233cab57aSLuciano Coelho 	mutex_lock(&wl->mutex);
23*48be5774SLi Zhijian 	len = sysfs_emit(buf, "%d\n\n0 - off\n1 - on\n", wl->sg_enabled);
2433cab57aSLuciano Coelho 	mutex_unlock(&wl->mutex);
2533cab57aSLuciano Coelho 
2633cab57aSLuciano Coelho 	return len;
2733cab57aSLuciano Coelho 
2833cab57aSLuciano Coelho }
2933cab57aSLuciano Coelho 
bt_coex_state_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)3086f1ea9dSYueHaibing static ssize_t bt_coex_state_store(struct device *dev,
3133cab57aSLuciano Coelho 				   struct device_attribute *attr,
3233cab57aSLuciano Coelho 				   const char *buf, size_t count)
3333cab57aSLuciano Coelho {
3433cab57aSLuciano Coelho 	struct wl1271 *wl = dev_get_drvdata(dev);
3533cab57aSLuciano Coelho 	unsigned long res;
3633cab57aSLuciano Coelho 	int ret;
3733cab57aSLuciano Coelho 
3833cab57aSLuciano Coelho 	ret = kstrtoul(buf, 10, &res);
3933cab57aSLuciano Coelho 	if (ret < 0) {
4033cab57aSLuciano Coelho 		wl1271_warning("incorrect value written to bt_coex_mode");
4133cab57aSLuciano Coelho 		return count;
4233cab57aSLuciano Coelho 	}
4333cab57aSLuciano Coelho 
4433cab57aSLuciano Coelho 	mutex_lock(&wl->mutex);
4533cab57aSLuciano Coelho 
4633cab57aSLuciano Coelho 	res = !!res;
4733cab57aSLuciano Coelho 
4833cab57aSLuciano Coelho 	if (res == wl->sg_enabled)
4933cab57aSLuciano Coelho 		goto out;
5033cab57aSLuciano Coelho 
5133cab57aSLuciano Coelho 	wl->sg_enabled = res;
5233cab57aSLuciano Coelho 
5333cab57aSLuciano Coelho 	if (unlikely(wl->state != WLCORE_STATE_ON))
5433cab57aSLuciano Coelho 		goto out;
5533cab57aSLuciano Coelho 
56da8e909cSMinghao Chi 	ret = pm_runtime_resume_and_get(wl->dev);
57da8e909cSMinghao Chi 	if (ret < 0)
5833cab57aSLuciano Coelho 		goto out;
5933cab57aSLuciano Coelho 
6033cab57aSLuciano Coelho 	wl1271_acx_sg_enable(wl, wl->sg_enabled);
619b71578dSTony Lindgren 	pm_runtime_mark_last_busy(wl->dev);
629b71578dSTony Lindgren 	pm_runtime_put_autosuspend(wl->dev);
6333cab57aSLuciano Coelho 
6433cab57aSLuciano Coelho  out:
6533cab57aSLuciano Coelho 	mutex_unlock(&wl->mutex);
6633cab57aSLuciano Coelho 	return count;
6733cab57aSLuciano Coelho }
6833cab57aSLuciano Coelho 
6986f1ea9dSYueHaibing static DEVICE_ATTR_RW(bt_coex_state);
7033cab57aSLuciano Coelho 
hw_pg_ver_show(struct device * dev,struct device_attribute * attr,char * buf)7186f1ea9dSYueHaibing static ssize_t hw_pg_ver_show(struct device *dev,
7233cab57aSLuciano Coelho 			      struct device_attribute *attr,
7333cab57aSLuciano Coelho 			      char *buf)
7433cab57aSLuciano Coelho {
7533cab57aSLuciano Coelho 	struct wl1271 *wl = dev_get_drvdata(dev);
7633cab57aSLuciano Coelho 	ssize_t len;
7733cab57aSLuciano Coelho 
7833cab57aSLuciano Coelho 	mutex_lock(&wl->mutex);
7933cab57aSLuciano Coelho 	if (wl->hw_pg_ver >= 0)
80*48be5774SLi Zhijian 		len = sysfs_emit(buf, "%d\n", wl->hw_pg_ver);
8133cab57aSLuciano Coelho 	else
82*48be5774SLi Zhijian 		len = sysfs_emit(buf, "n/a\n");
8333cab57aSLuciano Coelho 	mutex_unlock(&wl->mutex);
8433cab57aSLuciano Coelho 
8533cab57aSLuciano Coelho 	return len;
8633cab57aSLuciano Coelho }
8733cab57aSLuciano Coelho 
8886f1ea9dSYueHaibing static DEVICE_ATTR_RO(hw_pg_ver);
8933cab57aSLuciano Coelho 
wl1271_sysfs_read_fwlog(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buffer,loff_t pos,size_t count)9033cab57aSLuciano Coelho static ssize_t wl1271_sysfs_read_fwlog(struct file *filp, struct kobject *kobj,
9133cab57aSLuciano Coelho 				       struct bin_attribute *bin_attr,
9233cab57aSLuciano Coelho 				       char *buffer, loff_t pos, size_t count)
9333cab57aSLuciano Coelho {
943b52cf62STian Tao 	struct device *dev = kobj_to_dev(kobj);
9533cab57aSLuciano Coelho 	struct wl1271 *wl = dev_get_drvdata(dev);
9633cab57aSLuciano Coelho 	ssize_t len;
9733cab57aSLuciano Coelho 	int ret;
9833cab57aSLuciano Coelho 
9933cab57aSLuciano Coelho 	ret = mutex_lock_interruptible(&wl->mutex);
10033cab57aSLuciano Coelho 	if (ret < 0)
10133cab57aSLuciano Coelho 		return -ERESTARTSYS;
10233cab57aSLuciano Coelho 
10333cab57aSLuciano Coelho 	/* Check if the fwlog is still valid */
10433cab57aSLuciano Coelho 	if (wl->fwlog_size < 0) {
10533cab57aSLuciano Coelho 		mutex_unlock(&wl->mutex);
10633cab57aSLuciano Coelho 		return 0;
10733cab57aSLuciano Coelho 	}
10833cab57aSLuciano Coelho 
10933cab57aSLuciano Coelho 	/* Seeking is not supported - old logs are not kept. Disregard pos. */
110c8e49556SSilvan Jegen 	len = min_t(size_t, count, wl->fwlog_size);
11133cab57aSLuciano Coelho 	wl->fwlog_size -= len;
11233cab57aSLuciano Coelho 	memcpy(buffer, wl->fwlog, len);
11333cab57aSLuciano Coelho 
11433cab57aSLuciano Coelho 	/* Make room for new messages */
11533cab57aSLuciano Coelho 	memmove(wl->fwlog, wl->fwlog + len, wl->fwlog_size);
11633cab57aSLuciano Coelho 
11733cab57aSLuciano Coelho 	mutex_unlock(&wl->mutex);
11833cab57aSLuciano Coelho 
11933cab57aSLuciano Coelho 	return len;
12033cab57aSLuciano Coelho }
12133cab57aSLuciano Coelho 
1224f2949feSBhumika Goyal static const struct bin_attribute fwlog_attr = {
1232ef00c53SJoe Perches 	.attr = { .name = "fwlog", .mode = 0400 },
12433cab57aSLuciano Coelho 	.read = wl1271_sysfs_read_fwlog,
12533cab57aSLuciano Coelho };
12633cab57aSLuciano Coelho 
wlcore_sysfs_init(struct wl1271 * wl)12733cab57aSLuciano Coelho int wlcore_sysfs_init(struct wl1271 *wl)
12833cab57aSLuciano Coelho {
12933cab57aSLuciano Coelho 	int ret;
13033cab57aSLuciano Coelho 
13133cab57aSLuciano Coelho 	/* Create sysfs file to control bt coex state */
13233cab57aSLuciano Coelho 	ret = device_create_file(wl->dev, &dev_attr_bt_coex_state);
13333cab57aSLuciano Coelho 	if (ret < 0) {
13433cab57aSLuciano Coelho 		wl1271_error("failed to create sysfs file bt_coex_state");
13533cab57aSLuciano Coelho 		goto out;
13633cab57aSLuciano Coelho 	}
13733cab57aSLuciano Coelho 
13833cab57aSLuciano Coelho 	/* Create sysfs file to get HW PG version */
13933cab57aSLuciano Coelho 	ret = device_create_file(wl->dev, &dev_attr_hw_pg_ver);
14033cab57aSLuciano Coelho 	if (ret < 0) {
14133cab57aSLuciano Coelho 		wl1271_error("failed to create sysfs file hw_pg_ver");
14233cab57aSLuciano Coelho 		goto out_bt_coex_state;
14333cab57aSLuciano Coelho 	}
14433cab57aSLuciano Coelho 
14533cab57aSLuciano Coelho 	/* Create sysfs file for the FW log */
14633cab57aSLuciano Coelho 	ret = device_create_bin_file(wl->dev, &fwlog_attr);
14733cab57aSLuciano Coelho 	if (ret < 0) {
14833cab57aSLuciano Coelho 		wl1271_error("failed to create sysfs file fwlog");
14933cab57aSLuciano Coelho 		goto out_hw_pg_ver;
15033cab57aSLuciano Coelho 	}
15133cab57aSLuciano Coelho 
15233cab57aSLuciano Coelho 	goto out;
15333cab57aSLuciano Coelho 
15433cab57aSLuciano Coelho out_hw_pg_ver:
15533cab57aSLuciano Coelho 	device_remove_file(wl->dev, &dev_attr_hw_pg_ver);
15633cab57aSLuciano Coelho 
15733cab57aSLuciano Coelho out_bt_coex_state:
15833cab57aSLuciano Coelho 	device_remove_file(wl->dev, &dev_attr_bt_coex_state);
15933cab57aSLuciano Coelho 
16033cab57aSLuciano Coelho out:
16133cab57aSLuciano Coelho 	return ret;
16233cab57aSLuciano Coelho }
16333cab57aSLuciano Coelho 
wlcore_sysfs_free(struct wl1271 * wl)16433cab57aSLuciano Coelho void wlcore_sysfs_free(struct wl1271 *wl)
16533cab57aSLuciano Coelho {
16633cab57aSLuciano Coelho 	device_remove_bin_file(wl->dev, &fwlog_attr);
16733cab57aSLuciano Coelho 
16833cab57aSLuciano Coelho 	device_remove_file(wl->dev, &dev_attr_hw_pg_ver);
16933cab57aSLuciano Coelho 
17033cab57aSLuciano Coelho 	device_remove_file(wl->dev, &dev_attr_bt_coex_state);
17133cab57aSLuciano Coelho }
172