cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sysfs.c (3709B)


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