[PATCH 5.7 056/112] hsr: remove hsr interface if all slaves are removed

Greg Kroah-Hartman
2020-07-07T15:25:01Z

From: Taehee Yoo <ap420073@gmail.com>

[ Upstream commit 34a9c361dd480041d790fff3d6ea58513c8769e8 ]

When all hsr slave interfaces are removed, hsr interface doesn't work.
At that moment, it's fine to remove an unused hsr interface automatically
for saving resources.
That's a common behavior of virtual interfaces.

Signed-off-by: Taehee Yoo <ap420073@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/hsr/hsr_main.c | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/net/hsr/hsr_main.c b/net/hsr/hsr_main.c
index 26d6c39f24e16..e2564de676038 100644
--- a/net/hsr/hsr_main.c
+++ b/net/hsr/hsr_main.c
@@ -15,12 +15,23 @@
#include "hsr_framereg.h"
#include "hsr_slave.h"

+static bool hsr_slave_empty(struct hsr_priv *hsr)
+{
+ struct hsr_port *port;
+
+ hsr_for_each_port(hsr, port)
+ if (port->type != HSR_PT_MASTER)
+ return false;
+ return true;
+}
+
static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event,
void *ptr)
{
- struct net_device *dev;
struct hsr_port *port, *master;
+ struct net_device *dev;
struct hsr_priv *hsr;
+ LIST_HEAD(list_kill);
int mtu_max;
int res;

@@ -85,8 +96,15 @@ static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event,
master->dev->mtu = mtu_max;
break;
case NETDEV_UNREGISTER:
- if (!is_hsr_master(dev))
+ if (!is_hsr_master(dev)) {
+ master = hsr_port_get_hsr(port->hsr, HSR_PT_MASTER);
hsr_del_port(port);
+ if (hsr_slave_empty(master->hsr)) {
+ unregister_netdevice_queue(master->dev,
+ &list_kill);
+ unregister_netdevice_many(&list_kill);
+ }
+ }
break;
case NETDEV_PRE_TYPE_CHANGE:
/* HSR works only on Ethernet devices. Refuse slave to change
--
2.25.1