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