~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/sof/sof-client-ipc-kernel-injector.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 //
  3 // Copyright(c) 2023 Google Inc
  4 //
  5 // Author: Curtis Malainey <cujomalainey@chromium.org>
  6 //
  7 
  8 #include <linux/auxiliary_bus.h>
  9 #include <linux/debugfs.h>
 10 #include <linux/mod_devicetable.h>
 11 #include <linux/module.h>
 12 #include <linux/pm_runtime.h>
 13 #include <sound/sof/header.h>
 14 
 15 #include "sof-client.h"
 16 
 17 #define SOF_IPC_CLIENT_SUSPEND_DELAY_MS 3000
 18 
 19 struct sof_msg_inject_priv {
 20         struct dentry *kernel_dfs_file;
 21         size_t max_msg_size;
 22 
 23         void *kernel_buffer;
 24 };
 25 
 26 static int sof_msg_inject_dfs_open(struct inode *inode, struct file *file)
 27 {
 28         int ret = debugfs_file_get(file->f_path.dentry);
 29 
 30         if (unlikely(ret))
 31                 return ret;
 32 
 33         ret = simple_open(inode, file);
 34         if (ret)
 35                 debugfs_file_put(file->f_path.dentry);
 36 
 37         return ret;
 38 }
 39 
 40 static ssize_t sof_kernel_msg_inject_dfs_write(struct file *file, const char __user *buffer,
 41                                                size_t count, loff_t *ppos)
 42 {
 43         struct sof_client_dev *cdev = file->private_data;
 44         struct sof_msg_inject_priv *priv = cdev->data;
 45         struct sof_ipc_cmd_hdr *hdr = priv->kernel_buffer;
 46         struct device *dev = &cdev->auxdev.dev;
 47         ssize_t size;
 48         int ret;
 49 
 50         if (*ppos)
 51                 return 0;
 52 
 53         size = simple_write_to_buffer(priv->kernel_buffer, priv->max_msg_size,
 54                                       ppos, buffer, count);
 55         if (size < 0)
 56                 return size;
 57         if (size != count)
 58                 return -EFAULT;
 59 
 60         ret = pm_runtime_resume_and_get(dev);
 61         if (ret < 0 && ret != -EACCES) {
 62                 dev_err_ratelimited(dev, "debugfs write failed to resume %d\n", ret);
 63                 return ret;
 64         }
 65 
 66         sof_client_ipc_rx_message(cdev, hdr, priv->kernel_buffer);
 67 
 68         pm_runtime_mark_last_busy(dev);
 69         ret = pm_runtime_put_autosuspend(dev);
 70         if (ret < 0)
 71                 dev_err_ratelimited(dev, "debugfs write failed to idle %d\n", ret);
 72 
 73         return count;
 74 };
 75 
 76 static int sof_msg_inject_dfs_release(struct inode *inode, struct file *file)
 77 {
 78         debugfs_file_put(file->f_path.dentry);
 79 
 80         return 0;
 81 }
 82 
 83 static const struct file_operations sof_kernel_msg_inject_fops = {
 84         .open = sof_msg_inject_dfs_open,
 85         .write = sof_kernel_msg_inject_dfs_write,
 86         .release = sof_msg_inject_dfs_release,
 87 
 88         .owner = THIS_MODULE,
 89 };
 90 
 91 static int sof_msg_inject_probe(struct auxiliary_device *auxdev,
 92                                 const struct auxiliary_device_id *id)
 93 {
 94         struct sof_client_dev *cdev = auxiliary_dev_to_sof_client_dev(auxdev);
 95         struct dentry *debugfs_root = sof_client_get_debugfs_root(cdev);
 96         struct device *dev = &auxdev->dev;
 97         struct sof_msg_inject_priv *priv;
 98         size_t alloc_size;
 99 
100         /* allocate memory for client data */
101         priv = devm_kzalloc(&auxdev->dev, sizeof(*priv), GFP_KERNEL);
102         if (!priv)
103                 return -ENOMEM;
104 
105         priv->max_msg_size = sof_client_get_ipc_max_payload_size(cdev);
106         alloc_size = priv->max_msg_size;
107         priv->kernel_buffer = devm_kmalloc(dev, alloc_size, GFP_KERNEL);
108 
109         if (!priv->kernel_buffer)
110                 return -ENOMEM;
111 
112         cdev->data = priv;
113 
114         priv->kernel_dfs_file = debugfs_create_file("kernel_ipc_msg_inject", 0644,
115                                                     debugfs_root, cdev,
116                                                     &sof_kernel_msg_inject_fops);
117 
118         /* enable runtime PM */
119         pm_runtime_set_autosuspend_delay(dev, SOF_IPC_CLIENT_SUSPEND_DELAY_MS);
120         pm_runtime_use_autosuspend(dev);
121         pm_runtime_set_active(dev);
122         pm_runtime_enable(dev);
123         pm_runtime_mark_last_busy(dev);
124         pm_runtime_idle(dev);
125 
126         return 0;
127 }
128 
129 static void sof_msg_inject_remove(struct auxiliary_device *auxdev)
130 {
131         struct sof_client_dev *cdev = auxiliary_dev_to_sof_client_dev(auxdev);
132         struct sof_msg_inject_priv *priv = cdev->data;
133 
134         pm_runtime_disable(&auxdev->dev);
135 
136         debugfs_remove(priv->kernel_dfs_file);
137 }
138 
139 static const struct auxiliary_device_id sof_msg_inject_client_id_table[] = {
140         { .name = "snd_sof.kernel_injector" },
141         {},
142 };
143 MODULE_DEVICE_TABLE(auxiliary, sof_msg_inject_client_id_table);
144 
145 /*
146  * No need for driver pm_ops as the generic pm callbacks in the auxiliary bus
147  * type are enough to ensure that the parent SOF device resumes to bring the DSP
148  * back to D0.
149  * Driver name will be set based on KBUILD_MODNAME.
150  */
151 static struct auxiliary_driver sof_msg_inject_client_drv = {
152         .probe = sof_msg_inject_probe,
153         .remove = sof_msg_inject_remove,
154 
155         .id_table = sof_msg_inject_client_id_table,
156 };
157 
158 module_auxiliary_driver(sof_msg_inject_client_drv);
159 
160 MODULE_LICENSE("GPL");
161 MODULE_DESCRIPTION("SOF IPC Kernel Injector Client Driver");
162 MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT);
163 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php