File Index
Files and directories
Sign in
FILE

sysfs.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/wireless/ti/wlcore/sysfs.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * This file is part of wlcore
  4 *
  5 * Copyright (C) 2013 Texas Instruments Inc.
  6 */
  7
  8#include <linux/pm_runtime.h>
  9
 10#include "acx.h"
 11#include "wlcore.h"
 12#include "debug.h"
 13#include "sysfs.h"
 14
 15static ssize_t bt_coex_state_show(struct device *dev,
 16				  struct device_attribute *attr,
 17				  char *buf)
 18{
 19	struct wl1271 *wl = dev_get_drvdata(dev);
 20	ssize_t len;
 21
 22	mutex_lock(&wl->mutex);
 23	len = sysfs_emit(buf, "%d\n\n0 - off\n1 - on\n", wl->sg_enabled);
 24	mutex_unlock(&wl->mutex);
 25
 26	return len;
 27
 28}
 29
 30static ssize_t bt_coex_state_store(struct device *dev,
 31				   struct device_attribute *attr,
 32				   const char *buf, size_t count)
 33{
 34	struct wl1271 *wl = dev_get_drvdata(dev);
 35	unsigned long res;
 36	int ret;
 37
 38	ret = kstrtoul(buf, 10, &res);
 39	if (ret < 0) {
 40		wl1271_warning("incorrect value written to bt_coex_mode");
 41		return count;
 42	}
 43
 44	mutex_lock(&wl->mutex);
 45
 46	res = !!res;
 47
 48	if (res == wl->sg_enabled)
 49		goto out;
 50
 51	wl->sg_enabled = res;
 52
 53	if (unlikely(wl->state != WLCORE_STATE_ON))
 54		goto out;
 55
 56	ret = pm_runtime_resume_and_get(wl->dev);
 57	if (ret < 0)
 58		goto out;
 59
 60	wl1271_acx_sg_enable(wl, wl->sg_enabled);
 61	pm_runtime_put_autosuspend(wl->dev);
 62
 63 out:
 64	mutex_unlock(&wl->mutex);
 65	return count;
 66}
 67
 68static DEVICE_ATTR_RW(bt_coex_state);
 69
 70static ssize_t hw_pg_ver_show(struct device *dev,
 71			      struct device_attribute *attr,
 72			      char *buf)
 73{
 74	struct wl1271 *wl = dev_get_drvdata(dev);
 75	ssize_t len;
 76
 77	mutex_lock(&wl->mutex);
 78	if (wl->hw_pg_ver >= 0)
 79		len = sysfs_emit(buf, "%d\n", wl->hw_pg_ver);
 80	else
 81		len = sysfs_emit(buf, "n/a\n");
 82	mutex_unlock(&wl->mutex);
 83
 84	return len;
 85}
 86
 87static DEVICE_ATTR_RO(hw_pg_ver);
 88
 89static ssize_t wl1271_sysfs_read_fwlog(struct file *filp, struct kobject *kobj,
 90				       const struct bin_attribute *bin_attr,
 91				       char *buffer, loff_t pos, size_t count)
 92{
 93	struct device *dev = kobj_to_dev(kobj);
 94	struct wl1271 *wl = dev_get_drvdata(dev);
 95	ssize_t len;
 96	int ret;
 97
 98	ret = mutex_lock_interruptible(&wl->mutex);
 99	if (ret < 0)
100		return -ERESTARTSYS;
101
102	/* Check if the fwlog is still valid */
103	if (wl->fwlog_size < 0) {
104		mutex_unlock(&wl->mutex);
105		return 0;
106	}
107
108	/* Seeking is not supported - old logs are not kept. Disregard pos. */
109	len = min_t(size_t, count, wl->fwlog_size);
110	wl->fwlog_size -= len;
111	memcpy(buffer, wl->fwlog, len);
112
113	/* Make room for new messages */
114	memmove(wl->fwlog, wl->fwlog + len, wl->fwlog_size);
115
116	mutex_unlock(&wl->mutex);
117
118	return len;
119}
120
121static const struct bin_attribute fwlog_attr = {
122	.attr = { .name = "fwlog", .mode = 0400 },
123	.read = wl1271_sysfs_read_fwlog,
124};
125
126int wlcore_sysfs_init(struct wl1271 *wl)
127{
128	int ret;
129
130	/* Create sysfs file to control bt coex state */
131	ret = device_create_file(wl->dev, &dev_attr_bt_coex_state);
132	if (ret < 0) {
133		wl1271_error("failed to create sysfs file bt_coex_state");
134		goto out;
135	}
136
137	/* Create sysfs file to get HW PG version */
138	ret = device_create_file(wl->dev, &dev_attr_hw_pg_ver);
139	if (ret < 0) {
140		wl1271_error("failed to create sysfs file hw_pg_ver");
141		goto out_bt_coex_state;
142	}
143
144	/* Create sysfs file for the FW log */
145	ret = device_create_bin_file(wl->dev, &fwlog_attr);
146	if (ret < 0) {
147		wl1271_error("failed to create sysfs file fwlog");
148		goto out_hw_pg_ver;
149	}
150
151	goto out;
152
153out_hw_pg_ver:
154	device_remove_file(wl->dev, &dev_attr_hw_pg_ver);
155
156out_bt_coex_state:
157	device_remove_file(wl->dev, &dev_attr_bt_coex_state);
158
159out:
160	return ret;
161}
162
163void wlcore_sysfs_free(struct wl1271 *wl)
164{
165	device_remove_bin_file(wl->dev, &fwlog_attr);
166
167	device_remove_file(wl->dev, &dev_attr_hw_pg_ver);
168
169	device_remove_file(wl->dev, &dev_attr_bt_coex_state);
170}
~/ Read-only file preview.