1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * WWAN device simulator for WWAN framework testing. 4 * 5 * Copyright (c) 2021, 2025, Sergey Ryazanov <ryazanov.s.a@gmail.com> 6 */ 7 8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 9 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/time.h> 16 #include <linux/list.h> 17 #include <linux/skbuff.h> 18 #include <linux/timer.h> 19 #include <linux/netdevice.h> 20 #include <linux/wwan.h> 21 #include <linux/debugfs.h> 22 #include <linux/workqueue.h> 23 24 #include <net/arp.h> 25 26 static int wwan_hwsim_devsnum = 2; 27 module_param_named(devices, wwan_hwsim_devsnum, int, 0444); 28 MODULE_PARM_DESC(devices, "Number of simulated devices"); 29 30 static const struct class wwan_hwsim_class = { 31 .name = "wwan_hwsim", 32 }; 33 34 static struct dentry *wwan_hwsim_debugfs_topdir; 35 static struct dentry *wwan_hwsim_debugfs_devcreate; 36 37 static DEFINE_SPINLOCK(wwan_hwsim_devs_lock); 38 static LIST_HEAD(wwan_hwsim_devs); 39 static unsigned int wwan_hwsim_dev_idx; 40 static struct workqueue_struct *wwan_wq; 41 42 struct wwan_hwsim_dev { 43 struct list_head list; 44 unsigned int id; 45 struct device dev; 46 struct work_struct del_work; 47 struct dentry *debugfs_topdir; 48 struct dentry *debugfs_portcreate; 49 spinlock_t ports_lock; /* Serialize ports creation/deletion */ 50 unsigned int port_idx; 51 struct list_head ports; 52 }; 53 54 struct wwan_hwsim_port { 55 struct list_head list; 56 unsigned int id; 57 struct wwan_hwsim_dev *dev; 58 struct wwan_port *wwan; 59 struct work_struct del_work; 60 struct dentry *debugfs_topdir; 61 union { 62 struct { 63 enum { /* AT command parser state */ 64 AT_PARSER_WAIT_A, 65 AT_PARSER_WAIT_T, 66 AT_PARSER_WAIT_TERM, 67 AT_PARSER_SKIP_LINE, 68 } pstate; 69 } at_emul; 70 struct { 71 struct timer_list timer; 72 } nmea_emul; 73 }; 74 }; 75 76 static const struct file_operations wwan_hwsim_debugfs_portdestroy_fops; 77 static const struct file_operations wwan_hwsim_debugfs_portcreate_fops; 78 static const struct file_operations wwan_hwsim_debugfs_devdestroy_fops; 79 static void wwan_hwsim_port_del_work(struct work_struct *work); 80 static void wwan_hwsim_dev_del_work(struct work_struct *work); 81 82 static netdev_tx_t wwan_hwsim_netdev_xmit(struct sk_buff *skb, 83 struct net_device *ndev) 84 { 85 ndev->stats.tx_packets++; 86 ndev->stats.tx_bytes += skb->len; 87 consume_skb(skb); 88 return NETDEV_TX_OK; 89 } 90 91 static const struct net_device_ops wwan_hwsim_netdev_ops = { 92 .ndo_start_xmit = wwan_hwsim_netdev_xmit, 93 }; 94 95 static void wwan_hwsim_netdev_setup(struct net_device *ndev) 96 { 97 ndev->netdev_ops = &wwan_hwsim_netdev_ops; 98 ndev->needs_free_netdev = true; 99 100 ndev->mtu = ETH_DATA_LEN; 101 ndev->min_mtu = ETH_MIN_MTU; 102 ndev->max_mtu = ETH_MAX_MTU; 103 104 ndev->type = ARPHRD_NONE; 105 ndev->flags = IFF_POINTOPOINT | IFF_NOARP; 106 } 107 108 static const struct wwan_ops wwan_hwsim_wwan_rtnl_ops = { 109 .priv_size = 0, /* No private data */ 110 .setup = wwan_hwsim_netdev_setup, 111 }; 112 113 static int wwan_hwsim_at_emul_start(struct wwan_port *wport) 114 { 115 struct wwan_hwsim_port *port = wwan_port_get_drvdata(wport); 116 117 port->at_emul.pstate = AT_PARSER_WAIT_A; 118 119 return 0; 120 } 121 122 static void wwan_hwsim_at_emul_stop(struct wwan_port *wport) 123 { 124 } 125 126 /* Implements a minimalistic AT commands parser that echo input back and 127 * reply with 'OK' to each input command. See AT command protocol details in the 128 * ITU-T V.250 recomendations document. 129 * 130 * Be aware that this processor is not fully V.250 compliant. 131 */ 132 static int wwan_hwsim_at_emul_tx(struct wwan_port *wport, struct sk_buff *in) 133 { 134 struct wwan_hwsim_port *port = wwan_port_get_drvdata(wport); 135 struct sk_buff *out; 136 int i, n, s; 137 138 /* Estimate a max possible number of commands by counting the number of 139 * termination chars (S3 param, CR by default). And then allocate the 140 * output buffer that will be enough to fit the echo and result codes of 141 * all commands. 142 */ 143 for (i = 0, n = 0; i < in->len; ++i) 144 if (in->data[i] == '\r') 145 n++; 146 n = in->len + n * (2 + 2 + 2); /* Output buffer size */ 147 out = alloc_skb(n, GFP_KERNEL); 148 if (!out) 149 return -ENOMEM; 150 151 for (i = 0, s = 0; i < in->len; ++i) { 152 char c = in->data[i]; 153 154 if (port->at_emul.pstate == AT_PARSER_WAIT_A) { 155 if (c == 'A' || c == 'a') 156 port->at_emul.pstate = AT_PARSER_WAIT_T; 157 else if (c != '\n') /* Ignore formating char */ 158 port->at_emul.pstate = AT_PARSER_SKIP_LINE; 159 } else if (port->at_emul.pstate == AT_PARSER_WAIT_T) { 160 if (c == 'T' || c == 't') 161 port->at_emul.pstate = AT_PARSER_WAIT_TERM; 162 else 163 port->at_emul.pstate = AT_PARSER_SKIP_LINE; 164 } else if (port->at_emul.pstate == AT_PARSER_WAIT_TERM) { 165 if (c != '\r') 166 continue; 167 /* Consume the trailing formatting char as well */ 168 if ((i + 1) < in->len && in->data[i + 1] == '\n') 169 i++; 170 n = i - s + 1; 171 skb_put_data(out, &in->data[s], n);/* Echo */ 172 skb_put_data(out, "\r\nOK\r\n", 6); 173 s = i + 1; 174 port->at_emul.pstate = AT_PARSER_WAIT_A; 175 } else if (port->at_emul.pstate == AT_PARSER_SKIP_LINE) { 176 if (c != '\r') 177 continue; 178 port->at_emul.pstate = AT_PARSER_WAIT_A; 179 } 180 } 181 182 if (i > s) { 183 /* Echo the processed portion of a not yet completed command */ 184 n = i - s; 185 skb_put_data(out, &in->data[s], n); 186 } 187 188 consume_skb(in); 189 190 wwan_port_rx(wport, out); 191 192 return 0; 193 } 194 195 static const struct wwan_port_ops wwan_hwsim_at_emul_port_ops = { 196 .start = wwan_hwsim_at_emul_start, 197 .stop = wwan_hwsim_at_emul_stop, 198 .tx = wwan_hwsim_at_emul_tx, 199 }; 200 201 #if IS_ENABLED(CONFIG_GNSS) 202 #define NMEA_MAX_LEN 82 /* Max sentence length */ 203 #define NMEA_TRAIL_LEN 5 /* '*' + Checksum + <CR><LF> */ 204 #define NMEA_MAX_DATA_LEN (NMEA_MAX_LEN - NMEA_TRAIL_LEN) 205 206 static __printf(2, 3) 207 void wwan_hwsim_nmea_skb_push_sentence(struct sk_buff *skb, 208 const char *fmt, ...) 209 { 210 unsigned char *s, *p; 211 va_list ap; 212 u8 cs = 0; 213 int len; 214 215 s = skb_put(skb, NMEA_MAX_LEN + 1); /* +'\0' */ 216 if (!s) 217 return; 218 219 va_start(ap, fmt); 220 len = vsnprintf(s, NMEA_MAX_DATA_LEN + 1, fmt, ap); 221 va_end(ap); 222 if (WARN_ON_ONCE(len > NMEA_MAX_DATA_LEN))/* No space for trailer */ 223 return; 224 225 for (p = s + 1; *p != '\0'; ++p)/* Skip leading '$' or '!' */ 226 cs ^= *p; 227 p += snprintf(p, 5 + 1, "*%02X\r\n", cs); 228 229 len = (p - s) - (NMEA_MAX_LEN + 1); /* exp. vs real length diff */ 230 skb->tail += len; /* Adjust tail to real length */ 231 skb->len += len; 232 } 233 234 static void wwan_hwsim_nmea_emul_timer(struct timer_list *t) 235 { 236 /* 43.74754722298909 N 11.25759835922875 E in DMM format */ 237 static const unsigned int coord[4 * 2] = { 43, 44, 8528, 0, 238 11, 15, 4559, 0 }; 239 struct wwan_hwsim_port *port = timer_container_of(port, t, nmea_emul.timer); 240 struct sk_buff *skb; 241 struct tm tm; 242 243 time64_to_tm(ktime_get_real_seconds(), 0, &tm); 244 245 mod_timer(&port->nmea_emul.timer, jiffies + HZ); /* 1 second */ 246 247 skb = alloc_skb(NMEA_MAX_LEN * 2 + 2, GFP_ATOMIC); /* GGA + RMC */ 248 if (!skb) 249 return; 250 251 wwan_hwsim_nmea_skb_push_sentence(skb, 252 "$GPGGA,%02u%02u%02u.000,%02u%02u.%04u,%c,%03u%02u.%04u,%c,1,7,1.03,176.2,M,55.2,M,,", 253 tm.tm_hour, tm.tm_min, tm.tm_sec, 254 coord[0], coord[1], coord[2], 255 coord[3] ? 'S' : 'N', 256 coord[4], coord[5], coord[6], 257 coord[7] ? 'W' : 'E'); 258 259 wwan_hwsim_nmea_skb_push_sentence(skb, 260 "$GPRMC,%02u%02u%02u.000,A,%02u%02u.%04u,%c,%03u%02u.%04u,%c,0.02,31.66,%02u%02u%02u,,,A", 261 tm.tm_hour, tm.tm_min, tm.tm_sec, 262 coord[0], coord[1], coord[2], 263 coord[3] ? 'S' : 'N', 264 coord[4], coord[5], coord[6], 265 coord[7] ? 'W' : 'E', 266 tm.tm_mday, tm.tm_mon + 1, 267 (unsigned int)tm.tm_year - 100); 268 269 wwan_port_rx(port->wwan, skb); 270 } 271 272 static int wwan_hwsim_nmea_emul_start(struct wwan_port *wport) 273 { 274 struct wwan_hwsim_port *port = wwan_port_get_drvdata(wport); 275 276 timer_setup(&port->nmea_emul.timer, wwan_hwsim_nmea_emul_timer, 0); 277 wwan_hwsim_nmea_emul_timer(&port->nmea_emul.timer); 278 279 return 0; 280 } 281 282 static void wwan_hwsim_nmea_emul_stop(struct wwan_port *wport) 283 { 284 struct wwan_hwsim_port *port = wwan_port_get_drvdata(wport); 285 286 timer_delete_sync(&port->nmea_emul.timer); 287 } 288 289 static int wwan_hwsim_nmea_emul_tx(struct wwan_port *wport, struct sk_buff *in) 290 { 291 consume_skb(in); 292 293 return 0; 294 } 295 296 static const struct wwan_port_ops wwan_hwsim_nmea_emul_port_ops = { 297 .start = wwan_hwsim_nmea_emul_start, 298 .stop = wwan_hwsim_nmea_emul_stop, 299 .tx = wwan_hwsim_nmea_emul_tx, 300 }; 301 #endif 302 303 static struct wwan_hwsim_port *wwan_hwsim_port_new(struct wwan_hwsim_dev *dev, 304 enum wwan_port_type type) 305 { 306 const struct wwan_port_ops *ops; 307 struct wwan_hwsim_port *port; 308 char name[0x10]; 309 int err; 310 311 if (type == WWAN_PORT_AT) 312 ops = &wwan_hwsim_at_emul_port_ops; 313 #if IS_ENABLED(CONFIG_GNSS) 314 else if (type == WWAN_PORT_NMEA) 315 ops = &wwan_hwsim_nmea_emul_port_ops; 316 #endif 317 else 318 return ERR_PTR(-EINVAL); 319 320 port = kzalloc_obj(*port); 321 if (!port) 322 return ERR_PTR(-ENOMEM); 323 324 port->dev = dev; 325 326 spin_lock(&dev->ports_lock); 327 port->id = dev->port_idx++; 328 spin_unlock(&dev->ports_lock); 329 330 port->wwan = wwan_create_port(&dev->dev, type, ops, NULL, port); 331 if (IS_ERR(port->wwan)) { 332 err = PTR_ERR(port->wwan); 333 goto err_free_port; 334 } 335 336 INIT_WORK(&port->del_work, wwan_hwsim_port_del_work); 337 338 snprintf(name, sizeof(name), "port%u", port->id); 339 port->debugfs_topdir = debugfs_create_dir(name, dev->debugfs_topdir); 340 debugfs_create_file("destroy", 0200, port->debugfs_topdir, port, 341 &wwan_hwsim_debugfs_portdestroy_fops); 342 343 return port; 344 345 err_free_port: 346 kfree(port); 347 348 return ERR_PTR(err); 349 } 350 351 static void wwan_hwsim_port_del(struct wwan_hwsim_port *port) 352 { 353 debugfs_remove(port->debugfs_topdir); 354 355 /* Make sure that there is no pending deletion work */ 356 if (current_work() != &port->del_work) 357 cancel_work_sync(&port->del_work); 358 359 wwan_remove_port(port->wwan); 360 kfree(port); 361 } 362 363 static void wwan_hwsim_port_del_work(struct work_struct *work) 364 { 365 struct wwan_hwsim_port *port = 366 container_of(work, typeof(*port), del_work); 367 struct wwan_hwsim_dev *dev = port->dev; 368 369 spin_lock(&dev->ports_lock); 370 if (list_empty(&port->list)) { 371 /* Someone else deleting port at the moment */ 372 spin_unlock(&dev->ports_lock); 373 return; 374 } 375 list_del_init(&port->list); 376 spin_unlock(&dev->ports_lock); 377 378 wwan_hwsim_port_del(port); 379 } 380 381 static void wwan_hwsim_dev_release(struct device *sysdev) 382 { 383 struct wwan_hwsim_dev *dev = container_of(sysdev, typeof(*dev), dev); 384 385 kfree(dev); 386 } 387 388 static struct wwan_hwsim_dev *wwan_hwsim_dev_new(void) 389 { 390 struct wwan_hwsim_dev *dev; 391 int err; 392 393 dev = kzalloc_obj(*dev); 394 if (!dev) 395 return ERR_PTR(-ENOMEM); 396 397 spin_lock(&wwan_hwsim_devs_lock); 398 dev->id = wwan_hwsim_dev_idx++; 399 spin_unlock(&wwan_hwsim_devs_lock); 400 401 dev->dev.release = wwan_hwsim_dev_release; 402 dev->dev.class = &wwan_hwsim_class; 403 dev_set_name(&dev->dev, "hwsim%u", dev->id); 404 405 spin_lock_init(&dev->ports_lock); 406 INIT_LIST_HEAD(&dev->ports); 407 408 err = device_register(&dev->dev); 409 if (err) 410 goto err_free_dev; 411 412 INIT_WORK(&dev->del_work, wwan_hwsim_dev_del_work); 413 414 err = wwan_register_ops(&dev->dev, &wwan_hwsim_wwan_rtnl_ops, dev, 1); 415 if (err) 416 goto err_unreg_dev; 417 418 dev->debugfs_topdir = debugfs_create_dir(dev_name(&dev->dev), 419 wwan_hwsim_debugfs_topdir); 420 debugfs_create_file("destroy", 0200, dev->debugfs_topdir, dev, 421 &wwan_hwsim_debugfs_devdestroy_fops); 422 dev->debugfs_portcreate = 423 debugfs_create_file("portcreate", 0200, 424 dev->debugfs_topdir, dev, 425 &wwan_hwsim_debugfs_portcreate_fops); 426 427 return dev; 428 429 err_unreg_dev: 430 device_unregister(&dev->dev); 431 /* Memory will be freed in the device release callback */ 432 433 return ERR_PTR(err); 434 435 err_free_dev: 436 put_device(&dev->dev); 437 438 return ERR_PTR(err); 439 } 440 441 static void wwan_hwsim_dev_del(struct wwan_hwsim_dev *dev) 442 { 443 debugfs_remove(dev->debugfs_portcreate); /* Avoid new ports */ 444 445 spin_lock(&dev->ports_lock); 446 while (!list_empty(&dev->ports)) { 447 struct wwan_hwsim_port *port; 448 449 port = list_first_entry(&dev->ports, struct wwan_hwsim_port, 450 list); 451 list_del_init(&port->list); 452 spin_unlock(&dev->ports_lock); 453 wwan_hwsim_port_del(port); 454 spin_lock(&dev->ports_lock); 455 } 456 spin_unlock(&dev->ports_lock); 457 458 debugfs_remove(dev->debugfs_topdir); 459 460 /* This will remove all child netdev(s) */ 461 wwan_unregister_ops(&dev->dev); 462 463 /* Make sure that there is no pending deletion work */ 464 if (current_work() != &dev->del_work) 465 cancel_work_sync(&dev->del_work); 466 467 device_unregister(&dev->dev); 468 /* Memory will be freed in the device release callback */ 469 } 470 471 static void wwan_hwsim_dev_del_work(struct work_struct *work) 472 { 473 struct wwan_hwsim_dev *dev = container_of(work, typeof(*dev), del_work); 474 475 spin_lock(&wwan_hwsim_devs_lock); 476 if (list_empty(&dev->list)) { 477 /* Someone else deleting device at the moment */ 478 spin_unlock(&wwan_hwsim_devs_lock); 479 return; 480 } 481 list_del_init(&dev->list); 482 spin_unlock(&wwan_hwsim_devs_lock); 483 484 wwan_hwsim_dev_del(dev); 485 } 486 487 static ssize_t wwan_hwsim_debugfs_portdestroy_write(struct file *file, 488 const char __user *usrbuf, 489 size_t count, loff_t *ppos) 490 { 491 struct wwan_hwsim_port *port = file->private_data; 492 493 /* We can not delete port here since it will cause a deadlock due to 494 * waiting this callback to finish in the debugfs_remove() call. So, 495 * use workqueue. 496 */ 497 queue_work(wwan_wq, &port->del_work); 498 499 return count; 500 } 501 502 static const struct file_operations wwan_hwsim_debugfs_portdestroy_fops = { 503 .write = wwan_hwsim_debugfs_portdestroy_write, 504 .open = simple_open, 505 .llseek = noop_llseek, 506 }; 507 508 static ssize_t wwan_hwsim_debugfs_portcreate_write(struct file *file, 509 const char __user *usrbuf, 510 size_t count, loff_t *ppos) 511 { 512 struct wwan_hwsim_dev *dev = file->private_data; 513 struct wwan_hwsim_port *port; 514 515 port = wwan_hwsim_port_new(dev, WWAN_PORT_AT); 516 if (IS_ERR(port)) 517 return PTR_ERR(port); 518 519 spin_lock(&dev->ports_lock); 520 list_add_tail(&port->list, &dev->ports); 521 spin_unlock(&dev->ports_lock); 522 523 return count; 524 } 525 526 static const struct file_operations wwan_hwsim_debugfs_portcreate_fops = { 527 .write = wwan_hwsim_debugfs_portcreate_write, 528 .open = simple_open, 529 .llseek = noop_llseek, 530 }; 531 532 static ssize_t wwan_hwsim_debugfs_devdestroy_write(struct file *file, 533 const char __user *usrbuf, 534 size_t count, loff_t *ppos) 535 { 536 struct wwan_hwsim_dev *dev = file->private_data; 537 538 /* We can not delete device here since it will cause a deadlock due to 539 * waiting this callback to finish in the debugfs_remove() call. So, 540 * use workqueue. 541 */ 542 queue_work(wwan_wq, &dev->del_work); 543 544 return count; 545 } 546 547 static const struct file_operations wwan_hwsim_debugfs_devdestroy_fops = { 548 .write = wwan_hwsim_debugfs_devdestroy_write, 549 .open = simple_open, 550 .llseek = noop_llseek, 551 }; 552 553 static ssize_t wwan_hwsim_debugfs_devcreate_write(struct file *file, 554 const char __user *usrbuf, 555 size_t count, loff_t *ppos) 556 { 557 struct wwan_hwsim_dev *dev; 558 559 dev = wwan_hwsim_dev_new(); 560 if (IS_ERR(dev)) 561 return PTR_ERR(dev); 562 563 spin_lock(&wwan_hwsim_devs_lock); 564 list_add_tail(&dev->list, &wwan_hwsim_devs); 565 spin_unlock(&wwan_hwsim_devs_lock); 566 567 return count; 568 } 569 570 static const struct file_operations wwan_hwsim_debugfs_devcreate_fops = { 571 .write = wwan_hwsim_debugfs_devcreate_write, 572 .open = simple_open, 573 .llseek = noop_llseek, 574 }; 575 576 static int __init wwan_hwsim_init_devs(void) 577 { 578 struct wwan_hwsim_dev *dev; 579 int i, j; 580 581 for (i = 0; i < wwan_hwsim_devsnum; ++i) { 582 struct wwan_hwsim_port *port; 583 584 dev = wwan_hwsim_dev_new(); 585 if (IS_ERR(dev)) 586 return PTR_ERR(dev); 587 588 spin_lock(&wwan_hwsim_devs_lock); 589 list_add_tail(&dev->list, &wwan_hwsim_devs); 590 spin_unlock(&wwan_hwsim_devs_lock); 591 592 /* Create a few various ports per each device to accelerate 593 * the simulator readiness time. 594 */ 595 596 for (j = 0; j < 2; ++j) { 597 port = wwan_hwsim_port_new(dev, WWAN_PORT_AT); 598 if (IS_ERR(port)) 599 return PTR_ERR(port); 600 601 spin_lock(&dev->ports_lock); 602 list_add_tail(&port->list, &dev->ports); 603 spin_unlock(&dev->ports_lock); 604 } 605 606 #if IS_ENABLED(CONFIG_GNSS) 607 port = wwan_hwsim_port_new(dev, WWAN_PORT_NMEA); 608 if (IS_ERR(port)) { 609 dev_warn(&dev->dev, "failed to create initial NMEA port: %d\n", 610 (int)PTR_ERR(port)); 611 } else { 612 spin_lock(&dev->ports_lock); 613 list_add_tail(&port->list, &dev->ports); 614 spin_unlock(&dev->ports_lock); 615 } 616 #endif 617 } 618 619 return 0; 620 } 621 622 static void wwan_hwsim_free_devs(void) 623 { 624 struct wwan_hwsim_dev *dev; 625 626 spin_lock(&wwan_hwsim_devs_lock); 627 while (!list_empty(&wwan_hwsim_devs)) { 628 dev = list_first_entry(&wwan_hwsim_devs, struct wwan_hwsim_dev, 629 list); 630 list_del_init(&dev->list); 631 spin_unlock(&wwan_hwsim_devs_lock); 632 wwan_hwsim_dev_del(dev); 633 spin_lock(&wwan_hwsim_devs_lock); 634 } 635 spin_unlock(&wwan_hwsim_devs_lock); 636 } 637 638 static int __init wwan_hwsim_init(void) 639 { 640 int err; 641 642 if (wwan_hwsim_devsnum < 0 || wwan_hwsim_devsnum > 128) 643 return -EINVAL; 644 645 wwan_wq = alloc_workqueue("wwan_wq", WQ_PERCPU, 0); 646 if (!wwan_wq) 647 return -ENOMEM; 648 649 err = class_register(&wwan_hwsim_class); 650 if (err) 651 goto err_wq_destroy; 652 653 wwan_hwsim_debugfs_topdir = debugfs_create_dir("wwan_hwsim", NULL); 654 wwan_hwsim_debugfs_devcreate = 655 debugfs_create_file("devcreate", 0200, 656 wwan_hwsim_debugfs_topdir, NULL, 657 &wwan_hwsim_debugfs_devcreate_fops); 658 659 err = wwan_hwsim_init_devs(); 660 if (err) 661 goto err_clean_devs; 662 663 return 0; 664 665 err_clean_devs: 666 debugfs_remove(wwan_hwsim_debugfs_devcreate); /* Avoid new devs */ 667 wwan_hwsim_free_devs(); 668 flush_workqueue(wwan_wq); /* Wait deletion works completion */ 669 debugfs_remove(wwan_hwsim_debugfs_topdir); 670 class_unregister(&wwan_hwsim_class); 671 err_wq_destroy: 672 destroy_workqueue(wwan_wq); 673 674 return err; 675 } 676 677 static void __exit wwan_hwsim_exit(void) 678 { 679 debugfs_remove(wwan_hwsim_debugfs_devcreate); /* Avoid new devs */ 680 wwan_hwsim_free_devs(); 681 flush_workqueue(wwan_wq); /* Wait deletion works completion */ 682 debugfs_remove(wwan_hwsim_debugfs_topdir); 683 class_unregister(&wwan_hwsim_class); 684 destroy_workqueue(wwan_wq); 685 } 686 687 module_init(wwan_hwsim_init); 688 module_exit(wwan_hwsim_exit); 689 690 MODULE_AUTHOR("Sergey Ryazanov"); 691 MODULE_DESCRIPTION("Device simulator for WWAN framework"); 692 MODULE_LICENSE("GPL"); 693