wlcore: update channel_switch/stop_channel_switch commands

Some fields were added to the channel_switch and
stop_channel_switch commands. Unfortunately,
the new 18xx channel_switch struct is not backward
compatible with the 12xx channel switch struct.

Add a new channel_switch op to wlcore, and update
the driver accordingly.

Signed-off-by: Eliad Peller <eliad@wizery.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
This commit is contained in:
Eliad Peller 2012-11-22 18:06:18 +02:00 committed by Luciano Coelho
parent b6acb4e00e
commit fcab189027
11 changed files with 204 additions and 57 deletions

View file

@ -284,3 +284,40 @@ int wl128x_cmd_radio_parms(struct wl1271 *wl)
kfree(radio_parms);
return ret;
}
int wl12xx_cmd_channel_switch(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
struct ieee80211_channel_switch *ch_switch)
{
struct wl12xx_cmd_channel_switch *cmd;
int ret;
wl1271_debug(DEBUG_ACX, "cmd channel switch");
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
ret = -ENOMEM;
goto out;
}
cmd->role_id = wlvif->role_id;
cmd->channel = ch_switch->channel->hw_value;
cmd->switch_time = ch_switch->count;
cmd->stop_tx = ch_switch->block_tx;
/* FIXME: control from mac80211 in the future */
/* Enable TX on the target channel */
cmd->post_switch_tx_disable = 0;
ret = wl1271_cmd_send(wl, CMD_CHANNEL_SWITCH, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("failed to send channel switch command");
goto out_free;
}
out_free:
kfree(cmd);
out:
return ret;
}

View file

@ -103,10 +103,30 @@ struct wl1271_ext_radio_parms_cmd {
u8 padding[3];
} __packed;
struct wl12xx_cmd_channel_switch {
struct wl1271_cmd_header header;
u8 role_id;
/* The new serving channel */
u8 channel;
/* Relative time of the serving channel switch in TBTT units */
u8 switch_time;
/* Stop the role TX, should expect it after radar detection */
u8 stop_tx;
/* The target channel tx status 1-stopped 0-open*/
u8 post_switch_tx_disable;
u8 padding[3];
} __packed;
int wl1271_cmd_general_parms(struct wl1271 *wl);
int wl128x_cmd_general_parms(struct wl1271 *wl);
int wl1271_cmd_radio_parms(struct wl1271 *wl);
int wl128x_cmd_radio_parms(struct wl1271 *wl);
int wl1271_cmd_ext_radio_parms(struct wl1271 *wl);
int wl12xx_cmd_channel_switch(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
struct ieee80211_channel_switch *ch_switch);
#endif /* __WL12XX_CMD_H__ */

View file

@ -1632,6 +1632,7 @@ static struct wlcore_ops wl12xx_ops = {
.sched_scan_stop = wl12xx_scan_sched_scan_stop,
.get_spare_blocks = wl12xx_get_spare_blocks,
.set_key = wl12xx_set_key,
.channel_switch = wl12xx_cmd_channel_switch,
.pre_pkt_send = NULL,
};

View file

@ -1,3 +1,3 @@
wl18xx-objs = main.o acx.o tx.o io.o debugfs.o scan.o
wl18xx-objs = main.o acx.o tx.o io.o debugfs.o scan.o cmd.o
obj-$(CONFIG_WL18XX) += wl18xx.o

View file

@ -0,0 +1,80 @@
/*
* This file is part of wl18xx
*
* Copyright (C) 2011 Texas Instruments Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include "../wlcore/cmd.h"
#include "../wlcore/debug.h"
#include "../wlcore/hw_ops.h"
#include "cmd.h"
int wl18xx_cmd_channel_switch(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
struct ieee80211_channel_switch *ch_switch)
{
struct wl18xx_cmd_channel_switch *cmd;
u32 supported_rates;
int ret;
wl1271_debug(DEBUG_ACX, "cmd channel switch");
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
ret = -ENOMEM;
goto out;
}
cmd->role_id = wlvif->role_id;
cmd->channel = ch_switch->channel->hw_value;
cmd->switch_time = ch_switch->count;
cmd->stop_tx = ch_switch->block_tx;
switch (ch_switch->channel->band) {
case IEEE80211_BAND_2GHZ:
cmd->band = WLCORE_BAND_2_4GHZ;
break;
case IEEE80211_BAND_5GHZ:
cmd->band = WLCORE_BAND_5GHZ;
break;
default:
wl1271_error("invalid channel switch band: %d",
ch_switch->channel->band);
ret = -EINVAL;
goto out_free;
}
supported_rates = CONF_TX_ENABLED_RATES | CONF_TX_MCS_RATES |
wlcore_hw_sta_get_ap_rate_mask(wl, wlvif);
if (wlvif->p2p)
supported_rates &= ~CONF_TX_CCK_RATES;
cmd->local_supported_rates = cpu_to_le32(supported_rates);
cmd->channel_type = wlvif->channel_type;
ret = wl1271_cmd_send(wl, CMD_CHANNEL_SWITCH, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("failed to send channel switch command");
goto out_free;
}
out_free:
kfree(cmd);
out:
return ret;
}

View file

@ -0,0 +1,52 @@
/*
* This file is part of wl18xx
*
* Copyright (C) 2011 Texas Instruments. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __WL18XX_CMD_H__
#define __WL18XX_CMD_H__
#include "../wlcore/wlcore.h"
#include "../wlcore/acx.h"
struct wl18xx_cmd_channel_switch {
struct wl1271_cmd_header header;
u8 role_id;
/* The new serving channel */
u8 channel;
/* Relative time of the serving channel switch in TBTT units */
u8 switch_time;
/* Stop the role TX, should expect it after radar detection */
u8 stop_tx;
__le32 local_supported_rates;
u8 channel_type;
u8 band;
u8 padding[2];
} __packed;
int wl18xx_cmd_channel_switch(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
struct ieee80211_channel_switch *ch_switch);
#endif

