From 6d47f3c412abbb278fc566e2cab6ba43c10df537 Mon Sep 17 00:00:00 2001 From: Wu Gao Date: Wed, 15 Mar 2017 19:12:20 +0800 Subject: [PATCH 01/13] qcacmn: Defines os and target interfaces Defines API and callbacks of os interface for P2P component. At the same time, defines API of target interface. Change-Id: Ice1c86ecba1f2410d965d9f84923589f229a1864 CRs-Fixed: 2013763 --- inc/wlan_cfg80211_p2p.h | 115 ++++++++++ src/wlan_cfg80211_p2p.c | 457 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 572 insertions(+) create mode 100644 inc/wlan_cfg80211_p2p.h create mode 100644 src/wlan_cfg80211_p2p.c diff --git a/inc/wlan_cfg80211_p2p.h b/inc/wlan_cfg80211_p2p.h new file mode 100644 index 0000000000..1c8484b8de --- /dev/null +++ b/inc/wlan_cfg80211_p2p.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: declares P2P functions interfacing with linux kernel + */ + +#ifndef _WLAN_CFG80211_P2P_H_ +#define _WLAN_CFG80211_P2P_H_ + +#include + +struct wlan_objmgr_psoc; +struct wlan_objmgr_vdev; +struct ieee80211_channel; + +/** + * wlan_p2p_start() - start p2p component + * @psoc: soc object + * + * This function used to start P2P component and register events. + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ +QDF_STATUS wlan_p2p_start(struct wlan_objmgr_psoc *psoc); + +/** + * wlan_p2p_stop() - stop p2p component + * @psoc: soc object + * + * This function used to stop P2P component and unregister events. + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ +QDF_STATUS wlan_p2p_stop(struct wlan_objmgr_psoc *psoc); + +/** + * wlan_cfg80211_roc() - API to process cfg80211 roc request + * @vdev: Pointer to vdev object + * @chan: Pointer to channel + * @duration: Duration for this roc request + * @cookie: Pointer to return cookie to up layer + * + * API to trigger remain on channel request. It returns cookie + * as the identifier of roc. + * + * Return: 0 for success, non zero for failure + */ +int wlan_cfg80211_roc(struct wlan_objmgr_vdev *vdev, + struct ieee80211_channel *chan, uint32_t duration, + uint64_t *cookie); + +/** + * wlan_cfg80211_cancel_roc() - API to process cfg80211 cancel remain + * on channel request + * @vdev: Pointer to vdev object + * @cookie: Find out the roc request by cookie + * + * API to trigger cancel remain on channel request. + * + * Return: 0 for success, non zero for failure + */ +int wlan_cfg80211_cancel_roc(struct wlan_objmgr_vdev *vdev, + uint64_t cookie); + +/** + * wlan_cfg80211_mgmt_tx() - API to process cfg80211 mgmt tx request + * @vdev: Pointer to vdev object + * @chan: Pointer to channel + * @wait: wait time for this mgmt tx request + * @buf: TX buffer + * @len: Length of tx buffer + * @no_cck: Required cck or not + * @dont_wait_for_ack: Wait for ack or not + * @cookie: Return the cookie to caller + * + * API to trigger mgmt frame tx request. It returns cookie as the + * identifier of this tx. + * + * Return: 0 for success, non zero for failure + */ +int wlan_cfg80211_mgmt_tx(struct wlan_objmgr_vdev *vdev, + struct ieee80211_channel *chan, bool offchan, uint32_t wait, + const uint8_t *buf, uint32_t len, bool no_cck, + bool dont_wait_for_ack, uint64_t *cookie); + +/** + * wlan_cfg80211_mgmt_tx_cancel() - API to process cfg80211 cancel to + * wait mgmt tx + * @vdev: Pointer to vdev object + * @cookie: Find out the mgmt tx request by cookie + * + * API to trigger cancel mgmt frame tx request. + * + * Return: 0 for success, non zero for failure + */ +int wlan_cfg80211_mgmt_tx_cancel(struct wlan_objmgr_vdev *vdev, + uint64_t cookie); + +#endif /* _WLAN_CFG80211_P2P_H_ */ diff --git a/src/wlan_cfg80211_p2p.c b/src/wlan_cfg80211_p2p.c new file mode 100644 index 0000000000..8058a97f1b --- /dev/null +++ b/src/wlan_cfg80211_p2p.c @@ -0,0 +1,457 @@ +/* + * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: defines driver functions interfacing with linux kernel + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wlan_cfg80211.h" +#include "wlan_cfg80211_p2p.h" + +#define MAX_NO_OF_2_4_CHANNELS 14 + +/** + * wlan_p2p_rx_callback() - Callback for rx mgmt frame + * @user_data: pointer to soc object + * @rx_frame: RX mgmt frame information + * + * This callback will be used to rx frames in os interface. + * + * Return: None + */ +static void wlan_p2p_rx_callback(void *user_data, + struct p2p_rx_mgmt_frame *rx_frame) +{ + struct wlan_objmgr_psoc *psoc; + struct wlan_objmgr_vdev *vdev; + struct vdev_osif_priv *osif_priv; + struct wireless_dev *wdev; + uint16_t freq; + + cfg80211_debug("user data:%p, vdev id:%d, rssi:%d, buf:%p, len:%d", + user_data, rx_frame->vdev_id, rx_frame->rx_rssi, + rx_frame->buf, rx_frame->frame_len); + + psoc = user_data; + if (!psoc) { + cfg80211_err("psoc is null"); + return; + } + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, + rx_frame->vdev_id, WLAN_P2P_ID); + if (!vdev) { + cfg80211_err("vdev is null"); + return; + } + + wlan_vdev_obj_lock(vdev); + osif_priv = wlan_vdev_get_ospriv(vdev); + wlan_vdev_obj_unlock(vdev); + if (!osif_priv) { + cfg80211_err("osif_priv is null"); + goto fail; + } + + wdev = osif_priv->wdev; + if (!wdev) { + cfg80211_err("wdev is null"); + goto fail; + } + + if (rx_frame->rx_chan <= MAX_NO_OF_2_4_CHANNELS) + freq = ieee80211_channel_to_frequency( + rx_frame->rx_chan, NL80211_BAND_2GHZ); + else + freq = ieee80211_channel_to_frequency( + rx_frame->rx_chan, NL80211_BAND_5GHZ); + + cfg80211_notice("Indicate frame over nl80211, vdev id:%d, idx:%d", + rx_frame->vdev_id, wdev->netdev->ifindex); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) + cfg80211_rx_mgmt(wdev, freq, rx_frame->rx_rssi * 100, + rx_frame->buf, rx_frame->frame_len, + NL80211_RXMGMT_FLAG_ANSWERED); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) + cfg80211_rx_mgmt(wdev, freq, rx_frame->rx_rssi * 100, + rx_frame->buf, rx_frame->frame_len, + NL80211_RXMGMT_FLAG_ANSWERED, GFP_ATOMIC); +#else + cfg80211_rx_mgmt(wdev, freq, rx_frame->rx_rssi * 100, + rx_frame->buf, rx_frame->frame_len, GFP_ATOMIC); +#endif /* LINUX_VERSION_CODE */ +fail: + wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID); +} + +/** + * wlan_p2p_action_tx_cnf_callback() - Callback for tx confirmation + * @user_data: pointer to soc object + * @tx_cnf: tx confirmation information + * + * This callback will be used to give tx mgmt frame confirmation to + * os interface. + * + * Return: None + */ +static void wlan_p2p_action_tx_cnf_callback(void *user_data, + struct p2p_tx_cnf *tx_cnf) +{ + struct wlan_objmgr_psoc *psoc; + struct wlan_objmgr_vdev *vdev; + struct vdev_osif_priv *osif_priv; + struct wireless_dev *wdev; + + cfg80211_info("user data:%p, action cookie:%llx, buf:%p, len:%d, tx status:%d", + user_data, tx_cnf->action_cookie, tx_cnf->buf, + tx_cnf->buf_len, tx_cnf->status); + + psoc = user_data; + if (!psoc) { + cfg80211_err("psoc is null"); + return; + } + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, + tx_cnf->vdev_id, WLAN_P2P_ID); + if (!vdev) { + cfg80211_err("vdev is null"); + return; + } + + wlan_vdev_obj_lock(vdev); + osif_priv = wlan_vdev_get_ospriv(vdev); + wlan_vdev_obj_unlock(vdev); + if (!osif_priv) { + cfg80211_err("osif_priv is null"); + goto fail; + } + + wdev = osif_priv->wdev; + if (!wdev) { + cfg80211_err("wireless dev is null"); + goto fail; + } + + cfg80211_mgmt_tx_status( + wdev, + tx_cnf->action_cookie, + tx_cnf->buf, tx_cnf->buf_len, + (bool)tx_cnf->status, GFP_KERNEL); +fail: + wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID); +} + +/** + * wlan_p2p_lo_event_callback() - Callback for listen offload event + * @user_data: pointer to soc object + * @p2p_lo_event: listen offload event information + * + * This callback will be used to give listen offload event to os interface. + * + * Return: None + */ +static void wlan_p2p_lo_event_callback(void *user_data, + struct p2p_lo_event *p2p_lo_event) +{ + struct wlan_objmgr_psoc *psoc; + struct wlan_objmgr_vdev *vdev; + struct vdev_osif_priv *osif_priv; + struct wireless_dev *wdev; + struct sk_buff *vendor_event; + + cfg80211_debug("user data:%p, vdev id:%d, reason code:%d", + user_data, p2p_lo_event->vdev_id, + p2p_lo_event->reason_code); + + psoc = user_data; + if (!psoc) { + cfg80211_err("psoc is null"); + return; + } + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, + p2p_lo_event->vdev_id, WLAN_P2P_ID); + if (!vdev) { + cfg80211_err("vdev is null"); + return; + } + + wlan_vdev_obj_lock(vdev); + osif_priv = wlan_vdev_get_ospriv(vdev); + wlan_vdev_obj_unlock(vdev); + if (!osif_priv) { + cfg80211_err("osif_priv is null"); + goto fail; + } + + wdev = osif_priv->wdev; + if (!wdev) { + cfg80211_err("wireless dev is null"); + goto fail; + } + + vendor_event = cfg80211_vendor_event_alloc(wdev->wiphy, NULL, + sizeof(uint32_t) + NLMSG_HDRLEN, + QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX, + GFP_KERNEL); + if (!vendor_event) { + cfg80211_err("cfg80211_vendor_event_alloc failed"); + goto fail; + } + + if (nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON, + p2p_lo_event->reason_code)) { + cfg80211_err("nla put failed"); + kfree_skb(vendor_event); + goto fail; + } + + cfg80211_vendor_event(vendor_event, GFP_KERNEL); + +fail: + wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID); +} + +/** + * wlan_p2p_event_callback() - Callback for P2P event + * @user_data: pointer to soc object + * @p2p_event: p2p event information + * + * This callback will be used to give p2p event to os interface. + * + * Return: None + */ +static void wlan_p2p_event_callback(void *user_data, + struct p2p_event *p2p_event) +{ + struct wlan_objmgr_psoc *psoc; + struct wlan_objmgr_vdev *vdev; + struct ieee80211_channel *chan; + struct vdev_osif_priv *osif_priv; + struct wireless_dev *wdev; + + cfg80211_debug("user data:%p, vdev id:%d, event type:%d", + user_data, p2p_event->vdev_id, p2p_event->roc_event); + + psoc = user_data; + if (!psoc) { + cfg80211_err("psoc is null"); + return; + } + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, + p2p_event->vdev_id, WLAN_P2P_ID); + if (!vdev) { + cfg80211_err("vdev is null"); + return; + } + + wlan_vdev_obj_lock(vdev); + osif_priv = wlan_vdev_get_ospriv(vdev); + wlan_vdev_obj_unlock(vdev); + if (!osif_priv) { + cfg80211_err("osif_priv is null"); + goto fail; + } + + wdev = osif_priv->wdev; + if (!wdev) { + cfg80211_err("wireless dev is null"); + goto fail; + } + + chan = __ieee80211_get_channel(wdev->wiphy, + wlan_chan_to_freq(p2p_event->chan)); + if (p2p_event->roc_event == ROC_EVENT_READY_ON_CHAN) { + cfg80211_ready_on_channel(wdev, + p2p_event->cookie, chan, + p2p_event->duration, GFP_KERNEL); + } else if (p2p_event->roc_event == ROC_EVENT_COMPLETED) { + cfg80211_remain_on_channel_expired(wdev, + p2p_event->cookie, chan, GFP_KERNEL); + } else { + cfg80211_err("Invalid p2p event"); + } + +fail: + wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID); +} + +QDF_STATUS wlan_p2p_start(struct wlan_objmgr_psoc *psoc) +{ + struct p2p_start_param start_param; + + if (!psoc) { + cfg80211_err("psoc null"); + return QDF_STATUS_E_INVAL; + } + + start_param.rx_cb = wlan_p2p_rx_callback; + start_param.rx_cb_data = psoc; + start_param.event_cb = wlan_p2p_event_callback; + start_param.event_cb_data = psoc; + start_param.tx_cnf_cb = wlan_p2p_action_tx_cnf_callback; + start_param.tx_cnf_cb_data = psoc; + start_param.lo_event_cb = wlan_p2p_lo_event_callback; + start_param.lo_event_cb_data = psoc; + + return ucfg_p2p_psoc_start(psoc, &start_param); +} + +QDF_STATUS wlan_p2p_stop(struct wlan_objmgr_psoc *psoc) +{ + if (!psoc) { + cfg80211_err("psoc null"); + return QDF_STATUS_E_INVAL; + } + + return ucfg_p2p_psoc_stop(psoc); +} + +int wlan_cfg80211_roc(struct wlan_objmgr_vdev *vdev, + struct ieee80211_channel *chan, uint32_t duration, + uint64_t *cookie) +{ + struct p2p_roc_req roc_req; + struct wlan_objmgr_psoc *psoc; + uint8_t vdev_id; + + if (!vdev) { + cfg80211_err("invalid vdev object"); + return -EINVAL; + } + + if (!chan) { + cfg80211_err("invalid channel"); + return -EINVAL; + } + + wlan_vdev_obj_lock(vdev); + psoc = wlan_vdev_get_psoc(vdev); + vdev_id = wlan_vdev_get_id(vdev); + wlan_vdev_obj_unlock(vdev); + if (!psoc) { + cfg80211_err("psoc handle is NULL"); + return QDF_STATUS_E_INVAL; + } + + roc_req.chan = (uint32_t)wlan_freq_to_chan(chan->center_freq); + roc_req.duration = duration; + roc_req.vdev_id = (uint32_t)vdev_id; + + return qdf_status_to_os_return( + ucfg_p2p_roc_req(psoc, &roc_req, cookie)); +} + +int wlan_cfg80211_cancel_roc(struct wlan_objmgr_vdev *vdev, + uint64_t cookie) +{ + struct wlan_objmgr_psoc *psoc; + + if (!vdev) { + cfg80211_err("invalid vdev object"); + return -EINVAL; + } + + wlan_vdev_obj_lock(vdev); + psoc = wlan_vdev_get_psoc(vdev); + wlan_vdev_obj_unlock(vdev); + if (!psoc) { + cfg80211_err("psoc handle is NULL"); + return QDF_STATUS_E_INVAL; + } + + return qdf_status_to_os_return( + ucfg_p2p_roc_cancel_req(psoc, cookie)); +} + +int wlan_cfg80211_mgmt_tx(struct wlan_objmgr_vdev *vdev, + struct ieee80211_channel *chan, bool offchan, + unsigned int wait, + const uint8_t *buf, uint32_t len, bool no_cck, + bool dont_wait_for_ack, uint64_t *cookie) +{ + struct p2p_mgmt_tx mgmt_tx; + struct wlan_objmgr_psoc *psoc; + uint8_t vdev_id; + + if (!vdev) { + cfg80211_err("invalid vdev object"); + return -EINVAL; + } + + if (!chan) { + cfg80211_err("invalid channel"); + return -EINVAL; + } + + wlan_vdev_obj_lock(vdev); + psoc = wlan_vdev_get_psoc(vdev); + vdev_id = wlan_vdev_get_id(vdev); + wlan_vdev_obj_unlock(vdev); + if (!psoc) { + cfg80211_err("psoc handle is NULL"); + return QDF_STATUS_E_INVAL; + } + + mgmt_tx.vdev_id = (uint32_t)vdev_id; + mgmt_tx.chan = (uint32_t)wlan_freq_to_chan(chan->center_freq); + mgmt_tx.wait = wait; + mgmt_tx.len = len; + mgmt_tx.no_cck = (uint32_t)no_cck; + mgmt_tx.dont_wait_for_ack = (uint32_t)dont_wait_for_ack; + mgmt_tx.buf = buf; + + return qdf_status_to_os_return( + ucfg_p2p_mgmt_tx(psoc, &mgmt_tx, cookie)); +} + +int wlan_cfg80211_mgmt_tx_cancel(struct wlan_objmgr_vdev *vdev, + uint64_t cookie) +{ + struct wlan_objmgr_psoc *psoc; + + if (!vdev) { + cfg80211_err("invalid vdev object"); + return -EINVAL; + } + + wlan_vdev_obj_lock(vdev); + psoc = wlan_vdev_get_psoc(vdev); + wlan_vdev_obj_unlock(vdev); + if (!psoc) { + cfg80211_err("psoc handle is NULL"); + return QDF_STATUS_E_INVAL; + } + + return qdf_status_to_os_return( + ucfg_p2p_mgmt_tx_cancel(psoc, cookie)); +} From 2761077ad549c57aa20d26fc86b543dfe57ec707 Mon Sep 17 00:00:00 2001 From: Wu Gao Date: Wed, 22 Mar 2017 13:18:15 +0800 Subject: [PATCH 02/13] qcacmn: mgmt frame txrx Modify P2P IE and tx mgmt frame. Handles tx confirm and rx frame events. Change-Id: I0c0ada2e12ee5ebdd3e8d7b7a6f2bd2af4357548 CRs-Fixed: 2015297 --- src/wlan_cfg80211_p2p.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/wlan_cfg80211_p2p.c b/src/wlan_cfg80211_p2p.c index 8058a97f1b..853513955a 100644 --- a/src/wlan_cfg80211_p2p.c +++ b/src/wlan_cfg80211_p2p.c @@ -127,6 +127,7 @@ static void wlan_p2p_action_tx_cnf_callback(void *user_data, struct wlan_objmgr_vdev *vdev; struct vdev_osif_priv *osif_priv; struct wireless_dev *wdev; + bool is_success; cfg80211_info("user data:%p, action cookie:%llx, buf:%p, len:%d, tx status:%d", user_data, tx_cnf->action_cookie, tx_cnf->buf, @@ -159,11 +160,12 @@ static void wlan_p2p_action_tx_cnf_callback(void *user_data, goto fail; } + is_success = tx_cnf->status ? false : true; cfg80211_mgmt_tx_status( wdev, tx_cnf->action_cookie, tx_cnf->buf, tx_cnf->buf_len, - (bool)tx_cnf->status, GFP_KERNEL); + is_success, GFP_KERNEL); fail: wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID); } @@ -360,7 +362,7 @@ int wlan_cfg80211_roc(struct wlan_objmgr_vdev *vdev, wlan_vdev_obj_unlock(vdev); if (!psoc) { cfg80211_err("psoc handle is NULL"); - return QDF_STATUS_E_INVAL; + return -EINVAL; } roc_req.chan = (uint32_t)wlan_freq_to_chan(chan->center_freq); @@ -386,7 +388,7 @@ int wlan_cfg80211_cancel_roc(struct wlan_objmgr_vdev *vdev, wlan_vdev_obj_unlock(vdev); if (!psoc) { cfg80211_err("psoc handle is NULL"); - return QDF_STATUS_E_INVAL; + return -EINVAL; } return qdf_status_to_os_return( @@ -419,7 +421,7 @@ int wlan_cfg80211_mgmt_tx(struct wlan_objmgr_vdev *vdev, wlan_vdev_obj_unlock(vdev); if (!psoc) { cfg80211_err("psoc handle is NULL"); - return QDF_STATUS_E_INVAL; + return -EINVAL; } mgmt_tx.vdev_id = (uint32_t)vdev_id; @@ -428,6 +430,7 @@ int wlan_cfg80211_mgmt_tx(struct wlan_objmgr_vdev *vdev, mgmt_tx.len = len; mgmt_tx.no_cck = (uint32_t)no_cck; mgmt_tx.dont_wait_for_ack = (uint32_t)dont_wait_for_ack; + mgmt_tx.off_chan = (uint32_t)offchan; mgmt_tx.buf = buf; return qdf_status_to_os_return( @@ -449,7 +452,7 @@ int wlan_cfg80211_mgmt_tx_cancel(struct wlan_objmgr_vdev *vdev, wlan_vdev_obj_unlock(vdev); if (!psoc) { cfg80211_err("psoc handle is NULL"); - return QDF_STATUS_E_INVAL; + return -EINVAL; } return qdf_status_to_os_return( From a598cbe5c7cfc43eeefe243f1905b019a8878e55 Mon Sep 17 00:00:00 2001 From: Ajit Pal Singh Date: Sat, 22 Apr 2017 15:40:27 +0530 Subject: [PATCH 03/13] qcacmn: Reject remain on channel if Do_Not_Switch_Channel set Remain on Channel request is rejected: 1) If an AP/GO interface is already active AND 2) Do_Not_Switch_Channel is set for the AP/GO interface AND 3) The requested channel is on the same band but different from the AP/GO channel. We allow one time procedures like GO Negotiation/Provision Discovery/Invitation if the offchannel time is <= 150msecs Change-Id: If19e9a06916891c5d3dbe6823fca72d70ead460d CRs-Fixed: 2037302 --- src/wlan_cfg80211_p2p.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/wlan_cfg80211_p2p.c b/src/wlan_cfg80211_p2p.c index 853513955a..3963b64fd6 100644 --- a/src/wlan_cfg80211_p2p.c +++ b/src/wlan_cfg80211_p2p.c @@ -28,12 +28,14 @@ #include #include #include +#include #include #include #include "wlan_cfg80211.h" #include "wlan_cfg80211_p2p.h" #define MAX_NO_OF_2_4_CHANNELS 14 +#define MAX_OFFCHAN_TIME_FOR_DNBS 150 /** * wlan_p2p_rx_callback() - Callback for rx mgmt frame @@ -345,6 +347,8 @@ int wlan_cfg80211_roc(struct wlan_objmgr_vdev *vdev, struct p2p_roc_req roc_req; struct wlan_objmgr_psoc *psoc; uint8_t vdev_id; + bool ok; + int ret; if (!vdev) { cfg80211_err("invalid vdev object"); @@ -369,6 +373,18 @@ int wlan_cfg80211_roc(struct wlan_objmgr_vdev *vdev, roc_req.duration = duration; roc_req.vdev_id = (uint32_t)vdev_id; + ret = policy_mgr_is_chan_ok_for_dnbs(psoc, roc_req.chan, &ok); + if (QDF_IS_STATUS_ERROR(ret)) { + cfg80211_err("policy_mgr_is_chan_ok_for_dnbs():ret:%d", + ret); + return -EINVAL; + } + + if (!ok) { + cfg80211_err("channel%d not OK for DNBS", roc_req.chan); + return -EINVAL; + } + return qdf_status_to_os_return( ucfg_p2p_roc_req(psoc, &roc_req, cookie)); } @@ -424,6 +440,28 @@ int wlan_cfg80211_mgmt_tx(struct wlan_objmgr_vdev *vdev, return -EINVAL; } + /** + * When offchannel time is more than MAX_OFFCHAN_TIME_FOR_DNBS, + * allow offchannel only if Do_Not_Switch_Channel is not set. + */ + if (wait > MAX_OFFCHAN_TIME_FOR_DNBS) { + int ret; + bool ok; + uint32_t channel = wlan_freq_to_chan(chan->center_freq); + + ret = policy_mgr_is_chan_ok_for_dnbs(psoc, channel, &ok); + if (QDF_IS_STATUS_ERROR(ret)) { + cfg80211_err("policy_mgr_is_chan_ok_for_dnbs():ret:%d", + ret); + return -EINVAL; + } + if (!ok) { + cfg80211_err("Rejecting mgmt_tx for channel:%d as DNSC is set", + channel); + return -EINVAL; + } + } + mgmt_tx.vdev_id = (uint32_t)vdev_id; mgmt_tx.chan = (uint32_t)wlan_freq_to_chan(chan->center_freq); mgmt_tx.wait = wait; From c7bf604323512b53f5f5800b017aea3b95f4ea0c Mon Sep 17 00:00:00 2001 From: Vivek Date: Wed, 21 Jun 2017 08:21:58 +0530 Subject: [PATCH 04/13] qcacmn: Remove vdev/peer locks for trivial APIs Remove vdev/peer locks from trivial API's. This follows the changes from which the lock requirement from few simple APIs are removed. Change-Id: I9972d51dfd1a42bdedbfd0fd4e67af03d030a1f5 CRs-Fixed: 2060880 --- src/wlan_cfg80211_p2p.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/wlan_cfg80211_p2p.c b/src/wlan_cfg80211_p2p.c index 3963b64fd6..57429a1db8 100644 --- a/src/wlan_cfg80211_p2p.c +++ b/src/wlan_cfg80211_p2p.c @@ -72,9 +72,7 @@ static void wlan_p2p_rx_callback(void *user_data, return; } - wlan_vdev_obj_lock(vdev); osif_priv = wlan_vdev_get_ospriv(vdev); - wlan_vdev_obj_unlock(vdev); if (!osif_priv) { cfg80211_err("osif_priv is null"); goto fail; @@ -148,9 +146,7 @@ static void wlan_p2p_action_tx_cnf_callback(void *user_data, return; } - wlan_vdev_obj_lock(vdev); osif_priv = wlan_vdev_get_ospriv(vdev); - wlan_vdev_obj_unlock(vdev); if (!osif_priv) { cfg80211_err("osif_priv is null"); goto fail; @@ -207,9 +203,7 @@ static void wlan_p2p_lo_event_callback(void *user_data, return; } - wlan_vdev_obj_lock(vdev); osif_priv = wlan_vdev_get_ospriv(vdev); - wlan_vdev_obj_unlock(vdev); if (!osif_priv) { cfg80211_err("osif_priv is null"); goto fail; @@ -278,9 +272,7 @@ static void wlan_p2p_event_callback(void *user_data, return; } - wlan_vdev_obj_lock(vdev); osif_priv = wlan_vdev_get_ospriv(vdev); - wlan_vdev_obj_unlock(vdev); if (!osif_priv) { cfg80211_err("osif_priv is null"); goto fail; @@ -360,10 +352,8 @@ int wlan_cfg80211_roc(struct wlan_objmgr_vdev *vdev, return -EINVAL; } - wlan_vdev_obj_lock(vdev); psoc = wlan_vdev_get_psoc(vdev); vdev_id = wlan_vdev_get_id(vdev); - wlan_vdev_obj_unlock(vdev); if (!psoc) { cfg80211_err("psoc handle is NULL"); return -EINVAL; @@ -399,9 +389,7 @@ int wlan_cfg80211_cancel_roc(struct wlan_objmgr_vdev *vdev, return -EINVAL; } - wlan_vdev_obj_lock(vdev); psoc = wlan_vdev_get_psoc(vdev); - wlan_vdev_obj_unlock(vdev); if (!psoc) { cfg80211_err("psoc handle is NULL"); return -EINVAL; @@ -431,10 +419,8 @@ int wlan_cfg80211_mgmt_tx(struct wlan_objmgr_vdev *vdev, return -EINVAL; } - wlan_vdev_obj_lock(vdev); psoc = wlan_vdev_get_psoc(vdev); vdev_id = wlan_vdev_get_id(vdev); - wlan_vdev_obj_unlock(vdev); if (!psoc) { cfg80211_err("psoc handle is NULL"); return -EINVAL; @@ -485,9 +471,7 @@ int wlan_cfg80211_mgmt_tx_cancel(struct wlan_objmgr_vdev *vdev, return -EINVAL; } - wlan_vdev_obj_lock(vdev); psoc = wlan_vdev_get_psoc(vdev); - wlan_vdev_obj_unlock(vdev); if (!psoc) { cfg80211_err("psoc handle is NULL"); return -EINVAL; From 63b4af0cef5f8d1bbd98f192ceb300573a6a0091 Mon Sep 17 00:00:00 2001 From: Dustin Brown Date: Tue, 15 Aug 2017 12:31:27 -0700 Subject: [PATCH 05/13] qcacmn: Remove name indirection for ieee80211_get_channel() Versions 4.11+ of the Linux kernel removed '__' from the beginning of ieee80211_get_channel(). Migrate all calls from __ieee80211_get_channel to ieee80211_get_channel instead. Change-Id: I0548259beb59f0a3cb27fe6fee1dd9626cc624cc CRs-Fixed: 2098795 --- src/wlan_cfg80211_p2p.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wlan_cfg80211_p2p.c b/src/wlan_cfg80211_p2p.c index 57429a1db8..17d5178c34 100644 --- a/src/wlan_cfg80211_p2p.c +++ b/src/wlan_cfg80211_p2p.c @@ -284,8 +284,8 @@ static void wlan_p2p_event_callback(void *user_data, goto fail; } - chan = __ieee80211_get_channel(wdev->wiphy, - wlan_chan_to_freq(p2p_event->chan)); + chan = ieee80211_get_channel(wdev->wiphy, + wlan_chan_to_freq(p2p_event->chan)); if (p2p_event->roc_event == ROC_EVENT_READY_ON_CHAN) { cfg80211_ready_on_channel(wdev, p2p_event->cookie, chan, From 95a3ebacc1efbb13faa534e4d52f73b8d001769c Mon Sep 17 00:00:00 2001 From: Jeff Johnson Date: Mon, 18 Sep 2017 10:11:16 -0700 Subject: [PATCH 06/13] qcacmn: os_if: Replace instances of unadorned %p Replace instances of unadorned %p in os_if. Change-Id: Iddbd3deb6562e462358ed7bd0f51b18a027eee5a CRs-Fixed: 2111274 --- src/wlan_cfg80211_p2p.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/wlan_cfg80211_p2p.c b/src/wlan_cfg80211_p2p.c index 17d5178c34..96be4c5b87 100644 --- a/src/wlan_cfg80211_p2p.c +++ b/src/wlan_cfg80211_p2p.c @@ -55,7 +55,7 @@ static void wlan_p2p_rx_callback(void *user_data, struct wireless_dev *wdev; uint16_t freq; - cfg80211_debug("user data:%p, vdev id:%d, rssi:%d, buf:%p, len:%d", + cfg80211_debug("user data:%pK, vdev id:%d, rssi:%d, buf:%pK, len:%d", user_data, rx_frame->vdev_id, rx_frame->rx_rssi, rx_frame->buf, rx_frame->frame_len); @@ -129,7 +129,7 @@ static void wlan_p2p_action_tx_cnf_callback(void *user_data, struct wireless_dev *wdev; bool is_success; - cfg80211_info("user data:%p, action cookie:%llx, buf:%p, len:%d, tx status:%d", + cfg80211_info("user data:%pK, action cookie:%llx, buf:%pK, len:%d, tx status:%d", user_data, tx_cnf->action_cookie, tx_cnf->buf, tx_cnf->buf_len, tx_cnf->status); @@ -186,7 +186,7 @@ static void wlan_p2p_lo_event_callback(void *user_data, struct wireless_dev *wdev; struct sk_buff *vendor_event; - cfg80211_debug("user data:%p, vdev id:%d, reason code:%d", + cfg80211_debug("user data:%pK, vdev id:%d, reason code:%d", user_data, p2p_lo_event->vdev_id, p2p_lo_event->reason_code); @@ -256,7 +256,7 @@ static void wlan_p2p_event_callback(void *user_data, struct vdev_osif_priv *osif_priv; struct wireless_dev *wdev; - cfg80211_debug("user data:%p, vdev id:%d, event type:%d", + cfg80211_debug("user data:%pK, vdev id:%d, event type:%d", user_data, p2p_event->vdev_id, p2p_event->roc_event); psoc = user_data; From f2dce0cf16439d4b396ea34df624b5789f46bef1 Mon Sep 17 00:00:00 2001 From: Wu Gao Date: Fri, 25 Aug 2017 15:28:50 +0800 Subject: [PATCH 07/13] qcacmn: Initialize variable in cfg80211 roc and mgmt tx To avoid unexpect issue, initialize variable in cfg80211 roc and mgmt tx. Change-Id: I5cc11cf011a136f29f6815142a45918ed71583fa CRs-Fixed: 2091906 --- src/wlan_cfg80211_p2p.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wlan_cfg80211_p2p.c b/src/wlan_cfg80211_p2p.c index 96be4c5b87..372a115e39 100644 --- a/src/wlan_cfg80211_p2p.c +++ b/src/wlan_cfg80211_p2p.c @@ -336,7 +336,7 @@ int wlan_cfg80211_roc(struct wlan_objmgr_vdev *vdev, struct ieee80211_channel *chan, uint32_t duration, uint64_t *cookie) { - struct p2p_roc_req roc_req; + struct p2p_roc_req roc_req = {0}; struct wlan_objmgr_psoc *psoc; uint8_t vdev_id; bool ok; @@ -405,7 +405,7 @@ int wlan_cfg80211_mgmt_tx(struct wlan_objmgr_vdev *vdev, const uint8_t *buf, uint32_t len, bool no_cck, bool dont_wait_for_ack, uint64_t *cookie) { - struct p2p_mgmt_tx mgmt_tx; + struct p2p_mgmt_tx mgmt_tx = {0}; struct wlan_objmgr_psoc *psoc; uint8_t vdev_id; From d82af43cd3ba46325b1cf5ff659323e19b6104a5 Mon Sep 17 00:00:00 2001 From: Wu Gao Date: Fri, 19 Jan 2018 22:58:32 +0530 Subject: [PATCH 08/13] qcacmn: Save vdev id of current roc ctx RX mgmt frame is from interrupt thread, it may be access freed roc ctx for low rate case. Save vdev id of current roc ctx in p2p psoc object. Low log level of P2P RX and TX conf since too many output. Change-Id: I4c944244f32b844d78bb69d66e341a1f3bf13abf CRs-Fixed: 2180116 --- src/wlan_cfg80211_p2p.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wlan_cfg80211_p2p.c b/src/wlan_cfg80211_p2p.c index 372a115e39..e6ab17ab4d 100644 --- a/src/wlan_cfg80211_p2p.c +++ b/src/wlan_cfg80211_p2p.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -91,7 +91,7 @@ static void wlan_p2p_rx_callback(void *user_data, freq = ieee80211_channel_to_frequency( rx_frame->rx_chan, NL80211_BAND_5GHZ); - cfg80211_notice("Indicate frame over nl80211, vdev id:%d, idx:%d", + cfg80211_debug("Indicate frame over nl80211, vdev id:%d, idx:%d", rx_frame->vdev_id, wdev->netdev->ifindex); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) @@ -129,7 +129,7 @@ static void wlan_p2p_action_tx_cnf_callback(void *user_data, struct wireless_dev *wdev; bool is_success; - cfg80211_info("user data:%pK, action cookie:%llx, buf:%pK, len:%d, tx status:%d", + cfg80211_debug("user data:%pK, action cookie:%llx, buf:%pK, len:%d, tx status:%d", user_data, tx_cnf->action_cookie, tx_cnf->buf, tx_cnf->buf_len, tx_cnf->status); From 7044285902f51574dde43d26b7d942f2d3730eb0 Mon Sep 17 00:00:00 2001 From: Wu Gao Date: Mon, 21 May 2018 15:28:28 +0800 Subject: [PATCH 09/13] qcacmn: Check return value for channel conversion It may return NULL, which pass to another function and dereference it. Check return value, don't pass to another function if return value is NULL. Change-Id: Ib2e87231bb724c5631c12e9bee98c22d4dcc9bf2 CRs-Fixed: 2233639 --- src/wlan_cfg80211_p2p.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/wlan_cfg80211_p2p.c b/src/wlan_cfg80211_p2p.c index e6ab17ab4d..5f383e732e 100644 --- a/src/wlan_cfg80211_p2p.c +++ b/src/wlan_cfg80211_p2p.c @@ -286,6 +286,11 @@ static void wlan_p2p_event_callback(void *user_data, chan = ieee80211_get_channel(wdev->wiphy, wlan_chan_to_freq(p2p_event->chan)); + if (!chan) { + cfg80211_err("channel conversion failed"); + goto fail; + } + if (p2p_event->roc_event == ROC_EVENT_READY_ON_CHAN) { cfg80211_ready_on_channel(wdev, p2p_event->cookie, chan, From 6066a963685c0c467c69a10b70f5c8f8cfd1b46a Mon Sep 17 00:00:00 2001 From: Rachit Kankane Date: Tue, 31 Jul 2018 16:26:38 +0530 Subject: [PATCH 10/13] qcacmn: Featurize P2P Listen Offload P2P Listen offload is not a requirement for Genoa, hence featurize P2P listen offload code to save memory foot-print for Genoa. Change-Id: I3c32b4ee2b37421e49acee4bd20d36e7a8a3bf77 CRs-Fixed: 2304555 --- src/wlan_cfg80211_p2p.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/wlan_cfg80211_p2p.c b/src/wlan_cfg80211_p2p.c index 5f383e732e..2cfe0f3bf3 100644 --- a/src/wlan_cfg80211_p2p.c +++ b/src/wlan_cfg80211_p2p.c @@ -168,6 +168,7 @@ fail: wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID); } +#ifdef FEATURE_P2P_LISTEN_OFFLOAD /** * wlan_p2p_lo_event_callback() - Callback for listen offload event * @user_data: pointer to soc object @@ -238,6 +239,18 @@ fail: wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID); } +static inline void wlan_p2p_init_lo_event(struct p2p_start_param *start_param, + struct wlan_objmgr_psoc *psoc) +{ + start_param->lo_event_cb = wlan_p2p_lo_event_callback; + start_param->lo_event_cb_data = psoc; +} +#else +static inline void wlan_p2p_init_lo_event(struct p2p_start_param *start_param, + struct wlan_objmgr_psoc *psoc) +{ +} +#endif /* FEATURE_P2P_LISTEN_OFFLOAD */ /** * wlan_p2p_event_callback() - Callback for P2P event * @user_data: pointer to soc object @@ -321,8 +334,7 @@ QDF_STATUS wlan_p2p_start(struct wlan_objmgr_psoc *psoc) start_param.event_cb_data = psoc; start_param.tx_cnf_cb = wlan_p2p_action_tx_cnf_callback; start_param.tx_cnf_cb_data = psoc; - start_param.lo_event_cb = wlan_p2p_lo_event_callback; - start_param.lo_event_cb_data = psoc; + wlan_p2p_init_lo_event(&start_param, psoc); return ucfg_p2p_psoc_start(psoc, &start_param); } From e2492c05d3bef0117d0efec9b5275d606fcfd033 Mon Sep 17 00:00:00 2001 From: Liangwei Dong Date: Wed, 19 Sep 2018 23:35:14 -0400 Subject: [PATCH 11/13] 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 --- src/wlan_cfg80211_p2p.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wlan_cfg80211_p2p.c b/src/wlan_cfg80211_p2p.c index 2cfe0f3bf3..e4911ae8e2 100644 --- a/src/wlan_cfg80211_p2p.c +++ b/src/wlan_cfg80211_p2p.c @@ -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)); } From 22109fd1503fc59f44b7baf14b4582a025634be2 Mon Sep 17 00:00:00 2001 From: Linux Build Service Account Date: Tue, 4 Dec 2018 15:36:30 +0530 Subject: [PATCH 12/13] Move os_if/linux/p2p to components/os_if/linux/p2p Change-Id: I834f4ca6b8f5e56559a4de3f28c955d78deca7cb --- {inc => components/os_if/linux/p2p/inc}/wlan_cfg80211_p2p.h | 0 {src => components/os_if/linux/p2p/src}/wlan_cfg80211_p2p.c | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {inc => components/os_if/linux/p2p/inc}/wlan_cfg80211_p2p.h (100%) rename {src => components/os_if/linux/p2p/src}/wlan_cfg80211_p2p.c (100%) diff --git a/inc/wlan_cfg80211_p2p.h b/components/os_if/linux/p2p/inc/wlan_cfg80211_p2p.h similarity index 100% rename from inc/wlan_cfg80211_p2p.h rename to components/os_if/linux/p2p/inc/wlan_cfg80211_p2p.h diff --git a/src/wlan_cfg80211_p2p.c b/components/os_if/linux/p2p/src/wlan_cfg80211_p2p.c similarity index 100% rename from src/wlan_cfg80211_p2p.c rename to components/os_if/linux/p2p/src/wlan_cfg80211_p2p.c From 09afffa36feb0bc3b474e514df981f9151c7afc6 Mon Sep 17 00:00:00 2001 From: Linux Build Service Account Date: Tue, 4 Dec 2018 16:04:42 +0530 Subject: [PATCH 13/13] Move to os_if/p2p Change-Id: I08c7707a4a1acc4caa1842acd21e2104ddbd084a --- {components/os_if/linux => os_if}/p2p/inc/wlan_cfg80211_p2p.h | 0 {components/os_if/linux => os_if}/p2p/src/wlan_cfg80211_p2p.c | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {components/os_if/linux => os_if}/p2p/inc/wlan_cfg80211_p2p.h (100%) rename {components/os_if/linux => os_if}/p2p/src/wlan_cfg80211_p2p.c (100%) diff --git a/components/os_if/linux/p2p/inc/wlan_cfg80211_p2p.h b/os_if/p2p/inc/wlan_cfg80211_p2p.h similarity index 100% rename from components/os_if/linux/p2p/inc/wlan_cfg80211_p2p.h rename to os_if/p2p/inc/wlan_cfg80211_p2p.h diff --git a/components/os_if/linux/p2p/src/wlan_cfg80211_p2p.c b/os_if/p2p/src/wlan_cfg80211_p2p.c similarity index 100% rename from components/os_if/linux/p2p/src/wlan_cfg80211_p2p.c rename to os_if/p2p/src/wlan_cfg80211_p2p.c