Updated `README.md` with instructions for building/using the kernel module.
[xeon-phi-kernel-module] / host / linsysfs.c
CommitLineData
800f879a
AT
1/*
2 * Copyright 2010-2017 Intel Corporation.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * Disclaimer: The codes contained in these modules may be specific to
14 * the Intel Software Development Platform codenamed Knights Ferry,
15 * and the Intel product codenamed Knights Corner, and are not backward
16 * compatible with other Intel products. Additionally, Intel will NOT
17 * support the codes or instruction set in future products.
18 *
19 * Intel offers no warranty of any kind regarding the code. This code is
20 * licensed on an "AS IS" basis and Intel is not obligated to provide
21 * any support, assistance, installation, training, or other services
22 * of any kind. Intel is also not obligated to provide any updates,
23 * enhancements or extensions. Intel specifically disclaims any warranty
24 * of merchantability, non-infringement, fitness for any particular
25 * purpose, and any other warranty.
26 *
27 * Further, Intel disclaims all liability of any kind, including but
28 * not limited to liability for infringement of any proprietary rights,
29 * relating to the use of the code, even if Intel is notified of the
30 * possibility of such liability. Except as expressly stated in an Intel
31 * license agreement provided with this code and agreed upon with Intel,
32 * no license, express or implied, by estoppel or otherwise, to any
33 * intellectual property rights is granted herein.
34 */
35
36#include "micint.h"
37#include <linux/ip.h>
38#include <linux/tcp.h>
39#include <linux/kernel.h>
40#include "mic/micveth.h"
41
42#define SBOX_SCR9_VENDORID(x) ((x) & 0xf)
43#define SBOX_SCR9_REVISION(x) (((x) >> 4) & 0xf)
44#define SBOX_SCR9_DENSITY(x) (((x) >> 8) & 0x3)
45#define SBOX_SCR9_ECC(x) (((x) >> 29) & 0x1)
46
47bd_info_t *
48dev_to_bdi(struct device *dev)
49{
50 struct list_head *pos, *tmpq;
51 bd_info_t *bdi = NULL;
52 list_for_each_safe(pos, tmpq, &mic_data.dd_bdlist) {
53 bdi = list_entry(pos, bd_info_t, bi_list);
54 if (bdi->bi_sysfsdev == dev)
55 break;
56 }
57 return bdi;
58}
59
60/*
61 * sysfs entries in lieu of MMIO ioctl
62 */
63
64struct device_attribute_sbox {
65 struct device_attribute devattr;
66 uint32_t offset, mask, shift;
67};
68
69uint32_t
70bd_sbox_read(bd_info_t *bdi, uint32_t offset)
71{
72 uint32_t reg_value, ret;
73 ret = micpm_get_reference(&bdi->bi_ctx, true);
74 if (ret)
75 return -EAGAIN;
76 reg_value = SBOX_READ(bdi->bi_ctx.mmio.va, offset);
77 ret = micpm_put_reference(&bdi->bi_ctx);
78 if (ret)
79 return -EAGAIN;
80
81 return reg_value;
82}
83
84#define DEVICE_ATTR_SBOX(_name, _mode, _offset, _mask, _shift) \
85struct device_attribute_sbox sbox_attr_##_name = \
86{ __ATTR(_name, _mode, show_sbox_register, NULL), _offset, _mask, _shift }
87
88ssize_t
89show_sbox_register(struct device *dev, struct device_attribute *attr, char *buf)
90{
91 struct device_attribute_sbox *attr_sbox = container_of(attr,
92 struct device_attribute_sbox, devattr);
93 bd_info_t *bdi = dev_to_bdi(dev);
94 return snprintf(buf, PAGE_SIZE, "%x\n",
95 (bd_sbox_read(bdi, attr_sbox->offset) >> attr_sbox->shift) & attr_sbox->mask);
96}
97
98#ifdef CONFIG_ML1OM
99static DEVICE_ATTR_SBOX(corevoltage, S_IRUGO, SBOX_COREVOLT, MASK_COREVOLT, SHIFT_COREVOLT);
100static DEVICE_ATTR_SBOX(corefrequency, S_IRUGO, SBOX_COREFREQ, MASK_COREFREQ, SHIFT_COREFREQ);
101#endif
102static DEVICE_ATTR_SBOX(memoryvoltage, S_IRUGO, SBOX_MEMVOLT, MASK_MEMVOLT, SHIFT_MEMVOLT);
103static DEVICE_ATTR_SBOX(memoryfrequency, S_IRUGO, SBOX_MEMORYFREQ, MASK_MEMORYFREQ, SHIFT_MEMORYFREQ);
104static DEVICE_ATTR_SBOX(memsize, S_IRUGO, SBOX_SCRATCH0, MASK_MEMSIZE, SHIFT_MEMSIZE);
105static DEVICE_ATTR_SBOX(flashversion, S_IRUGO, SBOX_SCRATCH7, MASK_FLASHVERSION, SHIFT_FLASHVERSION);
106
107/* HW Info */
108static DEVICE_ATTR_SBOX(substepping_data, S_IRUGO, SBOX_SCRATCH13, MASK_SUBSTEPPING_DATA, SHIFT_SUBSTEPPING_DATA);
109static DEVICE_ATTR_SBOX(stepping_data, S_IRUGO, SBOX_SCRATCH13, MASK_STEPPING_DATA, SHIFT_STEPPING_DATA);
110static DEVICE_ATTR_SBOX(model, S_IRUGO, SBOX_SCRATCH13, MASK_MODEL, SHIFT_MODEL);
111static DEVICE_ATTR_SBOX(family_data, S_IRUGO, SBOX_SCRATCH13, MASK_FAMILY_DATA, SHIFT_FAMILY_DATA);
112static DEVICE_ATTR_SBOX(processor, S_IRUGO, SBOX_SCRATCH13, MASK_PROCESSOR, SHIFT_PROCESSOR);
113static DEVICE_ATTR_SBOX(platform, S_IRUGO, SBOX_SCRATCH13, MASK_PLATFORM, SHIFT_PLATFORM);
114static DEVICE_ATTR_SBOX(extended_model, S_IRUGO, SBOX_SCRATCH13, MASK_EXTENDED_MODEL, SHIFT_EXTENDED_MODEL);
115static DEVICE_ATTR_SBOX(extended_family, S_IRUGO, SBOX_SCRATCH13, MASK_EXTENDED_FAMILY, SHIFT_EXTENDED_FAMILY);
116/* copy of fuse_configuration_revision [129:120] */
117static DEVICE_ATTR_SBOX(fuse_config_rev, S_IRUGO, SBOX_SCRATCH7, MASK_FUSE_CONFIG_REV, SHIFT_FUSE_CONFIG_REV);
118
119static DEVICE_ATTR_SBOX(active_cores, S_IRUGO, SBOX_SCRATCH4, MASK_ACTIVE_CORES, SHIFT_ACTIVE_CORES);
120static DEVICE_ATTR_SBOX(fail_safe_offset, S_IRUSR, SBOX_FAIL_SAFE_OFFSET, MASK_FAIL_SAFE, SHIFT_FAIL_SAFE);
121
122ssize_t show_flash_update(struct device *dev, struct device_attribute *attr, char *buf)
123{
124 uint32_t value, ret;
125 bd_info_t *bdi = dev_to_bdi(dev);
126 ret = micpm_get_reference(&bdi->bi_ctx, true);
127 if (ret)
128 return -EAGAIN;
129 value = DBOX_READ(bdi->bi_ctx.mmio.va, DBOX_SWF0X0);
130 ret = micpm_put_reference(&bdi->bi_ctx);
131 if (ret)
132 return -EAGAIN;
133
134 return snprintf(buf, PAGE_SIZE, "%x\n", value);
135}
136
137static ssize_t
138set_flash_update(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
139{
140 unsigned long value;
141 int ret;
142 bd_info_t *bdi = dev_to_bdi(dev);
143#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,39)
144 ret = kstrtoul(buf, 0, &value);
145 if (ret)
146 return count;
147#else
148 value = simple_strtoul(buf, NULL, 10);
149#endif
150 ret = micpm_get_reference(&bdi->bi_ctx, true);
151 if (ret)
152 return -EAGAIN;
153 DBOX_WRITE((unsigned int)value, bdi->bi_ctx.mmio.va, DBOX_SWF0X0);
154 ret = micpm_put_reference(&bdi->bi_ctx);
155 if (ret)
156 return -EAGAIN;
157
158 return count;
159
160}
161static DEVICE_ATTR(flash_update, S_IRUSR | S_IWUSR, show_flash_update, set_flash_update);
162
163ssize_t
164show_meminfo(struct device *dev, struct device_attribute *attr, char *buf)
165{
166 uint32_t value;
167 bd_info_t *bdi = dev_to_bdi(dev);
168 value = bd_sbox_read(bdi, SBOX_SCRATCH9);
169 return snprintf(buf, PAGE_SIZE, "vendor:%x,revision:%x"
170 ",density:%x,ecc_enable:%x",
171 SBOX_SCR9_VENDORID(value), SBOX_SCR9_REVISION(value),
172 SBOX_SCR9_DENSITY(value), SBOX_SCR9_ECC(value));
173}
174static DEVICE_ATTR(meminfo, S_IRUGO, show_meminfo, NULL);
175
176ssize_t
177show_sku(struct device *dev, struct device_attribute *attr, char *buf)
178{
179 bd_info_t *bdi = dev_to_bdi(dev);
180 return snprintf(buf, PAGE_SIZE, "%s\n", bdi->bi_ctx.sku_name);
181}
182static DEVICE_ATTR(sku, S_IRUGO, show_sku, NULL);
183/******************************************************************************/
184
185static ssize_t
186show_version(struct device *dev, struct device_attribute *attr, char *buf)
187{
188 return snprintf(buf, PAGE_SIZE, "%s\n", BUILD_VERSION);
189}
190static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
191
192static ssize_t
193show_p2p(struct device *dev, struct device_attribute *attr, char *buf)
194{
195 return snprintf(buf, PAGE_SIZE, "%s\n", mic_p2p_enable? "enable" : "disable");
196}
197static DEVICE_ATTR(peer2peer, S_IRUGO, show_p2p, NULL);
198
199static struct attribute *host_attributes[] = {
200 &dev_attr_version.attr,
201 &dev_attr_peer2peer.attr,
202 NULL
203};
204
205struct attribute_group host_attr_group = {
206 .attrs = host_attributes
207};
208
209static ssize_t
210show_family(struct device *dev, struct device_attribute *attr, char *buf)
211{
212 static const char KNF[] = "Knights Ferry";
213 static const char KNC[] = "x100";
214 bd_info_t *bdi = dev_to_bdi(dev);
215 const char *card = NULL;
216 mic_ctx_t *mic_ctx = &bdi->bi_ctx;
217
218 if (mic_ctx->bi_family == FAMILY_ABR)
219 card = KNF;
220 else
221 card = KNC;
222
223 if (card)
224 return snprintf(buf, PAGE_SIZE, "%s\n", card);
225 else
226 return snprintf(buf, PAGE_SIZE, "Unknown\n");
227}
228static DEVICE_ATTR(family, S_IRUGO, show_family, NULL);
229
230static ssize_t
231show_stepping(struct device *dev, struct device_attribute *attr, char *buf)
232{
233 bd_info_t *bdi = dev_to_bdi(dev);
234 char string[3];
235 show_stepping_comm(&bdi->bi_ctx,string);
236 return snprintf(buf, PAGE_SIZE, "%s\n", string);
237}
238static DEVICE_ATTR(stepping, S_IRUGO, show_stepping, NULL);
239
240char *micstates[] = {"ready", "booting", "no response", "boot failed",
241 "online", "shutdown", "lost", "resetting", "reset failed", "invalid"};
242static ssize_t
243show_micstate(struct device *dev, struct device_attribute *attr, char *buf)
244{
245 bd_info_t *bdi = dev_to_bdi(dev);
246
247 if (bdi->bi_ctx.state >= MIC_INVALID)
248 mic_setstate(&bdi->bi_ctx, MIC_INVALID);
249 return snprintf(buf, PAGE_SIZE, "%s", micstates[bdi->bi_ctx.state]);
250}
251
252static int
253match_micstate(const char **buf, const char *string)
254{
255 size_t len = strlen(string);
256 if (!strncmp(*buf, string, len)) {
257 *buf += len;
258 return true;
259 }
260 return false;
261}
262
263static ssize_t
264set_micstate(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
265{
266 const char *default_mm_image = "/usr/share/mpss/boot/rasmm-kernel.from-eeprom.elf";
267
268 bd_info_t *bdi = dev_to_bdi(dev);
269 mic_ctx_t *mic_ctx = &bdi->bi_ctx;
270 int mode;
271 size_t len;
272 char *arg, *arg2 = NULL;
273 int err = 0;
274
275 /* parse the new state */
276 if (match_micstate(&buf, "boot:linux:")) {
277 mode = MODE_LINUX;
278 } else if (match_micstate(&buf, "boot:elf:")) {
279 mode = MODE_ELF;
280 } else if (match_micstate(&buf, "boot:flash:")) {
281 mode = MODE_FLASH;
282 } else if (sysfs_streq(buf, "reset")) {
283
284 mutex_lock(&mic_ctx->state_lock);
285 if (mic_ctx->state == MIC_READY) {
286 mutex_unlock(&mic_ctx->state_lock);
287 return -EINVAL;
288 }
289
290 mutex_unlock(&mic_ctx->state_lock);
291 adapter_stop_device(mic_ctx, 1, 0);
292 return count;
293 } else if (sysfs_streq(buf, "reset:force")) {
294 int reattempt = !RESET_REATTEMPT;
295
296 mutex_lock(&mic_ctx->state_lock);
297 if (mic_ctx->state == MIC_READY)
298 reattempt = RESET_REATTEMPT;
299
300 mutex_unlock(&mic_ctx->state_lock);
301 adapter_stop_device(mic_ctx, 1, reattempt);
302 return count;
303 } else if (sysfs_streq(buf, "shutdown")) {
304 adapter_shutdown_device(mic_ctx);
305 return count;
306 } else {
307 return -EINVAL;
308 }
309
310 /* we're booting something; a filename follows the colon */
311 len = strlen(buf);
312 if (buf && buf[0] == '\n') {
313 len = 0;
314 }
315 if (!len && mode == MODE_FLASH) {
316 buf = default_mm_image;
317 len = strlen(buf);
318 }
319 if (!(arg = kmalloc(len + 1, GFP_KERNEL)))
320 return -ENOMEM;
321 memcpy(arg, buf, len + 1);
322 if (arg[len - 1] == '\n')
323 arg[len - 1] = '\0';
324
325 /* if booting linux, there may be yet another filename */
326 if (mode == MODE_LINUX && (arg2 = strchr(arg, ':')))
327 *arg2++ = '\0';
328
329 /* atomically change the state */
330 mutex_lock(&mic_ctx->state_lock);
331 if (mic_ctx->state == MIC_READY) {
332 kfree(mic_ctx->image);
333 mic_ctx->mode = mode;
334 mic_ctx->image = arg;
335 mic_ctx->initramfs = arg2;
336 mic_setstate(mic_ctx, MIC_BOOT);
337 mutex_unlock(&mic_ctx->state_lock);
338 printk("mic image: %s\n", mic_ctx->image);
339 } else {
340 kfree(arg);
341 printk(KERN_ERR "Error! Card not in offline/ready state. Cannot change mode\n");
342 mutex_unlock(&mic_ctx->state_lock);
343 return -EIO;
344 }
345
346 /* actually perform the boot */
347 if (mode == MODE_LINUX) {
348 mic_ctx->card_usage_mode = USAGE_MODE_NORMAL;
349 err = boot_linux_uos(mic_ctx, mic_ctx->image, mic_ctx->initramfs);
350 if (!err)
351 adapter_post_boot_device(mic_ctx);
352 } else {
353 err = boot_micdev_app(mic_ctx, mic_ctx->image);
354 }
355
356 if (!err)
357 return count;
358 printk("booting failed %d\n", err);
359 return err;
360}
361static DEVICE_ATTR(state, S_IRUGO|S_IWUSR, show_micstate, set_micstate);
362
363char *micmodes[] = {"N/A", "linux", "elf", "flash"};
364
365static ssize_t
366show_mode(struct device *dev, struct device_attribute *attr, char *buf)
367{
368 bd_info_t *bdi = dev_to_bdi(dev);
369
370 if (bdi->bi_ctx.mode > MODE_FLASH)
371 bdi->bi_ctx.mode = MODE_NONE;
372 return snprintf(buf, PAGE_SIZE, "%s", micmodes[bdi->bi_ctx.mode]);
373}
374static DEVICE_ATTR(mode, S_IRUGO, show_mode, NULL);
375
376int scif_get_node_status(int node_id);
377static char *scif_status_stings[] = {"not present", "initializing", "online",
378 "sleeping", "stopping", "stopped"};
379static ssize_t
380show_scif_status(struct device *dev, struct device_attribute *attr, char *buf)
381{
382 bd_info_t *bdi = dev_to_bdi(dev);
383 int scif_status;
384
385 scif_status = scif_get_node_status(bdi->bi_ctx.bi_id + 1);
386 return snprintf(buf, PAGE_SIZE, "%s\n", scif_status_stings[scif_status]);
387}
388static DEVICE_ATTR(scif_status, S_IRUGO, show_scif_status, NULL);
389
390static ssize_t
391show_image(struct device *dev, struct device_attribute *attr, char *buf)
392{
393 bd_info_t *bdi = dev_to_bdi(dev);
394 return snprintf(buf, PAGE_SIZE, "%s", bdi->bi_ctx.image);
395}
396static DEVICE_ATTR(image, S_IRUGO, show_image, NULL);
397
398static ssize_t
399show_initramfs(struct device *dev, struct device_attribute *attr, char *buf)
400{
401 bd_info_t *bdi = dev_to_bdi(dev);
402 return snprintf(buf, PAGE_SIZE, "%s", bdi->bi_ctx.initramfs);
403}
404static DEVICE_ATTR(initramfs, S_IRUGO, show_initramfs, NULL);
405
406static ssize_t
407show_postcode(struct device *dev, struct device_attribute *attr, char *buf)
408{
409 bd_info_t *bdi = dev_to_bdi(dev);
410 mic_ctx_t *mic_ctx = &bdi->bi_ctx;
411 uint32_t postcode;
412
413 if ((micpm_get_reference(mic_ctx, true))) {
414 PM_DEBUG("get_reference failed. Node may be lost\n");
415 return -EBUSY;
416 }
417 postcode = mic_getpostcode(mic_ctx);
418 if (postcode == 0xffffffff) {
419 printk("Invalid Postcode : %c%c\n", postcode & 0xff, (postcode >> 8) & 0xff);
420 micpm_put_reference(mic_ctx);
421 return -ENXIO;
422 }
423
424 if (postcode == 0x0) {
425 printk("Postcode : %c%c\n", postcode & 0xff, (postcode >> 8) & 0xff);
426 micpm_put_reference(mic_ctx);
427 return -EAGAIN;
428 }
429 micpm_put_reference(mic_ctx);
430 return snprintf(buf, PAGE_SIZE, "%c%c", postcode & 0xff, (postcode >> 8) & 0xff);
431}
432static DEVICE_ATTR(post_code, S_IRUGO, show_postcode, NULL);
433
434static ssize_t
435show_boot_count(struct device *dev, struct device_attribute *attr, char *buf)
436{
437 bd_info_t *bdi = dev_to_bdi(dev);
438 mic_ctx_t *mic_ctx = &bdi->bi_ctx;
439
440 return snprintf(buf, PAGE_SIZE, "%d", mic_ctx->boot_count);
441}
442static DEVICE_ATTR(boot_count, S_IRUGO, show_boot_count, NULL);
443
444static ssize_t
445show_crash_count(struct device *dev, struct device_attribute *attr, char *buf)
446{
447 bd_info_t *bdi = dev_to_bdi(dev);
448 mic_ctx_t *mic_ctx = &bdi->bi_ctx;
449
450 return snprintf(buf, PAGE_SIZE, "%d", mic_ctx->crash_count);
451}
452static DEVICE_ATTR(crash_count, S_IRUGO, show_crash_count, NULL);
453
454static ssize_t
455show_cmdline(struct device *dev, struct device_attribute *attr, char *buf)
456{
457 bd_info_t *bdi = dev_to_bdi(dev);
458 mic_ctx_t *mic_ctx = &bdi->bi_ctx;
459 char *cmdline = mic_ctx->sysfs_info.cmdline;
460
461 if (cmdline == NULL) {
462 return snprintf(buf, PAGE_SIZE, "not set\n");
463 } else {
464 return snprintf(buf, PAGE_SIZE, "%s\n", cmdline);
465 }
466 return 0;
467}
468
469static ssize_t
470set_cmdline(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
471{
472 bd_info_t *bdi = dev_to_bdi(dev);
473 mic_ctx_t *mic_ctx = &bdi->bi_ctx;
474
475 if (mic_ctx->sysfs_info.cmdline != NULL)
476 kfree(mic_ctx->sysfs_info.cmdline);
477
478 if ((mic_ctx->sysfs_info.cmdline = kmalloc(count + 100, GFP_ATOMIC)) == NULL)
479 return -ENOMEM;
480 strcpy(mic_ctx->sysfs_info.cmdline, buf);
481
482 if (mic_ctx->sysfs_info.cmdline[count - 1] == '\n')
483 mic_ctx->sysfs_info.cmdline[count - 1] = '\0';
484
485 return count;
486}
487static DEVICE_ATTR(cmdline, S_IRUGO|S_IWUSR, show_cmdline, set_cmdline);
488
489static ssize_t
490show_kernel_cmdline(struct device *dev, struct device_attribute *attr, char *buf)
491{
492 bd_info_t *bdi = dev_to_bdi(dev);
493 mic_ctx_t *mic_ctx = &bdi->bi_ctx;
494 char *cmdline = mic_ctx->sysfs_info.kernel_cmdline;
495
496 if ((mic_ctx->state == MIC_READY) || (cmdline == NULL)) {
497 return snprintf(buf, PAGE_SIZE, "ready\n");
498 } else {
499 return snprintf(buf, PAGE_SIZE, "%s\n", cmdline);
500 }
501}
502static DEVICE_ATTR(kernel_cmdline, S_IRUGO, show_kernel_cmdline, NULL);
503
504static ssize_t show_pc3_enabled(struct device *dev,
505 struct device_attribute *attr,
506 char *buf)
507{
508 bd_info_t *bdi = dev_to_bdi(dev);
509 mic_ctx_t *mic_ctx = &bdi->bi_ctx;
510 return snprintf(buf, PAGE_SIZE, "%d\n", mic_ctx->micpm_ctx.pc3_enabled);
511}
512static ssize_t
513store_pc3_enabled(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
514{
515 int i, ret;
516 bd_info_t *bdi = dev_to_bdi(dev);
517 mic_ctx_t *mic_ctx = &bdi->bi_ctx;
518
519 if(sscanf(buf, "%d", &i) != 1) {
520 ret = -EINVAL;
521 goto exit;
522 }
523
524 if (i < 0) {
525 ret = -EINVAL;
526 goto exit;
527 }
528
529 ret = micpm_update_pc3(mic_ctx, (i) ? true : false);
530 if (ret)
531 goto exit;
532
533 pr_debug("pc3_enabled = %d\n", mic_ctx->micpm_ctx.pc3_enabled);
534 ret = count;
535exit:
536 return ret;
537}
538static DEVICE_ATTR(pc3_enabled, S_IRUGO | S_IWUSR, show_pc3_enabled, store_pc3_enabled);
539
540static ssize_t show_pc6_enabled(struct device *dev,
541 struct device_attribute *attr,
542 char *buf)
543{
544 bd_info_t *bdi = dev_to_bdi(dev);
545 mic_ctx_t *mic_ctx = &bdi->bi_ctx;
546 return snprintf(buf, PAGE_SIZE, "%d\n", mic_ctx->micpm_ctx.pc6_enabled);
547}
548
549static ssize_t
550store_pc6_enabled(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
551{
552 int i, ret;
553 bd_info_t *bdi = dev_to_bdi(dev);
554 mic_ctx_t *mic_ctx = &bdi->bi_ctx;
555
556 if(sscanf(buf, "%d", &i) != 1) {
557 ret = -EINVAL;
558 goto exit;
559 }
560
561 if (i < 0) {
562 ret = -EINVAL;
563 goto exit;
564 }
565
566 ret = micpm_update_pc6(mic_ctx, (i) ? true : false);
567 if (ret)
568 goto exit;
569
570 pr_debug("pc6_enabled = %d\n", mic_ctx->micpm_ctx.pc6_enabled);
571 ret = count;
572exit:
573 return ret;
574}
575
576static DEVICE_ATTR(pc6_enabled, S_IRUGO | S_IWUSR, show_pc6_enabled, store_pc6_enabled);
577
578static ssize_t show_pc6_timeout(struct device *dev,
579 struct device_attribute *attr,
580 char *buf)
581{
582 bd_info_t *bdi = dev_to_bdi(dev);
583 mic_ctx_t *mic_ctx = &bdi->bi_ctx;
584 return snprintf(buf, PAGE_SIZE, "%u\n", mic_ctx->micpm_ctx.pc6_timeout);
585}
586static ssize_t
587store_pc6_timeout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
588{
589 int i, ret;
590 bd_info_t *bdi = dev_to_bdi(dev);
591 mic_ctx_t *mic_ctx = &bdi->bi_ctx;
592
593 if(sscanf(buf, "%d", &i) != 1) {
594 ret = -EINVAL;
595 goto exit;
596 }
597
598 if (i < 0) {
599 ret = -EINVAL;
600 goto exit;
601 }
602
603 if (mic_ctx->micpm_ctx.pc6_timeout != i) {
604 mic_ctx->micpm_ctx.pc6_timeout = i;
605 }
606 pr_debug("pc6 timeout set to %us\n", mic_ctx->micpm_ctx.pc6_timeout);
607 ret = count;
608exit:
609 return ret;
610}
611static DEVICE_ATTR(pc6_timeout, S_IRUGO | S_IWUSR, show_pc6_timeout, store_pc6_timeout);
612
613static ssize_t show_log_buf_addr(struct device *dev,
614 struct device_attribute *attr,
615 char *buf)
616{
617 bd_info_t *bdi = dev_to_bdi(dev);
618 mic_ctx_t *mic_ctx = &bdi->bi_ctx;
619
620 return snprintf(buf, PAGE_SIZE, "%p\n", mic_ctx->log_buf_addr);
621}
622
623static ssize_t
624store_log_buf_addr(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
625{
626 int ret;
627 uint64_t addr;
628 bd_info_t *bdi = dev_to_bdi(dev);
629 mic_ctx_t *mic_ctx = &bdi->bi_ctx;
630
631 if (sscanf(buf, "%llx", &addr) != 1) {
632 ret = -EINVAL;
633 goto exit;
634 }
635
636 mic_ctx->log_buf_addr = (void*)addr;
637 ret = count;
638exit:
639 return ret;
640}
641static DEVICE_ATTR(log_buf_addr, S_IRUGO | S_IWUSR, show_log_buf_addr, store_log_buf_addr);
642
643static ssize_t show_log_buf_len(struct device *dev,
644 struct device_attribute *attr,
645 char *buf)
646{
647 bd_info_t *bdi = dev_to_bdi(dev);
648 mic_ctx_t *mic_ctx = &bdi->bi_ctx;
649
650 return snprintf(buf, PAGE_SIZE, "%p\n", mic_ctx->log_buf_len);
651}
652
653static ssize_t
654store_log_buf_len(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
655{
656 int ret;
657 uint64_t addr;
658 bd_info_t *bdi = dev_to_bdi(dev);
659 mic_ctx_t *mic_ctx = &bdi->bi_ctx;
660
661 if (sscanf(buf, "%llx", &addr) != 1) {
662 ret = -EINVAL;
663 goto exit;
664 }
665
666 mic_ctx->log_buf_len = (int*)addr;
667 ret = count;
668exit:
669 return ret;
670}
671static DEVICE_ATTR(log_buf_len, S_IRUGO | S_IWUSR, show_log_buf_len, store_log_buf_len);
672
673union serialnum {
674 uint32_t values[3];
675 char serial[13];
676};
677
678static ssize_t
679show_serialnumber(struct device *dev, struct device_attribute *attr, char *buf)
680{
681 bd_info_t *bdi = dev_to_bdi(dev);
682 union serialnum serial;
683 uint32_t ret;
684
685 memset(serial.serial, 0, sizeof(serial.serial));
686 ret = micpm_get_reference(&bdi->bi_ctx, true);
687 if (ret)
688 return -EAGAIN;
689 serial.values[0] = DBOX_READ(bdi->bi_ctx.mmio.va, DBOX_SWF1X0);
690 serial.values[1] = DBOX_READ(bdi->bi_ctx.mmio.va, DBOX_SWF1X1);
691 serial.values[2] = DBOX_READ(bdi->bi_ctx.mmio.va, DBOX_SWF1X2);
692 ret = micpm_put_reference(&bdi->bi_ctx);
693 if (ret)
694 return -EAGAIN;
695 return snprintf(buf, PAGE_SIZE, "%s", serial.serial);
696}
697static DEVICE_ATTR(serialnumber, S_IRUGO, show_serialnumber, NULL);
698
699static ssize_t
700show_interface_version(struct device *dev, struct device_attribute *attr, char *buf)
701{
702 return snprintf(buf, PAGE_SIZE, "%s", LINUX_INTERFACE_VERSION);
703}
704static DEVICE_ATTR(interface_version, S_IRUGO, show_interface_version, NULL);
705
706#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34) || \
707 defined(RHEL_RELEASE_CODE)
708extern ssize_t show_virtblk_file(struct device *dev, struct device_attribute *attr, char *buf);
709extern ssize_t store_virtblk_file(struct device *dev, struct device_attribute *attr,
710 const char *buf, size_t count);
711static DEVICE_ATTR(virtblk_file, S_IRUGO | S_IWUSR, show_virtblk_file, store_virtblk_file);
712#endif
713
714static struct attribute *bd_attributes[] = {
715 &dev_attr_family.attr,
716 &dev_attr_stepping.attr,
717 &dev_attr_state.attr,
718 &dev_attr_mode.attr,
719 &dev_attr_image.attr,
720 &dev_attr_initramfs.attr,
721 &dev_attr_post_code.attr,
722 &dev_attr_boot_count.attr,
723 &dev_attr_crash_count.attr,
724 &dev_attr_cmdline.attr,
725 &dev_attr_kernel_cmdline.attr,
726 &dev_attr_serialnumber.attr,
727 &dev_attr_scif_status.attr,
728 &dev_attr_meminfo.attr,
729 &dev_attr_pc3_enabled.attr,
730 &dev_attr_pc6_enabled.attr,
731 &dev_attr_pc6_timeout.attr,
732 &dev_attr_flash_update.attr,
733 &dev_attr_log_buf_addr.attr,
734 &dev_attr_log_buf_len.attr,
735#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34) || \
736 defined(RHEL_RELEASE_CODE)
737 &dev_attr_virtblk_file.attr,
738#endif
739 &dev_attr_sku.attr,
740 &dev_attr_interface_version.attr,
741
742#ifdef CONFIG_ML1OM
743 &sbox_attr_corevoltage.devattr.attr,
744 &sbox_attr_corefrequency.devattr.attr,
745#endif
746 &sbox_attr_memoryvoltage.devattr.attr,
747 &sbox_attr_memoryfrequency.devattr.attr,
748 &sbox_attr_memsize.devattr.attr,
749 &sbox_attr_flashversion.devattr.attr,
750 &sbox_attr_substepping_data.devattr.attr,
751 &sbox_attr_stepping_data.devattr.attr,
752 &sbox_attr_model.devattr.attr,
753 &sbox_attr_family_data.devattr.attr,
754 &sbox_attr_processor.devattr.attr,
755 &sbox_attr_platform.devattr.attr,
756 &sbox_attr_extended_model.devattr.attr,
757 &sbox_attr_extended_family.devattr.attr,
758 &sbox_attr_fuse_config_rev.devattr.attr,
759 &sbox_attr_active_cores.devattr.attr,
760 &sbox_attr_fail_safe_offset.devattr.attr,
761 NULL
762};
763
764struct attribute_group bd_attr_group = {
765 .attrs = bd_attributes
766};