diff --git a/components/p2p/core/src/wlan_p2p_off_chan_tx.c b/components/p2p/core/src/wlan_p2p_off_chan_tx.c index c53efb40f951..f0bea5c35d62 100644 --- a/components/p2p/core/src/wlan_p2p_off_chan_tx.c +++ b/components/p2p/core/src/wlan_p2p_off_chan_tx.c @@ -1548,6 +1548,13 @@ static QDF_STATUS p2p_populate_rmf_field(struct tx_action_context *tx_ctx, *ppbuf = frame; *ppkt = pkt; *size = frame_len; + /* + * Some target which support sending mgmt frame based on htt + * would DMA write this PMF tx frame buffer, it may cause smmu + * check permission fault, set a flag to do bi-direction DMA + * map, normal tx unmap is enough for this case. + */ + QDF_NBUF_CB_TX_DMA_BI_MAP(pkt) = 1; } return status; diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 3c0cc7ed7f17..8785da7cbb26 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -2025,6 +2025,17 @@ struct hdd_adapter *hdd_get_adapter_by_vdev(struct hdd_context *hdd_ctx, struct hdd_adapter *hdd_get_adapter_by_macaddr(struct hdd_context *hdd_ctx, tSirMacAddr mac_addr); +/** + * hdd_get_adapter_home_channel() - return home channel of adapter + * @adapter: hdd adapter of vdev + * + * This function returns operation channel of station/p2p-cli if + * connected, returns opration channel of sap/p2p-go if started. + * + * Return: home channel if connected/started or invalid channel 0 + */ +uint8_t hdd_get_adapter_home_channel(struct hdd_adapter *adapter); + /* * hdd_get_adapter_by_rand_macaddr() - find Random mac adapter * @hdd_ctx: hdd context diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index e8c9211b22da..1df288c3d3c5 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -699,6 +699,25 @@ int hdd_validate_channel_and_bandwidth(struct hdd_adapter *adapter, return 0; } +uint8_t hdd_get_adapter_home_channel(struct hdd_adapter *adapter) +{ + uint8_t home_channel = 0; + + if ((adapter->device_mode == QDF_SAP_MODE || + adapter->device_mode == QDF_P2P_GO_MODE) && + test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) { + home_channel = adapter->session.ap.operating_channel; + } else if ((adapter->device_mode == QDF_STA_MODE || + adapter->device_mode == QDF_P2P_CLIENT_MODE) && + adapter->session.station.conn_info.conn_state == + eConnectionState_Associated) { + home_channel = + adapter->session.station.conn_info.channel; + } + + return home_channel; +} + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) static inline struct net_device *hdd_net_dev_from_notifier(void *context) { diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c index f3e076a6f7e7..ebbc61e06a53 100644 --- a/core/hdd/src/wlan_hdd_p2p.c +++ b/core/hdd/src/wlan_hdd_p2p.c @@ -222,6 +222,35 @@ int wlan_hdd_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, return errno; } +/** + * wlan_hdd_validate_and_override_offchan() - To validate and override offchan + * @adapter: hdd adapter of vdev + * @chan: channel info of mgmt to be sent + * @offchan: off channel flag to check and override + * + * This function is to validate the channel info against adapter current state + * and home channel, if off channel not needed, override offchan flag. + * + * Return: None + */ +static void +wlan_hdd_validate_and_override_offchan(struct hdd_adapter *adapter, + struct ieee80211_channel *chan, + bool *offchan) +{ + uint8_t home_ch; + + if (!offchan || !chan || !(*offchan)) + return; + + home_ch = hdd_get_adapter_home_channel(adapter); + + if (ieee80211_frequency_to_channel(chan->center_freq) == home_ch) { + hdd_debug("override offchan to 0 at home channel %d", home_ch); + *offchan = false; + } +} + static int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, struct ieee80211_channel *chan, bool offchan, unsigned int wait, @@ -278,6 +307,14 @@ static int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, return -EINVAL; } + hdd_debug("device_mode:%d type:%d sub_type:%d chan:%d", + adapter->device_mode, type, sub_type, + chan ? chan->center_freq : 0); + hdd_debug("wait:%d offchan:%d do_not_wait_ack:%d", + wait, offchan, dont_wait_for_ack); + + wlan_hdd_validate_and_override_offchan(adapter, chan, &offchan); + qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_OS_IF, TRACE_CODE_HDD_SEND_MGMT_TX, wlan_vdev_get_id(adapter->vdev), 0);