root/drivers/net/wireless/ti/wlcore/sysfs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wl1271_sysfs_show_bt_coex_state
  2. wl1271_sysfs_store_bt_coex_state
  3. wl1271_sysfs_show_hw_pg_ver
  4. wl1271_sysfs_read_fwlog
  5. wlcore_sysfs_init
  6. wlcore_sysfs_free

   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 
  15 static ssize_t wl1271_sysfs_show_bt_coex_state(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 
  33 static ssize_t wl1271_sysfs_store_bt_coex_state(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_get_sync(wl->dev);
  60         if (ret < 0) {
  61                 pm_runtime_put_noidle(wl->dev);
  62                 goto out;
  63         }
  64 
  65         wl1271_acx_sg_enable(wl, wl->sg_enabled);
  66         pm_runtime_mark_last_busy(wl->dev);
  67         pm_runtime_put_autosuspend(wl->dev);
  68 
  69  out:
  70         mutex_unlock(&wl->mutex);
  71         return count;
  72 }
  73 
  74 static DEVICE_ATTR(bt_coex_state, 0644,
  75                    wl1271_sysfs_show_bt_coex_state,
  76                    wl1271_sysfs_store_bt_coex_state);
  77 
  78 static ssize_t wl1271_sysfs_show_hw_pg_ver(struct device *dev,
  79                                            struct device_attribute *attr,
  80                                            char *buf)
  81 {
  82         struct wl1271 *wl = dev_get_drvdata(dev);
  83         ssize_t len;
  84 
  85         len = PAGE_SIZE;
  86 
  87         mutex_lock(&wl->mutex);
  88         if (wl->hw_pg_ver >= 0)
  89                 len = snprintf(buf, len, "%d\n", wl->hw_pg_ver);
  90         else
  91                 len = snprintf(buf, len, "n/a\n");
  92         mutex_unlock(&wl->mutex);
  93 
  94         return len;
  95 }
  96 
  97 static DEVICE_ATTR(hw_pg_ver, 0444, wl1271_sysfs_show_hw_pg_ver, NULL);
  98 
  99 static ssize_t wl1271_sysfs_read_fwlog(struct file *filp, struct kobject *kobj,
 100                                        struct bin_attribute *bin_attr,
 101                                        char *buffer, loff_t pos, size_t count)
 102 {
 103         struct device *dev = container_of(kobj, struct device, kobj);
 104         struct wl1271 *wl = dev_get_drvdata(dev);
 105         ssize_t len;
 106         int ret;
 107 
 108         ret = mutex_lock_interruptible(&wl->mutex);
 109         if (ret < 0)
 110                 return -ERESTARTSYS;
 111 
 112         /* Check if the fwlog is still valid */
 113         if (wl->fwlog_size < 0) {
 114                 mutex_unlock(&wl->mutex);
 115                 return 0;
 116         }
 117 
 118         /* Seeking is not supported - old logs are not kept. Disregard pos. */
 119         len = min_t(size_t, count, wl->fwlog_size);
 120         wl->fwlog_size -= len;
 121         memcpy(buffer, wl->fwlog, len);
 122 
 123         /* Make room for new messages */
 124         memmove(wl->fwlog, wl->fwlog + len, wl->fwlog_size);
 125 
 126         mutex_unlock(&wl->mutex);
 127 
 128         return len;
 129 }
 130 
 131 static const struct bin_attribute fwlog_attr = {
 132         .attr = { .name = "fwlog", .mode = 0400 },
 133         .read = wl1271_sysfs_read_fwlog,
 134 };
 135 
 136 int wlcore_sysfs_init(struct wl1271 *wl)
 137 {
 138         int ret;
 139 
 140         /* Create sysfs file to control bt coex state */
 141         ret = device_create_file(wl->dev, &dev_attr_bt_coex_state);
 142         if (ret < 0) {
 143                 wl1271_error("failed to create sysfs file bt_coex_state");
 144                 goto out;
 145         }
 146 
 147         /* Create sysfs file to get HW PG version */
 148         ret = device_create_file(wl->dev, &dev_attr_hw_pg_ver);
 149         if (ret < 0) {
 150                 wl1271_error("failed to create sysfs file hw_pg_ver");
 151                 goto out_bt_coex_state;
 152         }
 153 
 154         /* Create sysfs file for the FW log */
 155         ret = device_create_bin_file(wl->dev, &fwlog_attr);
 156         if (ret < 0) {
 157                 wl1271_error("failed to create sysfs file fwlog");
 158                 goto out_hw_pg_ver;
 159         }
 160 
 161         goto out;
 162 
 163 out_hw_pg_ver:
 164         device_remove_file(wl->dev, &dev_attr_hw_pg_ver);
 165 
 166 out_bt_coex_state:
 167         device_remove_file(wl->dev, &dev_attr_bt_coex_state);
 168 
 169 out:
 170         return ret;
 171 }
 172 
 173 void wlcore_sysfs_free(struct wl1271 *wl)
 174 {
 175         device_remove_bin_file(wl->dev, &fwlog_attr);
 176 
 177         device_remove_file(wl->dev, &dev_attr_hw_pg_ver);
 178 
 179         device_remove_file(wl->dev, &dev_attr_bt_coex_state);
 180 }

/* [<][>][^][v][top][bottom][index][help] */