]> Git Repo - linux.git/blob - drivers/accel/qaic/qaic_debugfs.c
dma-mapping: don't return errors from dma_set_max_seg_size
[linux.git] / drivers / accel / qaic / qaic_debugfs.c
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 }
This page took 0.048911 seconds and 4 git commands to generate.