| .. | .. |
|---|
| 89 | 89 | .dev_groups = stm_groups, |
|---|
| 90 | 90 | }; |
|---|
| 91 | 91 | |
|---|
| 92 | | -static int stm_dev_match(struct device *dev, const void *data) |
|---|
| 93 | | -{ |
|---|
| 94 | | - const char *name = data; |
|---|
| 95 | | - |
|---|
| 96 | | - return sysfs_streq(name, dev_name(dev)); |
|---|
| 97 | | -} |
|---|
| 98 | | - |
|---|
| 99 | 92 | /** |
|---|
| 100 | 93 | * stm_find_device() - find stm device by name |
|---|
| 101 | 94 | * @buf: character buffer containing the name |
|---|
| .. | .. |
|---|
| 116 | 109 | if (!stm_core_up) |
|---|
| 117 | 110 | return NULL; |
|---|
| 118 | 111 | |
|---|
| 119 | | - dev = class_find_device(&stm_class, NULL, buf, stm_dev_match); |
|---|
| 112 | + dev = class_find_device_by_name(&stm_class, buf); |
|---|
| 120 | 113 | if (!dev) |
|---|
| 121 | 114 | return NULL; |
|---|
| 122 | 115 | |
|---|
| .. | .. |
|---|
| 295 | 288 | if (width > stm->data->sw_nchannels) |
|---|
| 296 | 289 | return -EINVAL; |
|---|
| 297 | 290 | |
|---|
| 298 | | - if (policy_node) { |
|---|
| 299 | | - stp_policy_node_get_ranges(policy_node, |
|---|
| 300 | | - &midx, &mend, &cidx, &cend); |
|---|
| 301 | | - } else { |
|---|
| 302 | | - midx = stm->data->sw_start; |
|---|
| 303 | | - cidx = 0; |
|---|
| 304 | | - mend = stm->data->sw_end; |
|---|
| 305 | | - cend = stm->data->sw_nchannels - 1; |
|---|
| 306 | | - } |
|---|
| 291 | + /* We no longer accept policy_node==NULL here */ |
|---|
| 292 | + if (WARN_ON_ONCE(!policy_node)) |
|---|
| 293 | + return -EINVAL; |
|---|
| 294 | + |
|---|
| 295 | + /* |
|---|
| 296 | + * Also, the caller holds reference to policy_node, so it won't |
|---|
| 297 | + * disappear on us. |
|---|
| 298 | + */ |
|---|
| 299 | + stp_policy_node_get_ranges(policy_node, &midx, &mend, &cidx, &cend); |
|---|
| 307 | 300 | |
|---|
| 308 | 301 | spin_lock(&stm->mc_lock); |
|---|
| 309 | 302 | spin_lock(&output->lock); |
|---|
| .. | .. |
|---|
| 318 | 311 | output->master = midx; |
|---|
| 319 | 312 | output->channel = cidx; |
|---|
| 320 | 313 | output->nr_chans = width; |
|---|
| 314 | + if (stm->pdrv->output_open) { |
|---|
| 315 | + void *priv = stp_policy_node_priv(policy_node); |
|---|
| 316 | + |
|---|
| 317 | + if (WARN_ON_ONCE(!priv)) |
|---|
| 318 | + goto unlock; |
|---|
| 319 | + |
|---|
| 320 | + /* configfs subsys mutex is held by the caller */ |
|---|
| 321 | + ret = stm->pdrv->output_open(priv, output); |
|---|
| 322 | + if (ret) |
|---|
| 323 | + goto unlock; |
|---|
| 324 | + } |
|---|
| 325 | + |
|---|
| 321 | 326 | stm_output_claim(stm, output); |
|---|
| 322 | 327 | dev_dbg(&stm->dev, "assigned %u:%u (+%u)\n", midx, cidx, width); |
|---|
| 323 | 328 | |
|---|
| 324 | 329 | ret = 0; |
|---|
| 325 | 330 | unlock: |
|---|
| 331 | + if (ret) |
|---|
| 332 | + output->nr_chans = 0; |
|---|
| 333 | + |
|---|
| 326 | 334 | spin_unlock(&output->lock); |
|---|
| 327 | 335 | spin_unlock(&stm->mc_lock); |
|---|
| 328 | 336 | |
|---|
| .. | .. |
|---|
| 335 | 343 | spin_lock(&output->lock); |
|---|
| 336 | 344 | if (output->nr_chans) |
|---|
| 337 | 345 | stm_output_disclaim(stm, output); |
|---|
| 346 | + if (stm->pdrv && stm->pdrv->output_close) |
|---|
| 347 | + stm->pdrv->output_close(output); |
|---|
| 338 | 348 | spin_unlock(&output->lock); |
|---|
| 339 | 349 | spin_unlock(&stm->mc_lock); |
|---|
| 340 | 350 | } |
|---|
| .. | .. |
|---|
| 349 | 359 | unsigned int major = *(unsigned int *)data; |
|---|
| 350 | 360 | |
|---|
| 351 | 361 | return MAJOR(dev->devt) == major; |
|---|
| 362 | +} |
|---|
| 363 | + |
|---|
| 364 | +/* |
|---|
| 365 | + * Framing protocol management |
|---|
| 366 | + * Modules can implement STM protocol drivers and (un-)register them |
|---|
| 367 | + * with the STM class framework. |
|---|
| 368 | + */ |
|---|
| 369 | +static struct list_head stm_pdrv_head; |
|---|
| 370 | +static struct mutex stm_pdrv_mutex; |
|---|
| 371 | + |
|---|
| 372 | +struct stm_pdrv_entry { |
|---|
| 373 | + struct list_head entry; |
|---|
| 374 | + const struct stm_protocol_driver *pdrv; |
|---|
| 375 | + const struct config_item_type *node_type; |
|---|
| 376 | +}; |
|---|
| 377 | + |
|---|
| 378 | +static const struct stm_pdrv_entry * |
|---|
| 379 | +__stm_lookup_protocol(const char *name) |
|---|
| 380 | +{ |
|---|
| 381 | + struct stm_pdrv_entry *pe; |
|---|
| 382 | + |
|---|
| 383 | + /* |
|---|
| 384 | + * If no name is given (NULL or ""), fall back to "p_basic". |
|---|
| 385 | + */ |
|---|
| 386 | + if (!name || !*name) |
|---|
| 387 | + name = "p_basic"; |
|---|
| 388 | + |
|---|
| 389 | + list_for_each_entry(pe, &stm_pdrv_head, entry) { |
|---|
| 390 | + if (!strcmp(name, pe->pdrv->name)) |
|---|
| 391 | + return pe; |
|---|
| 392 | + } |
|---|
| 393 | + |
|---|
| 394 | + return NULL; |
|---|
| 395 | +} |
|---|
| 396 | + |
|---|
| 397 | +int stm_register_protocol(const struct stm_protocol_driver *pdrv) |
|---|
| 398 | +{ |
|---|
| 399 | + struct stm_pdrv_entry *pe = NULL; |
|---|
| 400 | + int ret = -ENOMEM; |
|---|
| 401 | + |
|---|
| 402 | + mutex_lock(&stm_pdrv_mutex); |
|---|
| 403 | + |
|---|
| 404 | + if (__stm_lookup_protocol(pdrv->name)) { |
|---|
| 405 | + ret = -EEXIST; |
|---|
| 406 | + goto unlock; |
|---|
| 407 | + } |
|---|
| 408 | + |
|---|
| 409 | + pe = kzalloc(sizeof(*pe), GFP_KERNEL); |
|---|
| 410 | + if (!pe) |
|---|
| 411 | + goto unlock; |
|---|
| 412 | + |
|---|
| 413 | + if (pdrv->policy_attr) { |
|---|
| 414 | + pe->node_type = get_policy_node_type(pdrv->policy_attr); |
|---|
| 415 | + if (!pe->node_type) |
|---|
| 416 | + goto unlock; |
|---|
| 417 | + } |
|---|
| 418 | + |
|---|
| 419 | + list_add_tail(&pe->entry, &stm_pdrv_head); |
|---|
| 420 | + pe->pdrv = pdrv; |
|---|
| 421 | + |
|---|
| 422 | + ret = 0; |
|---|
| 423 | +unlock: |
|---|
| 424 | + mutex_unlock(&stm_pdrv_mutex); |
|---|
| 425 | + |
|---|
| 426 | + if (ret) |
|---|
| 427 | + kfree(pe); |
|---|
| 428 | + |
|---|
| 429 | + return ret; |
|---|
| 430 | +} |
|---|
| 431 | +EXPORT_SYMBOL_GPL(stm_register_protocol); |
|---|
| 432 | + |
|---|
| 433 | +void stm_unregister_protocol(const struct stm_protocol_driver *pdrv) |
|---|
| 434 | +{ |
|---|
| 435 | + struct stm_pdrv_entry *pe, *iter; |
|---|
| 436 | + |
|---|
| 437 | + mutex_lock(&stm_pdrv_mutex); |
|---|
| 438 | + |
|---|
| 439 | + list_for_each_entry_safe(pe, iter, &stm_pdrv_head, entry) { |
|---|
| 440 | + if (pe->pdrv == pdrv) { |
|---|
| 441 | + list_del(&pe->entry); |
|---|
| 442 | + |
|---|
| 443 | + if (pe->node_type) { |
|---|
| 444 | + kfree(pe->node_type->ct_attrs); |
|---|
| 445 | + kfree(pe->node_type); |
|---|
| 446 | + } |
|---|
| 447 | + kfree(pe); |
|---|
| 448 | + break; |
|---|
| 449 | + } |
|---|
| 450 | + } |
|---|
| 451 | + |
|---|
| 452 | + mutex_unlock(&stm_pdrv_mutex); |
|---|
| 453 | +} |
|---|
| 454 | +EXPORT_SYMBOL_GPL(stm_unregister_protocol); |
|---|
| 455 | + |
|---|
| 456 | +static bool stm_get_protocol(const struct stm_protocol_driver *pdrv) |
|---|
| 457 | +{ |
|---|
| 458 | + return try_module_get(pdrv->owner); |
|---|
| 459 | +} |
|---|
| 460 | + |
|---|
| 461 | +void stm_put_protocol(const struct stm_protocol_driver *pdrv) |
|---|
| 462 | +{ |
|---|
| 463 | + module_put(pdrv->owner); |
|---|
| 464 | +} |
|---|
| 465 | + |
|---|
| 466 | +int stm_lookup_protocol(const char *name, |
|---|
| 467 | + const struct stm_protocol_driver **pdrv, |
|---|
| 468 | + const struct config_item_type **node_type) |
|---|
| 469 | +{ |
|---|
| 470 | + const struct stm_pdrv_entry *pe; |
|---|
| 471 | + |
|---|
| 472 | + mutex_lock(&stm_pdrv_mutex); |
|---|
| 473 | + |
|---|
| 474 | + pe = __stm_lookup_protocol(name); |
|---|
| 475 | + if (pe && pe->pdrv && stm_get_protocol(pe->pdrv)) { |
|---|
| 476 | + *pdrv = pe->pdrv; |
|---|
| 477 | + *node_type = pe->node_type; |
|---|
| 478 | + } |
|---|
| 479 | + |
|---|
| 480 | + mutex_unlock(&stm_pdrv_mutex); |
|---|
| 481 | + |
|---|
| 482 | + return pe ? 0 : -ENOENT; |
|---|
| 352 | 483 | } |
|---|
| 353 | 484 | |
|---|
| 354 | 485 | static int stm_char_open(struct inode *inode, struct file *file) |
|---|
| .. | .. |
|---|
| 407 | 538 | return 0; |
|---|
| 408 | 539 | } |
|---|
| 409 | 540 | |
|---|
| 410 | | -static int stm_file_assign(struct stm_file *stmf, char *id, unsigned int width) |
|---|
| 541 | +static int |
|---|
| 542 | +stm_assign_first_policy(struct stm_device *stm, struct stm_output *output, |
|---|
| 543 | + char **ids, unsigned int width) |
|---|
| 411 | 544 | { |
|---|
| 412 | | - struct stm_device *stm = stmf->stm; |
|---|
| 413 | | - int ret; |
|---|
| 545 | + struct stp_policy_node *pn; |
|---|
| 546 | + int err, n; |
|---|
| 414 | 547 | |
|---|
| 415 | | - stmf->policy_node = stp_policy_node_lookup(stm, id); |
|---|
| 548 | + /* |
|---|
| 549 | + * On success, stp_policy_node_lookup() will return holding the |
|---|
| 550 | + * configfs subsystem mutex, which is then released in |
|---|
| 551 | + * stp_policy_node_put(). This allows the pdrv->output_open() in |
|---|
| 552 | + * stm_output_assign() to serialize against the attribute accessors. |
|---|
| 553 | + */ |
|---|
| 554 | + for (n = 0, pn = NULL; ids[n] && !pn; n++) |
|---|
| 555 | + pn = stp_policy_node_lookup(stm, ids[n]); |
|---|
| 416 | 556 | |
|---|
| 417 | | - ret = stm_output_assign(stm, width, stmf->policy_node, &stmf->output); |
|---|
| 557 | + if (!pn) |
|---|
| 558 | + return -EINVAL; |
|---|
| 418 | 559 | |
|---|
| 419 | | - if (stmf->policy_node) |
|---|
| 420 | | - stp_policy_node_put(stmf->policy_node); |
|---|
| 560 | + err = stm_output_assign(stm, width, pn, output); |
|---|
| 421 | 561 | |
|---|
| 422 | | - return ret; |
|---|
| 562 | + stp_policy_node_put(pn); |
|---|
| 563 | + |
|---|
| 564 | + return err; |
|---|
| 423 | 565 | } |
|---|
| 424 | 566 | |
|---|
| 425 | | -static ssize_t notrace stm_write(struct stm_data *data, unsigned int master, |
|---|
| 426 | | - unsigned int channel, const char *buf, size_t count) |
|---|
| 567 | +/** |
|---|
| 568 | + * stm_data_write() - send the given payload as data packets |
|---|
| 569 | + * @data: stm driver's data |
|---|
| 570 | + * @m: STP master |
|---|
| 571 | + * @c: STP channel |
|---|
| 572 | + * @ts_first: timestamp the first packet |
|---|
| 573 | + * @buf: data payload buffer |
|---|
| 574 | + * @count: data payload size |
|---|
| 575 | + */ |
|---|
| 576 | +ssize_t notrace stm_data_write(struct stm_data *data, unsigned int m, |
|---|
| 577 | + unsigned int c, bool ts_first, const void *buf, |
|---|
| 578 | + size_t count) |
|---|
| 427 | 579 | { |
|---|
| 428 | | - unsigned int flags = STP_PACKET_TIMESTAMPED; |
|---|
| 429 | | - const unsigned char *p = buf, nil = 0; |
|---|
| 430 | | - size_t pos; |
|---|
| 580 | + unsigned int flags = ts_first ? STP_PACKET_TIMESTAMPED : 0; |
|---|
| 431 | 581 | ssize_t sz; |
|---|
| 582 | + size_t pos; |
|---|
| 432 | 583 | |
|---|
| 433 | | - for (pos = 0, p = buf; count > pos; pos += sz, p += sz) { |
|---|
| 584 | + for (pos = 0, sz = 0; pos < count; pos += sz) { |
|---|
| 434 | 585 | sz = min_t(unsigned int, count - pos, 8); |
|---|
| 435 | | - sz = data->packet(data, master, channel, STP_PACKET_DATA, flags, |
|---|
| 436 | | - sz, p); |
|---|
| 437 | | - flags = 0; |
|---|
| 438 | | - |
|---|
| 439 | | - if (sz < 0) |
|---|
| 586 | + sz = data->packet(data, m, c, STP_PACKET_DATA, flags, sz, |
|---|
| 587 | + &((u8 *)buf)[pos]); |
|---|
| 588 | + if (sz <= 0) |
|---|
| 440 | 589 | break; |
|---|
| 590 | + |
|---|
| 591 | + if (ts_first) { |
|---|
| 592 | + flags = 0; |
|---|
| 593 | + ts_first = false; |
|---|
| 594 | + } |
|---|
| 441 | 595 | } |
|---|
| 442 | 596 | |
|---|
| 443 | | - data->packet(data, master, channel, STP_PACKET_FLAG, 0, 0, &nil); |
|---|
| 597 | + return sz < 0 ? sz : pos; |
|---|
| 598 | +} |
|---|
| 599 | +EXPORT_SYMBOL_GPL(stm_data_write); |
|---|
| 444 | 600 | |
|---|
| 445 | | - return pos; |
|---|
| 601 | +static ssize_t notrace |
|---|
| 602 | +stm_write(struct stm_device *stm, struct stm_output *output, |
|---|
| 603 | + unsigned int chan, const char *buf, size_t count) |
|---|
| 604 | +{ |
|---|
| 605 | + int err; |
|---|
| 606 | + |
|---|
| 607 | + /* stm->pdrv is serialized against policy_mutex */ |
|---|
| 608 | + if (!stm->pdrv) |
|---|
| 609 | + return -ENODEV; |
|---|
| 610 | + |
|---|
| 611 | + err = stm->pdrv->write(stm->data, output, chan, buf, count); |
|---|
| 612 | + if (err < 0) |
|---|
| 613 | + return err; |
|---|
| 614 | + |
|---|
| 615 | + return err; |
|---|
| 446 | 616 | } |
|---|
| 447 | 617 | |
|---|
| 448 | 618 | static ssize_t stm_char_write(struct file *file, const char __user *buf, |
|---|
| .. | .. |
|---|
| 457 | 627 | count = PAGE_SIZE - 1; |
|---|
| 458 | 628 | |
|---|
| 459 | 629 | /* |
|---|
| 460 | | - * if no m/c have been assigned to this writer up to this |
|---|
| 461 | | - * point, use "default" policy entry |
|---|
| 630 | + * If no m/c have been assigned to this writer up to this |
|---|
| 631 | + * point, try to use the task name and "default" policy entries. |
|---|
| 462 | 632 | */ |
|---|
| 463 | 633 | if (!stmf->output.nr_chans) { |
|---|
| 464 | | - err = stm_file_assign(stmf, "default", 1); |
|---|
| 634 | + char comm[sizeof(current->comm)]; |
|---|
| 635 | + char *ids[] = { comm, "default", NULL }; |
|---|
| 636 | + |
|---|
| 637 | + get_task_comm(comm, current); |
|---|
| 638 | + |
|---|
| 639 | + err = stm_assign_first_policy(stmf->stm, &stmf->output, ids, 1); |
|---|
| 465 | 640 | /* |
|---|
| 466 | 641 | * EBUSY means that somebody else just assigned this |
|---|
| 467 | 642 | * output, which is just fine for write() |
|---|
| 468 | 643 | */ |
|---|
| 469 | | - if (err && err != -EBUSY) |
|---|
| 644 | + if (err) |
|---|
| 470 | 645 | return err; |
|---|
| 471 | 646 | } |
|---|
| 472 | 647 | |
|---|
| .. | .. |
|---|
| 482 | 657 | |
|---|
| 483 | 658 | pm_runtime_get_sync(&stm->dev); |
|---|
| 484 | 659 | |
|---|
| 485 | | - count = stm_write(stm->data, stmf->output.master, stmf->output.channel, |
|---|
| 486 | | - kbuf, count); |
|---|
| 660 | + count = stm_write(stm, &stmf->output, 0, kbuf, count); |
|---|
| 487 | 661 | |
|---|
| 488 | 662 | pm_runtime_mark_last_busy(&stm->dev); |
|---|
| 489 | 663 | pm_runtime_put_autosuspend(&stm->dev); |
|---|
| .. | .. |
|---|
| 552 | 726 | { |
|---|
| 553 | 727 | struct stm_device *stm = stmf->stm; |
|---|
| 554 | 728 | struct stp_policy_id *id; |
|---|
| 729 | + char *ids[] = { NULL, NULL }; |
|---|
| 555 | 730 | int ret = -EINVAL, wlimit = 1; |
|---|
| 556 | 731 | u32 size; |
|---|
| 557 | 732 | |
|---|
| .. | .. |
|---|
| 586 | 761 | if (id->width < 1 || id->width > wlimit) |
|---|
| 587 | 762 | goto err_free; |
|---|
| 588 | 763 | |
|---|
| 589 | | - ret = stm_file_assign(stmf, id->id, id->width); |
|---|
| 764 | + ids[0] = id->id; |
|---|
| 765 | + ret = stm_assign_first_policy(stmf->stm, &stmf->output, ids, |
|---|
| 766 | + id->width); |
|---|
| 590 | 767 | if (ret) |
|---|
| 591 | 768 | goto err_free; |
|---|
| 592 | 769 | |
|---|
| .. | .. |
|---|
| 655 | 832 | return err; |
|---|
| 656 | 833 | } |
|---|
| 657 | 834 | |
|---|
| 658 | | -#ifdef CONFIG_COMPAT |
|---|
| 659 | | -static long |
|---|
| 660 | | -stm_char_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
|---|
| 661 | | -{ |
|---|
| 662 | | - return stm_char_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); |
|---|
| 663 | | -} |
|---|
| 664 | | -#else |
|---|
| 665 | | -#define stm_char_compat_ioctl NULL |
|---|
| 666 | | -#endif |
|---|
| 667 | | - |
|---|
| 668 | 835 | static const struct file_operations stm_fops = { |
|---|
| 669 | 836 | .open = stm_char_open, |
|---|
| 670 | 837 | .release = stm_char_release, |
|---|
| 671 | 838 | .write = stm_char_write, |
|---|
| 672 | 839 | .mmap = stm_char_mmap, |
|---|
| 673 | 840 | .unlocked_ioctl = stm_char_ioctl, |
|---|
| 674 | | - .compat_ioctl = stm_char_compat_ioctl, |
|---|
| 841 | + .compat_ioctl = compat_ptr_ioctl, |
|---|
| 675 | 842 | .llseek = no_llseek, |
|---|
| 676 | 843 | }; |
|---|
| 677 | 844 | |
|---|
| .. | .. |
|---|
| 822 | 989 | static int stm_source_link_add(struct stm_source_device *src, |
|---|
| 823 | 990 | struct stm_device *stm) |
|---|
| 824 | 991 | { |
|---|
| 825 | | - char *id; |
|---|
| 826 | | - int err; |
|---|
| 992 | + char *ids[] = { NULL, "default", NULL }; |
|---|
| 993 | + int err = -ENOMEM; |
|---|
| 827 | 994 | |
|---|
| 828 | 995 | mutex_lock(&stm->link_mutex); |
|---|
| 829 | 996 | spin_lock(&stm->link_lock); |
|---|
| .. | .. |
|---|
| 837 | 1004 | spin_unlock(&stm->link_lock); |
|---|
| 838 | 1005 | mutex_unlock(&stm->link_mutex); |
|---|
| 839 | 1006 | |
|---|
| 840 | | - id = kstrdup(src->data->name, GFP_KERNEL); |
|---|
| 841 | | - if (id) { |
|---|
| 842 | | - src->policy_node = |
|---|
| 843 | | - stp_policy_node_lookup(stm, id); |
|---|
| 1007 | + ids[0] = kstrdup(src->data->name, GFP_KERNEL); |
|---|
| 1008 | + if (!ids[0]) |
|---|
| 1009 | + goto fail_detach; |
|---|
| 844 | 1010 | |
|---|
| 845 | | - kfree(id); |
|---|
| 846 | | - } |
|---|
| 847 | | - |
|---|
| 848 | | - err = stm_output_assign(stm, src->data->nr_chans, |
|---|
| 849 | | - src->policy_node, &src->output); |
|---|
| 850 | | - |
|---|
| 851 | | - if (src->policy_node) |
|---|
| 852 | | - stp_policy_node_put(src->policy_node); |
|---|
| 1011 | + err = stm_assign_first_policy(stm, &src->output, ids, |
|---|
| 1012 | + src->data->nr_chans); |
|---|
| 1013 | + kfree(ids[0]); |
|---|
| 853 | 1014 | |
|---|
| 854 | 1015 | if (err) |
|---|
| 855 | 1016 | goto fail_detach; |
|---|
| .. | .. |
|---|
| 1137 | 1298 | |
|---|
| 1138 | 1299 | stm = srcu_dereference(src->link, &stm_source_srcu); |
|---|
| 1139 | 1300 | if (stm) |
|---|
| 1140 | | - count = stm_write(stm->data, src->output.master, |
|---|
| 1141 | | - src->output.channel + chan, |
|---|
| 1142 | | - buf, count); |
|---|
| 1301 | + count = stm_write(stm, &src->output, chan, buf, count); |
|---|
| 1143 | 1302 | else |
|---|
| 1144 | 1303 | count = -ENODEV; |
|---|
| 1145 | 1304 | |
|---|
| .. | .. |
|---|
| 1166 | 1325 | goto err_src; |
|---|
| 1167 | 1326 | |
|---|
| 1168 | 1327 | init_srcu_struct(&stm_source_srcu); |
|---|
| 1328 | + INIT_LIST_HEAD(&stm_pdrv_head); |
|---|
| 1329 | + mutex_init(&stm_pdrv_mutex); |
|---|
| 1169 | 1330 | |
|---|
| 1331 | + /* |
|---|
| 1332 | + * So as to not confuse existing users with a requirement |
|---|
| 1333 | + * to load yet another module, do it here. |
|---|
| 1334 | + */ |
|---|
| 1335 | + if (IS_ENABLED(CONFIG_STM_PROTO_BASIC)) |
|---|
| 1336 | + (void)request_module_nowait("stm_p_basic"); |
|---|
| 1170 | 1337 | stm_core_up++; |
|---|
| 1171 | 1338 | |
|---|
| 1172 | 1339 | return 0; |
|---|