summaryrefslogtreecommitdiff
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorDmitry Shmidt <dimitrysh@google.com>2011-12-16 12:54:51 -0800
committerOm Prakash Singh <omp@nvidia.com>2012-06-15 14:15:11 +0530
commit7329d57bb986d6a290076e3abdc105c2037288c6 (patch)
tree47b7a49b88cddeb85a0147bcf38f3d88cb010926 /drivers/net/wireless
parent95f2a420420a36d42b3be4eb59d0cdd376873f69 (diff)
net: wireless: bcmdhd: Fix P2P interface removal
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux.c3
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.c43
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.h9
3 files changed, 42 insertions, 13 deletions
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c
index f41a284ca37d..32dcc079ade3 100644
--- a/drivers/net/wireless/bcmdhd/dhd_linux.c
+++ b/drivers/net/wireless/bcmdhd/dhd_linux.c
@@ -1033,6 +1033,9 @@ dhd_op_if(dhd_if_t *ifp)
if (ret < 0) {
ifp->set_multicast = FALSE;
if (ifp->net) {
+#ifdef WL_CFG80211
+ wl_cfg80211_post_del((void*)(ifp->net));
+#endif
free_netdev(ifp->net);
}
dhd->iflist[ifp->idx] = NULL;
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
index 07200221ff12..11f14bba3167 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
@@ -16,7 +16,7 @@
* the license of that module. An independent module is a module which is not
* derived from this software. The special exception does not apply to any
* modifications of the software.
- *
+ *
* Notwithstanding the above, under no circumstances may you combine this
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
@@ -589,7 +589,7 @@ static const u32 __wl_cipher_suites[] = {
WLAN_CIPHER_SUITE_WEP104,
WLAN_CIPHER_SUITE_TKIP,
WLAN_CIPHER_SUITE_CCMP,
- WLAN_CIPHER_SUITE_AES_CMAC,
+ WLAN_CIPHER_SUITE_AES_CMAC
};
/* There isn't a lot of sense in it, but you can transmit anything you like */
@@ -844,8 +844,10 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
wl_set_p2p_status(wl, IF_ADD);
err = wl_cfgp2p_ifadd(wl, &wl->p2p->int_addr, htod32(wlif_type), chspec);
- if (unlikely(err))
+ if (unlikely(err)) {
+ WL_ERR((" virtual iface add failed (%d) \n", err));
return ERR_PTR(-ENOMEM);
+ }
timeout = wait_event_interruptible_timeout(wl->dongle_event_wait,
(wl_get_p2p_status(wl, IF_ADD) == false),
@@ -860,7 +862,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
}
vwdev->wiphy = wl->wdev->wiphy;
WL_INFO((" virtual interface(%s) is created memalloc done \n",
- wl->p2p->vir_ifname));
+ wl->p2p->vir_ifname));
index = alloc_idx_vwdev(wl);
wl->vwdev[index] = vwdev;
vwdev->iftype =
@@ -873,6 +875,8 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
wl_set_drv_status(wl, READY);
wl->p2p->vif_created = true;
set_mode_by_netdev(wl, _ndev, mode);
+ WL_DBG((" virtual interface(%s) wl->wdev %p wl->wdev->netdev %p vwdev %p vwdev->netdev %p\n",
+ wl->p2p->vir_ifname, wl->wdev, wl->wdev->netdev, vwdev, vwdev->netdev));
net_attach = wl_to_p2p_bss_private(wl, P2PAPI_BSSCFG_CONNECTION);
if (rtnl_is_locked()) {
rtnl_unlock();
@@ -927,10 +931,14 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev)
* ifconfig <inter> down and up sequnce, which will reload the fw
* however we should cleanup the linux network virtual interfaces
*/
- dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
- WL_ERR(("Firmware returned an error from p2p_ifdel\n"));
- WL_ERR(("try to remove linux virtual interface %s\n", dev->name));
- dhd_del_if(dhd->info, dhd_net2idx(dhd->info, dev));
+ /* Request framework to RESET and clean up */
+ struct net_device *ndev = wl_to_prmry_ndev(wl);
+ WL_ERR(("Firmware returned an error (%d) from p2p_ifdel"
+ "HANG Notification sent to %s dev %p wdev %p ndev %p\n", ret, ndev->name, dev, wl->wdev, wl_to_prmry_ndev(wl)));
+ wl_cfg80211_hang(ndev, WLAN_REASON_UNSPECIFIED);
+ }
+ else {
+ WL_ERR(("Firmware success from p2p_ifdel dev %p wdev %p ndev %p", dev, wl->wdev, wl_to_prmry_ndev(wl)));
}
/* Wait for any pending scan req to get aborted from the sysioc context */
@@ -1035,7 +1043,7 @@ int (*_net_attach)(dhd_pub_t *dhdp, int ifidx))
WL_ERR(("net is NULL\n"));
return 0;
}
- if (wl->p2p_supported) {
+ if (wl->p2p_supported && wl_get_p2p_status(wl, IF_ADD)) {
WL_DBG(("IF_ADD event called from dongle, old interface name: %s,"
"new name: %s\n", ndev->name, wl->p2p->vir_ifname));
/* Assign the net device to CONNECT BSSCFG */
@@ -1047,6 +1055,8 @@ int (*_net_attach)(dhd_pub_t *dhdp, int ifidx))
wl_clr_p2p_status(wl, IF_ADD);
wake_up_interruptible(&wl->dongle_event_wait);
+ } else {
+ ret = BCME_NOTREADY;
}
return ret;
}
@@ -1063,7 +1073,8 @@ wl_cfg80211_notify_ifdel(struct net_device *ndev)
return 0;
}
- if (p2p_is_on(wl) && wl->p2p->vif_created) {
+ if (p2p_is_on(wl) && wl->p2p->vif_created &&
+ wl_get_p2p_status(wl, IF_DELETING)) {
if (wl->scan_request) {
/* Abort any pending scan requests */
wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
@@ -1096,6 +1107,18 @@ wl_cfg80211_notify_ifdel(struct net_device *ndev)
return 0;
}
+s32 wl_cfg80211_post_del(void* ndev)
+{
+ int index;
+ struct wl_priv *wl = wlcfg_drv_priv;
+ index = get_idx_vwdev_by_netdev(wl, (struct net_device *)ndev);
+ WL_DBG(("index : %d\n", index));
+ if (index >= 0) {
+ free_vwdev_by_index(wl, index);
+ }
+ return 0;
+}
+
s32
wl_cfg80211_is_progress_ifadd(void)
{
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
index 262335ef99c2..232db1b1f830 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
@@ -2,13 +2,13 @@
* Linux cfg80211 driver
*
* Copyright (C) 1999-2011, Broadcom Corporation
- *
+ *
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
* under the terms of the GNU General Public License version 2 (the "GPL"),
* available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
- *
+ *
* As a special exception, the copyright holders of this software give you
* permission to link this software with independent modules, and to copy and
* distribute the resulting executable under terms of your choice, provided that
@@ -16,7 +16,7 @@
* the license of that module. An independent module is a module which is not
* derived from this software. The special exception does not apply to any
* modifications of the software.
- *
+ *
* Notwithstanding the above, under no circumstances may you combine this
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
@@ -452,6 +452,7 @@ static inline s32 alloc_idx_vwdev(struct wl_priv *wl)
if (wl->vwdev[i] == NULL)
return i;
}
+ WL_ERR((" *********alloc_idx_vwdev failed (%d) \n", -1));
return -1;
}
@@ -462,6 +463,7 @@ static inline s32 get_idx_vwdev_by_netdev(struct wl_priv *wl, struct net_device
if ((wl->vwdev[i] != NULL) && (wl->vwdev[i]->netdev == ndev))
return i;
}
+ WL_ERR((" *********get_idx_vwdev_by_netdev failed (%d) \n", -1));
return -1;
}
@@ -531,6 +533,7 @@ extern s32 wl_cfg80211_down(void); /* dongle down */
extern s32 wl_cfg80211_notify_ifadd(struct net_device *net, s32 idx, s32 bssidx,
int (*_net_attach)(dhd_pub_t *dhdp, int ifidx));
extern s32 wl_cfg80211_notify_ifdel(struct net_device *ndev);
+extern s32 wl_cfg80211_post_del(void *ndev);
extern s32 wl_cfg80211_is_progress_ifadd(void);
extern s32 wl_cfg80211_is_progress_ifchange(void);
extern s32 wl_cfg80211_is_progress_ifadd(void);