1 // SPDX-License-Identifier: GPL-2.0-only
3 * WWAN device simulator for WWAN framework testing.
5 * Copyright (c) 2021, Sergey Ryazanov <ryazanov.s.a@gmail.com>
8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/slab.h>
13 #include <linux/device.h>
14 #include <linux/spinlock.h>
15 #include <linux/list.h>
16 #include <linux/skbuff.h>
17 #include <linux/netdevice.h>
18 #include <linux/wwan.h>
19 #include <linux/debugfs.h>
20 #include <linux/workqueue.h>
24 static int wwan_hwsim_devsnum = 2;
25 module_param_named(devices, wwan_hwsim_devsnum, int, 0444);
26 MODULE_PARM_DESC(devices, "Number of simulated devices");
28 static struct class *wwan_hwsim_class;
30 static struct dentry *wwan_hwsim_debugfs_topdir;
31 static struct dentry *wwan_hwsim_debugfs_devcreate;
33 static DEFINE_SPINLOCK(wwan_hwsim_devs_lock);
34 static LIST_HEAD(wwan_hwsim_devs);
35 static unsigned int wwan_hwsim_dev_idx;
37 struct wwan_hwsim_dev {
38 struct list_head list;
41 struct work_struct del_work;
42 struct dentry *debugfs_topdir;
43 struct dentry *debugfs_portcreate;
44 spinlock_t ports_lock; /* Serialize ports creation/deletion */
45 unsigned int port_idx;
46 struct list_head ports;
49 struct wwan_hwsim_port {
50 struct list_head list;
52 struct wwan_hwsim_dev *dev;
53 struct wwan_port *wwan;
54 struct work_struct del_work;
55 struct dentry *debugfs_topdir;
56 enum { /* AT command parser state */
64 static const struct file_operations wwan_hwsim_debugfs_portdestroy_fops;
65 static const struct file_operations wwan_hwsim_debugfs_portcreate_fops;
66 static const struct file_operations wwan_hwsim_debugfs_devdestroy_fops;
67 static void wwan_hwsim_port_del_work(struct work_struct *work);
68 static void wwan_hwsim_dev_del_work(struct work_struct *work);
70 static netdev_tx_t wwan_hwsim_netdev_xmit(struct sk_buff *skb,
71 struct net_device *ndev)
73 ndev->stats.tx_packets++;
74 ndev->stats.tx_bytes += skb->len;
79 static const struct net_device_ops wwan_hwsim_netdev_ops = {
80 .ndo_start_xmit = wwan_hwsim_netdev_xmit,
83 static void wwan_hwsim_netdev_setup(struct net_device *ndev)
85 ndev->netdev_ops = &wwan_hwsim_netdev_ops;
86 ndev->needs_free_netdev = true;
88 ndev->mtu = ETH_DATA_LEN;
89 ndev->min_mtu = ETH_MIN_MTU;
90 ndev->max_mtu = ETH_MAX_MTU;
92 ndev->type = ARPHRD_NONE;
93 ndev->flags = IFF_POINTOPOINT | IFF_NOARP;
96 static const struct wwan_ops wwan_hwsim_wwan_rtnl_ops = {
97 .priv_size = 0, /* No private data */
98 .setup = wwan_hwsim_netdev_setup,
101 static int wwan_hwsim_port_start(struct wwan_port *wport)
103 struct wwan_hwsim_port *port = wwan_port_get_drvdata(wport);
105 port->pstate = AT_PARSER_WAIT_A;
110 static void wwan_hwsim_port_stop(struct wwan_port *wport)
114 /* Implements a minimalistic AT commands parser that echo input back and
115 * reply with 'OK' to each input command. See AT command protocol details in the
116 * ITU-T V.250 recomendations document.
118 * Be aware that this processor is not fully V.250 compliant.
120 static int wwan_hwsim_port_tx(struct wwan_port *wport, struct sk_buff *in)
122 struct wwan_hwsim_port *port = wwan_port_get_drvdata(wport);
126 /* Estimate a max possible number of commands by counting the number of
127 * termination chars (S3 param, CR by default). And then allocate the
128 * output buffer that will be enough to fit the echo and result codes of
131 for (i = 0, n = 0; i < in->len; ++i)
132 if (in->data[i] == '\r')
134 n = in->len + n * (2 + 2 + 2); /* Output buffer size */
135 out = alloc_skb(n, GFP_KERNEL);
139 for (i = 0, s = 0; i < in->len; ++i) {
140 char c = in->data[i];
142 if (port->pstate == AT_PARSER_WAIT_A) {
143 if (c == 'A' || c == 'a')
144 port->pstate = AT_PARSER_WAIT_T;
145 else if (c != '\n') /* Ignore formating char */
146 port->pstate = AT_PARSER_SKIP_LINE;
147 } else if (port->pstate == AT_PARSER_WAIT_T) {
148 if (c == 'T' || c == 't')
149 port->pstate = AT_PARSER_WAIT_TERM;
151 port->pstate = AT_PARSER_SKIP_LINE;
152 } else if (port->pstate == AT_PARSER_WAIT_TERM) {
155 /* Consume the trailing formatting char as well */
156 if ((i + 1) < in->len && in->data[i + 1] == '\n')
159 memcpy(skb_put(out, n), &in->data[s], n);/* Echo */
160 memcpy(skb_put(out, 6), "\r\nOK\r\n", 6);
162 port->pstate = AT_PARSER_WAIT_A;
163 } else if (port->pstate == AT_PARSER_SKIP_LINE) {
166 port->pstate = AT_PARSER_WAIT_A;
171 /* Echo the processed portion of a not yet completed command */
173 memcpy(skb_put(out, n), &in->data[s], n);
178 wwan_port_rx(wport, out);
183 static const struct wwan_port_ops wwan_hwsim_port_ops = {
184 .start = wwan_hwsim_port_start,
185 .stop = wwan_hwsim_port_stop,
186 .tx = wwan_hwsim_port_tx,
189 static struct wwan_hwsim_port *wwan_hwsim_port_new(struct wwan_hwsim_dev *dev)
191 struct wwan_hwsim_port *port;
195 port = kzalloc(sizeof(*port), GFP_KERNEL);
197 return ERR_PTR(-ENOMEM);
201 spin_lock(&dev->ports_lock);
202 port->id = dev->port_idx++;
203 spin_unlock(&dev->ports_lock);
205 port->wwan = wwan_create_port(&dev->dev, WWAN_PORT_AT,
206 &wwan_hwsim_port_ops,
208 if (IS_ERR(port->wwan)) {
209 err = PTR_ERR(port->wwan);
213 INIT_WORK(&port->del_work, wwan_hwsim_port_del_work);
215 snprintf(name, sizeof(name), "port%u", port->id);
216 port->debugfs_topdir = debugfs_create_dir(name, dev->debugfs_topdir);
217 debugfs_create_file("destroy", 0200, port->debugfs_topdir, port,
218 &wwan_hwsim_debugfs_portdestroy_fops);
228 static void wwan_hwsim_port_del(struct wwan_hwsim_port *port)
230 debugfs_remove(port->debugfs_topdir);
232 /* Make sure that there is no pending deletion work */
233 if (current_work() != &port->del_work)
234 cancel_work_sync(&port->del_work);
236 wwan_remove_port(port->wwan);
240 static void wwan_hwsim_port_del_work(struct work_struct *work)
242 struct wwan_hwsim_port *port =
243 container_of(work, typeof(*port), del_work);
244 struct wwan_hwsim_dev *dev = port->dev;
246 spin_lock(&dev->ports_lock);
247 if (list_empty(&port->list)) {
248 /* Someone else deleting port at the moment */
249 spin_unlock(&dev->ports_lock);
252 list_del_init(&port->list);
253 spin_unlock(&dev->ports_lock);
255 wwan_hwsim_port_del(port);
258 static void wwan_hwsim_dev_release(struct device *sysdev)
260 struct wwan_hwsim_dev *dev = container_of(sysdev, typeof(*dev), dev);
265 static struct wwan_hwsim_dev *wwan_hwsim_dev_new(void)
267 struct wwan_hwsim_dev *dev;
270 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
272 return ERR_PTR(-ENOMEM);
274 spin_lock(&wwan_hwsim_devs_lock);
275 dev->id = wwan_hwsim_dev_idx++;
276 spin_unlock(&wwan_hwsim_devs_lock);
278 dev->dev.release = wwan_hwsim_dev_release;
279 dev->dev.class = wwan_hwsim_class;
280 dev_set_name(&dev->dev, "hwsim%u", dev->id);
282 spin_lock_init(&dev->ports_lock);
283 INIT_LIST_HEAD(&dev->ports);
285 err = device_register(&dev->dev);
289 INIT_WORK(&dev->del_work, wwan_hwsim_dev_del_work);
291 err = wwan_register_ops(&dev->dev, &wwan_hwsim_wwan_rtnl_ops, dev, 1);
295 dev->debugfs_topdir = debugfs_create_dir(dev_name(&dev->dev),
296 wwan_hwsim_debugfs_topdir);
297 debugfs_create_file("destroy", 0200, dev->debugfs_topdir, dev,
298 &wwan_hwsim_debugfs_devdestroy_fops);
299 dev->debugfs_portcreate =
300 debugfs_create_file("portcreate", 0200,
301 dev->debugfs_topdir, dev,
302 &wwan_hwsim_debugfs_portcreate_fops);
307 device_unregister(&dev->dev);
308 /* Memory will be freed in the device release callback */
318 static void wwan_hwsim_dev_del(struct wwan_hwsim_dev *dev)
320 debugfs_remove(dev->debugfs_portcreate); /* Avoid new ports */
322 spin_lock(&dev->ports_lock);
323 while (!list_empty(&dev->ports)) {
324 struct wwan_hwsim_port *port;
326 port = list_first_entry(&dev->ports, struct wwan_hwsim_port,
328 list_del_init(&port->list);
329 spin_unlock(&dev->ports_lock);
330 wwan_hwsim_port_del(port);
331 spin_lock(&dev->ports_lock);
333 spin_unlock(&dev->ports_lock);
335 debugfs_remove(dev->debugfs_topdir);
337 /* This will remove all child netdev(s) */
338 wwan_unregister_ops(&dev->dev);
340 /* Make sure that there is no pending deletion work */
341 if (current_work() != &dev->del_work)
342 cancel_work_sync(&dev->del_work);
344 device_unregister(&dev->dev);
345 /* Memory will be freed in the device release callback */
348 static void wwan_hwsim_dev_del_work(struct work_struct *work)
350 struct wwan_hwsim_dev *dev = container_of(work, typeof(*dev), del_work);
352 spin_lock(&wwan_hwsim_devs_lock);
353 if (list_empty(&dev->list)) {
354 /* Someone else deleting device at the moment */
355 spin_unlock(&wwan_hwsim_devs_lock);
358 list_del_init(&dev->list);
359 spin_unlock(&wwan_hwsim_devs_lock);
361 wwan_hwsim_dev_del(dev);
364 static ssize_t wwan_hwsim_debugfs_portdestroy_write(struct file *file,
365 const char __user *usrbuf,
366 size_t count, loff_t *ppos)
368 struct wwan_hwsim_port *port = file->private_data;
370 /* We can not delete port here since it will cause a deadlock due to
371 * waiting this callback to finish in the debugfs_remove() call. So,
374 schedule_work(&port->del_work);
379 static const struct file_operations wwan_hwsim_debugfs_portdestroy_fops = {
380 .write = wwan_hwsim_debugfs_portdestroy_write,
382 .llseek = noop_llseek,
385 static ssize_t wwan_hwsim_debugfs_portcreate_write(struct file *file,
386 const char __user *usrbuf,
387 size_t count, loff_t *ppos)
389 struct wwan_hwsim_dev *dev = file->private_data;
390 struct wwan_hwsim_port *port;
392 port = wwan_hwsim_port_new(dev);
394 return PTR_ERR(port);
396 spin_lock(&dev->ports_lock);
397 list_add_tail(&port->list, &dev->ports);
398 spin_unlock(&dev->ports_lock);
403 static const struct file_operations wwan_hwsim_debugfs_portcreate_fops = {
404 .write = wwan_hwsim_debugfs_portcreate_write,
406 .llseek = noop_llseek,
409 static ssize_t wwan_hwsim_debugfs_devdestroy_write(struct file *file,
410 const char __user *usrbuf,
411 size_t count, loff_t *ppos)
413 struct wwan_hwsim_dev *dev = file->private_data;
415 /* We can not delete device here since it will cause a deadlock due to
416 * waiting this callback to finish in the debugfs_remove() call. So,
419 schedule_work(&dev->del_work);
424 static const struct file_operations wwan_hwsim_debugfs_devdestroy_fops = {
425 .write = wwan_hwsim_debugfs_devdestroy_write,
427 .llseek = noop_llseek,
430 static ssize_t wwan_hwsim_debugfs_devcreate_write(struct file *file,
431 const char __user *usrbuf,
432 size_t count, loff_t *ppos)
434 struct wwan_hwsim_dev *dev;
436 dev = wwan_hwsim_dev_new();
440 spin_lock(&wwan_hwsim_devs_lock);
441 list_add_tail(&dev->list, &wwan_hwsim_devs);
442 spin_unlock(&wwan_hwsim_devs_lock);
447 static const struct file_operations wwan_hwsim_debugfs_devcreate_fops = {
448 .write = wwan_hwsim_debugfs_devcreate_write,
450 .llseek = noop_llseek,
453 static int __init wwan_hwsim_init_devs(void)
455 struct wwan_hwsim_dev *dev;
458 for (i = 0; i < wwan_hwsim_devsnum; ++i) {
459 dev = wwan_hwsim_dev_new();
463 spin_lock(&wwan_hwsim_devs_lock);
464 list_add_tail(&dev->list, &wwan_hwsim_devs);
465 spin_unlock(&wwan_hwsim_devs_lock);
467 /* Create a couple of ports per each device to accelerate
468 * the simulator readiness time.
470 for (j = 0; j < 2; ++j) {
471 struct wwan_hwsim_port *port;
473 port = wwan_hwsim_port_new(dev);
475 return PTR_ERR(port);
477 spin_lock(&dev->ports_lock);
478 list_add_tail(&port->list, &dev->ports);
479 spin_unlock(&dev->ports_lock);
486 static void wwan_hwsim_free_devs(void)
488 struct wwan_hwsim_dev *dev;
490 spin_lock(&wwan_hwsim_devs_lock);
491 while (!list_empty(&wwan_hwsim_devs)) {
492 dev = list_first_entry(&wwan_hwsim_devs, struct wwan_hwsim_dev,
494 list_del_init(&dev->list);
495 spin_unlock(&wwan_hwsim_devs_lock);
496 wwan_hwsim_dev_del(dev);
497 spin_lock(&wwan_hwsim_devs_lock);
499 spin_unlock(&wwan_hwsim_devs_lock);
502 static int __init wwan_hwsim_init(void)
506 if (wwan_hwsim_devsnum < 0 || wwan_hwsim_devsnum > 128)
509 wwan_hwsim_class = class_create(THIS_MODULE, "wwan_hwsim");
510 if (IS_ERR(wwan_hwsim_class))
511 return PTR_ERR(wwan_hwsim_class);
513 wwan_hwsim_debugfs_topdir = debugfs_create_dir("wwan_hwsim", NULL);
514 wwan_hwsim_debugfs_devcreate =
515 debugfs_create_file("devcreate", 0200,
516 wwan_hwsim_debugfs_topdir, NULL,
517 &wwan_hwsim_debugfs_devcreate_fops);
519 err = wwan_hwsim_init_devs();
526 wwan_hwsim_free_devs();
527 debugfs_remove(wwan_hwsim_debugfs_topdir);
528 class_destroy(wwan_hwsim_class);
533 static void __exit wwan_hwsim_exit(void)
535 debugfs_remove(wwan_hwsim_debugfs_devcreate); /* Avoid new devs */
536 wwan_hwsim_free_devs();
537 flush_scheduled_work(); /* Wait deletion works completion */
538 debugfs_remove(wwan_hwsim_debugfs_topdir);
539 class_destroy(wwan_hwsim_class);
542 module_init(wwan_hwsim_init);
543 module_exit(wwan_hwsim_exit);
545 MODULE_AUTHOR("Sergey Ryazanov");
546 MODULE_DESCRIPTION("Device simulator for WWAN framework");
547 MODULE_LICENSE("GPL");