at v5.2 4.3 kB view raw
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 21static 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 */ 40static 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 116static 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 134static 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 142const 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 150int 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 168void fmc_debug_exit(struct fmc_device *fmc) 169{ 170 if (fmc->dbg_dir) 171 debugfs_remove_recursive(fmc->dbg_dir); 172}