]>
Commit | Line | Data |
---|---|---|
30e53bb8 TW |
1 | /* |
2 | * | |
3 | * Intel Management Engine Interface (Intel MEI) Linux driver | |
4 | * Copyright (c) 2012-2013, Intel Corporation. | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify it | |
7 | * under the terms and conditions of the GNU General Public License, | |
8 | * version 2, as published by the Free Software Foundation. | |
9 | * | |
10 | * This program is distributed in the hope it will be useful, but WITHOUT | |
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
13 | * more details. | |
14 | * | |
15 | */ | |
16 | #include <linux/slab.h> | |
17 | #include <linux/kernel.h> | |
18 | #include <linux/device.h> | |
19 | #include <linux/debugfs.h> | |
30e53bb8 TW |
20 | |
21 | #include <linux/mei.h> | |
22 | ||
23 | #include "mei_dev.h" | |
24 | #include "hw.h" | |
25 | ||
30e53bb8 TW |
26 | static ssize_t mei_dbgfs_read_meclients(struct file *fp, char __user *ubuf, |
27 | size_t cnt, loff_t *ppos) | |
28 | { | |
29 | struct mei_device *dev = fp->private_data; | |
5ca2d388 | 30 | struct mei_me_client *me_cl; |
c4495200 AU |
31 | size_t bufsz = 1; |
32 | char *buf; | |
5ca2d388 | 33 | int i = 0; |
30e53bb8 TW |
34 | int pos = 0; |
35 | int ret; | |
36 | ||
4ade4352 | 37 | #define HDR " |id|fix| UUID |con|msg len|sb|\n" |
30e53bb8 TW |
38 | |
39 | mutex_lock(&dev->device_lock); | |
40 | ||
c4495200 AU |
41 | list_for_each_entry(me_cl, &dev->me_clients, list) |
42 | bufsz++; | |
43 | ||
44 | bufsz *= sizeof(HDR) + 1; | |
45 | buf = kzalloc(bufsz, GFP_KERNEL); | |
46 | if (!buf) { | |
47 | mutex_unlock(&dev->device_lock); | |
48 | return -ENOMEM; | |
49 | } | |
50 | ||
51 | pos += scnprintf(buf + pos, bufsz - pos, HDR); | |
52 | ||
83ce0741 | 53 | /* if the driver is not enabled the list won't be consistent */ |
30e53bb8 TW |
54 | if (dev->dev_state != MEI_DEV_ENABLED) |
55 | goto out; | |
56 | ||
5ca2d388 | 57 | list_for_each_entry(me_cl, &dev->me_clients, list) { |
30e53bb8 | 58 | |
30e53bb8 | 59 | pos += scnprintf(buf + pos, bufsz - pos, |
4ade4352 | 60 | "%2d|%2d|%3d|%pUl|%3d|%7d|%2d|\n", |
5ca2d388 TW |
61 | i++, me_cl->client_id, |
62 | me_cl->props.fixed_address, | |
63 | &me_cl->props.protocol_name, | |
64 | me_cl->props.max_number_of_connections, | |
2fbab576 TW |
65 | me_cl->props.max_msg_length, |
66 | me_cl->props.single_recv_buf); | |
30e53bb8 TW |
67 | } |
68 | out: | |
69 | mutex_unlock(&dev->device_lock); | |
70 | ret = simple_read_from_buffer(ubuf, cnt, ppos, buf, pos); | |
71 | kfree(buf); | |
72 | return ret; | |
73 | } | |
74 | ||
75 | static const struct file_operations mei_dbgfs_fops_meclients = { | |
a42f82f5 | 76 | .open = simple_open, |
30e53bb8 TW |
77 | .read = mei_dbgfs_read_meclients, |
78 | .llseek = generic_file_llseek, | |
79 | }; | |
80 | ||
5baaf71f TW |
81 | static ssize_t mei_dbgfs_read_active(struct file *fp, char __user *ubuf, |
82 | size_t cnt, loff_t *ppos) | |
83 | { | |
84 | struct mei_device *dev = fp->private_data; | |
85 | struct mei_cl *cl; | |
86 | const size_t bufsz = 1024; | |
87 | char *buf; | |
88 | int i = 0; | |
89 | int pos = 0; | |
90 | int ret; | |
91 | ||
92 | if (!dev) | |
93 | return -ENODEV; | |
94 | ||
95 | buf = kzalloc(bufsz, GFP_KERNEL); | |
96 | if (!buf) | |
97 | return -ENOMEM; | |
98 | ||
99 | pos += scnprintf(buf + pos, bufsz - pos, | |
100 | " |me|host|state|rd|wr|\n"); | |
101 | ||
102 | mutex_lock(&dev->device_lock); | |
103 | ||
0a01e974 | 104 | /* if the driver is not enabled the list won't be consistent */ |
5baaf71f TW |
105 | if (dev->dev_state != MEI_DEV_ENABLED) |
106 | goto out; | |
107 | ||
108 | list_for_each_entry(cl, &dev->file_list, link) { | |
109 | ||
110 | pos += scnprintf(buf + pos, bufsz - pos, | |
111 | "%2d|%2d|%4d|%5d|%2d|%2d|\n", | |
112 | i, cl->me_client_id, cl->host_client_id, cl->state, | |
113 | cl->reading_state, cl->writing_state); | |
114 | i++; | |
115 | } | |
116 | out: | |
117 | mutex_unlock(&dev->device_lock); | |
118 | ret = simple_read_from_buffer(ubuf, cnt, ppos, buf, pos); | |
119 | kfree(buf); | |
120 | return ret; | |
121 | } | |
122 | ||
123 | static const struct file_operations mei_dbgfs_fops_active = { | |
124 | .open = simple_open, | |
125 | .read = mei_dbgfs_read_active, | |
126 | .llseek = generic_file_llseek, | |
127 | }; | |
128 | ||
30e53bb8 TW |
129 | static ssize_t mei_dbgfs_read_devstate(struct file *fp, char __user *ubuf, |
130 | size_t cnt, loff_t *ppos) | |
131 | { | |
132 | struct mei_device *dev = fp->private_data; | |
133 | const size_t bufsz = 1024; | |
134 | char *buf = kzalloc(bufsz, GFP_KERNEL); | |
135 | int pos = 0; | |
136 | int ret; | |
137 | ||
138 | if (!buf) | |
139 | return -ENOMEM; | |
140 | ||
1beeb4b9 | 141 | pos += scnprintf(buf + pos, bufsz - pos, "dev: %s\n", |
30e53bb8 | 142 | mei_dev_state_str(dev->dev_state)); |
1beeb4b9 AU |
143 | pos += scnprintf(buf + pos, bufsz - pos, "hbm: %s\n", |
144 | mei_hbm_state_str(dev->hbm_state)); | |
145 | pos += scnprintf(buf + pos, bufsz - pos, "pg: %s, %s\n", | |
146 | mei_pg_is_enabled(dev) ? "ENABLED" : "DISABLED", | |
147 | mei_pg_state_str(mei_pg_state(dev))); | |
30e53bb8 TW |
148 | ret = simple_read_from_buffer(ubuf, cnt, ppos, buf, pos); |
149 | kfree(buf); | |
150 | return ret; | |
151 | } | |
152 | static const struct file_operations mei_dbgfs_fops_devstate = { | |
a42f82f5 | 153 | .open = simple_open, |
30e53bb8 TW |
154 | .read = mei_dbgfs_read_devstate, |
155 | .llseek = generic_file_llseek, | |
156 | }; | |
157 | ||
158 | /** | |
159 | * mei_dbgfs_deregister - Remove the debugfs files and directories | |
a8605ea2 AU |
160 | * |
161 | * @dev: the mei device structure | |
30e53bb8 TW |
162 | */ |
163 | void mei_dbgfs_deregister(struct mei_device *dev) | |
164 | { | |
165 | if (!dev->dbgfs_dir) | |
166 | return; | |
167 | debugfs_remove_recursive(dev->dbgfs_dir); | |
168 | dev->dbgfs_dir = NULL; | |
169 | } | |
170 | ||
171 | /** | |
a8605ea2 | 172 | * mei_dbgfs_register - Add the debugfs files |
30e53bb8 | 173 | * |
a8605ea2 AU |
174 | * @dev: the mei device structure |
175 | * @name: the mei device name | |
ce23139c AU |
176 | * |
177 | * Return: 0 on success, <0 on failure. | |
30e53bb8 TW |
178 | */ |
179 | int mei_dbgfs_register(struct mei_device *dev, const char *name) | |
180 | { | |
181 | struct dentry *dir, *f; | |
92db1555 | 182 | |
30e53bb8 TW |
183 | dir = debugfs_create_dir(name, NULL); |
184 | if (!dir) | |
185 | return -ENOMEM; | |
186 | ||
187 | f = debugfs_create_file("meclients", S_IRUSR, dir, | |
188 | dev, &mei_dbgfs_fops_meclients); | |
189 | if (!f) { | |
2bf94cab | 190 | dev_err(dev->dev, "meclients: registration failed\n"); |
30e53bb8 TW |
191 | goto err; |
192 | } | |
5baaf71f TW |
193 | f = debugfs_create_file("active", S_IRUSR, dir, |
194 | dev, &mei_dbgfs_fops_active); | |
195 | if (!f) { | |
2bf94cab | 196 | dev_err(dev->dev, "meclients: registration failed\n"); |
5baaf71f TW |
197 | goto err; |
198 | } | |
30e53bb8 TW |
199 | f = debugfs_create_file("devstate", S_IRUSR, dir, |
200 | dev, &mei_dbgfs_fops_devstate); | |
201 | if (!f) { | |
2bf94cab | 202 | dev_err(dev->dev, "devstate: registration failed\n"); |
30e53bb8 TW |
203 | goto err; |
204 | } | |
205 | dev->dbgfs_dir = dir; | |
206 | return 0; | |
207 | err: | |
208 | mei_dbgfs_deregister(dev); | |
209 | return -ENODEV; | |
210 | } | |
211 |