2 * Copyright (C) 2009 Red Hat <bskeggs@redhat.com>
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 * Ben Skeggs <bskeggs@redhat.com>
31 #include <linux/debugfs.h>
32 #include <nvif/class.h>
33 #include <nvif/if0001.h>
34 #include "nouveau_debugfs.h"
35 #include "nouveau_drv.h"
38 nouveau_debugfs_vbios_image(struct seq_file
*m
, void *data
)
40 struct drm_info_node
*node
= (struct drm_info_node
*) m
->private;
41 struct nouveau_drm
*drm
= nouveau_drm(node
->minor
->dev
);
44 for (i
= 0; i
< drm
->vbios
.length
; i
++)
45 seq_printf(m
, "%c", drm
->vbios
.data
[i
]);
50 nouveau_debugfs_strap_peek(struct seq_file
*m
, void *data
)
52 struct drm_info_node
*node
= m
->private;
53 struct nouveau_drm
*drm
= nouveau_drm(node
->minor
->dev
);
56 ret
= pm_runtime_get_sync(drm
->dev
->dev
);
57 if (ret
< 0 && ret
!= -EACCES
)
60 seq_printf(m
, "0x%08x\n",
61 nvif_rd32(&drm
->client
.device
.object
, 0x101000));
63 pm_runtime_mark_last_busy(drm
->dev
->dev
);
64 pm_runtime_put_autosuspend(drm
->dev
->dev
);
70 nouveau_debugfs_pstate_get(struct seq_file
*m
, void *data
)
72 struct drm_device
*drm
= m
->private;
73 struct nouveau_debugfs
*debugfs
= nouveau_debugfs(drm
);
74 struct nvif_object
*ctrl
= &debugfs
->ctrl
;
75 struct nvif_control_pstate_info_v0 info
= {};
81 ret
= nvif_mthd(ctrl
, NVIF_CONTROL_PSTATE_INFO
, &info
, sizeof(info
));
85 for (i
= 0; i
< info
.count
+ 1; i
++) {
86 const s32 state
= i
< info
.count
? i
:
87 NVIF_CONTROL_PSTATE_ATTR_V0_STATE_CURRENT
;
88 struct nvif_control_pstate_attr_v0 attr
= {
93 ret
= nvif_mthd(ctrl
, NVIF_CONTROL_PSTATE_ATTR
,
99 seq_printf(m
, "%02x:", attr
.state
);
101 seq_printf(m
, "%s:", info
.pwrsrc
== 0 ? "DC" :
102 info
.pwrsrc
== 1 ? "AC" : "--");
107 ret
= nvif_mthd(ctrl
, NVIF_CONTROL_PSTATE_ATTR
,
108 &attr
, sizeof(attr
));
112 seq_printf(m
, " %s %d", attr
.name
, attr
.min
);
113 if (attr
.min
!= attr
.max
)
114 seq_printf(m
, "-%d", attr
.max
);
115 seq_printf(m
, " %s", attr
.unit
);
116 } while (attr
.index
);
119 if (info
.ustate_ac
== state
)
120 seq_printf(m
, " AC");
121 if (info
.ustate_dc
== state
)
122 seq_printf(m
, " DC");
123 if (info
.pstate
== state
)
126 if (info
.ustate_ac
< -1)
127 seq_printf(m
, " AC");
128 if (info
.ustate_dc
< -1)
129 seq_printf(m
, " DC");
139 nouveau_debugfs_pstate_set(struct file
*file
, const char __user
*ubuf
,
140 size_t len
, loff_t
*offp
)
142 struct seq_file
*m
= file
->private_data
;
143 struct drm_device
*drm
= m
->private;
144 struct nouveau_debugfs
*debugfs
= nouveau_debugfs(drm
);
145 struct nvif_object
*ctrl
= &debugfs
->ctrl
;
146 struct nvif_control_pstate_user_v0 args
= { .pwrsrc
= -EINVAL
};
147 char buf
[32] = {}, *tmp
, *cur
= buf
;
153 if (len
>= sizeof(buf
))
156 if (copy_from_user(buf
, ubuf
, len
))
159 if ((tmp
= strchr(buf
, '\n')))
162 if (!strncasecmp(cur
, "dc:", 3)) {
166 if (!strncasecmp(cur
, "ac:", 3)) {
171 if (!strcasecmp(cur
, "none"))
172 args
.ustate
= NVIF_CONTROL_PSTATE_USER_V0_STATE_UNKNOWN
;
174 if (!strcasecmp(cur
, "auto"))
175 args
.ustate
= NVIF_CONTROL_PSTATE_USER_V0_STATE_PERFMON
;
177 ret
= kstrtol(cur
, 16, &value
);
183 ret
= pm_runtime_get_sync(drm
->dev
);
184 if (IS_ERR_VALUE(ret
) && ret
!= -EACCES
)
186 ret
= nvif_mthd(ctrl
, NVIF_CONTROL_PSTATE_USER
, &args
, sizeof(args
));
187 pm_runtime_put_autosuspend(drm
->dev
);
195 nouveau_debugfs_pstate_open(struct inode
*inode
, struct file
*file
)
197 return single_open(file
, nouveau_debugfs_pstate_get
, inode
->i_private
);
200 static const struct file_operations nouveau_pstate_fops
= {
201 .owner
= THIS_MODULE
,
202 .open
= nouveau_debugfs_pstate_open
,
204 .write
= nouveau_debugfs_pstate_set
,
207 static struct drm_info_list nouveau_debugfs_list
[] = {
208 { "vbios.rom", nouveau_debugfs_vbios_image
, 0, NULL
},
209 { "strap_peek", nouveau_debugfs_strap_peek
, 0, NULL
},
211 #define NOUVEAU_DEBUGFS_ENTRIES ARRAY_SIZE(nouveau_debugfs_list)
213 static const struct nouveau_debugfs_files
{
215 const struct file_operations
*fops
;
216 } nouveau_debugfs_files
[] = {
217 {"pstate", &nouveau_pstate_fops
},
221 nouveau_drm_debugfs_init(struct drm_minor
*minor
)
223 struct nouveau_drm
*drm
= nouveau_drm(minor
->dev
);
224 struct dentry
*dentry
;
227 for (i
= 0; i
< ARRAY_SIZE(nouveau_debugfs_files
); i
++) {
228 dentry
= debugfs_create_file(nouveau_debugfs_files
[i
].name
,
230 minor
->debugfs_root
, minor
->dev
,
231 nouveau_debugfs_files
[i
].fops
);
236 ret
= drm_debugfs_create_files(nouveau_debugfs_list
,
237 NOUVEAU_DEBUGFS_ENTRIES
,
238 minor
->debugfs_root
, minor
);
242 /* Set the size of the vbios since we know it, and it's confusing to
243 * userspace if it wants to seek() but the file has a length of 0
245 dentry
= debugfs_lookup("vbios.rom", minor
->debugfs_root
);
249 d_inode(dentry
)->i_size
= drm
->vbios
.length
;
256 nouveau_debugfs_init(struct nouveau_drm
*drm
)
260 drm
->debugfs
= kzalloc(sizeof(*drm
->debugfs
), GFP_KERNEL
);
264 ret
= nvif_object_init(&drm
->client
.device
.object
, 0,
265 NVIF_CLASS_CONTROL
, NULL
, 0,
266 &drm
->debugfs
->ctrl
);
274 nouveau_debugfs_fini(struct nouveau_drm
*drm
)
276 if (drm
->debugfs
&& drm
->debugfs
->ctrl
.priv
)
277 nvif_object_fini(&drm
->debugfs
->ctrl
);