diff options
Diffstat (limited to 'net/ax25/af_ax25.c')
-rw-r--r-- | net/ax25/af_ax25.c | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index ecb14ee00498..b4725ff317c0 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c | |||
@@ -87,10 +87,22 @@ static void ax25_kill_by_device(struct net_device *dev) | |||
87 | return; | 87 | return; |
88 | 88 | ||
89 | spin_lock_bh(&ax25_list_lock); | 89 | spin_lock_bh(&ax25_list_lock); |
90 | again: | ||
90 | ax25_for_each(s, node, &ax25_list) { | 91 | ax25_for_each(s, node, &ax25_list) { |
91 | if (s->ax25_dev == ax25_dev) { | 92 | if (s->ax25_dev == ax25_dev) { |
92 | s->ax25_dev = NULL; | 93 | s->ax25_dev = NULL; |
94 | spin_unlock_bh(&ax25_list_lock); | ||
93 | ax25_disconnect(s, ENETUNREACH); | 95 | ax25_disconnect(s, ENETUNREACH); |
96 | spin_lock_bh(&ax25_list_lock); | ||
97 | |||
98 | /* The entry could have been deleted from the | ||
99 | * list meanwhile and thus the next pointer is | ||
100 | * no longer valid. Play it safe and restart | ||
101 | * the scan. Forward progress is ensured | ||
102 | * because we set s->ax25_dev to NULL and we | ||
103 | * are never passed a NULL 'dev' argument. | ||
104 | */ | ||
105 | goto again; | ||
94 | } | 106 | } |
95 | } | 107 | } |
96 | spin_unlock_bh(&ax25_list_lock); | 108 | spin_unlock_bh(&ax25_list_lock); |