| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * IEEE 802.1Q Multiple Registration Protocol (MRP) |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 5 | 6 | * |
|---|
| 6 | 7 | * Adapted from code in net/802/garp.c |
|---|
| 7 | 8 | * Copyright (c) 2008 Patrick McHardy <kaber@trash.net> |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is free software; you can redistribute it and/or |
|---|
| 10 | | - * modify it under the terms of the GNU General Public License |
|---|
| 11 | | - * version 2 as published by the Free Software Foundation. |
|---|
| 12 | 9 | */ |
|---|
| 13 | 10 | #include <linux/kernel.h> |
|---|
| 14 | 11 | #include <linux/timer.h> |
|---|
| .. | .. |
|---|
| 539 | 536 | struct mrp_attr *attr; |
|---|
| 540 | 537 | |
|---|
| 541 | 538 | if (sizeof(struct mrp_skb_cb) + len > |
|---|
| 542 | | - FIELD_SIZEOF(struct sk_buff, cb)) |
|---|
| 539 | + sizeof_field(struct sk_buff, cb)) |
|---|
| 543 | 540 | return -ENOMEM; |
|---|
| 544 | 541 | |
|---|
| 545 | 542 | spin_lock_bh(&app->lock); |
|---|
| .. | .. |
|---|
| 564 | 561 | struct mrp_attr *attr; |
|---|
| 565 | 562 | |
|---|
| 566 | 563 | if (sizeof(struct mrp_skb_cb) + len > |
|---|
| 567 | | - FIELD_SIZEOF(struct sk_buff, cb)) |
|---|
| 564 | + sizeof_field(struct sk_buff, cb)) |
|---|
| 568 | 565 | return; |
|---|
| 569 | 566 | |
|---|
| 570 | 567 | spin_lock_bh(&app->lock); |
|---|
| .. | .. |
|---|
| 609 | 606 | spin_unlock(&app->lock); |
|---|
| 610 | 607 | |
|---|
| 611 | 608 | mrp_queue_xmit(app); |
|---|
| 612 | | - mrp_join_timer_arm(app); |
|---|
| 609 | + spin_lock(&app->lock); |
|---|
| 610 | + if (likely(app->active)) |
|---|
| 611 | + mrp_join_timer_arm(app); |
|---|
| 612 | + spin_unlock(&app->lock); |
|---|
| 613 | 613 | } |
|---|
| 614 | 614 | |
|---|
| 615 | 615 | static void mrp_periodic_timer_arm(struct mrp_applicant *app) |
|---|
| .. | .. |
|---|
| 623 | 623 | struct mrp_applicant *app = from_timer(app, t, periodic_timer); |
|---|
| 624 | 624 | |
|---|
| 625 | 625 | spin_lock(&app->lock); |
|---|
| 626 | | - mrp_mad_event(app, MRP_EVENT_PERIODIC); |
|---|
| 627 | | - mrp_pdu_queue(app); |
|---|
| 626 | + if (likely(app->active)) { |
|---|
| 627 | + mrp_mad_event(app, MRP_EVENT_PERIODIC); |
|---|
| 628 | + mrp_pdu_queue(app); |
|---|
| 629 | + mrp_periodic_timer_arm(app); |
|---|
| 630 | + } |
|---|
| 628 | 631 | spin_unlock(&app->lock); |
|---|
| 629 | | - |
|---|
| 630 | | - mrp_periodic_timer_arm(app); |
|---|
| 631 | 632 | } |
|---|
| 632 | 633 | |
|---|
| 633 | 634 | static int mrp_pdu_parse_end_mark(struct sk_buff *skb, int *offset) |
|---|
| .. | .. |
|---|
| 708 | 709 | * advance to the next event in its Vector. |
|---|
| 709 | 710 | */ |
|---|
| 710 | 711 | if (sizeof(struct mrp_skb_cb) + mrp_cb(skb)->mh->attrlen > |
|---|
| 711 | | - FIELD_SIZEOF(struct sk_buff, cb)) |
|---|
| 712 | + sizeof_field(struct sk_buff, cb)) |
|---|
| 712 | 713 | return -1; |
|---|
| 713 | 714 | if (skb_copy_bits(skb, *offset, mrp_cb(skb)->attrvalue, |
|---|
| 714 | 715 | mrp_cb(skb)->mh->attrlen) < 0) |
|---|
| .. | .. |
|---|
| 875 | 876 | app->dev = dev; |
|---|
| 876 | 877 | app->app = appl; |
|---|
| 877 | 878 | app->mad = RB_ROOT; |
|---|
| 879 | + app->active = true; |
|---|
| 878 | 880 | spin_lock_init(&app->lock); |
|---|
| 879 | 881 | skb_queue_head_init(&app->queue); |
|---|
| 880 | 882 | rcu_assign_pointer(dev->mrp_port->applicants[appl->type], app); |
|---|
| .. | .. |
|---|
| 903 | 905 | |
|---|
| 904 | 906 | RCU_INIT_POINTER(port->applicants[appl->type], NULL); |
|---|
| 905 | 907 | |
|---|
| 908 | + spin_lock_bh(&app->lock); |
|---|
| 909 | + app->active = false; |
|---|
| 910 | + spin_unlock_bh(&app->lock); |
|---|
| 906 | 911 | /* Delete timer and generate a final TX event to flush out |
|---|
| 907 | 912 | * all pending messages before the applicant is gone. |
|---|
| 908 | 913 | */ |
|---|