qcacmn: Action frame random mac addr tx support

1. Send add random mac addr rx filter WMI command
to target
2. Add/Del the active random mac addr entry
3. Clear random mac addr from target if not active

Change-Id: I9dcbdc20b76d9865da7a8db6ee013bf5e44e4407
CRs-Fixed: 2322097
Цей коміт міститься в:
Liangwei Dong
2018-09-19 23:35:14 -04:00
зафіксовано nshrivas
джерело e159d1434f
коміт cc8676b6a8
19 змінених файлів з 1566 додано та 8 видалено

Переглянути файл

@@ -495,5 +495,5 @@ int wlan_cfg80211_mgmt_tx_cancel(struct wlan_objmgr_vdev *vdev,
}
return qdf_status_to_os_return(
ucfg_p2p_mgmt_tx_cancel(psoc, cookie));
ucfg_p2p_mgmt_tx_cancel(psoc, vdev, cookie));
}

Переглянути файл

@@ -368,6 +368,87 @@ QDF_STATUS target_if_p2p_set_noa(struct wlan_objmgr_psoc *psoc,
return wmi_unified_vdev_set_param_send(wmi_handle, &param);
}
static int target_p2p_mac_rx_filter_event_handler(ol_scn_t scn, uint8_t *data,
uint32_t datalen)
{
struct wlan_objmgr_psoc *psoc;
struct wmi_unified *wmi_handle;
struct p2p_set_mac_filter_evt event_info;
struct wlan_lmac_if_p2p_rx_ops *p2p_rx_ops;
QDF_STATUS status = QDF_STATUS_E_FAILURE;
if (!scn || !data) {
target_if_err("scn: 0x%pK, data: 0x%pK", scn, data);
return -EINVAL;
}
psoc = target_if_get_psoc_from_scn_hdl(scn);
if (!psoc) {
target_if_err("null psoc");
return -EINVAL;
}
wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
if (!wmi_handle) {
target_if_err("null wmi handle");
return -EINVAL;
}
if (wmi_extract_mac_addr_rx_filter_evt_param(wmi_handle, data,
&event_info)) {
target_if_err("failed to extract wmi p2p noa event");
return -EINVAL;
}
target_if_debug("vdev_id %d status %d", event_info.vdev_id,
event_info.status);
p2p_rx_ops = target_if_psoc_get_p2p_rx_ops(psoc);
if (p2p_rx_ops && p2p_rx_ops->add_mac_addr_filter_evt_handler)
status = p2p_rx_ops->add_mac_addr_filter_evt_handler(
psoc, &event_info);
else
target_if_debug("no add mac addr filter event handler");
return qdf_status_to_os_return(status);
}
static QDF_STATUS target_if_p2p_register_macaddr_rx_filter_evt_handler(
struct wlan_objmgr_psoc *psoc, bool reg)
{
int status;
wmi_unified_t wmi_handle = lmac_get_wmi_unified_hdl(psoc);
target_if_debug("psoc:%pK, register %d mac addr rx evt", psoc, reg);
if (!wmi_handle) {
target_if_err("Invalid wmi handle");
return QDF_STATUS_E_INVAL;
}
if (reg)
status = wmi_unified_register_event(
wmi_handle,
wmi_vdev_add_macaddr_rx_filter_event_id,
target_p2p_mac_rx_filter_event_handler);
else
status = wmi_unified_unregister_event(
wmi_handle,
wmi_vdev_add_macaddr_rx_filter_event_id);
return status == 0 ? QDF_STATUS_SUCCESS : QDF_STATUS_E_FAILURE;
}
static QDF_STATUS target_if_p2p_set_mac_addr_rx_filter_cmd(
struct wlan_objmgr_psoc *psoc, struct p2p_set_mac_filter *param)
{
wmi_unified_t wmi_handle = lmac_get_wmi_unified_hdl(psoc);
if (!wmi_handle) {
target_if_err("Invalid wmi handle");
return QDF_STATUS_E_INVAL;
}
return wmi_send_set_mac_addr_rx_filter_cmd(wmi_handle, param);
}
void target_if_p2p_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
{
struct wlan_lmac_if_p2p_tx_ops *p2p_tx_ops;
@@ -384,6 +465,10 @@ void target_if_p2p_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
target_if_p2p_register_noa_event_handler;
p2p_tx_ops->unreg_noa_ev_handler =
target_if_p2p_unregister_noa_event_handler;
p2p_tx_ops->reg_mac_addr_rx_filter_handler =
target_if_p2p_register_macaddr_rx_filter_evt_handler;
p2p_tx_ops->set_mac_addr_rx_filter_cmd =
target_if_p2p_set_mac_addr_rx_filter_cmd;
/* register P2P listen offload callbacks */
target_if_p2p_lo_register_tx_ops(p2p_tx_ops);
}

Переглянути файл

