Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
sparc
kernel
hvapi.c
Go to the documentation of this file.
1
/* hvapi.c: Hypervisor API management.
2
*
3
* Copyright (C) 2007 David S. Miller <
[email protected]
>
4
*/
5
#include <linux/kernel.h>
6
#include <linux/export.h>
7
#include <
linux/init.h
>
8
9
#include <asm/hypervisor.h>
10
#include <asm/oplib.h>
11
12
/* If the hypervisor indicates that the API setting
13
* calls are unsupported, by returning HV_EBADTRAP or
14
* HV_ENOTSUPPORTED, we assume that API groups with the
15
* PRE_API flag set are major 1 minor 0.
16
*/
17
struct
api_info
{
18
unsigned
long
group
;
19
unsigned
long
major
;
20
unsigned
long
minor
;
21
unsigned
int
refcnt
;
22
unsigned
int
flags
;
23
#define FLAG_PRE_API 0x00000001
24
};
25
26
static
struct
api_info
api_table[] = {
27
{ .group =
HV_GRP_SUN4V
, .flags =
FLAG_PRE_API
},
28
{ .group =
HV_GRP_CORE
, .flags =
FLAG_PRE_API
},
29
{ .group =
HV_GRP_INTR
, },
30
{ .group =
HV_GRP_SOFT_STATE
, },
31
{ .group =
HV_GRP_TM
, },
32
{ .group =
HV_GRP_PCI
, .flags =
FLAG_PRE_API
},
33
{ .group =
HV_GRP_LDOM
, },
34
{ .group =
HV_GRP_SVC_CHAN
, .flags =
FLAG_PRE_API
},
35
{ .group =
HV_GRP_NCS
, .flags =
FLAG_PRE_API
},
36
{ .group =
HV_GRP_RNG
, },
37
{ .group =
HV_GRP_PBOOT
, },
38
{ .group =
HV_GRP_TPM
, },
39
{ .group =
HV_GRP_SDIO
, },
40
{ .group =
HV_GRP_SDIO_ERR
, },
41
{ .group =
HV_GRP_REBOOT_DATA
, },
42
{ .group =
HV_GRP_NIAG_PERF
, .flags =
FLAG_PRE_API
},
43
{ .group =
HV_GRP_FIRE_PERF
, },
44
{ .group =
HV_GRP_N2_CPU
, },
45
{ .group =
HV_GRP_NIU
, },
46
{ .group =
HV_GRP_VF_CPU
, },
47
{ .group =
HV_GRP_KT_CPU
, },
48
{ .group =
HV_GRP_VT_CPU
, },
49
{ .group =
HV_GRP_DIAG
, .flags =
FLAG_PRE_API
},
50
};
51
52
static
DEFINE_SPINLOCK
(hvapi_lock);
53
54
static
struct
api_info
*__get_info(
unsigned
long
group
)
55
{
56
int
i
;
57
58
for
(i = 0; i <
ARRAY_SIZE
(api_table); i++) {
59
if
(api_table[i].group == group)
60
return
&api_table[
i
];
61
}
62
return
NULL
;
63
}
64
65
static
void
__get_ref(
struct
api_info
*
p
)
66
{
67
p->
refcnt
++;
68
}
69
70
static
void
__put_ref(
struct
api_info
*
p
)
71
{
72
if
(--p->
refcnt
== 0) {
73
unsigned
long
ignore;
74
75
sun4v_set_version
(p->
group
, 0, 0, &ignore);
76
p->
major
= p->
minor
= 0;
77
}
78
}
79
80
/* Register a hypervisor API specification. It indicates the
81
* API group and desired major+minor.
82
*
83
* If an existing API registration exists '0' (success) will
84
* be returned if it is compatible with the one being registered.
85
* Otherwise a negative error code will be returned.
86
*
87
* Otherwise an attempt will be made to negotiate the requested
88
* API group/major/minor with the hypervisor, and errors returned
89
* if that does not succeed.
90
*/
91
int
sun4v_hvapi_register
(
unsigned
long
group,
unsigned
long
major
,
92
unsigned
long
*
minor
)
93
{
94
struct
api_info
*
p
;
95
unsigned
long
flags
;
96
int
ret
;
97
98
spin_lock_irqsave
(&hvapi_lock, flags);
99
p = __get_info(group);
100
ret = -
EINVAL
;
101
if
(p) {
102
if
(p->
refcnt
) {
103
ret = -
EINVAL
;
104
if
(p->
major
== major) {
105
*minor = p->
minor
;
106
ret = 0;
107
}
108
}
else
{
109
unsigned
long
actual_minor;
110
unsigned
long
hv_ret;
111
112
hv_ret =
sun4v_set_version
(group, major, *minor,
113
&actual_minor);
114
ret = -
EINVAL
;
115
if
(hv_ret ==
HV_EOK
) {
116
*minor = actual_minor;
117
p->
major
=
major
;
118
p->
minor
= actual_minor;
119
ret = 0;
120
}
else
if
(hv_ret ==
HV_EBADTRAP
||
121
hv_ret ==
HV_ENOTSUPPORTED
) {
122
if
(p->
flags
&
FLAG_PRE_API
) {
123
if
(major == 1) {
124
p->
major
= 1;
125
p->
minor
= 0;
126
*minor = 0;
127
ret = 0;
128
}
129
}
130
}
131
}
132
133
if
(ret == 0)
134
__get_ref(p);
135
}
136
spin_unlock_irqrestore(&hvapi_lock, flags);
137
138
return
ret
;
139
}
140
EXPORT_SYMBOL
(
sun4v_hvapi_register
);
141
142
void
sun4v_hvapi_unregister
(
unsigned
long
group)
143
{
144
struct
api_info
*
p
;
145
unsigned
long
flags
;
146
147
spin_lock_irqsave
(&hvapi_lock, flags);
148
p = __get_info(group);
149
if
(p)
150
__put_ref(p);
151
spin_unlock_irqrestore(&hvapi_lock, flags);
152
}
153
EXPORT_SYMBOL
(
sun4v_hvapi_unregister
);
154
155
int
sun4v_hvapi_get
(
unsigned
long
group,
156
unsigned
long
*
major
,
157
unsigned
long
*
minor
)
158
{
159
struct
api_info
*
p
;
160
unsigned
long
flags
;
161
int
ret
;
162
163
spin_lock_irqsave
(&hvapi_lock, flags);
164
ret = -
EINVAL
;
165
p = __get_info(group);
166
if
(p && p->
refcnt
) {
167
*major = p->
major
;
168
*minor = p->
minor
;
169
ret = 0;
170
}
171
spin_unlock_irqrestore(&hvapi_lock, flags);
172
173
return
ret
;
174
}
175
EXPORT_SYMBOL
(
sun4v_hvapi_get
);
176
177
void
__init
sun4v_hvapi_init
(
void
)
178
{
179
unsigned
long
group
,
major
,
minor
;
180
181
group =
HV_GRP_SUN4V
;
182
major = 1;
183
minor = 0;
184
if
(
sun4v_hvapi_register
(group, major, &minor))
185
goto
bad
;
186
187
group =
HV_GRP_CORE
;
188
major = 1;
189
minor = 1;
190
if
(
sun4v_hvapi_register
(group, major, &minor))
191
goto
bad
;
192
193
return
;
194
195
bad
:
196
prom_printf
(
"HVAPI: Cannot register API group "
197
"%lx with major(%lu) minor(%lu)\n"
,
198
group, major, minor);
199
prom_halt
();
200
}
Generated on Thu Jan 10 2013 13:18:22 for Linux Kernel by
1.8.2