029a4f31bee79b74c16b0d4d08e6100c40ac6382
[firefly-linux-kernel-4.4.55.git] / drivers / misc / mic / host / mic_sysfs.c
1 /*
2  * Intel MIC Platform Software Stack (MPSS)
3  *
4  * Copyright(c) 2013 Intel Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License, version 2, as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * General Public License for more details.
14  *
15  * The full GNU General Public License is included in this distribution in
16  * the file called "COPYING".
17  *
18  * Intel MIC Host driver.
19  *
20  */
21 #include <linux/pci.h>
22
23 #include <linux/mic_common.h>
24 #include "../common/mic_dev.h"
25 #include "mic_device.h"
26
27 /*
28  * A state-to-string lookup table, for exposing a human readable state
29  * via sysfs. Always keep in sync with enum mic_states
30  */
31 static const char * const mic_state_string[] = {
32         [MIC_OFFLINE] = "offline",
33         [MIC_ONLINE] = "online",
34         [MIC_SHUTTING_DOWN] = "shutting_down",
35         [MIC_RESET_FAILED] = "reset_failed",
36 };
37
38 /*
39  * A shutdown-status-to-string lookup table, for exposing a human
40  * readable state via sysfs. Always keep in sync with enum mic_shutdown_status
41  */
42 static const char * const mic_shutdown_status_string[] = {
43         [MIC_NOP] = "nop",
44         [MIC_CRASHED] = "crashed",
45         [MIC_HALTED] = "halted",
46         [MIC_POWER_OFF] = "poweroff",
47         [MIC_RESTART] = "restart",
48 };
49
50 void mic_set_shutdown_status(struct mic_device *mdev, u8 shutdown_status)
51 {
52         dev_dbg(mdev->sdev->parent, "Shutdown Status %s -> %s\n",
53                 mic_shutdown_status_string[mdev->shutdown_status],
54                 mic_shutdown_status_string[shutdown_status]);
55         mdev->shutdown_status = shutdown_status;
56 }
57
58 void mic_set_state(struct mic_device *mdev, u8 state)
59 {
60         dev_dbg(mdev->sdev->parent, "State %s -> %s\n",
61                 mic_state_string[mdev->state],
62                 mic_state_string[state]);
63         mdev->state = state;
64         sysfs_notify_dirent(mdev->state_sysfs);
65 }
66
67 static ssize_t
68 family_show(struct device *dev, struct device_attribute *attr, char *buf)
69 {
70         static const char x100[] = "x100";
71         static const char unknown[] = "Unknown";
72         const char *card = NULL;
73         struct mic_device *mdev = dev_get_drvdata(dev->parent);
74
75         if (!mdev)
76                 return -EINVAL;
77
78         switch (mdev->family) {
79         case MIC_FAMILY_X100:
80                 card = x100;
81                 break;
82         default:
83                 card = unknown;
84                 break;
85         }
86         return scnprintf(buf, PAGE_SIZE, "%s\n", card);
87 }
88 static DEVICE_ATTR_RO(family);
89
90 static ssize_t
91 stepping_show(struct device *dev, struct device_attribute *attr, char *buf)
92 {
93         struct mic_device *mdev = dev_get_drvdata(dev->parent);
94         char *string = "??";
95
96         if (!mdev)
97                 return -EINVAL;
98
99         switch (mdev->stepping) {
100         case MIC_A0_STEP:
101                 string = "A0";
102                 break;
103         case MIC_B0_STEP:
104                 string = "B0";
105                 break;
106         case MIC_B1_STEP:
107                 string = "B1";
108                 break;
109         case MIC_C0_STEP:
110                 string = "C0";
111                 break;
112         default:
113                 break;
114         }
115         return scnprintf(buf, PAGE_SIZE, "%s\n", string);
116 }
117 static DEVICE_ATTR_RO(stepping);
118
119 static ssize_t
120 state_show(struct device *dev, struct device_attribute *attr, char *buf)
121 {
122         struct mic_device *mdev = dev_get_drvdata(dev->parent);
123
124         if (!mdev || mdev->state >= MIC_LAST)
125                 return -EINVAL;
126
127         return scnprintf(buf, PAGE_SIZE, "%s\n",
128                 mic_state_string[mdev->state]);
129 }
130
131 static ssize_t
132 state_store(struct device *dev, struct device_attribute *attr,
133         const char *buf, size_t count)
134 {
135         int rc = 0;
136         struct mic_device *mdev = dev_get_drvdata(dev->parent);
137         if (!mdev)
138                 return -EINVAL;
139         if (sysfs_streq(buf, "boot")) {
140                 rc = mic_start(mdev, buf);
141                 if (rc) {
142                         dev_err(mdev->sdev->parent,
143                                 "mic_boot failed rc %d\n", rc);
144                         count = rc;
145                 }
146                 goto done;
147         }
148
149         if (sysfs_streq(buf, "reset")) {
150                 schedule_work(&mdev->reset_trigger_work);
151                 goto done;
152         }
153
154         if (sysfs_streq(buf, "shutdown")) {
155                 mic_shutdown(mdev);
156                 goto done;
157         }
158
159         count = -EINVAL;
160 done:
161         return count;
162 }
163 static DEVICE_ATTR_RW(state);
164
165 static ssize_t shutdown_status_show(struct device *dev,
166         struct device_attribute *attr, char *buf)
167 {
168         struct mic_device *mdev = dev_get_drvdata(dev->parent);
169
170         if (!mdev || mdev->shutdown_status >= MIC_STATUS_LAST)
171                 return -EINVAL;
172
173         return scnprintf(buf, PAGE_SIZE, "%s\n",
174                 mic_shutdown_status_string[mdev->shutdown_status]);
175 }
176 static DEVICE_ATTR_RO(shutdown_status);
177
178 static ssize_t
179 cmdline_show(struct device *dev, struct device_attribute *attr, char *buf)
180 {
181         struct mic_device *mdev = dev_get_drvdata(dev->parent);
182         char *cmdline;
183
184         if (!mdev)
185                 return -EINVAL;
186
187         cmdline = mdev->cmdline;
188
189         if (cmdline)
190                 return scnprintf(buf, PAGE_SIZE, "%s\n", cmdline);
191         return 0;
192 }
193
194 static ssize_t
195 cmdline_store(struct device *dev, struct device_attribute *attr,
196         const char *buf, size_t count)
197 {
198         struct mic_device *mdev = dev_get_drvdata(dev->parent);
199
200         if (!mdev)
201                 return -EINVAL;
202
203         mutex_lock(&mdev->mic_mutex);
204         kfree(mdev->cmdline);
205
206         mdev->cmdline = kmalloc(count + 1, GFP_KERNEL);
207         if (!mdev->cmdline) {
208                 count = -ENOMEM;
209                 goto unlock;
210         }
211
212         strncpy(mdev->cmdline, buf, count);
213
214         if (mdev->cmdline[count - 1] == '\n')
215                 mdev->cmdline[count - 1] = '\0';
216         else
217                 mdev->cmdline[count] = '\0';
218 unlock:
219         mutex_unlock(&mdev->mic_mutex);
220         return count;
221 }
222 static DEVICE_ATTR_RW(cmdline);
223
224 static ssize_t
225 firmware_show(struct device *dev, struct device_attribute *attr, char *buf)
226 {
227         struct mic_device *mdev = dev_get_drvdata(dev->parent);
228         char *firmware;
229
230         if (!mdev)
231                 return -EINVAL;
232
233         firmware = mdev->firmware;
234
235         if (firmware)
236                 return scnprintf(buf, PAGE_SIZE, "%s\n", firmware);
237         return 0;
238 }
239
240 static ssize_t
241 firmware_store(struct device *dev, struct device_attribute *attr,
242         const char *buf, size_t count)
243 {
244         struct mic_device *mdev = dev_get_drvdata(dev->parent);
245
246         if (!mdev)
247                 return -EINVAL;
248
249         mutex_lock(&mdev->mic_mutex);
250         kfree(mdev->firmware);
251
252         mdev->firmware = kmalloc(count + 1, GFP_KERNEL);
253         if (!mdev->firmware) {
254                 count = -ENOMEM;
255                 goto unlock;
256         }
257         strncpy(mdev->firmware, buf, count);
258
259         if (mdev->firmware[count - 1] == '\n')
260                 mdev->firmware[count - 1] = '\0';
261         else
262                 mdev->firmware[count] = '\0';
263 unlock:
264         mutex_unlock(&mdev->mic_mutex);
265         return count;
266 }
267 static DEVICE_ATTR_RW(firmware);
268
269 static ssize_t
270 ramdisk_show(struct device *dev, struct device_attribute *attr, char *buf)
271 {
272         struct mic_device *mdev = dev_get_drvdata(dev->parent);
273         char *ramdisk;
274
275         if (!mdev)
276                 return -EINVAL;
277
278         ramdisk = mdev->ramdisk;
279
280         if (ramdisk)
281                 return scnprintf(buf, PAGE_SIZE, "%s\n", ramdisk);
282         return 0;
283 }
284
285 static ssize_t
286 ramdisk_store(struct device *dev, struct device_attribute *attr,
287         const char *buf, size_t count)
288 {
289         struct mic_device *mdev = dev_get_drvdata(dev->parent);
290
291         if (!mdev)
292                 return -EINVAL;
293
294         mutex_lock(&mdev->mic_mutex);
295         kfree(mdev->ramdisk);
296
297         mdev->ramdisk = kmalloc(count + 1, GFP_KERNEL);
298         if (!mdev->ramdisk) {
299                 count = -ENOMEM;
300                 goto unlock;
301         }
302
303         strncpy(mdev->ramdisk, buf, count);
304
305         if (mdev->ramdisk[count - 1] == '\n')
306                 mdev->ramdisk[count - 1] = '\0';
307         else
308                 mdev->ramdisk[count] = '\0';
309 unlock:
310         mutex_unlock(&mdev->mic_mutex);
311         return count;
312 }
313 static DEVICE_ATTR_RW(ramdisk);
314
315 static ssize_t
316 bootmode_show(struct device *dev, struct device_attribute *attr, char *buf)
317 {
318         struct mic_device *mdev = dev_get_drvdata(dev->parent);
319         char *bootmode;
320
321         if (!mdev)
322                 return -EINVAL;
323
324         bootmode = mdev->bootmode;
325
326         if (bootmode)
327                 return scnprintf(buf, PAGE_SIZE, "%s\n", bootmode);
328         return 0;
329 }
330
331 static ssize_t
332 bootmode_store(struct device *dev, struct device_attribute *attr,
333         const char *buf, size_t count)
334 {
335         struct mic_device *mdev = dev_get_drvdata(dev->parent);
336
337         if (!mdev)
338                 return -EINVAL;
339
340         if (!sysfs_streq(buf, "linux") && !sysfs_streq(buf, "elf"))
341                 return -EINVAL;
342
343         mutex_lock(&mdev->mic_mutex);
344         kfree(mdev->bootmode);
345
346         mdev->bootmode = kmalloc(count + 1, GFP_KERNEL);
347         if (!mdev->bootmode) {
348                 count = -ENOMEM;
349                 goto unlock;
350         }
351
352         strncpy(mdev->bootmode, buf, count);
353
354         if (mdev->bootmode[count - 1] == '\n')
355                 mdev->bootmode[count - 1] = '\0';
356         else
357                 mdev->bootmode[count] = '\0';
358 unlock:
359         mutex_unlock(&mdev->mic_mutex);
360         return count;
361 }
362 static DEVICE_ATTR_RW(bootmode);
363
364 static ssize_t
365 log_buf_addr_show(struct device *dev, struct device_attribute *attr,
366         char *buf)
367 {
368         struct mic_device *mdev = dev_get_drvdata(dev->parent);
369
370         if (!mdev)
371                 return -EINVAL;
372
373         return scnprintf(buf, PAGE_SIZE, "%p\n", mdev->log_buf_addr);
374 }
375
376 static ssize_t
377 log_buf_addr_store(struct device *dev, struct device_attribute *attr,
378         const char *buf, size_t count)
379 {
380         struct mic_device *mdev = dev_get_drvdata(dev->parent);
381         int ret;
382         unsigned long addr;
383
384         if (!mdev)
385                 return -EINVAL;
386
387         ret = kstrtoul(buf, 16, &addr);
388         if (ret)
389                 goto exit;
390
391         mdev->log_buf_addr = (void *)addr;
392         ret = count;
393 exit:
394         return ret;
395 }
396 static DEVICE_ATTR_RW(log_buf_addr);
397
398 static ssize_t
399 log_buf_len_show(struct device *dev, struct device_attribute *attr,
400         char *buf)
401 {
402         struct mic_device *mdev = dev_get_drvdata(dev->parent);
403
404         if (!mdev)
405                 return -EINVAL;
406
407         return scnprintf(buf, PAGE_SIZE, "%p\n", mdev->log_buf_len);
408 }
409
410 static ssize_t
411 log_buf_len_store(struct device *dev, struct device_attribute *attr,
412         const char *buf, size_t count)
413 {
414         struct mic_device *mdev = dev_get_drvdata(dev->parent);
415         int ret;
416         unsigned long addr;
417
418         if (!mdev)
419                 return -EINVAL;
420
421         ret = kstrtoul(buf, 16, &addr);
422         if (ret)
423                 goto exit;
424
425         mdev->log_buf_len = (int *)addr;
426         ret = count;
427 exit:
428         return ret;
429 }
430 static DEVICE_ATTR_RW(log_buf_len);
431
432 static struct attribute *mic_default_attrs[] = {
433         &dev_attr_family.attr,
434         &dev_attr_stepping.attr,
435         &dev_attr_state.attr,
436         &dev_attr_shutdown_status.attr,
437         &dev_attr_cmdline.attr,
438         &dev_attr_firmware.attr,
439         &dev_attr_ramdisk.attr,
440         &dev_attr_bootmode.attr,
441         &dev_attr_log_buf_addr.attr,
442         &dev_attr_log_buf_len.attr,
443
444         NULL
445 };
446
447 ATTRIBUTE_GROUPS(mic_default);
448
449 void mic_sysfs_init(struct mic_device *mdev)
450 {
451         mdev->attr_group = mic_default_groups;
452 }