1 // SPDX-License-Identifier: GPL-2.0-only 2 3 /* Copyright (c) 2020, The Linux Foundation. All rights reserved. */ 4 /* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ 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 /* Length of bootlog message */ 31 size_t len; 32 /* Root struct of device, used to access device resources */ 33 struct qaic_device *qdev; 34 /* Work struct to schedule work coming on QAIC_LOGGING channel */ 35 struct work_struct work; 36 }; 37 38 struct bootlog_page { 39 /* Node in list of bootlog pages maintained by root device struct */ 40 struct list_head node; 41 /* Total size of the buffer that holds the bootlogs. It is PAGE_SIZE */ 42 unsigned int size; 43 /* Offset for the next bootlog */ 44 unsigned int offset; 45 }; 46 47 static int bootlog_show(struct seq_file *s, void *unused) 48 { 49 struct bootlog_page *page; 50 struct qaic_device *qdev; 51 size_t len; 52 void *log; 53 54 qdev = s->private; 55 mutex_lock(&qdev->bootlog_mutex); 56 list_for_each_entry(page, &qdev->bootlog, node) { 57 log = page + 1; 58 len = page->offset - sizeof(*page); 59 seq_write(s, log, len); 60 } 61 mutex_unlock(&qdev->bootlog_mutex); 62 63 return 0; 64 } 65 66 DEFINE_SHOW_ATTRIBUTE(bootlog); 67 68 static int fifo_size_show(struct seq_file *s, void *unused) 69 { 70 struct dma_bridge_chan *dbc = s->private; 71 72 seq_printf(s, "%u\n", dbc->nelem); 73 return 0; 74 } 75 76 DEFINE_SHOW_ATTRIBUTE(fifo_size); 77 78 static int queued_show(struct seq_file *s, void *unused) 79 { 80 struct dma_bridge_chan *dbc = s->private; 81 u32 tail = 0, head = 0; 82 83 qaic_data_get_fifo_info(dbc, &head, &tail); 84 85 if (head == U32_MAX || tail == U32_MAX) 86 seq_printf(s, "%u\n", 0); 87 else if (head > tail) 88 seq_printf(s, "%u\n", dbc->nelem - head + tail); 89 else 90 seq_printf(s, "%u\n", tail - head); 91 92 return 0; 93 } 94 95 DEFINE_SHOW_ATTRIBUTE(queued); 96 97 void qaic_debugfs_init(struct qaic_drm_device *qddev) 98 { 99 struct qaic_device *qdev = qddev->qdev; 100 struct dentry *debugfs_root; 101 struct dentry *debugfs_dir; 102 char name[QAIC_DBC_DIR_NAME]; 103 u32 i; 104 105 debugfs_root = to_drm(qddev)->debugfs_root; 106 107 debugfs_create_file("bootlog", 0400, debugfs_root, qdev, &bootlog_fops); 108 /* 109 * 256 dbcs per device is likely the max we will ever see and lets static checking see a 110 * reasonable range. 111 */ 112 for (i = 0; i < qdev->num_dbc && i < 256; ++i) { 113 snprintf(name, QAIC_DBC_DIR_NAME, "dbc%03u", i); 114 debugfs_dir = debugfs_create_dir(name, debugfs_root); 115 debugfs_create_file("fifo_size", 0400, debugfs_dir, &qdev->dbc[i], &fifo_size_fops); 116 debugfs_create_file("queued", 0400, debugfs_dir, &qdev->dbc[i], &queued_fops); 117 } 118 } 119 120 static struct bootlog_page *alloc_bootlog_page(struct qaic_device *qdev) 121 { 122 struct bootlog_page *page; 123 124 page = (struct bootlog_page *)devm_get_free_pages(&qdev->pdev->dev, GFP_KERNEL, 0); 125 if (!page) 126 return page; 127 128 page->size = PAGE_SIZE; 129 page->offset = sizeof(*page); 130 list_add_tail(&page->node, &qdev->bootlog); 131 132 return page; 133 } 134 135 static int reset_bootlog(struct qaic_device *qdev) 136 { 137 struct bootlog_page *page; 138 struct bootlog_page *i; 139 140 mutex_lock(&qdev->bootlog_mutex); 141 list_for_each_entry_safe(page, i, &qdev->bootlog, node) { 142 list_del(&page->node); 143 devm_free_pages(&qdev->pdev->dev, (unsigned long)page); 144 } 145 146 page = alloc_bootlog_page(qdev); 147 mutex_unlock(&qdev->bootlog_mutex); 148 if (!page) 149 return -ENOMEM; 150 151 return 0; 152 } 153 154 static void *bootlog_get_space(struct qaic_device *qdev, unsigned int size) 155 { 156 struct bootlog_page *page; 157 158 page = list_last_entry(&qdev->bootlog, struct bootlog_page, node); 159 160 if (size_add(size, sizeof(*page)) > page->size) 161 return NULL; 162 163 if (page->offset + size > page->size) { 164 page = alloc_bootlog_page(qdev); 165 if (!page) 166 return NULL; 167 } 168 169 return (void *)page + page->offset; 170 } 171 172 static void bootlog_commit(struct qaic_device *qdev, unsigned int size) 173 { 174 struct bootlog_page *page; 175 176 page = list_last_entry(&qdev->bootlog, struct bootlog_page, node); 177 178 page->offset += size; 179 } 180 181 static void bootlog_log(struct work_struct *work) 182 { 183 struct bootlog_msg *msg = container_of(work, struct bootlog_msg, work); 184 struct qaic_device *qdev = msg->qdev; 185 void *log; 186 187 mutex_lock(&qdev->bootlog_mutex); 188 log = bootlog_get_space(qdev, msg->len); 189 if (log) { 190 memcpy(log, msg, msg->len); 191 bootlog_commit(qdev, msg->len); 192 } 193 mutex_unlock(&qdev->bootlog_mutex); 194 195 if (mhi_queue_buf(qdev->bootlog_ch, DMA_FROM_DEVICE, msg, BOOTLOG_MSG_SIZE, MHI_EOT)) 196 devm_kfree(&qdev->pdev->dev, msg); 197 } 198 199 static int qaic_bootlog_mhi_probe(struct mhi_device *mhi_dev, const struct mhi_device_id *id) 200 { 201 struct qaic_device *qdev = pci_get_drvdata(to_pci_dev(mhi_dev->mhi_cntrl->cntrl_dev)); 202 struct bootlog_msg *msg; 203 int i, ret; 204 205 qdev->bootlog_wq = alloc_ordered_workqueue("qaic_bootlog", 0); 206 if (!qdev->bootlog_wq) { 207 ret = -ENOMEM; 208 goto out; 209 } 210 211 ret = reset_bootlog(qdev); 212 if (ret) 213 goto destroy_workqueue; 214 215 ret = mhi_prepare_for_transfer(mhi_dev); 216 if (ret) 217 goto destroy_workqueue; 218 219 dev_set_drvdata(&mhi_dev->dev, qdev); 220 qdev->bootlog_ch = mhi_dev; 221 222 for (i = 0; i < BOOTLOG_POOL_SIZE; i++) { 223 msg = devm_kzalloc(&qdev->pdev->dev, sizeof(*msg), GFP_KERNEL); 224 if (!msg) { 225 ret = -ENOMEM; 226 goto mhi_unprepare; 227 } 228 229 msg->qdev = qdev; 230 INIT_WORK(&msg->work, bootlog_log); 231 232 ret = mhi_queue_buf(mhi_dev, DMA_FROM_DEVICE, msg, BOOTLOG_MSG_SIZE, MHI_EOT); 233 if (ret) 234 goto mhi_unprepare; 235 } 236 237 return 0; 238 239 mhi_unprepare: 240 mhi_unprepare_from_transfer(mhi_dev); 241 destroy_workqueue: 242 destroy_workqueue(qdev->bootlog_wq); 243 out: 244 return ret; 245 } 246 247 static void qaic_bootlog_mhi_remove(struct mhi_device *mhi_dev) 248 { 249 struct qaic_device *qdev; 250 251 qdev = dev_get_drvdata(&mhi_dev->dev); 252 253 mhi_unprepare_from_transfer(qdev->bootlog_ch); 254 destroy_workqueue(qdev->bootlog_wq); 255 qdev->bootlog_ch = NULL; 256 } 257 258 static void qaic_bootlog_mhi_ul_xfer_cb(struct mhi_device *mhi_dev, struct mhi_result *mhi_result) 259 { 260 } 261 262 static void qaic_bootlog_mhi_dl_xfer_cb(struct mhi_device *mhi_dev, struct mhi_result *mhi_result) 263 { 264 struct qaic_device *qdev = dev_get_drvdata(&mhi_dev->dev); 265 struct bootlog_msg *msg = mhi_result->buf_addr; 266 int status = mhi_result->transaction_status; 267 268 if (status && status != -EOVERFLOW) { 269 devm_kfree(&qdev->pdev->dev, msg); 270 return; 271 } 272 273 msg->len = mhi_result->bytes_xferd; 274 275 /* Exclude trailing null to normalize AIC100/AIC200 line endings */ 276 if (msg->len && msg->str[msg->len - 1] == '\0') 277 msg->len--; 278 279 queue_work(qdev->bootlog_wq, &msg->work); 280 } 281 282 static const struct mhi_device_id qaic_bootlog_mhi_match_table[] = { 283 { .chan = "QAIC_LOGGING", }, 284 {}, 285 }; 286 287 static struct mhi_driver qaic_bootlog_mhi_driver = { 288 .id_table = qaic_bootlog_mhi_match_table, 289 .remove = qaic_bootlog_mhi_remove, 290 .probe = qaic_bootlog_mhi_probe, 291 .ul_xfer_cb = qaic_bootlog_mhi_ul_xfer_cb, 292 .dl_xfer_cb = qaic_bootlog_mhi_dl_xfer_cb, 293 .driver = { 294 .name = "qaic_bootlog", 295 }, 296 }; 297 298 int qaic_bootlog_register(void) 299 { 300 return mhi_driver_register(&qaic_bootlog_mhi_driver); 301 } 302 303 void qaic_bootlog_unregister(void) 304 { 305 mhi_driver_unregister(&qaic_bootlog_mhi_driver); 306 } 307