@@ -201,6 +201,7 @@ struct wlan_lmac_if_scan_rx_ops {
/* forward declarations for p2p tx ops */
struct p2p_ps_config;
struct p2p_lo_start;
struct p2p_set_mac_filter;
/**
* struct wlan_lmac_if_p2p_tx_ops - structure of tx function pointers
@@ -213,6 +214,9 @@ struct p2p_lo_start;
* @reg_noa_ev_handler: function pointer to register noa event handler
* @unreg_lo_ev_handler: function pointer to unregister lo event handler
* @unreg_noa_ev_handler:function pointer to unregister noa event handler
* @reg_mac_addr_rx_filter_handler: function pointer to register/unregister
* set mac addr status event callback.
* @set_mac_addr_rx_filter_cmd: function pointer to set mac addr rx filter
*/
struct wlan_lmac_if_p2p_tx_ops {
QDF_STATUS (*set_ps)(struct wlan_objmgr_psoc *psoc,
@@ -233,6 +237,11 @@ struct wlan_lmac_if_p2p_tx_ops {
void *arg);
QDF_STATUS (*unreg_noa_ev_handler)(struct wlan_objmgr_psoc *psoc,
void *arg);
QDF_STATUS (*reg_mac_addr_rx_filter_handler)(
struct wlan_objmgr_psoc *psoc, bool reg);
QDF_STATUS (*set_mac_addr_rx_filter_cmd)(
struct wlan_objmgr_psoc *psoc,
struct p2p_set_mac_filter *param);
};
#endif
@@ -829,12 +838,15 @@ struct wlan_lmac_if_reg_rx_ops {
/* forward declarations for p2p rx ops */
struct p2p_noa_info;
struct p2p_lo_event;
struct p2p_set_mac_filter_evt;
/**
* struct wlan_lmac_if_p2p_rx_ops - structure of rx function pointers
* for P2P component
* @lo_ev_handler: function pointer to give listen offload event
* @noa_ev_handler: function pointer to give noa event
* @add_mac_addr_filter_evt_handler: function pointer to process add mac addr
* rx filter event
*/
struct wlan_lmac_if_p2p_rx_ops {
#ifdef FEATURE_P2P_LISTEN_OFFLOAD
@@ -843,6 +855,10 @@ struct wlan_lmac_if_p2p_rx_ops {
#endif
QDF_STATUS (*noa_ev_handler)(struct wlan_objmgr_psoc *psoc,
struct p2p_noa_info *event_info);
QDF_STATUS (*add_mac_addr_filter_evt_handler)(
struct wlan_objmgr_psoc *psoc,
struct p2p_set_mac_filter_evt *event_info);
};
#endif

Переглянути файл

@@ -298,12 +298,16 @@ static void wlan_lmac_if_umac_rx_ops_register_p2p(
{
rx_ops->p2p.lo_ev_handler = tgt_p2p_lo_event_cb;
rx_ops->p2p.noa_ev_handler = tgt_p2p_noa_event_cb;
rx_ops->p2p.add_mac_addr_filter_evt_handler =
tgt_p2p_add_mac_addr_status_event_cb;
}
#else
static void wlan_lmac_if_umac_rx_ops_register_p2p(
struct wlan_lmac_if_rx_ops *rx_ops)
{
rx_ops->p2p.noa_ev_handler = tgt_p2p_noa_event_cb;
rx_ops->p2p.add_mac_addr_filter_evt_handler =
tgt_p2p_add_mac_addr_status_event_cb;
}
#endif
#else

Переглянути файл

@@ -59,6 +59,8 @@ static char *p2p_get_cmd_type_str(enum p2p_cmd_type cmd_type)
return "P2P cleanup roc";
case P2P_CLEANUP_TX:
return "P2P cleanup tx";
case P2P_SET_RANDOM_MAC:
return "P2P set random mac";
default:
return "Invalid P2P command";
}
@@ -85,6 +87,8 @@ static char *p2p_get_event_type_str(enum p2p_event_type event_type)
return "P2P lo stop event";
case P2P_EVENT_NOA:
return "P2P noa event";
case P2P_EVENT_ADD_MAC_RSP:
return "P2P add mac filter resp event";
default:
return "Invalid P2P event";
}
@@ -202,8 +206,12 @@ static QDF_STATUS p2p_vdev_obj_create_notification(
mode = wlan_vdev_mlme_get_opmode(vdev);
p2p_debug("vdev mode:%d", mode);
if (mode != QDF_P2P_GO_MODE) {
p2p_debug("won't create p2p vdev private object if it is not GO");
if (mode != QDF_P2P_GO_MODE &&
mode != QDF_STA_MODE &&
mode != QDF_P2P_CLIENT_MODE &&
mode != QDF_P2P_DEVICE_MODE) {
p2p_debug("won't create p2p vdev private object for mode %d",
mode);
return QDF_STATUS_SUCCESS;
}
@@ -217,11 +225,13 @@ static QDF_STATUS p2p_vdev_obj_create_notification(
p2p_vdev_obj->vdev = vdev;
p2p_vdev_obj->noa_status = true;
p2p_vdev_obj->non_p2p_peer_count = 0;
p2p_init_random_mac_vdev(p2p_vdev_obj);
status = wlan_objmgr_vdev_component_obj_attach(vdev,
WLAN_UMAC_COMP_P2P, p2p_vdev_obj,
QDF_STATUS_SUCCESS);
if (status != QDF_STATUS_SUCCESS) {
p2p_deinit_random_mac_vdev(p2p_vdev_obj);
qdf_mem_free(p2p_vdev_obj);
p2p_err("Failed to attach p2p component to vdev, %d",
status);
@@ -257,8 +267,11 @@ static QDF_STATUS p2p_vdev_obj_destroy_notification(
mode = wlan_vdev_mlme_get_opmode(vdev);
p2p_debug("vdev mode:%d", mode);
if (mode != QDF_P2P_GO_MODE) {
p2p_debug("no p2p vdev private object if it is not GO");
if (mode != QDF_P2P_GO_MODE &&
mode != QDF_STA_MODE &&
mode != QDF_P2P_CLIENT_MODE &&
mode != QDF_P2P_DEVICE_MODE){
p2p_debug("no p2p vdev private object for mode %d", mode);
return QDF_STATUS_SUCCESS;
}
@@ -268,6 +281,7 @@ static QDF_STATUS p2p_vdev_obj_destroy_notification(
p2p_debug("p2p vdev object is NULL");
return QDF_STATUS_SUCCESS;
}
p2p_deinit_random_mac_vdev(p2p_vdev_obj);
p2p_vdev_obj->vdev = NULL;
@@ -313,6 +327,10 @@ static QDF_STATUS p2p_peer_obj_create_notification(
}
vdev = wlan_peer_get_vdev(peer);
mode = wlan_vdev_mlme_get_opmode(vdev);
if (mode != QDF_P2P_GO_MODE)
return QDF_STATUS_SUCCESS;
p2p_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(vdev,
WLAN_UMAC_COMP_P2P);
peer_type = wlan_peer_get_peer_type(peer);
@@ -356,6 +374,10 @@ static QDF_STATUS p2p_peer_obj_destroy_notification(
}
vdev = wlan_peer_get_vdev(peer);
mode = wlan_vdev_mlme_get_opmode(vdev);
if (mode != QDF_P2P_GO_MODE)
return QDF_STATUS_SUCCESS;
p2p_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(vdev,
WLAN_UMAC_COMP_P2P);
psoc = wlan_vdev_get_psoc(vdev);
@@ -842,6 +864,7 @@ QDF_STATUS p2p_psoc_start(struct wlan_objmgr_psoc *soc,
/* register p2p lo stop and noa event */
tgt_p2p_register_lo_ev_handler(soc);
tgt_p2p_register_noa_ev_handler(soc);
tgt_p2p_register_macaddr_rx_filter_evt_handler(soc, true);
/* register scan request id */
p2p_soc_obj->scan_req_id = ucfg_scan_register_requester(
@@ -892,6 +915,7 @@ QDF_STATUS p2p_psoc_stop(struct wlan_objmgr_psoc *soc)
ucfg_scan_unregister_requester(soc, p2p_soc_obj->scan_req_id);
/* unregister p2p lo stop and noa event */
tgt_p2p_register_macaddr_rx_filter_evt_handler(soc, false);
tgt_p2p_unregister_lo_ev_handler(soc);
tgt_p2p_unregister_noa_ev_handler(soc);
@@ -954,6 +978,11 @@ QDF_STATUS p2p_process_cmd(struct scheduler_msg *msg)
msg->bodyptr);
qdf_mem_free(msg->bodyptr);
break;
case P2P_SET_RANDOM_MAC:
status = p2p_process_set_rand_mac(msg->bodyptr);
qdf_mem_free(msg->bodyptr);
break;
default:
p2p_err("drop unexpected message received %d",
msg->type);
@@ -997,6 +1026,11 @@ QDF_STATUS p2p_process_evt(struct scheduler_msg *msg)
(struct p2p_noa_event *)
msg->bodyptr);
break;
case P2P_EVENT_ADD_MAC_RSP:
status = p2p_process_set_rand_mac_rsp(
(struct p2p_mac_filter_rsp *)
msg->bodyptr);
break;
default:
p2p_err("Drop unexpected message received %d",
msg->type);

Переглянути файл

@@ -34,6 +34,7 @@
#define P2P_NOA_ATTR_IND 0x1090
#define P2P_MODULE_NAME "P2P"
#define P2P_INVALID_VDEV_ID 0xFFFFFFFF
#define MAX_RANDOM_MAC_ADDRS 4
#define p2p_debug(params ...) \
QDF_TRACE_DEBUG(QDF_MODULE_ID_P2P, params)
@@ -73,6 +74,7 @@ struct tx_action_context;
* @P2P_MGMT_TX_CANCEL: Cancel tx action frame request
* @P2P_CLEANUP_ROC: Cleanup roc queue
* @P2P_CLEANUP_TX: Cleanup tx mgmt queue
* @P2P_SET_RANDOM_MAC: Set Random MAC addr filter request
*/
enum p2p_cmd_type {
P2P_ROC_REQ = 0,
@@ -81,6 +83,7 @@ enum p2p_cmd_type {
P2P_MGMT_TX_CANCEL,
P2P_CLEANUP_ROC,
P2P_CLEANUP_TX,
P2P_SET_RANDOM_MAC,
};
/**
@@ -90,6 +93,7 @@ enum p2p_cmd_type {
* @P2P_EVENT_RX_MGMT: P2P rx mgmt frame
* @P2P_EVENT_LO_STOPPED: P2P listen offload stopped event
* @P2P_EVENT_NOA: P2P noa event
* @P2P_EVENT_ADD_MAC_RSP: Set Random MAC addr event
*/
enum p2p_event_type {
P2P_EVENT_SCAN_EVENT = 0,
@@ -97,6 +101,7 @@ enum p2p_event_type {
P2P_EVENT_RX_MGMT,
P2P_EVENT_LO_STOPPED,
P2P_EVENT_NOA,
P2P_EVENT_ADD_MAC_RSP,
};
/**
@@ -141,6 +146,18 @@ struct p2p_noa_event {
struct p2p_noa_info *noa_info;
};
/**
* struct p2p_mac_filter_rsp - p2p set mac filter respone
* @p2p_soc_obj: p2p soc private object
* @vdev_id: vdev id
* @status: successfully(1) or not (0)
*/
struct p2p_mac_filter_rsp {
struct p2p_soc_priv_obj *p2p_soc_obj;
uint32_t vdev_id;
uint32_t status;
};
#ifdef WLAN_FEATURE_P2P_DEBUG
/**
* enum p2p_connection_status - p2p connection status
@@ -224,18 +241,92 @@ struct p2p_soc_priv_obj {
#endif
};
/**
* struct action_frame_cookie - Action frame cookie item in cookie list
* @cookie_node: qdf_list_node
* @cookie: Cookie value
*/
struct action_frame_cookie {
qdf_list_node_t cookie_node;
uint64_t cookie;
};
/**
* struct action_frame_random_mac - Action Frame random mac addr &
* related attrs
* @p2p_vdev_obj: p2p vdev private obj ptr
* @in_use: Checks whether random mac is in use
* @addr: Contains random mac addr
* @freq: Channel frequency
* @clear_timer: timer to clear random mac filter
* @cookie_list: List of cookies tied with random mac
*/
struct action_frame_random_mac {
struct p2p_vdev_priv_obj *p2p_vdev_obj;
bool in_use;
uint8_t addr[QDF_MAC_ADDR_SIZE];
uint32_t freq;
qdf_mc_timer_t clear_timer;
qdf_list_t cookie_list;
};
/**
* p2p_request_mgr_callback_t() - callback to process set mac filter result
* @result: bool
* @context: callback context.
*
* Return: void
*/
typedef void (*p2p_request_mgr_callback_t)(bool result, void *context);
/**
* struct random_mac_priv - request private data struct
* @result: result of request.
*/
struct random_mac_priv {
bool result;
};
/**
* struct p2p_set_mac_filter_req - set mac addr filter cmd data structure
* @soc: soc object
* @vdev_id: vdev id
* @mac: mac address to be set
* @freq: frequency
* @set: set or clear
* @cb: callback func to be called when the request completion
* @req_cookie: cookie to be used when request completed
*/
struct p2p_set_mac_filter_req {
struct wlan_objmgr_psoc *soc;
uint32_t vdev_id;
uint8_t mac[QDF_MAC_ADDR_SIZE];
uint32_t freq;
bool set;
p2p_request_mgr_callback_t cb;
void *req_cookie;
};
/**
* struct p2p_vdev_priv_obj - Per vdev p2p private object
* @vdev: Pointer to vdev context
* @noa_info: NoA information
* @noa_status: NoA status i.e. Enabled / Disabled (TRUE/FALSE)
* @non_p2p_peer_count: Number of legacy stations connected to this GO
* @random_mac_lock: lock for random_mac list
* @random_mac: active random mac filter lists
* @pending_req: pending set mac filter request.
*/
struct p2p_vdev_priv_obj {
struct wlan_objmgr_vdev *vdev;
struct p2p_noa_info *noa_info;
bool noa_status;
uint16_t non_p2p_peer_count;
/* random address management for management action frames */
qdf_spinlock_t random_mac_lock;
struct action_frame_random_mac random_mac[MAX_RANDOM_MAC_ADDRS];
struct p2p_set_mac_filter_req pending_req;
};
/**

Переглянути файл

@@ -32,6 +32,21 @@
#include "wlan_p2p_roc.h"
#include "wlan_p2p_main.h"
#include "wlan_p2p_off_chan_tx.h"
#include "wlan_osif_request_manager.h"
/**
* p2p_psoc_get_tx_ops() - get p2p tx ops
* @psoc: psoc object
*
* This function returns p2p tx ops callbacks.
*
* Return: wlan_lmac_if_p2p_tx_ops
*/
static inline struct wlan_lmac_if_p2p_tx_ops *
p2p_psoc_get_tx_ops(struct wlan_objmgr_psoc *psoc)
{
return &psoc->soc_cb.tx_ops.p2p;
}
/**
* p2p_tx_context_check_valid() - check tx action context
@@ -469,6 +484,7 @@ static QDF_STATUS p2p_populate_mac_header(
void *mac_addr;
uint16_t seq_num;
uint8_t pdev_id;
struct wlan_objmgr_vdev *vdev;
psoc = tx_ctx->p2p_soc_obj->soc;
@@ -482,7 +498,17 @@ static QDF_STATUS p2p_populate_mac_header(
peer = wlan_objmgr_get_peer(psoc, pdev_id, mac_addr,
WLAN_P2P_ID);
}
if (!peer && tx_ctx->rand_mac_tx) {
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
tx_ctx->vdev_id,
WLAN_P2P_ID);
if (vdev) {
mac_addr = wlan_vdev_mlme_get_macaddr(vdev);
peer = wlan_objmgr_get_peer(psoc, pdev_id, mac_addr,
WLAN_P2P_ID);
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
}
}
if (!peer) {
p2p_err("no valid peer");
return QDF_STATUS_E_INVAL;
@@ -855,6 +881,8 @@ static QDF_STATUS p2p_send_tx_conf(struct tx_action_context *tx_ctx,
tx_cnf.action_cookie, tx_cnf.buf_len,
tx_cnf.status, tx_cnf.buf);
p2p_rand_mac_tx_done(p2p_soc_obj->soc, tx_ctx);
start_param->tx_cnf_cb(start_param->tx_cnf_cb_data, &tx_cnf);
return QDF_STATUS_SUCCESS;
@@ -883,6 +911,7 @@ static QDF_STATUS p2p_mgmt_tx(struct tx_action_context *tx_ctx,
struct wlan_objmgr_psoc *psoc;
void *mac_addr;
uint8_t pdev_id;
struct wlan_objmgr_vdev *vdev;
psoc = tx_ctx->p2p_soc_obj->soc;
mgmt_param.tx_frame = packet;
@@ -907,6 +936,16 @@ static QDF_STATUS p2p_mgmt_tx(struct tx_action_context *tx_ctx,
peer = wlan_objmgr_get_peer(psoc, pdev_id, mac_addr,
WLAN_P2P_ID);
}
if (!peer && tx_ctx->rand_mac_tx) {
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(
psoc, tx_ctx->vdev_id, WLAN_P2P_ID);
if (vdev) {
mac_addr = wlan_vdev_mlme_get_macaddr(vdev);
peer = wlan_objmgr_get_peer(psoc, pdev_id, mac_addr,
WLAN_P2P_ID);
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
}
}
if (!peer) {
p2p_err("no valid peer");
@@ -1770,6 +1809,857 @@ QDF_STATUS p2p_process_cleanup_tx_queue(struct p2p_cleanup_param *param)
return QDF_STATUS_SUCCESS;
}
bool p2p_check_random_mac(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
uint8_t *random_mac_addr)
{
uint32_t i = 0;
struct p2p_vdev_priv_obj *p2p_vdev_obj;
struct wlan_objmgr_vdev *vdev;
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(soc, vdev_id, WLAN_P2P_ID);
if (!vdev) {
p2p_debug("vdev is null");
return false;
}
p2p_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(
vdev, WLAN_UMAC_COMP_P2P);
if (!p2p_vdev_obj) {
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
p2p_debug("p2p vdev object is NULL");
return false;
}
qdf_spin_lock(&p2p_vdev_obj->random_mac_lock);
for (i = 0; i < MAX_RANDOM_MAC_ADDRS; i++) {
if ((p2p_vdev_obj->random_mac[i].in_use) &&
(!qdf_mem_cmp(p2p_vdev_obj->random_mac[i].addr,
random_mac_addr, QDF_MAC_ADDR_SIZE))) {
qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
return true;
}
}
qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
return false;
}
/**
* find_action_frame_cookie() - Checks for action cookie in cookie list
* @cookie_list: List of cookies
* @rnd_cookie: Cookie to be searched
*
* Return: If search is successful return pointer to action_frame_cookie
* object in which cookie item is encapsulated.
*/
static struct action_frame_cookie *
find_action_frame_cookie(qdf_list_t *cookie_list, uint64_t rnd_cookie)
{
struct action_frame_cookie *action_cookie;
qdf_list_for_each(cookie_list, action_cookie, cookie_node) {
if (action_cookie->cookie == rnd_cookie)
return action_cookie;
}
return NULL;
}
/**
* allocate_action_frame_cookie() - Allocate and add action cookie to
* given list
* @cookie_list: List of cookies
* @rnd_cookie: Cookie to be added
*
* Return: If allocation and addition is successful return pointer to
* action_frame_cookie object in which cookie item is encapsulated.
*/
static struct action_frame_cookie *
allocate_action_frame_cookie(qdf_list_t *cookie_list, uint64_t rnd_cookie)
{
struct action_frame_cookie *action_cookie;
action_cookie = qdf_mem_malloc(sizeof(*action_cookie));
if (!action_cookie)
return NULL;
action_cookie->cookie = rnd_cookie;
qdf_list_insert_front(cookie_list, &action_cookie->cookie_node);
return action_cookie;
}
/**
* delete_action_frame_cookie() - Delete the cookie from given list
* @cookie_list: List of cookies
* @action_cookie: Cookie to be deleted
*
* This function deletes the cookie item from given list and corresponding
* object in which it is encapsulated.
*
* Return: None
*/
static void
delete_action_frame_cookie(qdf_list_t *cookie_list,
struct action_frame_cookie *action_cookie)
{
qdf_list_remove_node(cookie_list, &action_cookie->cookie_node);
qdf_mem_free(action_cookie);
}
/**
* append_action_frame_cookie() - Append action cookie to given list
* @cookie_list: List of cookies
* @rnd_cookie: Cookie to be append
*
* This is a wrapper function which invokes allocate_action_frame_cookie
* if the cookie to be added is not duplicate
*
* Return: true - for successful case
* false - failed.
*/
static bool
append_action_frame_cookie(qdf_list_t *cookie_list, uint64_t rnd_cookie)
{
struct action_frame_cookie *action_cookie;
/*
* There should be no mac entry with empty cookie list,
* check and ignore if duplicate
*/
action_cookie = find_action_frame_cookie(cookie_list, rnd_cookie);
if (action_cookie)
/* random mac address is already programmed */
return true;
/* insert new cookie in cookie list */
action_cookie = allocate_action_frame_cookie(cookie_list, rnd_cookie);
if (!action_cookie)
return false;
return true;
}
/**
* p2p_add_random_mac() - add or append random mac to given vdev rand mac list
* @soc: soc object
* @vdev_id: vdev id
* @mac: mac addr to be added or append
* @freq: frequency
* @rnd_cookie: random mac mgmt tx cookie
*
* This function will add or append the mac addr entry to vdev random mac list.
* Once the mac addr filter is not needed, it can be removed by
* p2p_del_random_mac.
*
* Return: QDF_STATUS_E_EXISTS - append to existing list
* QDF_STATUS_SUCCESS - add a new entry.
* other : failed to add the mac address entry.
*/
static QDF_STATUS
p2p_add_random_mac(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
uint8_t *mac, uint32_t freq, uint64_t rnd_cookie)
{
uint32_t i;
uint32_t first_unused = MAX_RANDOM_MAC_ADDRS;
struct action_frame_cookie *action_cookie;
int32_t append_ret;
struct p2p_vdev_priv_obj *p2p_vdev_obj;
struct wlan_objmgr_vdev *vdev;
p2p_debug("random_mac:vdev %d mac_addr:%pM rnd_cookie=%llu freq = %u",
vdev_id, mac, rnd_cookie, freq);
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(soc, vdev_id, WLAN_P2P_ID);
if (!vdev) {
p2p_debug("vdev is null");
return QDF_STATUS_E_INVAL;
}
p2p_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(
vdev, WLAN_UMAC_COMP_P2P);
if (!p2p_vdev_obj) {
p2p_debug("random_mac:p2p vdev object is NULL");
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
return QDF_STATUS_E_INVAL;
}
qdf_spin_lock(&p2p_vdev_obj->random_mac_lock);
/*
* Following loop checks whether random mac entry is already
* present, if present get the index of matched entry else
* get the first unused slot to store this new random mac
*/
for (i = 0; i < MAX_RANDOM_MAC_ADDRS; i++) {
if (!p2p_vdev_obj->random_mac[i].in_use) {
if (first_unused == MAX_RANDOM_MAC_ADDRS)
first_unused = i;
continue;
}
if (!qdf_mem_cmp(p2p_vdev_obj->random_mac[i].addr, mac,
QDF_MAC_ADDR_SIZE))
break;
}
if (i != MAX_RANDOM_MAC_ADDRS) {
append_ret = append_action_frame_cookie(
&p2p_vdev_obj->random_mac[i].cookie_list,
rnd_cookie);
qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
p2p_debug("random_mac:append %d vdev %d freq %d %pM rnd_cookie %llu",
append_ret, vdev_id, freq, mac, rnd_cookie);
if (!append_ret) {
p2p_debug("random_mac:failed to append rnd_cookie");
return QDF_STATUS_E_NOMEM;
}
return QDF_STATUS_E_EXISTS;
}
if (first_unused == MAX_RANDOM_MAC_ADDRS) {
qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
p2p_debug("random_mac:Reached the limit of Max random addresses");
return QDF_STATUS_E_RESOURCES;
}
/* get the first unused buf and store new random mac */
i = first_unused;
action_cookie = allocate_action_frame_cookie(
&p2p_vdev_obj->random_mac[i].cookie_list,
rnd_cookie);
if (!action_cookie) {
qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
p2p_err("random_mac:failed to alloc rnd cookie");
return QDF_STATUS_E_NOMEM;
}
qdf_mem_copy(p2p_vdev_obj->random_mac[i].addr, mac, QDF_MAC_ADDR_SIZE);
p2p_vdev_obj->random_mac[i].in_use = true;
p2p_vdev_obj->random_mac[i].freq = freq;
qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
p2p_debug("random_mac:add vdev %d freq %d %pM rnd_cookie %llu",
vdev_id, freq, mac, rnd_cookie);
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
p2p_del_random_mac(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
uint64_t rnd_cookie, uint32_t duration)
{
uint32_t i;
struct action_frame_cookie *action_cookie;
struct p2p_vdev_priv_obj *p2p_vdev_obj;
struct wlan_objmgr_vdev *vdev;
p2p_debug("random_mac:vdev %d cookie %llu duration %d", vdev_id,
rnd_cookie, duration);
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(soc, vdev_id,
WLAN_P2P_ID);
if (!vdev) {
p2p_debug("vdev is null");
return QDF_STATUS_E_INVAL;
}
p2p_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(
vdev, WLAN_UMAC_COMP_P2P);
if (!p2p_vdev_obj) {
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
p2p_debug("p2p vdev object is NULL");
return QDF_STATUS_E_INVAL;
}
qdf_spin_lock(&p2p_vdev_obj->random_mac_lock);
for (i = 0; i < MAX_RANDOM_MAC_ADDRS; i++) {
struct action_frame_random_mac *random_mac;
random_mac = &p2p_vdev_obj->random_mac[i];
if (!random_mac->in_use)
continue;
action_cookie = find_action_frame_cookie(
&random_mac->cookie_list, rnd_cookie);
if (!action_cookie)
continue;
delete_action_frame_cookie(
&random_mac->cookie_list,
action_cookie);
if (qdf_list_empty(&random_mac->cookie_list)) {
qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
if (qdf_mc_timer_get_current_state(
&random_mac->clear_timer) ==
QDF_TIMER_STATE_RUNNING)
qdf_mc_timer_stop(&random_mac->clear_timer);
qdf_mc_timer_start(&random_mac->clear_timer, duration);
qdf_spin_lock(&p2p_vdev_obj->random_mac_lock);
p2p_debug("random_mac:noref on vdev %d addr %pM",
vdev_id, random_mac->addr);
}
break;
}
qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
return QDF_STATUS_SUCCESS;
}
void p2p_del_all_rand_mac_vdev(struct wlan_objmgr_vdev *vdev)
{
int32_t i;
uint32_t freq;
uint8_t addr[QDF_MAC_ADDR_SIZE];
struct p2p_vdev_priv_obj *p2p_vdev_obj;
if (!vdev)
return;
p2p_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(
vdev, WLAN_UMAC_COMP_P2P);
if (!p2p_vdev_obj)
return;
qdf_spin_lock(&p2p_vdev_obj->random_mac_lock);
for (i = 0; i < MAX_RANDOM_MAC_ADDRS; i++) {
struct action_frame_cookie *action_cookie;
struct action_frame_cookie *action_cookie_next;
if (!p2p_vdev_obj->random_mac[i].in_use)
continue;
/* empty the list and clear random addr */
qdf_list_for_each_del(&p2p_vdev_obj->random_mac[i].cookie_list,
action_cookie, action_cookie_next,
cookie_node) {
qdf_list_remove_node(
&p2p_vdev_obj->random_mac[i].cookie_list,
&action_cookie->cookie_node);
qdf_mem_free(action_cookie);
}
p2p_vdev_obj->random_mac[i].in_use = false;
freq = p2p_vdev_obj->random_mac[i].freq;
qdf_mem_copy(addr, p2p_vdev_obj->random_mac[i].addr,
QDF_MAC_ADDR_SIZE);
qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
qdf_mc_timer_stop(&p2p_vdev_obj->random_mac[i].clear_timer);
p2p_clear_mac_filter(wlan_vdev_get_psoc(vdev),
wlan_vdev_get_id(vdev), addr, freq);
p2p_debug("random_mac:delall vdev %d freq %d addr %pM",
wlan_vdev_get_id(vdev), freq, addr);
qdf_spin_lock(&p2p_vdev_obj->random_mac_lock);
}
qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
}
static void
p2p_del_rand_mac_vdev_enum_handler(struct wlan_objmgr_psoc *psoc,
void *obj, void *arg)
{
struct wlan_objmgr_vdev *vdev = obj;
if (!vdev) {
p2p_err("random_mac:invalid vdev");
return;
}
if (!p2p_is_vdev_support_rand_mac(vdev))
return;
p2p_del_all_rand_mac_vdev(vdev);
}
void p2p_del_all_rand_mac_soc(struct wlan_objmgr_psoc *soc)
{
if (!soc) {
p2p_err("random_mac:soc object is NULL");
return;
}
wlan_objmgr_iterate_obj_list(soc, WLAN_VDEV_OP,
p2p_del_rand_mac_vdev_enum_handler,
NULL, 0, WLAN_P2P_ID);
}
/**
* p2p_is_random_mac() - check mac addr is random mac for vdev
* @soc: soc object
* @vdev_id: vdev id
* @mac: mac addr to be added or append
*
* This function will check the source mac addr same as vdev's mac addr or not.
* If not same, then the source mac addr should be random mac addr.
*
* Return: true if mac is random mac, otherwise false
*/
static bool
p2p_is_random_mac(struct wlan_objmgr_psoc *soc, uint32_t vdev_id, uint8_t *mac)
{
bool ret = false;
struct wlan_objmgr_vdev *vdev;
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(soc, vdev_id, WLAN_P2P_ID);
if (!vdev) {
p2p_debug("random_mac:vdev is null");
return false;
}
if (qdf_mem_cmp(wlan_vdev_mlme_get_macaddr(vdev),
mac, QDF_MAC_ADDR_SIZE))
ret = true;
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
return ret;
}
static void p2p_set_mac_filter_callback(bool result, void *context)
{
struct osif_request *request;
struct random_mac_priv *priv;
p2p_debug("random_mac:set random mac filter result %d", result);
request = osif_request_get(context);
if (!request) {
p2p_err("random_mac:invalid response");
return;
}
priv = osif_request_priv(request);
priv->result = result;
osif_request_complete(request);
osif_request_put(request);
}
QDF_STATUS p2p_process_set_rand_mac_rsp(struct p2p_mac_filter_rsp *resp)
{
struct wlan_objmgr_psoc *soc;
struct p2p_vdev_priv_obj *p2p_vdev_obj;
struct wlan_objmgr_vdev *vdev;
if (!resp || !resp->p2p_soc_obj || !resp->p2p_soc_obj->soc) {
p2p_debug("random_mac:set_filter_req is null");
return QDF_STATUS_E_INVAL;
}
p2p_debug("random_mac:process rsp on vdev %d status %d", resp->vdev_id,
resp->status);
soc = resp->p2p_soc_obj->soc;
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(soc, resp->vdev_id,
WLAN_P2P_ID);
if (!vdev) {
p2p_debug("random_mac:vdev is null vdev %d", resp->vdev_id);
return QDF_STATUS_E_INVAL;
}
p2p_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(
vdev, WLAN_UMAC_COMP_P2P);
if (!p2p_vdev_obj) {
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
p2p_debug("random_mac:p2p_vdev_obj is null vdev %d",
resp->vdev_id);
return QDF_STATUS_E_INVAL;
}
if (!p2p_vdev_obj->pending_req.soc) {
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
p2p_debug("random_mac:no pending set req for vdev %d",
resp->vdev_id);
return QDF_STATUS_E_INVAL;
}
p2p_debug("random_mac:get pending req on vdev %d set %d mac filter %pM freq %d",
p2p_vdev_obj->pending_req.vdev_id,
p2p_vdev_obj->pending_req.set, p2p_vdev_obj->pending_req.mac,
p2p_vdev_obj->pending_req.freq);
if (p2p_vdev_obj->pending_req.cb)
p2p_vdev_obj->pending_req.cb(
!!resp->status, p2p_vdev_obj->pending_req.req_cookie);
qdf_mem_zero(&p2p_vdev_obj->pending_req,
sizeof(p2p_vdev_obj->pending_req));
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
p2p_process_set_rand_mac(struct p2p_set_mac_filter_req *set_filter_req)
{
struct wlan_objmgr_psoc *soc;
struct wlan_lmac_if_p2p_tx_ops *p2p_ops;
QDF_STATUS status = QDF_STATUS_E_FAILURE;
struct p2p_set_mac_filter param;
struct p2p_vdev_priv_obj *p2p_vdev_obj;
struct wlan_objmgr_vdev *vdev;
if (!set_filter_req || !set_filter_req->soc) {
p2p_debug("random_mac:set_filter_req is null");
return QDF_STATUS_E_INVAL;
}
p2p_debug("random_mac:vdev %d set %d mac filter %pM freq %d",
set_filter_req->vdev_id, set_filter_req->set,
set_filter_req->mac, set_filter_req->freq);
soc = set_filter_req->soc;
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(
soc, set_filter_req->vdev_id, WLAN_P2P_ID);
if (!vdev) {
p2p_debug("random_mac:vdev is null vdev %d",
set_filter_req->vdev_id);
goto get_vdev_failed;
}
p2p_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(
vdev, WLAN_UMAC_COMP_P2P);
if (!p2p_vdev_obj) {
p2p_debug("random_mac:p2p_vdev_obj is null vdev %d",
set_filter_req->vdev_id);
goto get_p2p_obj_failed;
}
if (p2p_vdev_obj->pending_req.soc) {
p2p_debug("random_mac:Busy on vdev %d set %d mac filter %pM freq %d",
p2p_vdev_obj->pending_req.vdev_id,
p2p_vdev_obj->pending_req.set,
p2p_vdev_obj->pending_req.mac,
p2p_vdev_obj->pending_req.freq);
goto get_p2p_obj_failed;
}
p2p_ops = p2p_psoc_get_tx_ops(soc);
if (p2p_ops && p2p_ops->set_mac_addr_rx_filter_cmd) {
qdf_mem_zero(&param, sizeof(param));
param.vdev_id = set_filter_req->vdev_id;
qdf_mem_copy(param.mac, set_filter_req->mac,
QDF_MAC_ADDR_SIZE);
param.freq = set_filter_req->freq;
param.set = set_filter_req->set;
status = p2p_ops->set_mac_addr_rx_filter_cmd(soc, &param);
if (status == QDF_STATUS_SUCCESS && set_filter_req->set)
qdf_mem_copy(&p2p_vdev_obj->pending_req,
set_filter_req, sizeof(*set_filter_req));
p2p_debug("random_mac:p2p set mac addr rx filter, status:%d",
status);
}
get_p2p_obj_failed:
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
get_vdev_failed:
if (status != QDF_STATUS_SUCCESS &&
set_filter_req->cb)
set_filter_req->cb(false, set_filter_req->req_cookie);
return status;
}
/**
* p2p_set_mac_filter() - send set mac addr filter cmd
* @soc: soc
* @vdev_id: vdev id
* @mac: mac addr
* @freq: freq
* @set: set or clear
* @cb: callback func to be called when the request completed.
* @req_cookie: cookie to be returned
*
* This function send set random mac addr filter command to p2p component
* msg core
*
* Return: QDF_STATUS_SUCCESS - if sent successfully.
* otherwise : failed.
*/
static QDF_STATUS
p2p_set_mac_filter(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
uint8_t *mac, uint32_t freq, bool set,
p2p_request_mgr_callback_t cb, void *req_cookie)
{
struct p2p_set_mac_filter_req *set_filter_req;
struct scheduler_msg msg = {0};
QDF_STATUS status;
p2p_debug("random_mac:vdev %d freq %d set %d %pM",
vdev_id, freq, set, mac);
set_filter_req = qdf_mem_malloc(sizeof(*set_filter_req));
if (!set_filter_req)
return QDF_STATUS_E_NOMEM;
set_filter_req->soc = soc;
set_filter_req->vdev_id = vdev_id;
set_filter_req->freq = freq;
qdf_mem_copy(set_filter_req->mac, mac, QDF_MAC_ADDR_SIZE);
set_filter_req->set = set;
set_filter_req->cb = cb;
set_filter_req->req_cookie = req_cookie;
msg.type = P2P_SET_RANDOM_MAC;
msg.bodyptr = set_filter_req;
msg.callback = p2p_process_cmd;
status = scheduler_post_msg(QDF_MODULE_ID_OS_IF, &msg);
if (status != QDF_STATUS_SUCCESS)
qdf_mem_free(set_filter_req);
return status;
}
QDF_STATUS
p2p_clear_mac_filter(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
uint8_t *mac, uint32_t freq)
{
return p2p_set_mac_filter(soc, vdev_id, mac, freq, false, NULL, NULL);
}
bool
p2p_is_vdev_support_rand_mac(struct wlan_objmgr_vdev *vdev)
{
enum QDF_OPMODE mode;
mode = wlan_vdev_mlme_get_opmode(vdev);
if (mode == QDF_STA_MODE ||
mode == QDF_P2P_CLIENT_MODE ||
mode == QDF_P2P_DEVICE_MODE)
return true;
return false;
}
/**
* p2p_is_vdev_support_rand_mac_by_id() - check vdev type support random mac
* mgmt tx or not
* @soc: soc obj
* @vdev_id: vdev id
*
* Return: true: support random mac mgmt tx
* false: not support random mac mgmt tx.
*/
static bool
p2p_is_vdev_support_rand_mac_by_id(struct wlan_objmgr_psoc *soc,
uint32_t vdev_id)
{
struct wlan_objmgr_vdev *vdev;
bool ret = false;
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(soc, vdev_id, WLAN_P2P_ID);
if (!vdev)
return false;
ret = p2p_is_vdev_support_rand_mac(vdev);
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
return ret;
}
/**
* p2p_set_rand_mac() - set random mac address rx filter
* @soc: soc
* @vdev_id: vdev id
* @mac: mac addr
* @freq: freq
* @rnd_cookie: cookie to be returned
*
* This function will post msg to p2p core to set random mac addr rx filter.
* It will wait the respone and return the result to caller.
*
* Return: true: set successfully
* false: failed
*/
static bool
p2p_set_rand_mac(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
uint8_t *mac, uint32_t freq, uint64_t rnd_cookie)
{
bool ret = false;
int err;
QDF_STATUS status;
struct osif_request *request;
static const struct osif_request_params params = {
.priv_size = sizeof(struct random_mac_priv),
.timeout_ms = WLAN_WAIT_TIME_SET_RND,
};
void *req_cookie;
struct random_mac_priv *priv;
request = osif_request_alloc(&params);
if (!request) {
p2p_err("Request allocation failure");
return false;
}
req_cookie = osif_request_cookie(request);
status = p2p_set_mac_filter(soc, vdev_id, mac, freq, true,
p2p_set_mac_filter_callback, req_cookie);
if (status != QDF_STATUS_SUCCESS) {
p2p_err("random_mac:set mac fitler failure %d", status);
} else {
err = osif_request_wait_for_response(request);
if (err) {
p2p_err("random_mac:timeout for set mac fitler %d",
err);
} else {
priv = osif_request_priv(request);
ret = priv->result;
p2p_debug("random_mac:vdev %d freq %d result %d %pM rnd_cookie %llu",
vdev_id, freq, priv->result, mac, rnd_cookie);
}
}
osif_request_put(request);
return ret;
}
/**
* p2p_request_random_mac() - request random mac mgmt tx
* @soc: soc
* @vdev_id: vdev id
* @mac: mac addr
* @freq: freq
* @rnd_cookie: cookie to be returned
* @duration: duration of tx timeout
*
* This function will add/append the random mac addr filter entry to vdev.
* If it is new added entry, it will request to set filter in target.
*
* Return: QDF_STATUS_SUCCESS: request successfully
* other: failed
*/
static QDF_STATUS
p2p_request_random_mac(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
uint8_t *mac, uint32_t freq, uint64_t rnd_cookie,
uint32_t duration)
{
QDF_STATUS status;
status = p2p_add_random_mac(soc, vdev_id, mac, freq, rnd_cookie);
if (status == QDF_STATUS_E_EXISTS)
return QDF_STATUS_SUCCESS;
else if (status != QDF_STATUS_SUCCESS)
return status;
if (!p2p_set_rand_mac(soc, vdev_id, mac, freq, rnd_cookie))
status = p2p_del_random_mac(soc, vdev_id, rnd_cookie,
duration);
return status;
}
void p2p_rand_mac_tx(struct tx_action_context *tx_action)
{
struct wlan_objmgr_psoc *soc;
QDF_STATUS status;
if (!tx_action || !tx_action->p2p_soc_obj ||
!tx_action->p2p_soc_obj->soc)
return;
soc = tx_action->p2p_soc_obj->soc;
if (!tx_action->no_ack && tx_action->chan &&
tx_action->buf_len > MIN_MAC_HEADER_LEN &&
p2p_is_vdev_support_rand_mac_by_id(soc, tx_action->vdev_id) &&
p2p_is_random_mac(soc, tx_action->vdev_id,
&tx_action->buf[SRC_MAC_ADDR_OFFSET])) {
status = p2p_request_random_mac(
soc, tx_action->vdev_id,
&tx_action->buf[SRC_MAC_ADDR_OFFSET],
wlan_chan_to_freq(tx_action->chan),
tx_action->id,
tx_action->duration);
if (status == QDF_STATUS_SUCCESS)
tx_action->rand_mac_tx = true;
else
tx_action->rand_mac_tx = false;
}
}
void
p2p_rand_mac_tx_done(struct wlan_objmgr_psoc *soc,
struct tx_action_context *tx_ctx)
{
if (!tx_ctx || !tx_ctx->rand_mac_tx || !soc)
return;
p2p_del_random_mac(soc, tx_ctx->vdev_id, tx_ctx->id, tx_ctx->duration);
}
/**
* p2p_mac_clear_timeout() - clear random mac filter timeout
* @context: timer context
*
* This function will clear the mac addr rx filter in target if no
* reference to it.
*
* Return: void
*/
static void p2p_mac_clear_timeout(void *context)
{
struct action_frame_random_mac *random_mac = context;
struct p2p_vdev_priv_obj *p2p_vdev_obj;
uint32_t freq;
uint8_t addr[QDF_MAC_ADDR_SIZE];
uint32_t vdev_id;
bool clear = false;
if (!random_mac || !random_mac->p2p_vdev_obj) {
p2p_err("invalid context for mac_clear timeout");
return;
}
p2p_vdev_obj = random_mac->p2p_vdev_obj;
if (!p2p_vdev_obj || !p2p_vdev_obj->vdev)
return;
qdf_spin_lock(&p2p_vdev_obj->random_mac_lock);
if (qdf_list_empty(&random_mac->cookie_list)) {
random_mac->in_use = false;
clear = true;
}
freq = random_mac->freq;
qdf_mem_copy(addr, random_mac->addr, QDF_MAC_ADDR_SIZE);
qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
vdev_id = wlan_vdev_get_id(p2p_vdev_obj->vdev);
p2p_debug("random_mac:clear timeout vdev %d %pM freq %d clr %d",
vdev_id, addr, freq, clear);
if (clear)
p2p_clear_mac_filter(wlan_vdev_get_psoc(p2p_vdev_obj->vdev),
vdev_id, addr, freq);
}
void p2p_init_random_mac_vdev(struct p2p_vdev_priv_obj *p2p_vdev_obj)
{
int32_t i;
qdf_spinlock_create(&p2p_vdev_obj->random_mac_lock);
for (i = 0; i < MAX_RANDOM_MAC_ADDRS; i++) {
qdf_mem_zero(&p2p_vdev_obj->random_mac[i],
sizeof(struct action_frame_random_mac));
p2p_vdev_obj->random_mac[i].in_use = false;
p2p_vdev_obj->random_mac[i].p2p_vdev_obj = p2p_vdev_obj;
qdf_list_create(&p2p_vdev_obj->random_mac[i].cookie_list, 0);
qdf_mc_timer_init(&p2p_vdev_obj->random_mac[i].clear_timer,
QDF_TIMER_TYPE_SW, p2p_mac_clear_timeout,
&p2p_vdev_obj->random_mac[i]);
}
}
void p2p_deinit_random_mac_vdev(struct p2p_vdev_priv_obj *p2p_vdev_obj)
{
int32_t i;
p2p_del_all_rand_mac_vdev(p2p_vdev_obj->vdev);
for (i = 0; i < MAX_RANDOM_MAC_ADDRS; i++) {
qdf_mc_timer_destroy(&p2p_vdev_obj->random_mac[i].clear_timer);
qdf_list_destroy(&p2p_vdev_obj->random_mac[i].cookie_list);
}
qdf_spinlock_destroy(&p2p_vdev_obj->random_mac_lock);
}
QDF_STATUS p2p_process_mgmt_tx(struct tx_action_context *tx_ctx)
{
struct p2p_soc_priv_obj *p2p_soc_obj;
@@ -1983,6 +2873,8 @@ QDF_STATUS p2p_process_mgmt_tx_ack_cnf(
tx_cnf.action_cookie, tx_cnf.buf_len,
tx_cnf.status, tx_cnf.buf);
p2p_rand_mac_tx_done(p2p_soc_obj->soc, tx_ctx);
/* disable tx timer */
p2p_disable_tx_timer(tx_ctx);

Переглянути файл

@@ -59,6 +59,8 @@
#define P2P_GET_TYPE_FRM_FC(__fc__) (((__fc__) & 0x0F) >> 2)
#define P2P_GET_SUBTYPE_FRM_FC(__fc__) (((__fc__) & 0xF0) >> 4)
#define WLAN_WAIT_TIME_SET_RND 100
struct p2p_soc_priv_obj;
struct cancel_roc_context;
struct p2p_tx_conf_event;
@@ -172,12 +174,54 @@ struct tx_action_context {
bool off_chan;
bool no_cck;
bool no_ack;
bool rand_mac_tx;
uint32_t duration;
qdf_mc_timer_t tx_timer;
struct p2p_frame_info frame_info;
qdf_nbuf_t nbuf;
};
/**
* p2p_rand_mac_tx_done() - process random mac mgmt tx done
* @soc: soc
* @tx_ctx: tx context
*
* This function will remove the random mac addr filter reference.
*
* Return: void
*/
void
p2p_rand_mac_tx_done(struct wlan_objmgr_psoc *soc,
struct tx_action_context *tx_ctx);
/**
* p2p_clear_mac_filter() - send clear mac addr filter cmd
* @soc: soc
* @vdev_id: vdev id
* @mac: mac addr
* @freq: freq
*
* This function send clear random mac addr filter command to p2p component
* msg core
*
* Return: QDF_STATUS_SUCCESS - if sent successfully.
* otherwise: failed.
*/
QDF_STATUS
p2p_clear_mac_filter(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
uint8_t *mac, uint32_t freq);
/**
* p2p_is_vdev_support_rand_mac() - check vdev type support random mac mgmt
* tx or not
* @vdev: vdev object
*
* Return: true: support random mac mgmt tx
* false: not support random mac mgmt tx.
*/
bool
p2p_is_vdev_support_rand_mac(struct wlan_objmgr_vdev *vdev);
/**
* p2p_dump_tx_queue() - dump tx queue
* @p2p_soc_obj: p2p soc private object
@@ -285,4 +329,111 @@ QDF_STATUS p2p_process_rx_mgmt(
struct tx_action_context *p2p_find_tx_ctx_by_nbuf(
struct p2p_soc_priv_obj *p2p_soc_obj, void *nbuf);
#define P2P_80211_FRM_SA_OFFSET 10
/**
* p2p_del_random_mac() - del mac fitler from given vdev rand mac list
* @soc: soc object
* @vdev_id: vdev id
* @rnd_cookie: random mac mgmt tx cookie
* @duration: timeout value to flush the addr in target.
*
* This function will del the mac addr filter from vdev random mac addr list.
* If there is no reference to mac addr, it will set a clear timer to flush it
* in target finally.
*
* Return: QDF_STATUS_SUCCESS - del successfully.
* other : failed to del the mac address entry.
*/
QDF_STATUS
p2p_del_random_mac(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
uint64_t rnd_cookie, uint32_t duration);
/**
* p2p_check_random_mac() - check random mac addr or not
* @soc: soc context
* @vdev_id: vdev id
* @random_mac_addr: mac addr to be checked
*
* This function check the input addr is random mac addr or not for vdev.
*
* Return: true if addr is random mac address else false.
*/
bool p2p_check_random_mac(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
uint8_t *random_mac_addr);
/**
* p2p_process_set_rand_mac() - process the set random mac command
* @set_filter_req: request data
*
* This function will process the set mac addr filter command.
*
* Return: QDF_STATUS_SUCCESS: if process successfully
* other: failed.
*/
QDF_STATUS p2p_process_set_rand_mac(
struct p2p_set_mac_filter_req *set_filter_req);
/**
* p2p_process_set_rand_mac_rsp() - process the set random mac response
* @resp: response date
*
* This function will process the set mac addr filter event.
*
* Return: QDF_STATUS_SUCCESS: if process successfully
* other: failed.
*/
QDF_STATUS p2p_process_set_rand_mac_rsp(struct p2p_mac_filter_rsp *resp);
/**
* p2p_del_all_rand_mac_vdev() - del all random mac filter in vdev
* @vdev: vdev object
*
* This function will del all random mac filter in vdev
*
* Return: void
*/
void p2p_del_all_rand_mac_vdev(struct wlan_objmgr_vdev *vdev);
/**
* p2p_del_all_rand_mac_soc() - del all random mac filter in soc
* @soc: soc object
*
* This function will del all random mac filter in all vdev of soc
*
* Return: void
*/
void p2p_del_all_rand_mac_soc(struct wlan_objmgr_psoc *soc);
/**
* p2p_rand_mac_tx() - handle random mac mgmt tx
* @tx_action: tx action context
*
* This function will check whether need to set random mac tx filter for a
* given mgmt tx request and do the mac addr filter process as needed.
*
* Return: void
*/
void p2p_rand_mac_tx(struct tx_action_context *tx_action);
/**
* p2p_init_random_mac_vdev() - Init random mac data for vdev
* @p2p_vdev_obj: p2p vdev private object
*
* This function will init the per vdev random mac data structure.
*
* Return: void
*/
void p2p_init_random_mac_vdev(struct p2p_vdev_priv_obj *p2p_vdev_obj);
/**
* p2p_deinit_random_mac_vdev() - Init random mac data for vdev
* @p2p_vdev_obj: p2p vdev private object
*
* This function will deinit the per vdev random mac data structure.
*
* Return: void
*/
void p2p_deinit_random_mac_vdev(struct p2p_vdev_priv_obj *p2p_vdev_obj);
#endif /* _WLAN_P2P_OFF_CHAN_TX_H_ */

Переглянути файл

@@ -147,6 +147,30 @@ struct p2p_mgmt_tx {
const uint8_t *buf;
};
/**
* struct p2p_set_mac_filter
* @vdev_id: Vdev id
* @mac: mac addr
* @freq: frequency
* @set: set or clear
*/
struct p2p_set_mac_filter {
uint32_t vdev_id;
uint8_t mac[QDF_MAC_ADDR_SIZE];
uint32_t freq;
bool set;
};
/**
* struct p2p_set_mac_filter_evt
* @vdev_id: Vdev id
* @status: target reported result of set mac addr filter
*/
struct p2p_set_mac_filter_evt {
uint32_t vdev_id;
uint32_t status;
};
/**
* struct p2p_ps_config
* @vdev_id: Vdev id

Переглянути файл

@@ -83,6 +83,19 @@ static inline QDF_STATUS tgt_p2p_unregister_lo_ev_handler(
}
#endif
/**
* tgt_p2p_register_macaddr_rx_filter_evt_handler() - register add mac rx
* filter status event
* @psoc: soc object
* @register: register or unregister
*
* p2p tgt api to register add mac rx filter status event
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS tgt_p2p_register_macaddr_rx_filter_evt_handler(
struct wlan_objmgr_psoc *psoc, bool register);
/**
* tgt_p2p_register_noa_ev_handler() - register noa event
* @psoc: soc object
@@ -178,4 +191,18 @@ QDF_STATUS tgt_p2p_mgmt_frame_rx_cb(struct wlan_objmgr_psoc *psoc,
QDF_STATUS tgt_p2p_noa_event_cb(struct wlan_objmgr_psoc *psoc,
struct p2p_noa_info *event_info);
/**
* tgt_p2p_add_mac_addr_status_event_cb() - Callback for set mac addr filter evt
* @psoc: soc object
* @event_info: event information type of p2p_set_mac_filter_evt
*
* This function gets called from target interface.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS
tgt_p2p_add_mac_addr_status_event_cb(
struct wlan_objmgr_psoc *psoc,
struct p2p_set_mac_filter_evt *event_info);
#endif /* _WLAN_P2P_TGT_API_H_ */

Переглянути файл

@@ -257,6 +257,7 @@ QDF_STATUS ucfg_p2p_mgmt_tx(struct wlan_objmgr_psoc *soc,
/**
* ucfg_p2p_mgmt_tx_cancel() - Cancel mgmt frame tx request
* @soc: soc context
* @vdev: vdev object
* @cookie: Find out the mgmt tx request by cookie
*
* This function delivers cancel mgmt frame tx request request to P2P
@@ -265,7 +266,7 @@ QDF_STATUS ucfg_p2p_mgmt_tx(struct wlan_objmgr_psoc *soc,
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS ucfg_p2p_mgmt_tx_cancel(struct wlan_objmgr_psoc *soc,
uint64_t cookie);
struct wlan_objmgr_vdev *vdev, uint64_t cookie);
/**
* ucfg_p2p_set_ps() - P2P set power save
@@ -331,6 +332,19 @@ void p2p_peer_authorized(struct wlan_objmgr_vdev *vdev, uint8_t *mac_addr);
QDF_STATUS ucfg_p2p_set_noa(struct wlan_objmgr_psoc *soc,
uint32_t vdev_id, bool disable_noa);
/**
* ucfg_p2p_check_random_mac() - check random mac addr or not
* @soc: soc context
* @vdev_id: vdev id
* @random_mac_addr: mac addr to be checked
*
* This function check the input addr is random mac addr or not for vdev.
*
* Return: true if addr is random mac address else false.
*/
bool ucfg_p2p_check_random_mac(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
uint8_t *random_mac_addr);
/**
* ucfg_p2p_register_callbacks() - register p2p callbacks
* @soc: soc context

Переглянути файл

@@ -124,6 +124,67 @@ QDF_STATUS tgt_p2p_lo_event_cb(struct wlan_objmgr_psoc *psoc,
}
#endif /* FEATURE_P2P_LISTEN_OFFLOAD */
QDF_STATUS
tgt_p2p_add_mac_addr_status_event_cb(struct wlan_objmgr_psoc *psoc,
struct p2p_set_mac_filter_evt *event_info)
{
struct p2p_mac_filter_rsp *mac_filter_rsp;
struct scheduler_msg msg = {0};
struct p2p_soc_priv_obj *p2p_soc_obj;
QDF_STATUS status;
if (!psoc) {
p2p_err("random_mac:psoc context passed is NULL");
return QDF_STATUS_E_INVAL;
}
if (!event_info) {
p2p_err("random_mac:invalid event_info");
return QDF_STATUS_E_INVAL;
}
p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(
psoc, WLAN_UMAC_COMP_P2P);
if (!p2p_soc_obj) {
p2p_err("random_mac:p2p soc object is NULL");
return QDF_STATUS_E_INVAL;
}
mac_filter_rsp = qdf_mem_malloc(sizeof(*mac_filter_rsp));
if (!mac_filter_rsp) {
p2p_err("random_mac:Failed to allocate mac_filter_rsp");
return QDF_STATUS_E_NOMEM;
}
mac_filter_rsp->p2p_soc_obj = p2p_soc_obj;
mac_filter_rsp->vdev_id = event_info->vdev_id;
mac_filter_rsp->status = event_info->status;
msg.type = P2P_EVENT_ADD_MAC_RSP;
msg.bodyptr = mac_filter_rsp;
msg.callback = p2p_process_evt;
status = scheduler_post_msg(QDF_MODULE_ID_TARGET_IF, &msg);
if (status != QDF_STATUS_SUCCESS)
qdf_mem_free(mac_filter_rsp);
return status;
}
QDF_STATUS tgt_p2p_register_macaddr_rx_filter_evt_handler(
struct wlan_objmgr_psoc *psoc, bool reg)
{
struct wlan_lmac_if_p2p_tx_ops *p2p_ops;
QDF_STATUS status = QDF_STATUS_E_FAILURE;
p2p_ops = wlan_psoc_get_p2p_tx_ops(psoc);
if (p2p_ops && p2p_ops->reg_mac_addr_rx_filter_handler) {
status = p2p_ops->reg_mac_addr_rx_filter_handler(psoc, reg);
p2p_debug("register mac addr rx filter event, register %d status:%d",
reg, status);
}
return status;
}
QDF_STATUS tgt_p2p_register_noa_ev_handler(
struct wlan_objmgr_psoc *psoc)
{

Переглянути файл

@@ -280,6 +280,7 @@ QDF_STATUS ucfg_p2p_cleanup_tx_by_vdev(struct wlan_objmgr_vdev *vdev)
p2p_err("null p2p soc obj");
return QDF_STATUS_E_FAILURE;
}
p2p_del_all_rand_mac_vdev(vdev);
return p2p_cleanup_tx_sync(obj, vdev);
}
@@ -298,6 +299,7 @@ QDF_STATUS ucfg_p2p_cleanup_tx_by_psoc(struct wlan_objmgr_psoc *psoc)
p2p_err("null p2p soc obj");
return QDF_STATUS_E_FAILURE;
}
p2p_del_all_rand_mac_soc(psoc);
return p2p_cleanup_tx_sync(obj, NULL);
}
@@ -365,6 +367,9 @@ QDF_STATUS ucfg_p2p_mgmt_tx(struct wlan_objmgr_psoc *soc,
qdf_mem_copy(tx_action->buf, mgmt_frm->buf, tx_action->buf_len);
tx_action->nbuf = NULL;
tx_action->id = id;
p2p_rand_mac_tx(tx_action);
msg.type = P2P_MGMT_TX;
msg.bodyptr = tx_action;
msg.callback = p2p_process_cmd;
@@ -376,7 +381,7 @@ QDF_STATUS ucfg_p2p_mgmt_tx(struct wlan_objmgr_psoc *soc,
}
QDF_STATUS ucfg_p2p_mgmt_tx_cancel(struct wlan_objmgr_psoc *soc,
uint64_t cookie)
struct wlan_objmgr_vdev *vdev, uint64_t cookie)
{
struct scheduler_msg msg = {0};
struct p2p_soc_priv_obj *p2p_soc_obj;
@@ -402,6 +407,7 @@ QDF_STATUS ucfg_p2p_mgmt_tx_cancel(struct wlan_objmgr_psoc *soc,
p2p_debug("invalid id");
return QDF_STATUS_E_INVAL;
}
p2p_del_random_mac(soc, wlan_vdev_get_id(vdev), cookie, 20);
cancel_tx = qdf_mem_malloc(sizeof(*cancel_tx));
if (!cancel_tx) {
@@ -421,6 +427,12 @@ QDF_STATUS ucfg_p2p_mgmt_tx_cancel(struct wlan_objmgr_psoc *soc,
return QDF_STATUS_SUCCESS;
}
bool ucfg_p2p_check_random_mac(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
uint8_t *random_mac_addr)
{
return p2p_check_random_mac(soc, vdev_id, random_mac_addr);
}
QDF_STATUS ucfg_p2p_set_ps(struct wlan_objmgr_psoc *soc,
struct p2p_ps_config *ps_config)
{

Переглянути файл

@@ -56,6 +56,29 @@ QDF_STATUS wmi_extract_p2p_noa_ev_param(void *wmi_hdl,
void *evt_buf,
struct p2p_noa_info *param);
/**
* wmi_send_set_mac_addr_rx_filter_cmd() - set mac addr rx filter cmd
* @wmi_hdl: wmi handle
* @param: Pointer to set mac filter struct
*
* Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
*/
QDF_STATUS
wmi_send_set_mac_addr_rx_filter_cmd(void *wmi_hdl,
struct p2p_set_mac_filter *param);
/**
* wmi_extract_mac_addr_rx_filter_evt_param() - extract mac addr rx filter evt
* @wmi_hdl: wmi handle
* @evt_buf: pointer to event buffer
* @param: Pointer to extracted evt info
*
* Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
*/
QDF_STATUS
wmi_extract_mac_addr_rx_filter_evt_param(void *wmi_hdl, void *evt_buf,
struct p2p_set_mac_filter_evt *param);
#ifdef FEATURE_P2P_LISTEN_OFFLOAD
/**
* wmi_unified_p2p_lo_start_cmd() - send p2p lo start request to fw

Переглянути файл

@@ -4622,6 +4622,7 @@ typedef enum {
wmi_p2p_disc_event_id,
wmi_p2p_noa_event_id,
wmi_p2p_lo_stop_event_id,
wmi_vdev_add_macaddr_rx_filter_event_id,
wmi_pdev_resume_event_id,
wmi_d0_wow_disable_ack_event_id,
wmi_wow_initial_wakeup_event_id,

Переглянути файл

@@ -1439,6 +1439,13 @@ QDF_STATUS (*extract_p2p_lo_stop_ev_param)(wmi_unified_t wmi_handle,
QDF_STATUS (*extract_p2p_noa_ev_param)(wmi_unified_t wmi_handle,
void *evt_buf, struct p2p_noa_info *param);
QDF_STATUS (*set_mac_addr_rx_filter)(wmi_unified_t wmi_handle,
struct p2p_set_mac_filter *param);
QDF_STATUS
(*extract_mac_addr_rx_filter_evt_param)(wmi_unified_t wmi_handle,
void *evt_buf,
struct p2p_set_mac_filter_evt *param);
#endif
QDF_STATUS (*extract_peer_sta_ps_statechange_ev)(wmi_unified_t wmi_handle,

Переглянути файл

@@ -63,6 +63,42 @@ QDF_STATUS wmi_extract_p2p_noa_ev_param(void *wmi_hdl, void *evt_buf,
return QDF_STATUS_E_FAILURE;
}
QDF_STATUS
wmi_send_set_mac_addr_rx_filter_cmd(void *wmi_hdl,
struct p2p_set_mac_filter *param)
{
wmi_unified_t wmi_handle = (wmi_unified_t)wmi_hdl;
if (!wmi_handle) {
WMI_LOGE("wmi handle is null");
return QDF_STATUS_E_INVAL;
}
if (wmi_handle->ops->set_mac_addr_rx_filter)
return wmi_handle->ops->set_mac_addr_rx_filter(
wmi_handle, param);
return QDF_STATUS_E_FAILURE;
}
QDF_STATUS
wmi_extract_mac_addr_rx_filter_evt_param(void *wmi_hdl, void *evt_buf,
struct p2p_set_mac_filter_evt *param)
{
wmi_unified_t wmi_handle = (wmi_unified_t)wmi_hdl;
if (!wmi_handle) {
WMI_LOGE("wmi handle is null");
return QDF_STATUS_E_INVAL;
}
if (wmi_handle->ops->extract_mac_addr_rx_filter_evt_param)
return wmi_handle->ops->extract_mac_addr_rx_filter_evt_param(
wmi_handle, evt_buf, param);
return QDF_STATUS_E_FAILURE;
}
#ifdef FEATURE_P2P_LISTEN_OFFLOAD
QDF_STATUS wmi_unified_p2p_lo_start_cmd(void *wmi_hdl,
struct p2p_lo_start *param)

Переглянути файл

@@ -213,6 +213,81 @@ static QDF_STATUS extract_p2p_noa_ev_param_tlv(
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS
send_set_mac_addr_rx_filter_cmd_tlv(wmi_unified_t wmi_handle,
struct p2p_set_mac_filter *param)
{
wmi_vdev_add_mac_addr_to_rx_filter_cmd_fixed_param *cmd;
uint32_t len;
wmi_buf_t buf;
int ret;
if (!wmi_handle) {
WMI_LOGE("WMA context is invald!");
return QDF_STATUS_E_INVAL;
}
len = sizeof(*cmd);
buf = wmi_buf_alloc(wmi_handle, len);
if (!buf) {
WMI_LOGE("Failed allocate wmi buffer");
return QDF_STATUS_E_NOMEM;
}
cmd = (wmi_vdev_add_mac_addr_to_rx_filter_cmd_fixed_param *)
wmi_buf_data(buf);
WMITLV_SET_HDR(
&cmd->tlv_header,
WMITLV_TAG_STRUC_wmi_vdev_add_mac_addr_to_rx_filter_cmd_fixed_param,
WMITLV_GET_STRUCT_TLVLEN(
wmi_vdev_add_mac_addr_to_rx_filter_cmd_fixed_param));
cmd->vdev_id = param->vdev_id;
cmd->freq = param->freq;
WMI_CHAR_ARRAY_TO_MAC_ADDR(param->mac, &cmd->mac_addr);
if (param->set)
cmd->enable = 1;
else
cmd->enable = 0;
WMI_LOGD("set random mac rx vdev %d freq %d set %d %pM",
param->vdev_id, param->freq, param->set, param->mac);
ret = wmi_unified_cmd_send(wmi_handle, buf, len,
WMI_VDEV_ADD_MAC_ADDR_TO_RX_FILTER_CMDID);
if (ret) {
WMI_LOGE("Failed to send action frame random mac cmd");
wmi_buf_free(buf);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS extract_mac_addr_rx_filter_evt_param_tlv(
wmi_unified_t wmi_handle, void *evt_buf,
struct p2p_set_mac_filter_evt *param)
{
WMI_VDEV_ADD_MAC_ADDR_TO_RX_FILTER_STATUS_EVENTID_param_tlvs *param_buf;
wmi_vdev_add_mac_addr_to_rx_filter_status_event_fixed_param *event;
param_buf =
(WMI_VDEV_ADD_MAC_ADDR_TO_RX_FILTER_STATUS_EVENTID_param_tlvs *)
evt_buf;
if (!param_buf) {
WMI_LOGE("Invalid action frame filter mac event");
return QDF_STATUS_E_INVAL;
}
event = param_buf->fixed_param;
if (!event) {
WMI_LOGE("Invalid fixed param");
return QDF_STATUS_E_INVAL;
}
param->vdev_id = event->vdev_id;
param->status = event->status;
return QDF_STATUS_SUCCESS;
}
#ifdef FEATURE_P2P_LISTEN_OFFLOAD
/**
* send_p2p_lo_start_cmd_tlv() - send p2p lo start request to fw
@@ -406,6 +481,9 @@ void wmi_p2p_attach_tlv(wmi_unified_t wmi_handle)
ops->send_set_p2pgo_oppps_req_cmd = send_set_p2pgo_oppps_req_cmd_tlv;
ops->send_set_p2pgo_noa_req_cmd = send_set_p2pgo_noa_req_cmd_tlv;
ops->extract_p2p_noa_ev_param = extract_p2p_noa_ev_param_tlv;
ops->set_mac_addr_rx_filter = send_set_mac_addr_rx_filter_cmd_tlv,
ops->extract_mac_addr_rx_filter_evt_param =
extract_mac_addr_rx_filter_evt_param_tlv,
wmi_p2p_listen_offload_attach_tlv(wmi_handle);
}

Переглянути файл

@@ -11246,6 +11246,8 @@ static void populate_tlv_events_id(uint32_t *event_ids)
event_ids[wmi_p2p_noa_event_id] = WMI_P2P_NOA_EVENTID;
event_ids[wmi_p2p_lo_stop_event_id] =
WMI_P2P_LISTEN_OFFLOAD_STOPPED_EVENTID;
event_ids[wmi_vdev_add_macaddr_rx_filter_event_id] =
WMI_VDEV_ADD_MAC_ADDR_TO_RX_FILTER_STATUS_EVENTID;
event_ids[wmi_pdev_resume_event_id] = WMI_PDEV_RESUME_EVENTID;
event_ids[wmi_wow_wakeup_host_event_id] = WMI_WOW_WAKEUP_HOST_EVENTID;
event_ids[wmi_d0_wow_disable_ack_event_id] =