channels[i] = request->channels[i];
chan_count = request->n_channels;
- if (SLSI_IS_VIF_INDEX_WLAN(ndev_vif))
+ if (SLSI_IS_VIF_INDEX_WLAN(ndev_vif)) {
if (sdev->initial_scan) {
sdev->initial_scan = false;
scan_type = FAPI_SCANTYPE_INITIAL_SCAN;
}
+ ndev_vif->unsync.slsi_p2p_continuous_fullscan = false;
+ }
/* Update scan timing for P2P social channels scan. */
if ((request->ie) &&
* with GO's operating channel comes on P2P device. Hence added the
* check for n_channels as 1
*/
+ if (!ndev_vif->drv_in_p2p_procedure) {
+ if (delayed_work_pending(&ndev_vif->unsync.unset_channel_expiry_work)) {
+ cancel_delayed_work(&ndev_vif->unsync.unset_channel_expiry_work);
+ slsi_mlme_spare_signal_1(sdev, dev);
+ ndev_vif->driver_channel = 0;
+ }
+ }
if (request->n_channels == SLSI_P2P_SOCIAL_CHAN_COUNT || request->n_channels == 1) {
p2p_state = P2P_SCANNING;
scan_type = FAPI_SCANTYPE_P2P_SCAN_SOCIAL;
+ ndev_vif->unsync.slsi_p2p_continuous_fullscan = false;
} else if (request->n_channels > SLSI_P2P_SOCIAL_CHAN_COUNT) {
- scan_type = FAPI_SCANTYPE_P2P_SCAN_FULL;
+ if (!ndev_vif->unsync.slsi_p2p_continuous_fullscan) {
+ scan_type = FAPI_SCANTYPE_P2P_SCAN_FULL;
+ ndev_vif->unsync.slsi_p2p_continuous_fullscan = true;
+ } else {
+ int count = 0, chann = 0;
+
+ scan_type = FAPI_SCANTYPE_P2P_SCAN_SOCIAL;
+ ndev_vif->unsync.slsi_p2p_continuous_fullscan = false;
+ for (i = 0; i < request->n_channels; i++) {
+ chann = channels[i]->hw_value & 0xFF;
+ if (chann == 1 || chann == 6 || chann == 11) {
+ channels[count] = request->channels[i];
+ count++;
+ }
+ }
+ chan_count = count;
+ }
}
}
*/
cancel_delayed_work(&ndev_vif->unsync.roc_expiry_work);
+ if (delayed_work_pending(&ndev_vif->unsync.unset_channel_expiry_work))
+ cancel_delayed_work(&ndev_vif->unsync.unset_channel_expiry_work);
+
/* If action frame tx is in progress and ROC comes, then it would mean action frame tx was done in ROC and
* frame tx ind is awaited, don't change state. Also allow back to back ROC in case it comes.
*/
SLSI_P2P_STATE_CHANGE(sdev, P2P_LISTENING);
exit_with_roc:
+ /* Cancel remain on channel is sent to the supplicant 10ms before the duration
+ *This is to avoid the race condition of supplicant sending cancel remain on channel and
+ *drv sending cancel_remain on channel because of roc expiry.
+ *This race condition causes delay to the next p2p search
+ */
queue_delayed_work(sdev->device_wq, &ndev_vif->unsync.roc_expiry_work,
- msecs_to_jiffies(duration + SLSI_P2P_ROC_EXTRA_MSEC));
+ msecs_to_jiffies(duration - SLSI_P2P_ROC_EXTRA_MSEC));
slsi_assign_cookie_id(cookie, &ndev_vif->unsync.roc_cookie);
SLSI_NET_DBG2(dev, SLSI_CFG80211, "Cookie = 0x%llx\n", *cookie);
cancel_delayed_work(&ndev_vif->unsync.roc_expiry_work);
- /* Supplicant has stopped FIND/LISTEN. Clear Probe Response IEs in firmware and driver */
- if (slsi_mlme_add_info_elements(sdev, dev, FAPI_PURPOSE_PROBE_RESPONSE, NULL, 0) != 0)
- SLSI_NET_ERR(dev, "Clearing Probe Response IEs failed for unsync vif\n");
- slsi_unsync_vif_set_probe_rsp_ie(ndev_vif, NULL, 0);
-
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9))
cfg80211_remain_on_channel_expired(&ndev_vif->wdev, ndev_vif->unsync.roc_cookie, ndev_vif->chan, GFP_KERNEL);
#else
cfg80211_remain_on_channel_expired(ndev_vif->wdev.netdev, ndev_vif->unsync.roc_cookie,
ndev_vif->chan, ndev_vif->channel_type, GFP_KERNEL);
#endif
-
- if (!ndev_vif->drv_in_p2p_procedure) {
- slsi_mlme_spare_signal_1(sdev, dev);
- ndev_vif->driver_channel = 0;
- }
-
+ if (!ndev_vif->drv_in_p2p_procedure) {
+ if (delayed_work_pending(&ndev_vif->unsync.unset_channel_expiry_work))
+ cancel_delayed_work(&ndev_vif->unsync.unset_channel_expiry_work);
+ queue_delayed_work(sdev->device_wq, &ndev_vif->unsync.unset_channel_expiry_work,
+ msecs_to_jiffies(SLSI_P2P_UNSET_CHANNEL_EXTRA_MSEC));
+ }
/* Queue work to delete unsync vif */
slsi_p2p_queue_unsync_vif_del_work(ndev_vif, SLSI_P2P_UNSYNC_VIF_EXTRA_MSEC);
SLSI_P2P_STATE_CHANGE(sdev, P2P_IDLE_VIF_ACTIVE);
/* After sucessful frame transmission, we will move to LISTENING or VIF ACTIVE state.
* Unset channel should not be sent down during p2p procedure.
*/
- if (ndev_vif->drv_in_p2p_procedure == 0) {
- slsi_mlme_spare_signal_1(ndev_vif->sdev, ndev_vif->wdev.netdev);
- ndev_vif->driver_channel = 0;
+ if (!ndev_vif->drv_in_p2p_procedure) {
+ if (delayed_work_pending(&ndev_vif->unsync.unset_channel_expiry_work))
+ cancel_delayed_work(&ndev_vif->unsync.unset_channel_expiry_work);
+ queue_delayed_work(ndev_vif->sdev->device_wq, &ndev_vif->unsync.unset_channel_expiry_work,
+ msecs_to_jiffies(SLSI_P2P_UNSET_CHANNEL_EXTRA_MSEC));
}
slsi_p2p_queue_unsync_vif_del_work(ndev_vif, SLSI_P2P_UNSYNC_VIF_EXTRA_MSEC);
SLSI_P2P_STATE_CHANGE(ndev_vif->sdev, P2P_IDLE_VIF_ACTIVE);
SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
}
+/**
+ * Work to be done after roc expiry or cancel remain on channel:
+ * Unset channel to be sent to Fw.
+ */
+static void slsi_p2p_unset_channel_expiry_work(struct work_struct *work)
+{
+ struct netdev_vif *ndev_vif = container_of((struct delayed_work *)work, struct netdev_vif,
+ unsync.unset_channel_expiry_work);
+ struct slsi_dev *sdev = ndev_vif->sdev;
+ struct net_device *dev = ndev_vif->wdev.netdev;
+
+ SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
+ SLSI_NET_DBG1(ndev_vif->wdev.netdev, SLSI_CFG80211, "Unset channel expiry work-Send Unset Channel\n");
+
+ if (!ndev_vif->drv_in_p2p_procedure) {
+ /* Supplicant has stopped FIND/LISTEN. Clear Probe Response IEs in firmware and driver */
+ if (slsi_mlme_add_info_elements(sdev, dev, FAPI_PURPOSE_PROBE_RESPONSE, NULL, 0) != 0)
+ SLSI_NET_ERR(dev, "Clearing Probe Response IEs failed for unsync vif\n");
+ slsi_unsync_vif_set_probe_rsp_ie(ndev_vif, NULL, 0);
+
+ /* Send Unset Channel */
+ if (ndev_vif->driver_channel != 0) {
+ slsi_mlme_spare_signal_1(sdev, dev);
+ ndev_vif->driver_channel = 0;
+ }
+ }
+ SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+}
+
/* Initializations for P2P - Change vif type to unsync, create workqueue and init work */
int slsi_p2p_init(struct slsi_dev *sdev, struct netdev_vif *ndev_vif)
{
sdev->p2p_group_exp_frame = SLSI_P2P_PA_INVALID;
ndev_vif->vif_type = FAPI_VIFTYPE_UNSYNCHRONISED;
+ ndev_vif->unsync.slsi_p2p_continuous_fullscan = false;
+
INIT_DELAYED_WORK(&ndev_vif->unsync.roc_expiry_work, slsi_p2p_roc_duration_expiry_work);
INIT_DELAYED_WORK(&ndev_vif->unsync.del_vif_work, slsi_p2p_unsync_vif_delete_work);
-
+ INIT_DELAYED_WORK(&ndev_vif->unsync.unset_channel_expiry_work, slsi_p2p_unset_channel_expiry_work);
return 0;
}