wiphy_lock(&rdev->wiphy);
                        cfg80211_leave(rdev, wdev);
-                       rdev_del_virtual_intf(rdev, wdev);
+                       cfg80211_remove_virtual_intf(rdev, wdev);
                        wiphy_unlock(&rdev->wiphy);
                }
        }
        case NETDEV_GOING_DOWN:
                wiphy_lock(&rdev->wiphy);
                cfg80211_leave(rdev, wdev);
+               cfg80211_remove_links(wdev);
                wiphy_unlock(&rdev->wiphy);
                break;
        case NETDEV_DOWN:
 
 void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev);
 void cfg80211_pmsr_free_wk(struct work_struct *work);
 
+void cfg80211_remove_link(struct wireless_dev *wdev, unsigned int link_id);
+void cfg80211_remove_links(struct wireless_dev *wdev);
+int cfg80211_remove_virtual_intf(struct cfg80211_registered_device *rdev,
+                                struct wireless_dev *wdev);
+
 #endif /* __NET_WIRELESS_CORE_H */
 
 
        mutex_lock(&rdev->wiphy.mtx);
 
-       return rdev_del_virtual_intf(rdev, wdev);
+       return cfg80211_remove_virtual_intf(rdev, wdev);
 }
 
 static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info)
 
 static int nl80211_remove_link(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *rdev = info->user_ptr[0];
        unsigned int link_id = nl80211_link_id(info->attrs);
        struct net_device *dev = info->user_ptr[1];
        struct wireless_dev *wdev = dev->ieee80211_ptr;
                return -EINVAL;
        }
 
-       /* FIXME: stop the link operations first */
-
        wdev_lock(wdev);
-       wdev->valid_links &= ~BIT(link_id);
-
-       rdev_del_intf_link(rdev, wdev, link_id);
-
-       eth_zero_addr(wdev->links[link_id].addr);
+       cfg80211_remove_link(wdev, link_id);
        wdev_unlock(wdev);
 
        return 0;
 
        return false;
 }
 EXPORT_SYMBOL(cfg80211_iftype_allowed);
+
+void cfg80211_remove_link(struct wireless_dev *wdev, unsigned int link_id)
+{
+       struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
+
+       ASSERT_WDEV_LOCK(wdev);
+
+       switch (wdev->iftype) {
+       case NL80211_IFTYPE_AP:
+       case NL80211_IFTYPE_P2P_GO:
+               __cfg80211_stop_ap(rdev, wdev->netdev, link_id, true);
+               break;
+       default:
+               /* per-link not relevant */
+               break;
+       }
+
+       wdev->valid_links &= ~BIT(link_id);
+
+       rdev_del_intf_link(rdev, wdev, link_id);
+
+       eth_zero_addr(wdev->links[link_id].addr);
+}
+
+void cfg80211_remove_links(struct wireless_dev *wdev)
+{
+       unsigned int link_id;
+
+       wdev_lock(wdev);
+       if (wdev->valid_links) {
+               for_each_valid_link(wdev, link_id)
+                       cfg80211_remove_link(wdev, link_id);
+       }
+       wdev_unlock(wdev);
+}
+
+int cfg80211_remove_virtual_intf(struct cfg80211_registered_device *rdev,
+                                struct wireless_dev *wdev)
+{
+       cfg80211_remove_links(wdev);
+
+       return rdev_del_virtual_intf(rdev, wdev);
+}