]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/fmc/fmc-debug.c
drm/amd/powerplay: check before issuing messages for max sustainable clocks
[linux.git] / drivers / fmc / fmc-debug.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2015 CERN (www.cern.ch)
4  * Author: Federico Vaga <federico.vaga@cern.ch>
5  */
6
7 #include <linux/module.h>
8 #include <linux/device.h>
9 #include <linux/init.h>
10 #include <linux/fs.h>
11 #include <linux/debugfs.h>
12 #include <linux/seq_file.h>
13 #include <asm/byteorder.h>
14
15 #include <linux/fmc.h>
16 #include <linux/sdb.h>
17 #include <linux/fmc-sdb.h>
18
19 #define FMC_DBG_SDB_DUMP "dump_sdb"
20
21 static char *__strip_trailing_space(char *buf, char *str, int len)
22 {
23         int i = len - 1;
24
25         memcpy(buf, str, len);
26         buf[len] = '\0';
27         while (i >= 0 && buf[i] == ' ')
28                 buf[i--] = '\0';
29         return buf;
30 }
31
32 #define __sdb_string(buf, field) ({                     \
33         BUILD_BUG_ON(sizeof(buf) < sizeof(field));      \
34         __strip_trailing_space(buf, (void *)(field), sizeof(field));    \
35                 })
36
37 /**
38  * We do not check seq_printf() errors because we want to see things in any case
39  */
40 static void fmc_sdb_dump_recursive(struct fmc_device *fmc, struct seq_file *s,
41                                    const struct sdb_array *arr)
42 {
43         unsigned long base = arr->baseaddr;
44         int i, j, n = arr->len, level = arr->level;
45         char tmp[64];
46
47         for (i = 0; i < n; i++) {
48                 union  sdb_record *r;
49                 struct sdb_product *p;
50                 struct sdb_component *c;
51
52                 r = &arr->record[i];
53                 c = &r->dev.sdb_component;
54                 p = &c->product;
55
56                 for (j = 0; j < level; j++)
57                         seq_printf(s, "   ");
58                 switch (r->empty.record_type) {
59                 case sdb_type_interconnect:
60                         seq_printf(s, "%08llx:%08x %.19s\n",
61                                    __be64_to_cpu(p->vendor_id),
62                                    __be32_to_cpu(p->device_id),
63                                    p->name);
64                         break;
65                 case sdb_type_device:
66                         seq_printf(s, "%08llx:%08x %.19s (%08llx-%08llx)\n",
67                                    __be64_to_cpu(p->vendor_id),
68                                    __be32_to_cpu(p->device_id),
69                                    p->name,
70                                    __be64_to_cpu(c->addr_first) + base,
71                                    __be64_to_cpu(c->addr_last) + base);
72                         break;
73                 case sdb_type_bridge:
74                         seq_printf(s, "%08llx:%08x %.19s (bridge: %08llx)\n",
75                                    __be64_to_cpu(p->vendor_id),
76                                    __be32_to_cpu(p->device_id),
77                                    p->name,
78                                    __be64_to_cpu(c->addr_first) + base);
79                         if (IS_ERR(arr->subtree[i])) {
80                                 seq_printf(s, "SDB: (bridge error %li)\n",
81                                          PTR_ERR(arr->subtree[i]));
82                                 break;
83                         }
84                         fmc_sdb_dump_recursive(fmc, s, arr->subtree[i]);
85                         break;
86                 case sdb_type_integration:
87                         seq_printf(s, "integration\n");
88                         break;
89                 case sdb_type_repo_url:
90                         seq_printf(s, "Synthesis repository: %s\n",
91                                           __sdb_string(tmp, r->repo_url.repo_url));
92                         break;
93                 case sdb_type_synthesis:
94                         seq_printf(s, "Bitstream '%s' ",
95                                           __sdb_string(tmp, r->synthesis.syn_name));
96                         seq_printf(s, "synthesized %08x by %s ",
97                                           __be32_to_cpu(r->synthesis.date),
98                                           __sdb_string(tmp, r->synthesis.user_name));
99                         seq_printf(s, "(%s version %x), ",
100                                           __sdb_string(tmp, r->synthesis.tool_name),
101                                           __be32_to_cpu(r->synthesis.tool_version));
102                         seq_printf(s, "commit %pm\n",
103                                           r->synthesis.commit_id);
104                         break;
105                 case sdb_type_empty:
106                         seq_printf(s, "empty\n");
107                         break;
108                 default:
109                         seq_printf(s, "UNKNOWN TYPE 0x%02x\n",
110                                    r->empty.record_type);
111                         break;
112                 }
113         }
114 }
115
116 static int fmc_sdb_dump(struct seq_file *s, void *offset)
117 {
118         struct fmc_device *fmc = s->private;
119
120         if (!fmc->sdb) {
121                 seq_printf(s, "no SDB information\n");
122                 return 0;
123         }
124
125         seq_printf(s, "FMC: %s (%s), slot %i, device %s\n", dev_name(fmc->hwdev),
126         fmc->carrier_name, fmc->slot_id, dev_name(&fmc->dev));
127         /* Dump SDB information */
128         fmc_sdb_dump_recursive(fmc, s, fmc->sdb);
129
130         return 0;
131 }
132
133
134 static int fmc_sdb_dump_open(struct inode *inode, struct file *file)
135 {
136         struct fmc_device *fmc = inode->i_private;
137
138         return single_open(file, fmc_sdb_dump, fmc);
139 }
140
141
142 const struct file_operations fmc_dbgfs_sdb_dump = {
143         .owner = THIS_MODULE,
144         .open  = fmc_sdb_dump_open,
145         .read = seq_read,
146         .llseek = seq_lseek,
147         .release = single_release,
148 };
149
150 int fmc_debug_init(struct fmc_device *fmc)
151 {
152         fmc->dbg_dir = debugfs_create_dir(dev_name(&fmc->dev), NULL);
153         if (IS_ERR_OR_NULL(fmc->dbg_dir)) {
154                 pr_err("FMC: Cannot create debugfs\n");
155                 return PTR_ERR(fmc->dbg_dir);
156         }
157
158         fmc->dbg_sdb_dump = debugfs_create_file(FMC_DBG_SDB_DUMP, 0444,
159                                                 fmc->dbg_dir, fmc,
160                                                 &fmc_dbgfs_sdb_dump);
161         if (IS_ERR_OR_NULL(fmc->dbg_sdb_dump))
162                 pr_err("FMC: Cannot create debugfs file %s\n",
163                        FMC_DBG_SDB_DUMP);
164
165         return 0;
166 }
167
168 void fmc_debug_exit(struct fmc_device *fmc)
169 {
170         if (fmc->dbg_dir)
171                 debugfs_remove_recursive(fmc->dbg_dir);
172 }