Commit df771911 authored by Prameela Rani Garnepudi's avatar Prameela Rani Garnepudi Committed by Kalle Valo

rsi: add support for p2p listen

Remain-on-channel and cancel-remain-on-channel are implemented
to support p2p listen phase.
Signed-off-by: default avatarPrameela Rani Garnepudi <prameela.j04cs@gmail.com>
Signed-off-by: default avatarAmitkumar Karwar <amit.karwar@redpinesignals.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent b8bd3a43
...@@ -334,6 +334,21 @@ struct rsi_sta *rsi_find_sta(struct rsi_common *common, u8 *mac_addr) ...@@ -334,6 +334,21 @@ struct rsi_sta *rsi_find_sta(struct rsi_common *common, u8 *mac_addr)
return NULL; return NULL;
} }
struct ieee80211_vif *rsi_get_vif(struct rsi_hw *adapter, u8 *mac)
{
struct ieee80211_vif *vif;
int i;
for (i = 0; i < RSI_MAX_VIFS; i++) {
vif = adapter->vifs[i];
if (!vif)
continue;
if (!memcmp(vif->addr, mac, ETH_ALEN))
return vif;
}
return NULL;
}
/** /**
* rsi_core_xmit() - This function transmits the packets received from mac80211 * rsi_core_xmit() - This function transmits the packets received from mac80211
* @common: Pointer to the driver private structure. * @common: Pointer to the driver private structure.
......
...@@ -503,35 +503,44 @@ static int rsi_channel_change(struct ieee80211_hw *hw) ...@@ -503,35 +503,44 @@ static int rsi_channel_change(struct ieee80211_hw *hw)
int status = -EOPNOTSUPP; int status = -EOPNOTSUPP;
struct ieee80211_channel *curchan = hw->conf.chandef.chan; struct ieee80211_channel *curchan = hw->conf.chandef.chan;
u16 channel = curchan->hw_value; u16 channel = curchan->hw_value;
struct ieee80211_bss_conf *bss = &adapter->vifs[0]->bss_conf; struct ieee80211_vif *vif;
struct ieee80211_bss_conf *bss;
bool assoc = false;
int i;
rsi_dbg(INFO_ZONE, rsi_dbg(INFO_ZONE,
"%s: Set channel: %d MHz type: %d channel_no %d\n", "%s: Set channel: %d MHz type: %d channel_no %d\n",
__func__, curchan->center_freq, __func__, curchan->center_freq,
curchan->flags, channel); curchan->flags, channel);
for (i = 0; i < RSI_MAX_VIFS; i++) {
vif = adapter->vifs[i];
if (!vif)
continue;
if (vif->type == NL80211_IFTYPE_STATION) {
bss = &vif->bss_conf;
if (bss->assoc) { if (bss->assoc) {
assoc = true;
break;
}
}
}
if (assoc) {
if (!common->hw_data_qs_blocked && if (!common->hw_data_qs_blocked &&
(rsi_get_connected_channel(adapter) != channel)) { (rsi_get_connected_channel(vif) != channel)) {
rsi_dbg(INFO_ZONE, "blk data q %d\n", channel); rsi_dbg(INFO_ZONE, "blk data q %d\n", channel);
if (!rsi_send_block_unblock_frame(common, true)) if (!rsi_send_block_unblock_frame(common, true))
common->hw_data_qs_blocked = true; common->hw_data_qs_blocked = true;
} }
} }
status = rsi_band_check(common); status = rsi_band_check(common, curchan);
if (!status) if (!status)
status = rsi_set_channel(adapter->priv, curchan); status = rsi_set_channel(adapter->priv, curchan);
if (bss->assoc) { if (assoc) {
if (common->hw_data_qs_blocked && if (common->hw_data_qs_blocked &&
(rsi_get_connected_channel(adapter) == channel)) { (rsi_get_connected_channel(vif) == channel)) {
rsi_dbg(INFO_ZONE, "unblk data q %d\n", channel);
if (!rsi_send_block_unblock_frame(common, false))
common->hw_data_qs_blocked = false;
}
} else {
if (common->hw_data_qs_blocked) {
rsi_dbg(INFO_ZONE, "unblk data q %d\n", channel); rsi_dbg(INFO_ZONE, "unblk data q %d\n", channel);
if (!rsi_send_block_unblock_frame(common, false)) if (!rsi_send_block_unblock_frame(common, false))
common->hw_data_qs_blocked = false; common->hw_data_qs_blocked = false;
...@@ -632,16 +641,42 @@ static int rsi_mac80211_config(struct ieee80211_hw *hw, ...@@ -632,16 +641,42 @@ static int rsi_mac80211_config(struct ieee80211_hw *hw,
* *
* Return: Current connected AP's channel number is returned. * Return: Current connected AP's channel number is returned.
*/ */
u16 rsi_get_connected_channel(struct rsi_hw *adapter) u16 rsi_get_connected_channel(struct ieee80211_vif *vif)
{ {
struct ieee80211_vif *vif = adapter->vifs[0]; struct ieee80211_bss_conf *bss;
if (vif) { struct ieee80211_channel *channel;
struct ieee80211_bss_conf *bss = &vif->bss_conf;
struct ieee80211_channel *channel = bss->chandef.chan;
return channel->hw_value;
}
if (!vif)
return 0; return 0;
bss = &vif->bss_conf;
channel = bss->chandef.chan;
if (!channel)
return 0;
return channel->hw_value;
}
static void rsi_switch_channel(struct rsi_hw *adapter,
struct ieee80211_vif *vif)
{
struct rsi_common *common = adapter->priv;
struct ieee80211_channel *channel;
if (common->iface_down)
return;
if (!vif)
return;
channel = vif->bss_conf.chandef.chan;
if (!channel)
return;
rsi_band_check(common, channel);
rsi_set_channel(common, channel);
rsi_dbg(INFO_ZONE, "Switched to channel - %d\n", channel->hw_value);
} }
/** /**
...@@ -1561,6 +1596,114 @@ static void rsi_mac80211_rfkill_poll(struct ieee80211_hw *hw) ...@@ -1561,6 +1596,114 @@ static void rsi_mac80211_rfkill_poll(struct ieee80211_hw *hw)
mutex_unlock(&common->mutex); mutex_unlock(&common->mutex);
} }
static void rsi_resume_conn_channel(struct rsi_common *common)
{
struct rsi_hw *adapter = common->priv;
struct ieee80211_vif *vif;
int cnt;
for (cnt = 0; cnt < RSI_MAX_VIFS; cnt++) {
vif = adapter->vifs[cnt];
if (!vif)
continue;
if ((vif->type == NL80211_IFTYPE_AP) ||
(vif->type == NL80211_IFTYPE_P2P_GO)) {
rsi_switch_channel(adapter, vif);
break;
}
if (((vif->type == NL80211_IFTYPE_STATION) ||
(vif->type == NL80211_IFTYPE_P2P_CLIENT)) &&
vif->bss_conf.assoc) {
rsi_switch_channel(adapter, vif);
break;
}
}
}
void rsi_roc_timeout(unsigned long data)
{
struct rsi_common *common = (struct rsi_common *)data;
rsi_dbg(INFO_ZONE, "Remain on channel expired\n");
mutex_lock(&common->mutex);
ieee80211_remain_on_channel_expired(common->priv->hw);
if (timer_pending(&common->roc_timer))
del_timer(&common->roc_timer);
rsi_resume_conn_channel(common);
mutex_unlock(&common->mutex);
}
static int rsi_mac80211_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_channel *chan, int duration,
enum ieee80211_roc_type type)
{
struct rsi_hw *adapter = (struct rsi_hw *)hw->priv;
struct rsi_common *common = (struct rsi_common *)adapter->priv;
int status = 0;
rsi_dbg(INFO_ZONE, "***** Remain on channel *****\n");
mutex_lock(&common->mutex);
rsi_dbg(INFO_ZONE, "%s: channel: %d duration: %dms\n",
__func__, chan->hw_value, duration);
if (timer_pending(&common->roc_timer)) {
rsi_dbg(INFO_ZONE, "Stop on-going ROC\n");
del_timer(&common->roc_timer);
}
common->roc_timer.expires = msecs_to_jiffies(duration) + jiffies;
add_timer(&common->roc_timer);
/* Configure band */
if (rsi_band_check(common, chan)) {
rsi_dbg(ERR_ZONE, "Failed to set band\n");
status = -EINVAL;
goto out;
}
/* Configure channel */
if (rsi_set_channel(common, chan)) {
rsi_dbg(ERR_ZONE, "Failed to set the channel\n");
status = -EINVAL;
goto out;
}
common->roc_vif = vif;
ieee80211_ready_on_channel(hw);
rsi_dbg(INFO_ZONE, "%s: Ready on channel :%d\n",
__func__, chan->hw_value);
out:
mutex_unlock(&common->mutex);
return status;
}
static int rsi_mac80211_cancel_roc(struct ieee80211_hw *hw)
{
struct rsi_hw *adapter = hw->priv;
struct rsi_common *common = adapter->priv;
rsi_dbg(INFO_ZONE, "Cancel remain on channel\n");
mutex_lock(&common->mutex);
if (!timer_pending(&common->roc_timer)) {
mutex_unlock(&common->mutex);
return 0;
}
del_timer(&common->roc_timer);
rsi_resume_conn_channel(common);
mutex_unlock(&common->mutex);
return 0;
}
static const struct ieee80211_ops mac80211_ops = { static const struct ieee80211_ops mac80211_ops = {
.tx = rsi_mac80211_tx, .tx = rsi_mac80211_tx,
.start = rsi_mac80211_start, .start = rsi_mac80211_start,
...@@ -1580,6 +1723,8 @@ static const struct ieee80211_ops mac80211_ops = { ...@@ -1580,6 +1723,8 @@ static const struct ieee80211_ops mac80211_ops = {
.set_antenna = rsi_mac80211_set_antenna, .set_antenna = rsi_mac80211_set_antenna,
.get_antenna = rsi_mac80211_get_antenna, .get_antenna = rsi_mac80211_get_antenna,
.rfkill_poll = rsi_mac80211_rfkill_poll, .rfkill_poll = rsi_mac80211_rfkill_poll,
.remain_on_channel = rsi_mac80211_roc,
.cancel_remain_on_channel = rsi_mac80211_cancel_roc,
}; };
/** /**
...@@ -1666,6 +1811,9 @@ int rsi_mac80211_attach(struct rsi_common *common) ...@@ -1666,6 +1811,9 @@ int rsi_mac80211_attach(struct rsi_common *common)
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
/* Wi-Fi direct parameters */ /* Wi-Fi direct parameters */
wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
wiphy->flags |= WIPHY_FLAG_OFFCHAN_TX;
wiphy->max_remain_on_channel_duration = 10000;
hw->max_listen_interval = 10; hw->max_listen_interval = 10;
wiphy->iface_combinations = rsi_iface_combinations; wiphy->iface_combinations = rsi_iface_combinations;
wiphy->n_iface_combinations = ARRAY_SIZE(rsi_iface_combinations); wiphy->n_iface_combinations = ARRAY_SIZE(rsi_iface_combinations);
......
...@@ -74,6 +74,8 @@ static struct sk_buff *rsi_prepare_skb(struct rsi_common *common, ...@@ -74,6 +74,8 @@ static struct sk_buff *rsi_prepare_skb(struct rsi_common *common,
struct skb_info *rx_params; struct skb_info *rx_params;
struct sk_buff *skb = NULL; struct sk_buff *skb = NULL;
u8 payload_offset; u8 payload_offset;
struct ieee80211_vif *vif;
struct ieee80211_hdr *wh;
if (WARN(!pkt_len, "%s: Dummy pkt received", __func__)) if (WARN(!pkt_len, "%s: Dummy pkt received", __func__))
return NULL; return NULL;
...@@ -92,11 +94,13 @@ static struct sk_buff *rsi_prepare_skb(struct rsi_common *common, ...@@ -92,11 +94,13 @@ static struct sk_buff *rsi_prepare_skb(struct rsi_common *common,
payload_offset = (extended_desc + FRAME_DESC_SZ); payload_offset = (extended_desc + FRAME_DESC_SZ);
skb_put(skb, pkt_len); skb_put(skb, pkt_len);
memcpy((skb->data), (buffer + payload_offset), skb->len); memcpy((skb->data), (buffer + payload_offset), skb->len);
wh = (struct ieee80211_hdr *)skb->data;
vif = rsi_get_vif(common->priv, wh->addr1);
info = IEEE80211_SKB_CB(skb); info = IEEE80211_SKB_CB(skb);
rx_params = (struct skb_info *)info->driver_data; rx_params = (struct skb_info *)info->driver_data;
rx_params->rssi = rsi_get_rssi(buffer); rx_params->rssi = rsi_get_rssi(buffer);
rx_params->channel = rsi_get_connected_channel(common->priv); rx_params->channel = rsi_get_connected_channel(vif);
return skb; return skb;
} }
...@@ -233,6 +237,9 @@ struct rsi_hw *rsi_91x_init(void) ...@@ -233,6 +237,9 @@ struct rsi_hw *rsi_91x_init(void)
rsi_default_ps_params(adapter); rsi_default_ps_params(adapter);
spin_lock_init(&adapter->ps_lock); spin_lock_init(&adapter->ps_lock);
common->roc_timer.data = (unsigned long)common;
common->roc_timer.function = (void *)&rsi_roc_timeout;
init_timer(&common->roc_timer);
common->init_done = true; common->init_done = true;
return adapter; return adapter;
......
...@@ -926,13 +926,13 @@ static int rsi_send_reset_mac(struct rsi_common *common) ...@@ -926,13 +926,13 @@ static int rsi_send_reset_mac(struct rsi_common *common)
* *
* Return: 0 on success, corresponding error code on failure. * Return: 0 on success, corresponding error code on failure.
*/ */
int rsi_band_check(struct rsi_common *common) int rsi_band_check(struct rsi_common *common,
struct ieee80211_channel *curchan)
{ {
struct rsi_hw *adapter = common->priv; struct rsi_hw *adapter = common->priv;
struct ieee80211_hw *hw = adapter->hw; struct ieee80211_hw *hw = adapter->hw;
u8 prev_bw = common->channel_width; u8 prev_bw = common->channel_width;
u8 prev_ep = common->endpoint; u8 prev_ep = common->endpoint;
struct ieee80211_channel *curchan = hw->conf.chandef.chan;
int status = 0; int status = 0;
if (common->band != curchan->band) { if (common->band != curchan->band) {
......
...@@ -79,9 +79,11 @@ static inline int rsi_kill_thread(struct rsi_thread *handle) ...@@ -79,9 +79,11 @@ static inline int rsi_kill_thread(struct rsi_thread *handle)
} }
void rsi_mac80211_detach(struct rsi_hw *hw); void rsi_mac80211_detach(struct rsi_hw *hw);
u16 rsi_get_connected_channel(struct rsi_hw *adapter); u16 rsi_get_connected_channel(struct ieee80211_vif *vif);
struct rsi_hw *rsi_91x_init(void); struct rsi_hw *rsi_91x_init(void);
void rsi_91x_deinit(struct rsi_hw *adapter); void rsi_91x_deinit(struct rsi_hw *adapter);
int rsi_read_pkt(struct rsi_common *common, s32 rcv_pkt_len); int rsi_read_pkt(struct rsi_common *common, s32 rcv_pkt_len);
struct rsi_sta *rsi_find_sta(struct rsi_common *common, u8 *mac_addr); struct rsi_sta *rsi_find_sta(struct rsi_common *common, u8 *mac_addr);
struct ieee80211_vif *rsi_get_vif(struct rsi_hw *adapter, u8 *mac);
void rsi_roc_timeout(unsigned long data);
#endif #endif
...@@ -274,6 +274,8 @@ struct rsi_common { ...@@ -274,6 +274,8 @@ struct rsi_common {
/* Wi-Fi direct mode related */ /* Wi-Fi direct mode related */
bool p2p_enabled; bool p2p_enabled;
struct timer_list roc_timer;
struct ieee80211_vif *roc_vif;
}; };
enum host_intf { enum host_intf {
......
...@@ -633,7 +633,7 @@ void rsi_core_qos_processor(struct rsi_common *common); ...@@ -633,7 +633,7 @@ void rsi_core_qos_processor(struct rsi_common *common);
void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb); void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb);
int rsi_send_mgmt_pkt(struct rsi_common *common, struct sk_buff *skb); int rsi_send_mgmt_pkt(struct rsi_common *common, struct sk_buff *skb);
int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb); int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb);
int rsi_band_check(struct rsi_common *common); int rsi_band_check(struct rsi_common *common, struct ieee80211_channel *chan);
int rsi_send_rx_filter_frame(struct rsi_common *common, u16 rx_filter_word); int rsi_send_rx_filter_frame(struct rsi_common *common, u16 rx_filter_word);
int rsi_send_radio_params_update(struct rsi_common *common); int rsi_send_radio_params_update(struct rsi_common *common);
int rsi_set_antenna(struct rsi_common *common, u8 antenna); int rsi_set_antenna(struct rsi_common *common, u8 antenna);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment