1 // SPDX-License-Identifier: GPL-2.0-only 2 3 /* Copyright (c) 2020, The Linux Foundation. All rights reserved. */ 4 /* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. */ 5 6 #include <linux/debugfs.h> 7 #include <linux/device.h> 8 #include <linux/fs.h> 9 #include <linux/list.h> 10 #include <linux/mhi.h> 11 #include <linux/mutex.h> 12 #include <linux/overflow.h> 13 #include <linux/pci.h> 14 #include <linux/seq_file.h> 15 #include <linux/sprintf.h> 16 #include <linux/string.h> 17 #include <linux/types.h> 18 #include <linux/workqueue.h> 19 20 #include "qaic.h" 21 #include "qaic_debugfs.h" 22 23 #define BOOTLOG_POOL_SIZE 16 24 #define BOOTLOG_MSG_SIZE 512 25 #define QAIC_DBC_DIR_NAME 9 26 27 struct bootlog_msg { 28 /* Buffer for bootlog messages */ 29 char str[BOOTLOG_MSG_SIZE]; 30 /* Root struct of device, used to access device resources */ 31 struct qaic_device *qdev; 32 /* Work struct to schedule work coming on QAIC_LOGGING channel */ 33 struct work_struct work; 34 }; 35 36 struct bootlog_page { 37 /* Node in list of bootlog pages maintained by root device struct */ 38 struct list_head node; 39 /* Total size of the buffer that holds the bootlogs. It is PAGE_SIZE */ 40 unsigned int size; 41 /* Offset for the next bootlog */ 42 unsigned int offset; 43 }; 44 45 static int bootlog_show(struct seq_file *s, void *unused) 46 { 47 struct bootlog_page *page; 48 struct qaic_device *qdev; 49 void *page_end; 50 void *log; 51 52 qdev = s->private; 53 mutex_lock(&qdev->bootlog_mutex); 54 list_for_each_entry(page, &qdev->bootlog, node) { 55 log = page + 1; 56 page_end = (void *)page + page->offset; 57 while (log < page_end) { 58 seq_printf(s, "%s", (char *)log); 59 log += strlen(log) + 1; 60 } 61 } 62 mutex_unlock(&qdev->bootlog_mutex); 63 64 return 0; 65 } 66 67 static int bootlog_fops_open(struct inode *inode, struct file *file) 68 { 69 return single_open(file, bootlog_show, inode->i_private); 70 } 71 72 static const struct file_operations bootlog_fops = { 73 .owner = THIS_MODULE, 74 .open = bootlog_fops_open, 75 .read = seq_read, 76 .llseek = seq_lseek, 77 .release = single_release, 78 }; 79 80 static int read_dbc_fifo_size(struct seq_file *s, void *unused) 81 { 82 struct dma_bridge_chan *dbc = s->private; 83 84 seq_printf(s, "%u\n", dbc->nelem); 85 return 0; 86 } 87 88 static int fifo_size_open(struct inode *inode, struct file *file) 89 { 90 return single_open(file, read_dbc_fifo_size, inode->i_private); 91 } 92 93 static const struct file_operations fifo_size_fops = { 94 .owner = THIS_MODULE, 95 .open = fifo_size_open, 96 .read = seq_read, 97 .llseek = seq_lseek, 98 .release = single_release, 99 }; 100 101 static int read_dbc_queued(struct seq_file *s, void *unused) 102 { 103 struct dma_bridge_chan *dbc = s->private; 104 u32 tail = 0, head = 0; 105 106 qaic_data_get_fifo_info(dbc, &head, &tail); 107 108 if (head == U32_MAX || tail == U32_MAX) 109 seq_printf(s, "%u\n", 0); 110 else if (head > tail) 111 seq_printf(s, "%u\n", dbc->nelem - head + tail); 112 else 113 seq_printf(s, "%u\n", tail - head); 114 115 return 0; 116 } 117 118 static int queued_open(struct inode *inode, struct file *file) 119 { 120 return single_open(file, read_dbc_queued, inode->i_private); 121 } 122 123 static const struct file_operations queued_fops = { 124 .owner = THIS_MODULE, 125 .open = queued_open, 126 .read = seq_read, 127 .llseek = seq_lseek, 128 .release = single_release, 129 }; 130 131 void qaic_debugfs_init(struct qaic_drm_device *qddev) 132 { 133 struct qaic_device *qdev = qddev->qdev; 134 struct dentry *debugfs_root; 135 struct dentry *debugfs_dir; 136 char name[QAIC_DBC_DIR_NAME]; 137 u32 i; 138 139 debugfs_root = to_drm(qddev)->debugfs_root; 140 141 debugfs_create_file("bootlog", 0400, debugfs_root, qdev, &bootlog_fops); 142 /* 143 * 256 dbcs per device is likely the max we will ever see and lets static checking see a 144 * reasonable range. 145 */ 146 for (i = 0; i < qdev->num_dbc && i < 256; ++i) { 147 snprintf(name, QAIC_DBC_DIR_NAME, "dbc%03u", i); 148 debugfs_dir = debugfs_create_dir(name, debugfs_root); 149 debugfs_create_file("fifo_size", 0400, debugfs_dir, &qdev->dbc[i], &fifo_size_fops); 150 debugfs_create_file("queued", 0400, debugfs_dir, &qdev->dbc[i], &queued_fops); 151 } 152 } 153 154 static struct bootlog_page *alloc_bootlog_page(struct qaic_device *qdev) 155 { 156 struct bootlog_page *page; 157 158 page = (struct bootlog_page *)devm_get_free_pages(&qdev->pdev->dev, GFP_KERNEL, 0); 159 if (!page) 160 return page; 161 162 page->size = PAGE_SIZE; 163 page->offset = sizeof(*page); 164 list_add_tail(&page->node, &qdev->bootlog); 165 166 return page; 167 } 168 169 static int reset_bootlog(struct qaic_device *qdev) 170 { 171 struct bootlog_page *page; 172 struct bootlog_page *i; 173 174 mutex_lock(&qdev->bootlog_mutex); 175 list_for_each_entry_safe(page, i, &qdev->bootlog, node) { 176 list_del(&page->node); 177 devm_free_pages(&qdev->pdev->dev, (unsigned long)page); 178 } 179 180 page = alloc_bootlog_page(qdev); 181 mutex_unlock(&qdev->bootlog_mutex); 182 if (!page) 183 return -ENOMEM; 184 185 return 0; 186 } 187 188 static void *bootlog_get_space(struct qaic_device *qdev, unsigned int size) 189 { 190 struct bootlog_page *page; 191 192 page = list_last_entry(&qdev->bootlog, struct bootlog_page, node); 193 194 if (size_add(size, sizeof(*page)) > page->size) 195 return NULL; 196 197 if (page->offset + size > page->size) { 198 page = alloc_bootlog_page(qdev); 199 if (!page) 200 return NULL; 201 } 202 203 return (void *)page + page->offset; 204 } 205 206 static void bootlog_commit(struct qaic_device *qdev, unsigned int size) 207 { 208 struct bootlog_page *page; 209 210 page = list_last_entry(&qdev->bootlog, struct bootlog_page, node); 211 212 page->offset += size; 213 } 214 215 static void bootlog_log(struct work_struct *work) 216 { 217 struct bootlog_msg *msg = container_of(work, struct bootlog_msg, work); 218 unsigned int len = strlen(msg->str) + 1; 219 struct qaic_device *qdev = msg->qdev; 220 void *log; 221 222 mutex_lock(&qdev->bootlog_mutex); 223 log = bootlog_get_space(qdev, len); 224 if (log) { 225 memcpy(log, msg, len); 226 bootlog_commit(qdev, len); 227 } 228 mutex_unlock(&qdev->bootlog_mutex); 229 230 if (mhi_queue_buf(qdev->bootlog_ch, DMA_FROM_DEVICE, msg, BOOTLOG_MSG_SIZE, MHI_EOT)) 231 devm_kfree(&qdev->pdev->dev, msg); 232 } 233 234 static int qaic_bootlog_mhi_probe(struct mhi_device *mhi_dev, const struct mhi_device_id *id) 235 { 236 struct qaic_device *qdev = pci_get_drvdata(to_pci_dev(mhi_dev->mhi_cntrl->cntrl_dev)); 237 struct bootlog_msg *msg; 238 int i, ret; 239 240 qdev->bootlog_wq = alloc_ordered_workqueue("qaic_bootlog", 0); 241 if (!qdev->bootlog_wq) { 242 ret = -ENOMEM; 243 goto out; 244 } 245 246 ret = reset_bootlog(qdev); 247 if (ret) 248 goto destroy_workqueue; 249 250 ret = mhi_prepare_for_transfer(mhi_dev); 251 if (ret) 252 goto destroy_workqueue; 253 254 for (i = 0; i < BOOTLOG_POOL_SIZE; i++) { 255 msg = devm_kzalloc(&qdev->pdev->dev, sizeof(*msg), GFP_KERNEL); 256 if (!msg) { 257 ret = -ENOMEM; 258 goto mhi_unprepare; 259 } 260 261 msg->qdev = qdev; 262 INIT_WORK(&msg->work, bootlog_log); 263 264 ret = mhi_queue_buf(mhi_dev, DMA_FROM_DEVICE, msg, BOOTLOG_MSG_SIZE, MHI_EOT); 265 if (ret) 266 goto mhi_unprepare; 267 } 268 269 dev_set_drvdata(&mhi_dev->dev, qdev); 270 qdev->bootlog_ch = mhi_dev; 271 return 0; 272 273 mhi_unprepare: 274 mhi_unprepare_from_transfer(mhi_dev); 275 destroy_workqueue: 276 flush_workqueue(qdev->bootlog_wq); 277 destroy_workqueue(qdev->bootlog_wq); 278 out: 279 return ret; 280 } 281 282 static void qaic_bootlog_mhi_remove(struct mhi_device *mhi_dev) 283 { 284 struct qaic_device *qdev; 285 286 qdev = dev_get_drvdata(&mhi_dev->dev); 287 288 mhi_unprepare_from_transfer(qdev->bootlog_ch); 289 flush_workqueue(qdev->bootlog_wq); 290 destroy_workqueue(qdev->bootlog_wq); 291 qdev->bootlog_ch = NULL; 292 } 293 294 static void qaic_bootlog_mhi_ul_xfer_cb(struct mhi_device *mhi_dev, struct mhi_result *mhi_result) 295 { 296 } 297 298 static void qaic_bootlog_mhi_dl_xfer_cb(struct mhi_device *mhi_dev, struct mhi_result *mhi_result) 299 { 300 struct qaic_device *qdev = dev_get_drvdata(&mhi_dev->dev); 301 struct bootlog_msg *msg = mhi_result->buf_addr; 302 303 if (mhi_result->transaction_status) { 304 devm_kfree(&qdev->pdev->dev, msg); 305 return; 306 } 307 308 /* Force a null at the end of the transferred string */ 309 msg->str[mhi_result->bytes_xferd - 1] = 0; 310 311 queue_work(qdev->bootlog_wq, &msg->work); 312 } 313 314 static const struct mhi_device_id qaic_bootlog_mhi_match_table[] = { 315 { .chan = "QAIC_LOGGING", }, 316 {}, 317 }; 318 319 static struct mhi_driver qaic_bootlog_mhi_driver = { 320 .id_table = qaic_bootlog_mhi_match_table, 321 .remove = qaic_bootlog_mhi_remove, 322 .probe = qaic_bootlog_mhi_probe, 323 .ul_xfer_cb = qaic_bootlog_mhi_ul_xfer_cb, 324 .dl_xfer_cb = qaic_bootlog_mhi_dl_xfer_cb, 325 .driver = { 326 .name = "qaic_bootlog", 327 }, 328 }; 329 330 int qaic_bootlog_register(void) 331 { 332 return mhi_driver_register(&qaic_bootlog_mhi_driver); 333 } 334 335 void qaic_bootlog_unregister(void) 336 { 337 mhi_driver_unregister(&qaic_bootlog_mhi_driver); 338 } 339