| 1 | |
| 2 | |
| 3 | * Copyright (c) 2012-2022, Intel Corporation. All rights reserved
|
| 4 | * Intel Management Engine Interface (Intel MEI) Linux driver
|
| 5 |
|
| 6 |
|
| 7 | #include <linux/slab.h>
|
| 8 | #include <linux/kernel.h>
|
| 9 | #include <linux/device.h>
|
| 10 | #include <linux/debugfs.h>
|
| 11 | #include <linux/seq_file.h>
|
| 12 |
|
| 13 | #include <linux/mei.h>
|
| 14 |
|
| 15 | #include "mei_dev.h"
|
| 16 | #include "client.h"
|
| 17 | #include "hw.h"
|
| 18 |
|
| 19 | static int mei_dbgfs_meclients_show(struct seq_file *m, void *unused)
|
| 20 | {
|
| 21 | struct mei_device *dev = m->private;
|
| 22 | struct mei_me_client *me_cl;
|
| 23 | int i = 0;
|
| 24 |
|
| 25 | if (!dev)
|
| 26 | return -ENODEV;
|
| 27 |
|
| 28 | down_read(&dev->me_clients_rwsem);
|
| 29 |
|
| 30 | seq_puts(m, " |id|fix| UUID |con|msg len|sb|refc|vt|\n");
|
| 31 |
|
| 32 |
|
| 33 | if (dev->dev_state != MEI_DEV_ENABLED)
|
| 34 | goto out;
|
| 35 |
|
| 36 | list_for_each_entry(me_cl, &dev->me_clients, list) {
|
| 37 | if (!mei_me_cl_get(me_cl))
|
| 38 | continue;
|
| 39 |
|
| 40 | seq_printf(m, "%2d|%2d|%3d|%pUl|%3d|%7d|%2d|%4d|%2d|\n",
|
| 41 | i++, me_cl->client_id,
|
| 42 | me_cl->props.fixed_address,
|
| 43 | &me_cl->props.protocol_name,
|
| 44 | me_cl->props.max_number_of_connections,
|
| 45 | me_cl->props.max_msg_length,
|
| 46 | me_cl->props.single_recv_buf,
|
| 47 | kref_read(&me_cl->refcnt),
|
| 48 | me_cl->props.vt_supported);
|
| 49 | mei_me_cl_put(me_cl);
|
| 50 | }
|
| 51 |
|
| 52 | out:
|
| 53 | up_read(&dev->me_clients_rwsem);
|
| 54 | return 0;
|
| 55 | }
|
| 56 | DEFINE_SHOW_ATTRIBUTE(mei_dbgfs_meclients);
|
| 57 |
|
| 58 | static int mei_dbgfs_active_show(struct seq_file *m, void *unused)
|
| 59 | {
|
| 60 | struct mei_device *dev = m->private;
|
| 61 | struct mei_cl *cl;
|
| 62 | int i = 0;
|
| 63 |
|
| 64 | if (!dev)
|
| 65 | return -ENODEV;
|
| 66 |
|
| 67 | mutex_lock(&dev->device_lock);
|
| 68 |
|
| 69 | seq_puts(m, " |me|host|state|rd|wr|wrq\n");
|
| 70 |
|
| 71 |
|
| 72 | if (dev->dev_state != MEI_DEV_ENABLED)
|
| 73 | goto out;
|
| 74 |
|
| 75 | list_for_each_entry(cl, &dev->file_list, link) {
|
| 76 |
|
| 77 | seq_printf(m, "%3d|%2d|%4d|%5d|%2d|%2d|%3u\n",
|
| 78 | i, mei_cl_me_id(cl), cl->host_client_id, cl->state,
|
| 79 | !list_empty(&cl->rd_completed), cl->writing_state,
|
| 80 | cl->tx_cb_queued);
|
| 81 | i++;
|
| 82 | }
|
| 83 | out:
|
| 84 | mutex_unlock(&dev->device_lock);
|
| 85 | return 0;
|
| 86 | }
|
| 87 | DEFINE_SHOW_ATTRIBUTE(mei_dbgfs_active);
|
| 88 |
|
| 89 | static const char *mei_dev_pxp_mode_str(enum mei_dev_pxp_mode state)
|
| 90 | {
|
| 91 | #define MEI_PXP_MODE(state) case MEI_DEV_PXP_##state: return #state
|
| 92 | switch (state) {
|
| 93 | MEI_PXP_MODE(DEFAULT);
|
| 94 | MEI_PXP_MODE(INIT);
|
| 95 | MEI_PXP_MODE(SETUP);
|
| 96 | MEI_PXP_MODE(READY);
|
| 97 | default:
|
| 98 | return "unknown";
|
| 99 | }
|
| 100 | #undef MEI_PXP_MODE
|
| 101 | }
|
| 102 |
|
| 103 | static int mei_dbgfs_devstate_show(struct seq_file *m, void *unused)
|
| 104 | {
|
| 105 | struct mei_device *dev = m->private;
|
| 106 |
|
| 107 | seq_printf(m, "dev: %s\n", mei_dev_state_str(dev->dev_state));
|
| 108 | seq_printf(m, "hbm: %s\n", mei_hbm_state_str(dev->hbm_state));
|
| 109 |
|
| 110 | if (dev->hbm_state >= MEI_HBM_ENUM_CLIENTS &&
|
| 111 | dev->hbm_state <= MEI_HBM_STARTED) {
|
| 112 | seq_puts(m, "hbm features:\n");
|
| 113 | seq_printf(m, "\tPG: %01d\n", dev->hbm_f_pg_supported);
|
| 114 | seq_printf(m, "\tDC: %01d\n", dev->hbm_f_dc_supported);
|
| 115 | seq_printf(m, "\tIE: %01d\n", dev->hbm_f_ie_supported);
|
| 116 | seq_printf(m, "\tDOT: %01d\n", dev->hbm_f_dot_supported);
|
| 117 | seq_printf(m, "\tEV: %01d\n", dev->hbm_f_ev_supported);
|
| 118 | seq_printf(m, "\tFA: %01d\n", dev->hbm_f_fa_supported);
|
| 119 | seq_printf(m, "\tOS: %01d\n", dev->hbm_f_os_supported);
|
| 120 | seq_printf(m, "\tDR: %01d\n", dev->hbm_f_dr_supported);
|
| 121 | seq_printf(m, "\tVT: %01d\n", dev->hbm_f_vt_supported);
|
| 122 | seq_printf(m, "\tCAP: %01d\n", dev->hbm_f_cap_supported);
|
| 123 | seq_printf(m, "\tCD: %01d\n", dev->hbm_f_cd_supported);
|
| 124 | }
|
| 125 |
|
| 126 | seq_printf(m, "pg: %s, %s\n",
|
| 127 | mei_pg_is_enabled(dev) ? "ENABLED" : "DISABLED",
|
| 128 | mei_pg_state_str(mei_pg_state(dev)));
|
| 129 |
|
| 130 | seq_printf(m, "pxp: %s\n", mei_dev_pxp_mode_str(dev->pxp_mode));
|
| 131 |
|
| 132 | return 0;
|
| 133 | }
|
| 134 | DEFINE_SHOW_ATTRIBUTE(mei_dbgfs_devstate);
|
| 135 |
|
| 136 | static ssize_t mei_dbgfs_write_allow_fa(struct file *file,
|
| 137 | const char __user *user_buf,
|
| 138 | size_t count, loff_t *ppos)
|
| 139 | {
|
| 140 | struct mei_device *dev;
|
| 141 | int ret;
|
| 142 |
|
| 143 | dev = container_of(file->private_data,
|
| 144 | struct mei_device, allow_fixed_address);
|
| 145 |
|
| 146 | ret = debugfs_write_file_bool(file, user_buf, count, ppos);
|
| 147 | if (ret < 0)
|
| 148 | return ret;
|
| 149 | dev->override_fixed_address = true;
|
| 150 | return ret;
|
| 151 | }
|
| 152 |
|
| 153 | static const struct file_operations mei_dbgfs_allow_fa_fops = {
|
| 154 | .open = simple_open,
|
| 155 | .read = debugfs_read_file_bool,
|
| 156 | .write = mei_dbgfs_write_allow_fa,
|
| 157 | .llseek = generic_file_llseek,
|
| 158 | };
|
| 159 |
|
| 160 | |
| 161 | * mei_dbgfs_deregister - Remove the debugfs files and directories
|
| 162 | *
|
| 163 | * @dev: the mei device structure
|
| 164 |
|
| 165 | void mei_dbgfs_deregister(struct mei_device *dev)
|
| 166 | {
|
| 167 | if (!dev->dbgfs_dir)
|
| 168 | return;
|
| 169 | debugfs_remove_recursive(dev->dbgfs_dir);
|
| 170 | dev->dbgfs_dir = NULL;
|
| 171 | }
|
| 172 |
|
| 173 | |
| 174 | * mei_dbgfs_register - Add the debugfs files
|
| 175 | *
|
| 176 | * @dev: the mei device structure
|
| 177 | * @name: the mei device name
|
| 178 |
|
| 179 | void mei_dbgfs_register(struct mei_device *dev, const char *name)
|
| 180 | {
|
| 181 | struct dentry *dir;
|
| 182 |
|
| 183 | dir = debugfs_create_dir(name, NULL);
|
| 184 | dev->dbgfs_dir = dir;
|
| 185 |
|
| 186 | debugfs_create_file("meclients", S_IRUSR, dir, dev,
|
| 187 | &mei_dbgfs_meclients_fops);
|
| 188 | debugfs_create_file("active", S_IRUSR, dir, dev,
|
| 189 | &mei_dbgfs_active_fops);
|
| 190 | debugfs_create_file("devstate", S_IRUSR, dir, dev,
|
| 191 | &mei_dbgfs_devstate_fops);
|
| 192 | debugfs_create_file("allow_fixed_address", S_IRUSR | S_IWUSR, dir,
|
| 193 | &dev->allow_fixed_address,
|
| 194 | &mei_dbgfs_allow_fa_fops);
|
| 195 | }
|