0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/auxiliary_bus.h>
0009 #include <linux/completion.h>
0010 #include <linux/debugfs.h>
0011 #include <linux/ktime.h>
0012 #include <linux/mod_devicetable.h>
0013 #include <linux/module.h>
0014 #include <linux/pm_runtime.h>
0015 #include <linux/slab.h>
0016 #include <linux/uaccess.h>
0017 #include <sound/sof/header.h>
0018 #include <sound/sof/ipc4/header.h>
0019
0020 #include "sof-client.h"
0021
0022 #define SOF_IPC_CLIENT_SUSPEND_DELAY_MS 3000
0023
0024 struct sof_msg_inject_priv {
0025 struct dentry *dfs_file;
0026 size_t max_msg_size;
0027 enum sof_ipc_type ipc_type;
0028
0029 void *tx_buffer;
0030 void *rx_buffer;
0031 };
0032
0033 static int sof_msg_inject_dfs_open(struct inode *inode, struct file *file)
0034 {
0035 struct sof_client_dev *cdev = inode->i_private;
0036 int ret;
0037
0038 if (sof_client_get_fw_state(cdev) == SOF_FW_CRASHED)
0039 return -ENODEV;
0040
0041 ret = debugfs_file_get(file->f_path.dentry);
0042 if (unlikely(ret))
0043 return ret;
0044
0045 ret = simple_open(inode, file);
0046 if (ret)
0047 debugfs_file_put(file->f_path.dentry);
0048
0049 return ret;
0050 }
0051
0052 static ssize_t sof_msg_inject_dfs_read(struct file *file, char __user *buffer,
0053 size_t count, loff_t *ppos)
0054 {
0055 struct sof_client_dev *cdev = file->private_data;
0056 struct sof_msg_inject_priv *priv = cdev->data;
0057 struct sof_ipc_reply *rhdr = priv->rx_buffer;
0058
0059 if (!rhdr->hdr.size || !count || *ppos)
0060 return 0;
0061
0062 if (count > rhdr->hdr.size)
0063 count = rhdr->hdr.size;
0064
0065 if (copy_to_user(buffer, priv->rx_buffer, count))
0066 return -EFAULT;
0067
0068 *ppos += count;
0069 return count;
0070 }
0071
0072 static ssize_t sof_msg_inject_ipc4_dfs_read(struct file *file,
0073 char __user *buffer,
0074 size_t count, loff_t *ppos)
0075 {
0076 struct sof_client_dev *cdev = file->private_data;
0077 struct sof_msg_inject_priv *priv = cdev->data;
0078 struct sof_ipc4_msg *ipc4_msg = priv->rx_buffer;
0079 size_t header_size = sizeof(ipc4_msg->header_u64);
0080 size_t remaining;
0081
0082 if (!ipc4_msg->header_u64 || !count || *ppos)
0083 return 0;
0084
0085
0086 if (count < header_size)
0087 return -ENOSPC;
0088
0089 remaining = header_size;
0090
0091
0092 if (SOF_IPC4_MSG_IS_MODULE_MSG(ipc4_msg->primary) &&
0093 (SOF_IPC4_MSG_TYPE_GET(ipc4_msg->primary) == SOF_IPC4_MOD_LARGE_CONFIG_GET))
0094 remaining += ipc4_msg->data_size;
0095
0096 if (count > remaining)
0097 count = remaining;
0098 else if (count < remaining)
0099 remaining = count;
0100
0101
0102 if (copy_to_user(buffer, &ipc4_msg->header_u64, header_size))
0103 return -EFAULT;
0104
0105 *ppos += header_size;
0106 remaining -= header_size;
0107
0108 if (!remaining)
0109 return count;
0110
0111 if (remaining > ipc4_msg->data_size)
0112 remaining = ipc4_msg->data_size;
0113
0114
0115 if (copy_to_user(buffer + *ppos, ipc4_msg->data_ptr, remaining))
0116 return -EFAULT;
0117
0118 *ppos += remaining;
0119 return count;
0120 }
0121
0122 static int sof_msg_inject_send_message(struct sof_client_dev *cdev)
0123 {
0124 struct sof_msg_inject_priv *priv = cdev->data;
0125 struct device *dev = &cdev->auxdev.dev;
0126 int ret, err;
0127
0128 ret = pm_runtime_resume_and_get(dev);
0129 if (ret < 0 && ret != -EACCES) {
0130 dev_err_ratelimited(dev, "debugfs write failed to resume %d\n", ret);
0131 return ret;
0132 }
0133
0134
0135 ret = sof_client_ipc_tx_message(cdev, priv->tx_buffer, priv->rx_buffer,
0136 priv->max_msg_size);
0137 if (ret)
0138 dev_err(dev, "IPC message send failed: %d\n", ret);
0139
0140 pm_runtime_mark_last_busy(dev);
0141 err = pm_runtime_put_autosuspend(dev);
0142 if (err < 0)
0143 dev_err_ratelimited(dev, "debugfs write failed to idle %d\n", err);
0144
0145 return ret;
0146 }
0147
0148 static ssize_t sof_msg_inject_dfs_write(struct file *file, const char __user *buffer,
0149 size_t count, loff_t *ppos)
0150 {
0151 struct sof_client_dev *cdev = file->private_data;
0152 struct sof_msg_inject_priv *priv = cdev->data;
0153 ssize_t size;
0154 int ret;
0155
0156 if (*ppos)
0157 return 0;
0158
0159 size = simple_write_to_buffer(priv->tx_buffer, priv->max_msg_size,
0160 ppos, buffer, count);
0161 if (size < 0)
0162 return size;
0163 if (size != count)
0164 return -EFAULT;
0165
0166 memset(priv->rx_buffer, 0, priv->max_msg_size);
0167
0168 ret = sof_msg_inject_send_message(cdev);
0169
0170
0171 if (ret < 0)
0172 size = ret;
0173
0174 return size;
0175 };
0176
0177 static ssize_t sof_msg_inject_ipc4_dfs_write(struct file *file,
0178 const char __user *buffer,
0179 size_t count, loff_t *ppos)
0180 {
0181 struct sof_client_dev *cdev = file->private_data;
0182 struct sof_msg_inject_priv *priv = cdev->data;
0183 struct sof_ipc4_msg *ipc4_msg = priv->tx_buffer;
0184 size_t data_size;
0185 int ret;
0186
0187 if (*ppos)
0188 return 0;
0189
0190 if (count < sizeof(ipc4_msg->header_u64))
0191 return -EINVAL;
0192
0193
0194 if (copy_from_user(&ipc4_msg->header_u64, buffer,
0195 sizeof(ipc4_msg->header_u64)))
0196 return -EFAULT;
0197
0198 data_size = count - sizeof(ipc4_msg->header_u64);
0199 if (data_size > priv->max_msg_size)
0200 return -EINVAL;
0201
0202
0203 if (copy_from_user(ipc4_msg->data_ptr,
0204 buffer + sizeof(ipc4_msg->header_u64), data_size))
0205 return -EFAULT;
0206
0207 ipc4_msg->data_size = data_size;
0208
0209
0210 ipc4_msg = priv->rx_buffer;
0211 ipc4_msg->header_u64 = 0;
0212 ipc4_msg->data_size = priv->max_msg_size;
0213 memset(ipc4_msg->data_ptr, 0, priv->max_msg_size);
0214
0215 ret = sof_msg_inject_send_message(cdev);
0216
0217
0218 if (ret < 0)
0219 return ret;
0220
0221 return count;
0222 };
0223
0224 static int sof_msg_inject_dfs_release(struct inode *inode, struct file *file)
0225 {
0226 debugfs_file_put(file->f_path.dentry);
0227
0228 return 0;
0229 }
0230
0231 static const struct file_operations sof_msg_inject_fops = {
0232 .open = sof_msg_inject_dfs_open,
0233 .read = sof_msg_inject_dfs_read,
0234 .write = sof_msg_inject_dfs_write,
0235 .llseek = default_llseek,
0236 .release = sof_msg_inject_dfs_release,
0237
0238 .owner = THIS_MODULE,
0239 };
0240
0241 static const struct file_operations sof_msg_inject_ipc4_fops = {
0242 .open = sof_msg_inject_dfs_open,
0243 .read = sof_msg_inject_ipc4_dfs_read,
0244 .write = sof_msg_inject_ipc4_dfs_write,
0245 .llseek = default_llseek,
0246 .release = sof_msg_inject_dfs_release,
0247
0248 .owner = THIS_MODULE,
0249 };
0250
0251 static int sof_msg_inject_probe(struct auxiliary_device *auxdev,
0252 const struct auxiliary_device_id *id)
0253 {
0254 struct sof_client_dev *cdev = auxiliary_dev_to_sof_client_dev(auxdev);
0255 struct dentry *debugfs_root = sof_client_get_debugfs_root(cdev);
0256 static const struct file_operations *fops;
0257 struct device *dev = &auxdev->dev;
0258 struct sof_msg_inject_priv *priv;
0259 size_t alloc_size;
0260
0261
0262 priv = devm_kzalloc(&auxdev->dev, sizeof(*priv), GFP_KERNEL);
0263 if (!priv)
0264 return -ENOMEM;
0265
0266 priv->ipc_type = sof_client_get_ipc_type(cdev);
0267 priv->max_msg_size = sof_client_get_ipc_max_payload_size(cdev);
0268 alloc_size = priv->max_msg_size;
0269
0270 if (priv->ipc_type == SOF_INTEL_IPC4)
0271 alloc_size += sizeof(struct sof_ipc4_msg);
0272
0273 priv->tx_buffer = devm_kmalloc(dev, alloc_size, GFP_KERNEL);
0274 priv->rx_buffer = devm_kzalloc(dev, alloc_size, GFP_KERNEL);
0275 if (!priv->tx_buffer || !priv->rx_buffer)
0276 return -ENOMEM;
0277
0278 if (priv->ipc_type == SOF_INTEL_IPC4) {
0279 struct sof_ipc4_msg *ipc4_msg;
0280
0281 ipc4_msg = priv->tx_buffer;
0282 ipc4_msg->data_ptr = priv->tx_buffer + sizeof(struct sof_ipc4_msg);
0283
0284 ipc4_msg = priv->rx_buffer;
0285 ipc4_msg->data_ptr = priv->rx_buffer + sizeof(struct sof_ipc4_msg);
0286
0287 fops = &sof_msg_inject_ipc4_fops;
0288 } else {
0289 fops = &sof_msg_inject_fops;
0290 }
0291
0292 cdev->data = priv;
0293
0294 priv->dfs_file = debugfs_create_file("ipc_msg_inject", 0644, debugfs_root,
0295 cdev, fops);
0296
0297
0298 pm_runtime_set_autosuspend_delay(dev, SOF_IPC_CLIENT_SUSPEND_DELAY_MS);
0299 pm_runtime_use_autosuspend(dev);
0300 pm_runtime_enable(dev);
0301 pm_runtime_mark_last_busy(dev);
0302 pm_runtime_idle(dev);
0303
0304 return 0;
0305 }
0306
0307 static void sof_msg_inject_remove(struct auxiliary_device *auxdev)
0308 {
0309 struct sof_client_dev *cdev = auxiliary_dev_to_sof_client_dev(auxdev);
0310 struct sof_msg_inject_priv *priv = cdev->data;
0311
0312 pm_runtime_disable(&auxdev->dev);
0313
0314 debugfs_remove(priv->dfs_file);
0315 }
0316
0317 static const struct auxiliary_device_id sof_msg_inject_client_id_table[] = {
0318 { .name = "snd_sof.msg_injector" },
0319 {},
0320 };
0321 MODULE_DEVICE_TABLE(auxiliary, sof_msg_inject_client_id_table);
0322
0323
0324
0325
0326
0327
0328
0329 static struct auxiliary_driver sof_msg_inject_client_drv = {
0330 .probe = sof_msg_inject_probe,
0331 .remove = sof_msg_inject_remove,
0332
0333 .id_table = sof_msg_inject_client_id_table,
0334 };
0335
0336 module_auxiliary_driver(sof_msg_inject_client_drv);
0337
0338 MODULE_DESCRIPTION("SOF IPC Message Injector Client Driver");
0339 MODULE_LICENSE("GPL");
0340 MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT);