-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtso.c
More file actions
129 lines (108 loc) · 2.79 KB
/
tso.c
File metadata and controls
129 lines (108 loc) · 2.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// SPDX-License-Identifier: GPL-2.0
#include "global.h"
#include <asm/loongarchregs.h>
#include <linux/init.h>
#include <linux/kobject.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/smp.h>
#include <linux/sysfs.h>
static int tso_disabled = 1;
static int prev_value;
//[30:28] 101
#define CSR_TSO 5 << 28
static int get_bits(uint64_t value)
{
return (value >> 28) & 0x7;
}
static void disable_tso(void* failed)
{
uint64_t tmp;
tmp = read_csr_impctl1();
// save
prev_value = get_bits(tmp);
// empty
tmp &= ~(0x7 << 28);
// set 0b101
tmp |= CSR_STFILL;
write_csr_impctl1(tmp);
if (tmp != read_csr_impctl1())
*(int*)failed |= 1 << smp_processor_id();
printk("loongarch: gsconfig[%1d] %llx\n", smp_processor_id(), tmp);
}
static void enable_tso(void* failed)
{
uint64_t tmp;
tmp = read_csr_impctl1();
// empty
tmp &= ~(0x7 << 28);
// restore
tmp |= prev_value << 28;
write_csr_impctl1(tmp);
if (tmp != read_csr_impctl1())
*(int*)failed |= 1 << smp_processor_id();
printk("loongarch: gsconfig[%1d] %llx\n", smp_processor_id(), tmp);
}
static ssize_t tso_show(struct kobject* kobj, struct kobj_attribute* attr,
char* buf)
{
return sprintf(buf, "%d\n", tso_disabled);
}
static ssize_t tso_store(struct kobject* kobj, struct kobj_attribute* attr,
const char* buf, size_t count)
{
int ret = 0;
switch (buf[0]) {
case '0':
on_each_cpu(enable_tso, &ret, 1);
if (ret) {
printk("loongarch: failed to enable store fill %x\n", ret);
} else {
tso_disabled = 0;
printk("loongarch: store fill is now enabled\n");
}
break;
case '1':
on_each_cpu(disable_tso, &ret, 1);
if (ret) {
printk("loongarch: failed to disable store fill %x\n", ret);
} else {
tso_disabled = 1;
printk("loongarch: store fill is now disabled\n");
}
break;
default:
ret = -EINVAL;
}
return (ret == 0) ? count : -EPERM;
}
static void init_value(void)
{
int tmp;
tmp = read_csr_impctl1();
// save
prev_value = get_bits(tmp);
tso_disabled = (prev_value != 0b101);
}
static struct kobj_attribute tso_attribute = __ATTR(tso_disabled, 0660,
tso_show, tso_store);
int tso_init(void)
{
int error = 0;
if (!csr_kobj) {
printk("kobject is not initialized.\n");
return -ENOMEM;
}
error = sysfs_create_file(csr_kobj, &tso_attribute.attr);
if (error) {
init_value();
printk("failed to create the file in /sys/kernel/loongarch_csr\n");
} else {
printk("create file /sys/kernel/loongarch_csr/tso_disabled\n");
}
return error;
}
void tso_exit(void)
{
kobject_put(csr_kobj);
}