View file

@ -34,6 +34,7 @@
#include "reg.h"
#include "conf.h"
#include "cmd.h"
#include "acx.h"
#include "tx.h"
#include "wl18xx.h"
@ -1335,6 +1336,7 @@ static struct wlcore_ops wl18xx_ops = {
.handle_static_data = wl18xx_handle_static_data,
.get_spare_blocks = wl18xx_get_spare_blocks,
.set_key = wl18xx_set_key,
.channel_switch = wl18xx_cmd_channel_switch,
.pre_pkt_send = wl18xx_pre_pkt_send,
};

View file

@ -1722,43 +1722,7 @@ out:
return ret;
}
int wl12xx_cmd_channel_switch(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
struct ieee80211_channel_switch *ch_switch)
{
struct wl12xx_cmd_channel_switch *cmd;
int ret;
wl1271_debug(DEBUG_ACX, "cmd channel switch");
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
ret = -ENOMEM;
goto out;
}
cmd->role_id = wlvif->role_id;
cmd->channel = ch_switch->channel->hw_value;
cmd->switch_time = ch_switch->count;
cmd->stop_tx = ch_switch->block_tx;
/* FIXME: control from mac80211 in the future */
cmd->post_switch_tx_disable = 0; /* Enable TX on the target channel */
ret = wl1271_cmd_send(wl, CMD_CHANNEL_SWITCH, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("failed to send channel switch command");
goto out_free;
}
out_free:
kfree(cmd);
out:
return ret;
}
int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl)
int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{
struct wl12xx_cmd_stop_channel_switch *cmd;
int ret;
@ -1771,6 +1735,8 @@ int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl)
goto out;
}
cmd->role_id = wlvif->role_id;
ret = wl1271_cmd_send(wl, CMD_STOP_CHANNEL_SWICTH, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("failed to stop channel switch command");

View file

@ -89,7 +89,8 @@ int wl12xx_cmd_stop_fwlog(struct wl1271 *wl);
int wl12xx_cmd_channel_switch(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
struct ieee80211_channel_switch *ch_switch);
int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl);
int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl,
struct wl12xx_vif *wlvif);
int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u8 *hlid);
void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid);
@ -633,27 +634,13 @@ struct wl12xx_cmd_stop_fwlog {
struct wl1271_cmd_header header;
} __packed;
struct wl12xx_cmd_channel_switch {
struct wl12xx_cmd_stop_channel_switch {
struct wl1271_cmd_header header;
u8 role_id;
/* The new serving channel */
u8 channel;
/* Relative time of the serving channel switch in TBTT units */
u8 switch_time;
/* Stop the role TX, should expect it after radar detection */
u8 stop_tx;
/* The target channel tx status 1-stopped 0-open*/
u8 post_switch_tx_disable;
u8 padding[3];
} __packed;
struct wl12xx_cmd_stop_channel_switch {
struct wl1271_cmd_header header;
} __packed;
/* Used to check radio status after calibration */
#define MAX_TLV_LENGTH 500
#define TEST_CMD_P2G_CAL 2 /* TX BiP */

View file

@ -2673,7 +2673,7 @@ static int wlcore_unset_assoc(struct wl1271 *wl, struct wl12xx_vif *wlvif)
if (test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags)) {
struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
wl12xx_cmd_stop_channel_switch(wl);
wl12xx_cmd_stop_channel_switch(wl, wlvif);
ieee80211_chswitch_done(vif, false);
}
@ -4680,8 +4680,7 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw,
/* TODO: change mac80211 to pass vif as param */
wl12xx_for_each_wlvif_sta(wl, wlvif) {
ret = wl12xx_cmd_channel_switch(wl, wlvif, ch_switch);
ret = wl->ops->channel_switch(wl, wlvif, ch_switch);
if (!ret)
set_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags);
}

View file

@ -95,6 +95,9 @@ struct wlcore_ops {
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct ieee80211_key_conf *key_conf);
int (*channel_switch)(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
struct ieee80211_channel_switch *ch_switch);
u32 (*pre_pkt_send)(struct wl1271 *wl, u32 buf_offset, u32 last_len);
};