| 1 | // SPDX-License-Identifier: GPL-2.0 | 
|---|
| 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(sem: &dev->me_clients_rwsem); | 
|---|
| 29 |  | 
|---|
| 30 | seq_puts(m, s: "  |id|fix|         UUID                       |con|msg len|sb|refc|vt|\n"); | 
|---|
| 31 |  | 
|---|
| 32 | /*  if the driver is not enabled the list won't be consistent */ | 
|---|
| 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, fmt: "%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(kref: &me_cl->refcnt), | 
|---|
| 48 | me_cl->props.vt_supported); | 
|---|
| 49 | mei_me_cl_put(me_cl); | 
|---|
| 50 | } | 
|---|
| 51 |  | 
|---|
| 52 | out: | 
|---|
| 53 | up_read(sem: &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(lock: &dev->device_lock); | 
|---|
| 68 |  | 
|---|
| 69 | seq_puts(m, s: "   |me|host|state|rd|wr|wrq\n"); | 
|---|
| 70 |  | 
|---|
| 71 | /*  if the driver is not enabled the list won't be consistent */ | 
|---|
| 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, fmt: "%3d|%2d|%4d|%5d|%2d|%2d|%3u\n", | 
|---|
| 78 | i, mei_cl_me_id(cl), cl->host_client_id, cl->state, | 
|---|
| 79 | !list_empty(head: &cl->rd_completed), cl->writing_state, | 
|---|
| 80 | cl->tx_cb_queued); | 
|---|
| 81 | i++; | 
|---|
| 82 | } | 
|---|
| 83 | out: | 
|---|
| 84 | mutex_unlock(lock: &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, fmt: "dev: %s\n", mei_dev_state_str(state: dev->dev_state)); | 
|---|
| 108 | seq_printf(m, fmt: "hbm: %s\n", mei_hbm_state_str(state: dev->hbm_state)); | 
|---|
| 109 |  | 
|---|
| 110 | if (dev->hbm_state >= MEI_HBM_ENUM_CLIENTS && | 
|---|
| 111 | dev->hbm_state <= MEI_HBM_STARTED) { | 
|---|
| 112 | seq_puts(m, s: "hbm features:\n"); | 
|---|
| 113 | seq_printf(m, fmt: "\tPG: %01d\n", dev->hbm_f_pg_supported); | 
|---|
| 114 | seq_printf(m, fmt: "\tDC: %01d\n", dev->hbm_f_dc_supported); | 
|---|
| 115 | seq_printf(m, fmt: "\tIE: %01d\n", dev->hbm_f_ie_supported); | 
|---|
| 116 | seq_printf(m, fmt: "\tDOT: %01d\n", dev->hbm_f_dot_supported); | 
|---|
| 117 | seq_printf(m, fmt: "\tEV: %01d\n", dev->hbm_f_ev_supported); | 
|---|
| 118 | seq_printf(m, fmt: "\tFA: %01d\n", dev->hbm_f_fa_supported); | 
|---|
| 119 | seq_printf(m, fmt: "\tOS: %01d\n", dev->hbm_f_os_supported); | 
|---|
| 120 | seq_printf(m, fmt: "\tDR: %01d\n", dev->hbm_f_dr_supported); | 
|---|
| 121 | seq_printf(m, fmt: "\tVT: %01d\n", dev->hbm_f_vt_supported); | 
|---|
| 122 | seq_printf(m, fmt: "\tCAP: %01d\n", dev->hbm_f_cap_supported); | 
|---|
| 123 | seq_printf(m, fmt: "\tCD: %01d\n", dev->hbm_f_cd_supported); | 
|---|
| 124 | } | 
|---|
| 125 |  | 
|---|
| 126 | seq_printf(m, fmt: "pg:  %s, %s\n", | 
|---|
| 127 | mei_pg_is_enabled(dev) ? "ENABLED": "DISABLED", | 
|---|
| 128 | mei_pg_state_str(state: mei_pg_state(dev))); | 
|---|
| 129 |  | 
|---|
| 130 | seq_printf(m, fmt: "pxp: %s\n", mei_dev_pxp_mode_str(state: 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(dentry: 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 | } | 
|---|
| 196 |  | 
|---|