0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 #include <linux/debugfs.h>
0032 #include <nvif/class.h>
0033 #include <nvif/if0001.h>
0034 #include "nouveau_debugfs.h"
0035 #include "nouveau_drv.h"
0036
0037 static int
0038 nouveau_debugfs_vbios_image(struct seq_file *m, void *data)
0039 {
0040 struct drm_info_node *node = (struct drm_info_node *) m->private;
0041 struct nouveau_drm *drm = nouveau_drm(node->minor->dev);
0042 int i;
0043
0044 for (i = 0; i < drm->vbios.length; i++)
0045 seq_printf(m, "%c", drm->vbios.data[i]);
0046 return 0;
0047 }
0048
0049 static int
0050 nouveau_debugfs_strap_peek(struct seq_file *m, void *data)
0051 {
0052 struct drm_info_node *node = m->private;
0053 struct nouveau_drm *drm = nouveau_drm(node->minor->dev);
0054 int ret;
0055
0056 ret = pm_runtime_get_sync(drm->dev->dev);
0057 if (ret < 0 && ret != -EACCES) {
0058 pm_runtime_put_autosuspend(drm->dev->dev);
0059 return ret;
0060 }
0061
0062 seq_printf(m, "0x%08x\n",
0063 nvif_rd32(&drm->client.device.object, 0x101000));
0064
0065 pm_runtime_mark_last_busy(drm->dev->dev);
0066 pm_runtime_put_autosuspend(drm->dev->dev);
0067
0068 return 0;
0069 }
0070
0071 static int
0072 nouveau_debugfs_pstate_get(struct seq_file *m, void *data)
0073 {
0074 struct drm_device *drm = m->private;
0075 struct nouveau_debugfs *debugfs = nouveau_debugfs(drm);
0076 struct nvif_object *ctrl = &debugfs->ctrl;
0077 struct nvif_control_pstate_info_v0 info = {};
0078 int ret, i;
0079
0080 if (!debugfs)
0081 return -ENODEV;
0082
0083 ret = nvif_mthd(ctrl, NVIF_CONTROL_PSTATE_INFO, &info, sizeof(info));
0084 if (ret)
0085 return ret;
0086
0087 for (i = 0; i < info.count + 1; i++) {
0088 const s32 state = i < info.count ? i :
0089 NVIF_CONTROL_PSTATE_ATTR_V0_STATE_CURRENT;
0090 struct nvif_control_pstate_attr_v0 attr = {
0091 .state = state,
0092 .index = 0,
0093 };
0094
0095 ret = nvif_mthd(ctrl, NVIF_CONTROL_PSTATE_ATTR,
0096 &attr, sizeof(attr));
0097 if (ret)
0098 return ret;
0099
0100 if (i < info.count)
0101 seq_printf(m, "%02x:", attr.state);
0102 else
0103 seq_printf(m, "%s:", info.pwrsrc == 0 ? "DC" :
0104 info.pwrsrc == 1 ? "AC" : "--");
0105
0106 attr.index = 0;
0107 do {
0108 attr.state = state;
0109 ret = nvif_mthd(ctrl, NVIF_CONTROL_PSTATE_ATTR,
0110 &attr, sizeof(attr));
0111 if (ret)
0112 return ret;
0113
0114 seq_printf(m, " %s %d", attr.name, attr.min);
0115 if (attr.min != attr.max)
0116 seq_printf(m, "-%d", attr.max);
0117 seq_printf(m, " %s", attr.unit);
0118 } while (attr.index);
0119
0120 if (state >= 0) {
0121 if (info.ustate_ac == state)
0122 seq_printf(m, " AC");
0123 if (info.ustate_dc == state)
0124 seq_printf(m, " DC");
0125 if (info.pstate == state)
0126 seq_printf(m, " *");
0127 } else {
0128 if (info.ustate_ac < -1)
0129 seq_printf(m, " AC");
0130 if (info.ustate_dc < -1)
0131 seq_printf(m, " DC");
0132 }
0133
0134 seq_printf(m, "\n");
0135 }
0136
0137 return 0;
0138 }
0139
0140 static ssize_t
0141 nouveau_debugfs_pstate_set(struct file *file, const char __user *ubuf,
0142 size_t len, loff_t *offp)
0143 {
0144 struct seq_file *m = file->private_data;
0145 struct drm_device *drm = m->private;
0146 struct nouveau_debugfs *debugfs = nouveau_debugfs(drm);
0147 struct nvif_object *ctrl = &debugfs->ctrl;
0148 struct nvif_control_pstate_user_v0 args = { .pwrsrc = -EINVAL };
0149 char buf[32] = {}, *tmp, *cur = buf;
0150 long value, ret;
0151
0152 if (!debugfs)
0153 return -ENODEV;
0154
0155 if (len >= sizeof(buf))
0156 return -EINVAL;
0157
0158 if (copy_from_user(buf, ubuf, len))
0159 return -EFAULT;
0160
0161 if ((tmp = strchr(buf, '\n')))
0162 *tmp = '\0';
0163
0164 if (!strncasecmp(cur, "dc:", 3)) {
0165 args.pwrsrc = 0;
0166 cur += 3;
0167 } else
0168 if (!strncasecmp(cur, "ac:", 3)) {
0169 args.pwrsrc = 1;
0170 cur += 3;
0171 }
0172
0173 if (!strcasecmp(cur, "none"))
0174 args.ustate = NVIF_CONTROL_PSTATE_USER_V0_STATE_UNKNOWN;
0175 else
0176 if (!strcasecmp(cur, "auto"))
0177 args.ustate = NVIF_CONTROL_PSTATE_USER_V0_STATE_PERFMON;
0178 else {
0179 ret = kstrtol(cur, 16, &value);
0180 if (ret)
0181 return ret;
0182 args.ustate = value;
0183 }
0184
0185 ret = pm_runtime_get_sync(drm->dev);
0186 if (ret < 0 && ret != -EACCES) {
0187 pm_runtime_put_autosuspend(drm->dev);
0188 return ret;
0189 }
0190
0191 ret = nvif_mthd(ctrl, NVIF_CONTROL_PSTATE_USER, &args, sizeof(args));
0192 pm_runtime_put_autosuspend(drm->dev);
0193 if (ret < 0)
0194 return ret;
0195
0196 return len;
0197 }
0198
0199 static int
0200 nouveau_debugfs_pstate_open(struct inode *inode, struct file *file)
0201 {
0202 return single_open(file, nouveau_debugfs_pstate_get, inode->i_private);
0203 }
0204
0205 static const struct file_operations nouveau_pstate_fops = {
0206 .owner = THIS_MODULE,
0207 .open = nouveau_debugfs_pstate_open,
0208 .read = seq_read,
0209 .write = nouveau_debugfs_pstate_set,
0210 .release = single_release,
0211 };
0212
0213 static struct drm_info_list nouveau_debugfs_list[] = {
0214 { "vbios.rom", nouveau_debugfs_vbios_image, 0, NULL },
0215 { "strap_peek", nouveau_debugfs_strap_peek, 0, NULL },
0216 };
0217 #define NOUVEAU_DEBUGFS_ENTRIES ARRAY_SIZE(nouveau_debugfs_list)
0218
0219 static const struct nouveau_debugfs_files {
0220 const char *name;
0221 const struct file_operations *fops;
0222 } nouveau_debugfs_files[] = {
0223 {"pstate", &nouveau_pstate_fops},
0224 };
0225
0226 void
0227 nouveau_drm_debugfs_init(struct drm_minor *minor)
0228 {
0229 struct nouveau_drm *drm = nouveau_drm(minor->dev);
0230 struct dentry *dentry;
0231 int i;
0232
0233 for (i = 0; i < ARRAY_SIZE(nouveau_debugfs_files); i++) {
0234 debugfs_create_file(nouveau_debugfs_files[i].name,
0235 S_IRUGO | S_IWUSR,
0236 minor->debugfs_root, minor->dev,
0237 nouveau_debugfs_files[i].fops);
0238 }
0239
0240 drm_debugfs_create_files(nouveau_debugfs_list,
0241 NOUVEAU_DEBUGFS_ENTRIES,
0242 minor->debugfs_root, minor);
0243
0244
0245
0246
0247 dentry = debugfs_lookup("vbios.rom", minor->debugfs_root);
0248 if (!dentry)
0249 return;
0250
0251 d_inode(dentry)->i_size = drm->vbios.length;
0252 dput(dentry);
0253 }
0254
0255 int
0256 nouveau_debugfs_init(struct nouveau_drm *drm)
0257 {
0258 drm->debugfs = kzalloc(sizeof(*drm->debugfs), GFP_KERNEL);
0259 if (!drm->debugfs)
0260 return -ENOMEM;
0261
0262 return nvif_object_ctor(&drm->client.device.object, "debugfsCtrl", 0,
0263 NVIF_CLASS_CONTROL, NULL, 0,
0264 &drm->debugfs->ctrl);
0265 }
0266
0267 void
0268 nouveau_debugfs_fini(struct nouveau_drm *drm)
0269 {
0270 if (drm->debugfs && drm->debugfs->ctrl.priv)
0271 nvif_object_dtor(&drm->debugfs->ctrl);
0272
0273 kfree(drm->debugfs);
0274 drm->debugfs = NULL;
0275 }