struct wid wid;
struct host_if_drv *hif_drv = vif->hif_drv;
- if (!hif_drv->remain_on_ch_pending) {
- hif_drv->remain_on_ch.arg = hif_remain_ch->arg;
- hif_drv->remain_on_ch.expired = hif_remain_ch->expired;
- hif_drv->remain_on_ch.ready = hif_remain_ch->ready;
- hif_drv->remain_on_ch.ch = hif_remain_ch->ch;
- hif_drv->remain_on_ch.id = hif_remain_ch->id;
- } else {
- hif_remain_ch->ch = hif_drv->remain_on_ch.ch;
- }
+ if (hif_drv->usr_scan_req.scan_result)
+ return -EBUSY;
- if (hif_drv->usr_scan_req.scan_result) {
- hif_drv->remain_on_ch_pending = 1;
- result = -EBUSY;
- goto error;
- }
- if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
- result = -EBUSY;
- goto error;
- }
+ if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP)
+ return -EBUSY;
- if (vif->obtaining_ip || vif->connecting) {
- result = -EBUSY;
- goto error;
- }
+ if (vif->obtaining_ip || vif->connecting)
+ return -EBUSY;
remain_on_chan_flag = true;
wid.id = WID_REMAIN_ON_CHAN;
wid.type = WID_STR;
wid.size = 2;
wid.val = kmalloc(wid.size, GFP_KERNEL);
- if (!wid.val) {
- result = -ENOMEM;
- goto error;
- }
+ if (!wid.val)
+ return -ENOMEM;
wid.val[0] = remain_on_chan_flag;
wid.val[1] = (s8)hif_remain_ch->ch;
result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
wilc_get_vif_idx(vif));
kfree(wid.val);
- if (result != 0)
- netdev_err(vif->ndev, "Failed to set remain on channel\n");
+ if (result)
+ return -EBUSY;
-error:
+ hif_drv->remain_on_ch.arg = hif_remain_ch->arg;
+ hif_drv->remain_on_ch.expired = hif_remain_ch->expired;
+ hif_drv->remain_on_ch.ch = hif_remain_ch->ch;
+ hif_drv->remain_on_ch.cookie = hif_remain_ch->cookie;
hif_drv->remain_on_ch_timer_vif = vif;
- mod_timer(&hif_drv->remain_on_ch_timer,
- jiffies + msecs_to_jiffies(hif_remain_ch->duration));
-
- if (hif_drv->remain_on_ch.ready)
- hif_drv->remain_on_ch.ready(hif_drv->remain_on_ch.arg);
- if (hif_drv->remain_on_ch_pending)
- hif_drv->remain_on_ch_pending = 0;
-
- return result;
+ return 0;
}
static void handle_listen_state_expired(struct work_struct *work)
if (hif_drv->remain_on_ch.expired) {
hif_drv->remain_on_ch.expired(hif_drv->remain_on_ch.arg,
- hif_remain_ch->id);
+ hif_remain_ch->cookie);
}
} else {
netdev_dbg(vif->ndev, "Not in listen state\n");
if (IS_ERR(msg))
return;
- msg->body.remain_on_ch.id = vif->hif_drv->remain_on_ch.id;
+ msg->body.remain_on_ch.cookie = vif->hif_drv->remain_on_ch.cookie;
result = wilc_enqueue_work(msg);
if (result) {
handle_scan_done(msg->vif, SCAN_EVENT_DONE);
- if (msg->vif->hif_drv->remain_on_ch_pending)
- handle_remain_on_chan(msg->vif,
- &msg->vif->hif_drv->remain_on_ch);
kfree(msg);
}
}
}
-int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id,
+int wilc_remain_on_channel(struct wilc_vif *vif, u64 cookie,
u32 duration, u16 chan,
- void (*expired)(void *, u32),
- void (*ready)(void *),
+ void (*expired)(void *, u64),
void *user_arg)
{
struct remain_ch roc;
roc.ch = chan;
roc.expired = expired;
- roc.ready = ready;
roc.arg = user_arg;
roc.duration = duration;
- roc.id = session_id;
+ roc.cookie = cookie;
result = handle_remain_on_chan(vif, &roc);
if (result)
netdev_err(vif->ndev, "%s: failed to set remain on channel\n",
return result;
}
-int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id)
+int wilc_listen_state_expired(struct wilc_vif *vif, u64 cookie)
{
int result;
struct host_if_msg *msg;
if (IS_ERR(msg))
return PTR_ERR(msg);
- msg->body.remain_on_ch.id = session_id;
+ msg->body.remain_on_ch.cookie = cookie;
result = wilc_enqueue_work(msg);
if (result) {
struct remain_ch {
u16 ch;
u32 duration;
- void (*expired)(void *priv, u32 session_id);
- void (*ready)(void *priv);
+ void (*expired)(void *priv, u64 cookie);
void *arg;
- u32 id;
+ u32 cookie;
};
struct wilc;
struct user_scan_req usr_scan_req;
struct wilc_conn_info conn_info;
struct remain_ch remain_on_ch;
- u8 remain_on_ch_pending;
u64 p2p_timeout;
enum host_if_state hif_state;
int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout);
int wilc_setup_multicast_filter(struct wilc_vif *vif, u32 enabled, u32 count,
u8 *mc_list);
-int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id,
+int wilc_remain_on_channel(struct wilc_vif *vif, u64 cookie,
u32 duration, u16 chan,
- void (*expired)(void *, u32),
- void (*ready)(void *),
+ void (*expired)(void *, u64),
void *user_arg);
-int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id);
+int wilc_listen_state_expired(struct wilc_vif *vif, u64 cookie);
void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg);
int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode,
u8 ifc_id);
kfree(pv_data);
}
-static void wilc_wfi_remain_on_channel_ready(void *priv_data)
-{
- struct wilc_priv *priv;
-
- priv = priv_data;
-
- priv->p2p_listen_state = true;
-
- cfg80211_ready_on_channel(priv->wdev,
- priv->remain_on_ch_params.listen_cookie,
- priv->remain_on_ch_params.listen_ch,
- priv->remain_on_ch_params.listen_duration,
- GFP_KERNEL);
-}
-
-static void wilc_wfi_remain_on_channel_expired(void *data, u32 session_id)
+static void wilc_wfi_remain_on_channel_expired(void *data, u64 cookie)
{
struct wilc_priv *priv = data;
struct wilc_wfi_p2p_listen_params *params = &priv->remain_on_ch_params;
- if (session_id != params->listen_session_id)
+ if (cookie != params->listen_cookie)
return;
priv->p2p_listen_state = false;
int ret = 0;
struct wilc_priv *priv = wiphy_priv(wiphy);
struct wilc_vif *vif = netdev_priv(priv->dev);
+ u64 id;
if (wdev->iftype == NL80211_IFTYPE_AP) {
netdev_dbg(vif->ndev, "Required while in AP mode\n");
return ret;
}
+ id = ++priv->inc_roc_cookie;
+ if (id == 0)
+ id = ++priv->inc_roc_cookie;
+
+ ret = wilc_remain_on_channel(vif, id, duration, chan->hw_value,
+ wilc_wfi_remain_on_channel_expired,
+ (void *)priv);
+ if (ret)
+ return ret;
+
curr_channel = chan->hw_value;
priv->remain_on_ch_params.listen_ch = chan;
- priv->remain_on_ch_params.listen_cookie = *cookie;
+ priv->remain_on_ch_params.listen_cookie = id;
+ *cookie = id;
+ priv->p2p_listen_state = true;
priv->remain_on_ch_params.listen_duration = duration;
- priv->remain_on_ch_params.listen_session_id++;
- return wilc_remain_on_channel(vif,
- priv->remain_on_ch_params.listen_session_id,
- duration, chan->hw_value,
- wilc_wfi_remain_on_channel_expired,
- wilc_wfi_remain_on_channel_ready, (void *)priv);
+ cfg80211_ready_on_channel(wdev, *cookie, chan, duration, GFP_KERNEL);
+ mod_timer(&vif->hif_drv->remain_on_ch_timer,
+ jiffies + msecs_to_jiffies(duration));
+
+ return ret;
}
static int cancel_remain_on_channel(struct wiphy *wiphy,
struct wilc_priv *priv = wiphy_priv(wiphy);
struct wilc_vif *vif = netdev_priv(priv->dev);
- return wilc_listen_state_expired(vif,
- priv->remain_on_ch_params.listen_session_id);
+ if (cookie != priv->remain_on_ch_params.listen_cookie)
+ return -ENOENT;
+
+ return wilc_listen_state_expired(vif, cookie);
}
static void wilc_wfi_cfg_tx_vendor_spec(struct wilc_priv *priv,
struct ieee80211_channel *listen_ch;
u32 listen_duration;
u64 listen_cookie;
- u32 listen_session_id;
};
struct wilc_p2p_var {
struct ieee80211_rate bitrates[ARRAY_SIZE(wilc_bitrates)];
struct ieee80211_supported_band band;
u32 cipher_suites[ARRAY_SIZE(wilc_cipher_suites)];
+ u64 inc_roc_cookie;
};
struct frame_reg {