1 /*
2 * Copyright (c) 2020, The Linux Foundation. All rights reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 /**
18 * DOC: wlan_hdd_sysfs_crash_inject.c
19 *
20 * implementation for creating sysfs file crash_inject
21 */
22
23 #include <wlan_hdd_includes.h>
24 #include "osif_vdev_sync.h"
25 #include "wlan_hdd_sysfs.h"
26 #include "wlan_hdd_sysfs_crash_inject.h"
27
__hdd_sysfs_crash_inject_store(struct net_device * net_dev,const char * buf,size_t count)28 static ssize_t __hdd_sysfs_crash_inject_store(
29 struct net_device *net_dev,
30 const char *buf, size_t count)
31 {
32 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(net_dev);
33 struct hdd_context *hdd_ctx;
34 char buf_local[MAX_SYSFS_USER_COMMAND_SIZE_LENGTH + 1];
35 char *sptr, *token;
36 uint32_t val1, val2;
37 int ret;
38
39 if (hdd_validate_adapter(adapter))
40 return -EINVAL;
41
42 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
43 ret = wlan_hdd_validate_context(hdd_ctx);
44 if (ret != 0)
45 return ret;
46
47 if (!wlan_hdd_validate_modules_state(hdd_ctx))
48 return -EINVAL;
49
50 ret = hdd_sysfs_validate_and_copy_buf(buf_local, sizeof(buf_local),
51 buf, count);
52 if (ret) {
53 hdd_err_rl("invalid input");
54 return ret;
55 }
56
57 hdd_nofl_info("crash_inject: count %zu buf_local:(%s) net_devname %s",
58 count, buf_local, net_dev->name);
59
60 sptr = buf_local;
61 /* Get val1 */
62 token = strsep(&sptr, " ");
63 if (!token)
64 return -EINVAL;
65 if (kstrtou32(token, 0, &val1))
66 return -EINVAL;
67
68 /* Get val2 */
69 token = strsep(&sptr, " ");
70 if (!token)
71 return -EINVAL;
72 if (kstrtou32(token, 0, &val2))
73 return -EINVAL;
74
75 ret = hdd_crash_inject(adapter, val1, val2);
76 if (ret != 0) {
77 hdd_err_rl("hdd_crash_inject returned %d", ret);
78 return -EINVAL;
79 }
80
81 return count;
82 }
83
hdd_sysfs_crash_inject_store(struct device * dev,struct device_attribute * attr,char const * buf,size_t count)84 static ssize_t hdd_sysfs_crash_inject_store(struct device *dev,
85 struct device_attribute *attr,
86 char const *buf, size_t count)
87 {
88 struct net_device *net_dev = container_of(dev, struct net_device, dev);
89 struct osif_vdev_sync *vdev_sync;
90 ssize_t errno_size;
91
92 errno_size = osif_vdev_sync_op_start(net_dev, &vdev_sync);
93 if (errno_size)
94 return errno_size;
95
96 errno_size = __hdd_sysfs_crash_inject_store(
97 net_dev, buf, count);
98 if (errno_size < 0)
99 hdd_err_rl("errno_size %zd", errno_size);
100
101 osif_vdev_sync_op_stop(vdev_sync);
102
103 return errno_size;
104 }
105
106 static DEVICE_ATTR(crash_inject, 0220,
107 NULL, hdd_sysfs_crash_inject_store);
108
hdd_sysfs_crash_inject_create(struct hdd_adapter * adapter)109 int hdd_sysfs_crash_inject_create(struct hdd_adapter *adapter)
110 {
111 int error;
112
113 error = device_create_file(&adapter->dev->dev, &dev_attr_crash_inject);
114 if (error)
115 hdd_err("could not create crash_inject sysfs file");
116
117 return error;
118 }
119
hdd_sysfs_crash_inject_destroy(struct hdd_adapter * adapter)120 void hdd_sysfs_crash_inject_destroy(struct hdd_adapter *adapter)
121 {
122 device_remove_file(&adapter->dev->dev, &dev_attr_crash_inject);
123 }
124