1 // SPDX-License-Identifier: GPL-2.0-only
3 * Intel MIC Platform Software Stack (MPSS)
5 * Copyright(c) 2015 Intel Corporation.
7 * Intel MIC Coprocessor State Management (COSM) Driver
9 #include <linux/slab.h>
10 #include "cosm_main.h"
13 * A state-to-string lookup table, for exposing a human readable state
14 * via sysfs. Always keep in sync with enum cosm_states
16 const char * const cosm_state_string
[] = {
17 [MIC_READY
] = "ready",
18 [MIC_BOOTING
] = "booting",
19 [MIC_ONLINE
] = "online",
20 [MIC_SHUTTING_DOWN
] = "shutting_down",
21 [MIC_RESETTING
] = "resetting",
22 [MIC_RESET_FAILED
] = "reset_failed",
26 * A shutdown-status-to-string lookup table, for exposing a human
27 * readable state via sysfs. Always keep in sync with enum cosm_shutdown_status
29 const char * const cosm_shutdown_status_string
[] = {
31 [MIC_CRASHED
] = "crashed",
32 [MIC_HALTED
] = "halted",
33 [MIC_POWER_OFF
] = "poweroff",
34 [MIC_RESTART
] = "restart",
37 void cosm_set_shutdown_status(struct cosm_device
*cdev
, u8 shutdown_status
)
39 dev_dbg(&cdev
->dev
, "Shutdown Status %s -> %s\n",
40 cosm_shutdown_status_string
[cdev
->shutdown_status
],
41 cosm_shutdown_status_string
[shutdown_status
]);
42 cdev
->shutdown_status
= shutdown_status
;
45 void cosm_set_state(struct cosm_device
*cdev
, u8 state
)
47 dev_dbg(&cdev
->dev
, "State %s -> %s\n",
48 cosm_state_string
[cdev
->state
],
49 cosm_state_string
[state
]);
51 sysfs_notify_dirent(cdev
->state_sysfs
);
55 family_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
57 struct cosm_device
*cdev
= dev_get_drvdata(dev
);
62 return cdev
->hw_ops
->family(cdev
, buf
);
64 static DEVICE_ATTR_RO(family
);
67 stepping_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
69 struct cosm_device
*cdev
= dev_get_drvdata(dev
);
74 return cdev
->hw_ops
->stepping(cdev
, buf
);
76 static DEVICE_ATTR_RO(stepping
);
79 state_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
81 struct cosm_device
*cdev
= dev_get_drvdata(dev
);
83 if (!cdev
|| cdev
->state
>= MIC_LAST
)
86 return scnprintf(buf
, PAGE_SIZE
, "%s\n",
87 cosm_state_string
[cdev
->state
]);
91 state_store(struct device
*dev
, struct device_attribute
*attr
,
92 const char *buf
, size_t count
)
94 struct cosm_device
*cdev
= dev_get_drvdata(dev
);
100 if (sysfs_streq(buf
, "boot")) {
101 rc
= cosm_start(cdev
);
104 if (sysfs_streq(buf
, "reset")) {
105 rc
= cosm_reset(cdev
);
109 if (sysfs_streq(buf
, "shutdown")) {
110 rc
= cosm_shutdown(cdev
);
119 static DEVICE_ATTR_RW(state
);
121 static ssize_t
shutdown_status_show(struct device
*dev
,
122 struct device_attribute
*attr
, char *buf
)
124 struct cosm_device
*cdev
= dev_get_drvdata(dev
);
126 if (!cdev
|| cdev
->shutdown_status
>= MIC_STATUS_LAST
)
129 return scnprintf(buf
, PAGE_SIZE
, "%s\n",
130 cosm_shutdown_status_string
[cdev
->shutdown_status
]);
132 static DEVICE_ATTR_RO(shutdown_status
);
135 heartbeat_enable_show(struct device
*dev
,
136 struct device_attribute
*attr
, char *buf
)
138 struct cosm_device
*cdev
= dev_get_drvdata(dev
);
143 return scnprintf(buf
, PAGE_SIZE
, "%d\n", cdev
->sysfs_heartbeat_enable
);
147 heartbeat_enable_store(struct device
*dev
,
148 struct device_attribute
*attr
,
149 const char *buf
, size_t count
)
151 struct cosm_device
*cdev
= dev_get_drvdata(dev
);
158 mutex_lock(&cdev
->cosm_mutex
);
159 ret
= kstrtoint(buf
, 10, &enable
);
163 cdev
->sysfs_heartbeat_enable
= enable
;
164 /* if state is not online, cdev->heartbeat_watchdog_enable is 0 */
165 if (cdev
->state
== MIC_ONLINE
)
166 cdev
->heartbeat_watchdog_enable
= enable
;
169 mutex_unlock(&cdev
->cosm_mutex
);
172 static DEVICE_ATTR_RW(heartbeat_enable
);
175 cmdline_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
177 struct cosm_device
*cdev
= dev_get_drvdata(dev
);
183 cmdline
= cdev
->cmdline
;
186 return scnprintf(buf
, PAGE_SIZE
, "%s\n", cmdline
);
191 cmdline_store(struct device
*dev
, struct device_attribute
*attr
,
192 const char *buf
, size_t count
)
194 struct cosm_device
*cdev
= dev_get_drvdata(dev
);
199 mutex_lock(&cdev
->cosm_mutex
);
200 kfree(cdev
->cmdline
);
202 cdev
->cmdline
= kmalloc(count
+ 1, GFP_KERNEL
);
203 if (!cdev
->cmdline
) {
208 strncpy(cdev
->cmdline
, buf
, count
);
210 if (cdev
->cmdline
[count
- 1] == '\n')
211 cdev
->cmdline
[count
- 1] = '\0';
213 cdev
->cmdline
[count
] = '\0';
215 mutex_unlock(&cdev
->cosm_mutex
);
218 static DEVICE_ATTR_RW(cmdline
);
221 firmware_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
223 struct cosm_device
*cdev
= dev_get_drvdata(dev
);
229 firmware
= cdev
->firmware
;
232 return scnprintf(buf
, PAGE_SIZE
, "%s\n", firmware
);
237 firmware_store(struct device
*dev
, struct device_attribute
*attr
,
238 const char *buf
, size_t count
)
240 struct cosm_device
*cdev
= dev_get_drvdata(dev
);
245 mutex_lock(&cdev
->cosm_mutex
);
246 kfree(cdev
->firmware
);
248 cdev
->firmware
= kmalloc(count
+ 1, GFP_KERNEL
);
249 if (!cdev
->firmware
) {
253 strncpy(cdev
->firmware
, buf
, count
);
255 if (cdev
->firmware
[count
- 1] == '\n')
256 cdev
->firmware
[count
- 1] = '\0';
258 cdev
->firmware
[count
] = '\0';
260 mutex_unlock(&cdev
->cosm_mutex
);
263 static DEVICE_ATTR_RW(firmware
);
266 ramdisk_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
268 struct cosm_device
*cdev
= dev_get_drvdata(dev
);
274 ramdisk
= cdev
->ramdisk
;
277 return scnprintf(buf
, PAGE_SIZE
, "%s\n", ramdisk
);
282 ramdisk_store(struct device
*dev
, struct device_attribute
*attr
,
283 const char *buf
, size_t count
)
285 struct cosm_device
*cdev
= dev_get_drvdata(dev
);
290 mutex_lock(&cdev
->cosm_mutex
);
291 kfree(cdev
->ramdisk
);
293 cdev
->ramdisk
= kmalloc(count
+ 1, GFP_KERNEL
);
294 if (!cdev
->ramdisk
) {
299 strncpy(cdev
->ramdisk
, buf
, count
);
301 if (cdev
->ramdisk
[count
- 1] == '\n')
302 cdev
->ramdisk
[count
- 1] = '\0';
304 cdev
->ramdisk
[count
] = '\0';
306 mutex_unlock(&cdev
->cosm_mutex
);
309 static DEVICE_ATTR_RW(ramdisk
);
312 bootmode_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
314 struct cosm_device
*cdev
= dev_get_drvdata(dev
);
320 bootmode
= cdev
->bootmode
;
323 return scnprintf(buf
, PAGE_SIZE
, "%s\n", bootmode
);
328 bootmode_store(struct device
*dev
, struct device_attribute
*attr
,
329 const char *buf
, size_t count
)
331 struct cosm_device
*cdev
= dev_get_drvdata(dev
);
336 if (!sysfs_streq(buf
, "linux") && !sysfs_streq(buf
, "flash"))
339 mutex_lock(&cdev
->cosm_mutex
);
340 kfree(cdev
->bootmode
);
342 cdev
->bootmode
= kmalloc(count
+ 1, GFP_KERNEL
);
343 if (!cdev
->bootmode
) {
348 strncpy(cdev
->bootmode
, buf
, count
);
350 if (cdev
->bootmode
[count
- 1] == '\n')
351 cdev
->bootmode
[count
- 1] = '\0';
353 cdev
->bootmode
[count
] = '\0';
355 mutex_unlock(&cdev
->cosm_mutex
);
358 static DEVICE_ATTR_RW(bootmode
);
361 log_buf_addr_show(struct device
*dev
, struct device_attribute
*attr
,
364 struct cosm_device
*cdev
= dev_get_drvdata(dev
);
369 return scnprintf(buf
, PAGE_SIZE
, "%p\n", cdev
->log_buf_addr
);
373 log_buf_addr_store(struct device
*dev
, struct device_attribute
*attr
,
374 const char *buf
, size_t count
)
376 struct cosm_device
*cdev
= dev_get_drvdata(dev
);
383 ret
= kstrtoul(buf
, 16, &addr
);
387 cdev
->log_buf_addr
= (void *)addr
;
392 static DEVICE_ATTR_RW(log_buf_addr
);
395 log_buf_len_show(struct device
*dev
, struct device_attribute
*attr
,
398 struct cosm_device
*cdev
= dev_get_drvdata(dev
);
403 return scnprintf(buf
, PAGE_SIZE
, "%p\n", cdev
->log_buf_len
);
407 log_buf_len_store(struct device
*dev
, struct device_attribute
*attr
,
408 const char *buf
, size_t count
)
410 struct cosm_device
*cdev
= dev_get_drvdata(dev
);
417 ret
= kstrtoul(buf
, 16, &addr
);
421 cdev
->log_buf_len
= (int *)addr
;
426 static DEVICE_ATTR_RW(log_buf_len
);
428 static struct attribute
*cosm_default_attrs
[] = {
429 &dev_attr_family
.attr
,
430 &dev_attr_stepping
.attr
,
431 &dev_attr_state
.attr
,
432 &dev_attr_shutdown_status
.attr
,
433 &dev_attr_heartbeat_enable
.attr
,
434 &dev_attr_cmdline
.attr
,
435 &dev_attr_firmware
.attr
,
436 &dev_attr_ramdisk
.attr
,
437 &dev_attr_bootmode
.attr
,
438 &dev_attr_log_buf_addr
.attr
,
439 &dev_attr_log_buf_len
.attr
,
444 ATTRIBUTE_GROUPS(cosm_default
);
446 void cosm_sysfs_init(struct cosm_device
*cdev
)
448 cdev
->attr_group
= cosm_default_groups
;