cfg80211: check for and abort dangling scan requests

If you trigger a scan request on an interface and then
take it down, or rmmod the module or unplug the device
the driver might "forget" to cancel the scan request.
That is a bug in the driver, but the current behaviour
is that we just hang endlessly waiting for the netdev
refcount to become 0 which it never will. To improve
robustness, check for this situation in cfg80211, warn
about it and clean up behind the driver. I don't just
clean up silently because it's likely that the driver
also has some internal state it has now leaked.

Additionally, this fixes a locking bug, clearing the
scan_req pointer should be done under the rdev lock.

Finally, we also need to _wait_ for the scan work and
not just abort it since it might be pending and wanting
to do a cleanup.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/net/wireless/core.c b/net/wireless/core.c
index e630648..35d83be 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -601,8 +601,8 @@
 
 	mutex_unlock(&cfg80211_mutex);
 
+	flush_work(&rdev->scan_done_wk);
 	cancel_work_sync(&rdev->conn_work);
-	cancel_work_sync(&rdev->scan_done_wk);
 	kfree(rdev->scan_req);
 	flush_work(&rdev->event_work);
 }
@@ -728,6 +728,13 @@
 #endif
 		break;
 	case NETDEV_UNREGISTER:
+		cfg80211_lock_rdev(rdev);
+
+		if (WARN_ON(rdev->scan_req && rdev->scan_req->dev == dev)) {
+			rdev->scan_req->aborted = true;
+			___cfg80211_scan_done(rdev);
+		}
+
 		mutex_lock(&rdev->devlist_mtx);
 		/*
 		 * It is possible to get NETDEV_UNREGISTER
@@ -746,6 +753,7 @@
 #endif
 		}
 		mutex_unlock(&rdev->devlist_mtx);
+		cfg80211_unlock_rdev(rdev);
 		break;
 	case NETDEV_PRE_UP:
 		if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))