1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2021 Intel Corporation. All rights rsvd. */
3 #include <linux/init.h>
4 #include <linux/kernel.h>
5 #include <linux/module.h>
7 #include <linux/debugfs.h>
8 #include <linux/io-64-nonatomic-lo-hi.h>
9 #include <uapi/linux/idxd.h>
11 #include "registers.h"
13 static struct dentry
*idxd_debugfs_dir
;
15 static void dump_event_entry(struct idxd_device
*idxd
, struct seq_file
*s
,
16 u16 index
, int *count
, bool processed
)
18 struct idxd_evl
*evl
= idxd
->evl
;
19 struct dsa_evl_entry
*entry
;
20 struct dsa_completion_record
*cr
;
23 int evl_strides
= evl_ent_size(idxd
) / sizeof(u64
);
25 entry
= (struct dsa_evl_entry
*)evl
->log
+ index
;
27 if (!entry
->e
.desc_valid
)
30 seq_printf(s
, "Event Log entry %d (real index %u) processed: %u\n",
31 *count
, index
, processed
);
33 seq_printf(s
, "desc valid %u wq idx valid %u\n"
34 "batch %u fault rw %u priv %u error 0x%x\n"
35 "wq idx %u op %#x pasid %u batch idx %u\n"
37 entry
->e
.desc_valid
, entry
->e
.wq_idx_valid
,
38 entry
->e
.batch
, entry
->e
.fault_rw
, entry
->e
.priv
,
39 entry
->e
.error
, entry
->e
.wq_idx
, entry
->e
.operation
,
40 entry
->e
.pasid
, entry
->e
.batch_idx
, entry
->e
.fault_addr
);
43 seq_printf(s
, "status %#x result %#x fault_info %#x bytes_completed %u\n"
44 "fault addr %#llx inv flags %#x\n\n",
45 cr
->status
, cr
->result
, cr
->fault_info
, cr
->bytes_completed
,
46 cr
->fault_addr
, cr
->invalid_flags
);
50 for (i
= 0; i
< evl_strides
; i
++)
51 seq_printf(s
, "entry[%d] = %#llx\n", i
, raw
[i
]);
57 static int debugfs_evl_show(struct seq_file
*s
, void *d
)
59 struct idxd_device
*idxd
= s
->private;
60 struct idxd_evl
*evl
= idxd
->evl
;
61 union evl_status_reg evl_status
;
62 u16 h
, t
, evl_size
, i
;
64 bool processed
= true;
66 if (!evl
|| !evl
->log
)
69 mutex_lock(&evl
->lock
);
71 evl_status
.bits
= ioread64(idxd
->reg_base
+ IDXD_EVLSTATUS_OFFSET
);
76 seq_printf(s
, "Event Log head %u tail %u interrupt pending %u\n\n",
77 evl_status
.head
, evl_status
.tail
, evl_status
.int_pending
);
81 i
= (i
+ 1) % evl_size
;
85 if (processed
&& i
== h
)
87 dump_event_entry(idxd
, s
, i
, &count
, processed
);
90 mutex_unlock(&evl
->lock
);
94 DEFINE_SHOW_ATTRIBUTE(debugfs_evl
);
96 int idxd_device_init_debugfs(struct idxd_device
*idxd
)
98 if (IS_ERR_OR_NULL(idxd_debugfs_dir
))
101 idxd
->dbgfs_dir
= debugfs_create_dir(dev_name(idxd_confdev(idxd
)), idxd_debugfs_dir
);
102 if (IS_ERR(idxd
->dbgfs_dir
))
103 return PTR_ERR(idxd
->dbgfs_dir
);
106 idxd
->dbgfs_evl_file
= debugfs_create_file("event_log", 0400,
107 idxd
->dbgfs_dir
, idxd
,
109 if (IS_ERR(idxd
->dbgfs_evl_file
)) {
110 debugfs_remove_recursive(idxd
->dbgfs_dir
);
111 idxd
->dbgfs_dir
= NULL
;
112 return PTR_ERR(idxd
->dbgfs_evl_file
);
119 void idxd_device_remove_debugfs(struct idxd_device
*idxd
)
121 debugfs_remove_recursive(idxd
->dbgfs_dir
);
124 int idxd_init_debugfs(void)
126 if (!debugfs_initialized())
129 idxd_debugfs_dir
= debugfs_create_dir(KBUILD_MODNAME
, NULL
);
130 if (IS_ERR(idxd_debugfs_dir
))
131 return PTR_ERR(idxd_debugfs_dir
);
135 void idxd_remove_debugfs(void)
137 debugfs_remove_recursive(idxd_debugfs_dir
);