qcacmn: Handle disconnect ind to kernel for connection manager
Add support in connection manager for disconnect done indication to kernel. Change-Id: Ia4e767a95403de04268ed8c5e424974788c90b17 CRs-Fixed: 2765978
这个提交包含在:
@@ -24,4 +24,22 @@
|
||||
#ifndef __WLAN_CFG80211_CM_RSP_H
|
||||
#define __WLAN_CFG80211_CM_RSP_H
|
||||
|
||||
#include "wlan_objmgr_vdev_obj.h"
|
||||
#include "wlan_cm_public_struct.h"
|
||||
|
||||
/**
|
||||
* osif_disconnect_handler() - Indicate disconnnect to userspace
|
||||
* @vdev: vdev pointer
|
||||
* @rsp: Disconnect response from connection manager
|
||||
*
|
||||
* This function indicates disconnect to the kernel which thus indicates
|
||||
* to the userspace.
|
||||
*
|
||||
* Context: Any context
|
||||
* Return: QDF_STATUS_SUCCESS on successful indication to kernel,
|
||||
* else QDF_STATUS with failure reason
|
||||
*/
|
||||
QDF_STATUS osif_disconnect_handler(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_cm_discon_rsp *rsp);
|
||||
|
||||
#endif /* __WLAN_CFG80211_CM_RSP_H */
|
||||
|
@@ -31,4 +31,33 @@
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
QDF_STATUS osif_cm_register_cb(void);
|
||||
|
||||
/**
|
||||
* osif_cm_reset_id_and_src_no_lock() - Function to resets last
|
||||
* connection manager command id and source in osif
|
||||
* @osif_priv: Pointer to vdev osif priv
|
||||
*
|
||||
* This function resets the last connection manager command id
|
||||
* and source.
|
||||
*
|
||||
* Context: Any context. This function should be called by holding
|
||||
* cmd id spinlock
|
||||
* Return: None
|
||||
*/
|
||||
|
||||
void osif_cm_reset_id_and_src_no_lock(struct vdev_osif_priv *osif_priv);
|
||||
|
||||
/**
|
||||
* osif_cm_reset_id_and_src() - Function to resets last
|
||||
* connection manager command id and source in osif
|
||||
* @vdev: vdev pointer
|
||||
*
|
||||
* This function resets the last connection manager command id
|
||||
* and source.
|
||||
*
|
||||
* Context: Any context. Takes and release cmd id spinlock
|
||||
* Return: None
|
||||
*/
|
||||
QDF_STATUS osif_cm_reset_id_and_src(struct wlan_objmgr_vdev *vdev);
|
||||
|
||||
#endif /* __WLAN_CFG80211_CM_UTIL_H */
|
||||
|
@@ -20,3 +20,109 @@
|
||||
* This file maintains definitaions of disconnect response
|
||||
* fucntions.
|
||||
*/
|
||||
|
||||
#include <wlan_cfg80211.h>
|
||||
#include <linux/wireless.h>
|
||||
#include "wlan_cfg80211_cm_rsp.h"
|
||||
#include "wlan_osif_priv.h"
|
||||
#include "wlan_cfg80211_cm_util.h"
|
||||
|
||||
/**
|
||||
* osif_validate_disconnect_and_reset_src_id() - Validate disconnection
|
||||
* and resets source and id
|
||||
* @osif_priv: Pointer to vdev osif priv
|
||||
* @rsp: Disconnect response from connectin manager
|
||||
*
|
||||
* This function validates disconnect response and if the disconnect
|
||||
* response is valid, resets the source and id of the command
|
||||
*
|
||||
* Context: Any context. Takes and releases cmd id spinlock.
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
|
||||
static QDF_STATUS
|
||||
osif_validate_disconnect_and_reset_src_id(struct vdev_osif_priv *osif_priv,
|
||||
struct wlan_cm_discon_rsp *rsp)
|
||||
{
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
|
||||
/* Always drop internal disconnect */
|
||||
qdf_spinlock_acquire(&osif_priv->last_cmd_info.cmd_id_lock);
|
||||
if (rsp->req.req.source == CM_INTERNAL_DISCONNECT) {
|
||||
osif_debug("ignore internal disconnect");
|
||||
status = QDF_STATUS_E_INVAL;
|
||||
goto rel_lock;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send to kernel only if last osif cmd type is disconnect and
|
||||
* cookie match else drop. If cookie match reset the cookie
|
||||
* and source
|
||||
*/
|
||||
if (rsp->req.cm_id != osif_priv->last_cmd_info.last_id ||
|
||||
rsp->req.req.source != osif_priv->last_cmd_info.last_source) {
|
||||
osif_debug("Ignore as cm_id(%d)/src(%d) didn't match stored cm_id(%d)/src(%d)",
|
||||
rsp->req.cm_id, rsp->req.req.source,
|
||||
osif_priv->last_cmd_info.last_id,
|
||||
osif_priv->last_cmd_info.last_source);
|
||||
status = QDF_STATUS_E_INVAL;
|
||||
goto rel_lock;
|
||||
}
|
||||
|
||||
osif_cm_reset_id_and_src_no_lock(osif_priv);
|
||||
rel_lock:
|
||||
qdf_spinlock_release(&osif_priv->last_cmd_info.cmd_id_lock);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#if defined(CFG80211_DISCONNECTED_V2) || \
|
||||
(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0))
|
||||
static void
|
||||
osif_cm_indicate_disconnect(struct net_device *dev,
|
||||
enum ieee80211_reasoncode reason,
|
||||
bool locally_generated, const u8 *ie,
|
||||
size_t ie_len, gfp_t gfp)
|
||||
{
|
||||
cfg80211_disconnected(dev, reason, ie, ie_len, locally_generated, gfp);
|
||||
}
|
||||
#else
|
||||
static void
|
||||
osif_cm_indicate_disconnect(struct net_device *dev,
|
||||
enum ieee80211_reasoncode reason,
|
||||
bool locally_generated, const u8 *ie,
|
||||
size_t ie_len, gfp_t gfp)
|
||||
{
|
||||
cfg80211_disconnected(dev, reason, ie, ie_len, gfp);
|
||||
}
|
||||
#endif
|
||||
|
||||
QDF_STATUS osif_disconnect_handler(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_cm_discon_rsp *rsp)
|
||||
{
|
||||
enum ieee80211_reasoncode ieee80211_reason = rsp->req.req.reason_code;
|
||||
struct vdev_osif_priv *osif_priv = wlan_vdev_get_ospriv(vdev);
|
||||
bool locally_generated = true;
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
|
||||
osif_info("%s(vdevid-%d): Disconnected, bssid: " QDF_MAC_ADDR_FMT " cm_id %d source %d reason_code %d locally_generated %d",
|
||||
osif_priv->wdev->netdev->name,
|
||||
rsp->req.req.vdev_id,
|
||||
QDF_MAC_ADDR_REF(rsp->req.req.bssid.bytes),
|
||||
rsp->req.cm_id, rsp->req.req.source,
|
||||
rsp->req.req.reason_code,
|
||||
locally_generated);
|
||||
|
||||
status = osif_validate_disconnect_and_reset_src_id(osif_priv, rsp);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
return status;
|
||||
|
||||
if (rsp->req.req.source == CM_PEER_DISCONNECT)
|
||||
locally_generated = false;
|
||||
|
||||
osif_cm_indicate_disconnect(osif_priv->wdev->netdev, ieee80211_reason,
|
||||
locally_generated, rsp->ap_discon_ie.ptr,
|
||||
rsp->ap_discon_ie.len, GFP_KERNEL);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#include "wlan_cm_ucfg_api.h"
|
||||
#include "wlan_nl_to_crypto_params.h"
|
||||
#include <wlan_cfg80211.h>
|
||||
#include "wlan_cfg80211_cm_util.h"
|
||||
|
||||
static void wlan_osif_free_wep_key_params(
|
||||
struct wlan_cm_connect_req *connect_req)
|
||||
@@ -319,6 +320,10 @@ int wlan_osif_cfg80211_connect(struct net_device *dev,
|
||||
|
||||
osif_dump_connect_req(dev, vdev_id, req);
|
||||
|
||||
status = osif_cm_reset_id_and_src(vdev);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
return qdf_status_to_os_return(status);
|
||||
|
||||
connect_req = qdf_mem_malloc(sizeof(*connect_req));
|
||||
if (!connect_req)
|
||||
return -ENOMEM;
|
||||
@@ -398,14 +403,18 @@ int wlan_osif_cfg80211_disconnect(struct net_device *dev,
|
||||
uint8_t vdev_id = vdev->vdev_objmgr.vdev_id;
|
||||
QDF_STATUS status;
|
||||
|
||||
req = qdf_mem_malloc(sizeof(*req));
|
||||
if (!req)
|
||||
return -ENOMEM;
|
||||
|
||||
/* print reason in string */
|
||||
osif_info("%s(vdevid-%d): Received Disconnect reason:%d",
|
||||
dev->name, vdev_id, reason);
|
||||
|
||||
status = osif_cm_reset_id_and_src(vdev);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
return qdf_status_to_os_return(status);
|
||||
|
||||
req = qdf_mem_malloc(sizeof(*req));
|
||||
if (!req)
|
||||
return -ENOMEM;
|
||||
|
||||
req->vdev_id = vdev_id;
|
||||
req->source = CM_OSIF_DISCONNECT;
|
||||
req->reason_code = reason;
|
||||
|
@@ -24,6 +24,28 @@
|
||||
#include "wlan_cfg80211_cm_util.h"
|
||||
#include "wlan_osif_priv.h"
|
||||
#include "wlan_cfg80211.h"
|
||||
#include "wlan_cfg80211_cm_rsp.h"
|
||||
|
||||
void osif_cm_reset_id_and_src_no_lock(struct vdev_osif_priv *osif_priv)
|
||||
{
|
||||
osif_priv->last_cmd_info.last_id = CM_ID_INVALID;
|
||||
osif_priv->last_cmd_info.last_source = CM_SOURCE_INVALID;
|
||||
}
|
||||
|
||||
QDF_STATUS osif_cm_reset_id_and_src(struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
struct vdev_osif_priv *osif_priv = wlan_vdev_get_ospriv(vdev);
|
||||
|
||||
if (!osif_priv) {
|
||||
osif_err("Invalid vdev osif priv");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
qdf_spinlock_acquire(&osif_priv->last_cmd_info.cmd_id_lock);
|
||||
osif_cm_reset_id_and_src_no_lock(osif_priv);
|
||||
qdf_spinlock_release(&osif_priv->last_cmd_info.cmd_id_lock);
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* osif_cm_connect_complete_cb() - Connect complete callback
|
||||
@@ -85,16 +107,17 @@ osif_cm_update_id_and_src_cb(struct wlan_objmgr_vdev *vdev,
|
||||
/**
|
||||
* osif_cm_disconnect_complete_cb() - Disconnect done callback
|
||||
* @vdev: vdev pointer
|
||||
* @cm_disconnect_rsp: Disconnect response
|
||||
* @disconnect_rsp: Disconnect response
|
||||
*
|
||||
* Context: Any context
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
|
||||
static QDF_STATUS
|
||||
osif_cm_disconnect_complete_cb(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_cm_discon_rsp *cm_disconnect_rsp)
|
||||
struct wlan_cm_discon_rsp *rsp)
|
||||
{
|
||||
return QDF_STATUS_SUCCESS;
|
||||
return osif_disconnect_handler(vdev, rsp);
|
||||
}
|
||||
|
||||
/**
|
||||
|
在新工单中引用
屏蔽一个用户