提交 28bf8312 编写于 作者: G Ganapathi Bhat 提交者: Kalle Valo

mwifiex: get_channel from firmware

At present driver gets chan_type by referring to
IEEE80211_HT_PARAM_CHA_SEC_OFFSET, in ASSOC response. Sometimes
AP shows IEEE80211_HT_PARAM_CHA_SEC_OFFSET as above/below in
assoc response, even if the association is done on HT20 channel
only. So, it will be accurate to get econdary channel offset from
firmware.
Signed-off-by: NCathy Luo <cluo@marvell.com>
Signed-off-by: NGanapathi Bhat <gbhat@marvell.com>
Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
上级 77423fa7
...@@ -95,18 +95,32 @@ u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type) ...@@ -95,18 +95,32 @@ u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type)
/* This function maps IEEE HT secondary channel type to NL80211 channel type /* This function maps IEEE HT secondary channel type to NL80211 channel type
*/ */
u8 mwifiex_sec_chan_offset_to_chan_type(u8 second_chan_offset) u8 mwifiex_get_chan_type(struct mwifiex_private *priv)
{ {
switch (second_chan_offset) { struct mwifiex_channel_band channel_band;
case IEEE80211_HT_PARAM_CHA_SEC_NONE: int ret;
return NL80211_CHAN_HT20;
case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: ret = mwifiex_get_chan_info(priv, &channel_band);
return NL80211_CHAN_HT40PLUS;
case IEEE80211_HT_PARAM_CHA_SEC_BELOW: if (!ret) {
return NL80211_CHAN_HT40MINUS; switch (channel_band.band_config.chan_width) {
default: case CHAN_BW_20MHZ:
return NL80211_CHAN_HT20; if (IS_11N_ENABLED(priv))
return NL80211_CHAN_HT20;
else
return NL80211_CHAN_NO_HT;
case CHAN_BW_40MHZ:
if (channel_band.band_config.chan2_offset ==
SEC_CHAN_ABOVE)
return NL80211_CHAN_HT40PLUS;
else
return NL80211_CHAN_HT40MINUS;
default:
return NL80211_CHAN_HT20;
}
} }
return NL80211_CHAN_HT20;
} }
/* /*
...@@ -3937,7 +3951,6 @@ static int mwifiex_cfg80211_get_channel(struct wiphy *wiphy, ...@@ -3937,7 +3951,6 @@ static int mwifiex_cfg80211_get_channel(struct wiphy *wiphy,
struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
struct mwifiex_bssdescriptor *curr_bss; struct mwifiex_bssdescriptor *curr_bss;
struct ieee80211_channel *chan; struct ieee80211_channel *chan;
u8 second_chan_offset;
enum nl80211_channel_type chan_type; enum nl80211_channel_type chan_type;
enum nl80211_band band; enum nl80211_band band;
int freq; int freq;
...@@ -3954,10 +3967,7 @@ static int mwifiex_cfg80211_get_channel(struct wiphy *wiphy, ...@@ -3954,10 +3967,7 @@ static int mwifiex_cfg80211_get_channel(struct wiphy *wiphy,
chan = ieee80211_get_channel(wiphy, freq); chan = ieee80211_get_channel(wiphy, freq);
if (priv->ht_param_present) { if (priv->ht_param_present) {
second_chan_offset = priv->assoc_resp_ht_param & chan_type = mwifiex_get_chan_type(priv);
IEEE80211_HT_PARAM_CHA_SEC_OFFSET;
chan_type = mwifiex_sec_chan_offset_to_chan_type
(second_chan_offset);
cfg80211_chandef_create(chandef, chan, chan_type); cfg80211_chandef_create(chandef, chan, chan_type);
} else { } else {
cfg80211_chandef_create(chandef, chan, cfg80211_chandef_create(chandef, chan,
......
...@@ -294,4 +294,21 @@ enum rdwr_status { ...@@ -294,4 +294,21 @@ enum rdwr_status {
RDWR_STATUS_DONE = 2 RDWR_STATUS_DONE = 2
}; };
enum mwifiex_chan_width {
CHAN_BW_20MHZ = 0,
CHAN_BW_10MHZ,
CHAN_BW_40MHZ,
CHAN_BW_80MHZ,
CHAN_BW_8080MHZ,
CHAN_BW_160MHZ,
CHAN_BW_5MHZ,
};
enum mwifiex_chan_offset {
SEC_CHAN_NONE = 0,
SEC_CHAN_ABOVE = 1,
SEC_CHAN_5MHZ = 2,
SEC_CHAN_BELOW = 3
};
#endif /* !_MWIFIEX_DECL_H_ */ #endif /* !_MWIFIEX_DECL_H_ */
...@@ -411,6 +411,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { ...@@ -411,6 +411,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define HostCmd_CMD_TDLS_OPER 0x0122 #define HostCmd_CMD_TDLS_OPER 0x0122
#define HostCmd_CMD_FW_DUMP_EVENT 0x0125 #define HostCmd_CMD_FW_DUMP_EVENT 0x0125
#define HostCmd_CMD_SDIO_SP_RX_AGGR_CFG 0x0223 #define HostCmd_CMD_SDIO_SP_RX_AGGR_CFG 0x0223
#define HostCmd_CMD_STA_CONFIGURE 0x023f
#define HostCmd_CMD_CHAN_REGION_CFG 0x0242 #define HostCmd_CMD_CHAN_REGION_CFG 0x0242
#define HostCmd_CMD_PACKET_AGGR_CTRL 0x0251 #define HostCmd_CMD_PACKET_AGGR_CTRL 0x0251
...@@ -2285,6 +2286,11 @@ struct host_cmd_ds_pkt_aggr_ctrl { ...@@ -2285,6 +2286,11 @@ struct host_cmd_ds_pkt_aggr_ctrl {
__le16 tx_aggr_align; __le16 tx_aggr_align;
} __packed; } __packed;
struct host_cmd_ds_sta_configure {
__le16 action;
u8 tlv_buffer[0];
} __packed;
struct host_cmd_ds_command { struct host_cmd_ds_command {
__le16 command; __le16 command;
__le16 size; __le16 size;
...@@ -2361,6 +2367,7 @@ struct host_cmd_ds_command { ...@@ -2361,6 +2367,7 @@ struct host_cmd_ds_command {
struct host_cmd_ds_gtk_rekey_params rekey; struct host_cmd_ds_gtk_rekey_params rekey;
struct host_cmd_ds_chan_region_cfg reg_cfg; struct host_cmd_ds_chan_region_cfg reg_cfg;
struct host_cmd_ds_pkt_aggr_ctrl pkt_aggr_ctrl; struct host_cmd_ds_pkt_aggr_ctrl pkt_aggr_ctrl;
struct host_cmd_ds_sta_configure sta_cfg;
} params; } params;
} __packed; } __packed;
......
...@@ -517,6 +517,18 @@ enum mwifiex_iface_work_flags { ...@@ -517,6 +517,18 @@ enum mwifiex_iface_work_flags {
MWIFIEX_IFACE_WORK_CARD_RESET, MWIFIEX_IFACE_WORK_CARD_RESET,
}; };
struct mwifiex_band_config {
u8 chan_band:2;
u8 chan_width:2;
u8 chan2_offset:2;
u8 scan_mode:2;
} __packed;
struct mwifiex_channel_band {
struct mwifiex_band_config band_config;
u8 channel;
};
struct mwifiex_private { struct mwifiex_private {
struct mwifiex_adapter *adapter; struct mwifiex_adapter *adapter;
u8 bss_type; u8 bss_type;
...@@ -1557,7 +1569,7 @@ int mwifiex_check_network_compatibility(struct mwifiex_private *priv, ...@@ -1557,7 +1569,7 @@ int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
struct mwifiex_bssdescriptor *bss_desc); struct mwifiex_bssdescriptor *bss_desc);
u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type); u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type);
u8 mwifiex_sec_chan_offset_to_chan_type(u8 second_chan_offset); u8 mwifiex_get_chan_type(struct mwifiex_private *priv);
struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
const char *name, const char *name,
...@@ -1683,6 +1695,8 @@ void mwifiex_queue_main_work(struct mwifiex_adapter *adapter); ...@@ -1683,6 +1695,8 @@ void mwifiex_queue_main_work(struct mwifiex_adapter *adapter);
int mwifiex_get_wakeup_reason(struct mwifiex_private *priv, u16 action, int mwifiex_get_wakeup_reason(struct mwifiex_private *priv, u16 action,
int cmd_type, int cmd_type,
struct mwifiex_ds_wakeup_reason *wakeup_reason); struct mwifiex_ds_wakeup_reason *wakeup_reason);
int mwifiex_get_chan_info(struct mwifiex_private *priv,
struct mwifiex_channel_band *channel_band);
int mwifiex_ret_wakeup_reason(struct mwifiex_private *priv, int mwifiex_ret_wakeup_reason(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp, struct host_cmd_ds_command *resp,
struct host_cmd_ds_wakeup_reason *wakeup_reason); struct host_cmd_ds_wakeup_reason *wakeup_reason);
......
...@@ -1898,6 +1898,25 @@ static int mwifiex_cmd_get_wakeup_reason(struct mwifiex_private *priv, ...@@ -1898,6 +1898,25 @@ static int mwifiex_cmd_get_wakeup_reason(struct mwifiex_private *priv,
return 0; return 0;
} }
static int mwifiex_cmd_get_chan_info(struct host_cmd_ds_command *cmd,
u16 cmd_action)
{
struct host_cmd_ds_sta_configure *sta_cfg_cmd = &cmd->params.sta_cfg;
struct host_cmd_tlv_channel_band *tlv_band_channel =
(struct host_cmd_tlv_channel_band *)sta_cfg_cmd->tlv_buffer;
cmd->command = cpu_to_le16(HostCmd_CMD_STA_CONFIGURE);
cmd->size = cpu_to_le16(sizeof(*sta_cfg_cmd) +
sizeof(*tlv_band_channel) + S_DS_GEN);
sta_cfg_cmd->action = cpu_to_le16(cmd_action);
memset(tlv_band_channel, 0, sizeof(*tlv_band_channel));
tlv_band_channel->header.type = cpu_to_le16(TLV_TYPE_CHANNELBANDLIST);
tlv_band_channel->header.len = cpu_to_le16(sizeof(*tlv_band_channel) -
sizeof(struct mwifiex_ie_types_header));
return 0;
}
/* This function check if the command is supported by firmware */ /* This function check if the command is supported by firmware */
static int mwifiex_is_cmd_supported(struct mwifiex_private *priv, u16 cmd_no) static int mwifiex_is_cmd_supported(struct mwifiex_private *priv, u16 cmd_no)
{ {
...@@ -2210,6 +2229,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, ...@@ -2210,6 +2229,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
cmd_ptr->command = cpu_to_le16(cmd_no); cmd_ptr->command = cpu_to_le16(cmd_no);
cmd_ptr->size = cpu_to_le16(S_DS_GEN); cmd_ptr->size = cpu_to_le16(S_DS_GEN);
break; break;
case HostCmd_CMD_STA_CONFIGURE:
ret = mwifiex_cmd_get_chan_info(cmd_ptr, cmd_action);
break;
default: default:
mwifiex_dbg(priv->adapter, ERROR, mwifiex_dbg(priv->adapter, ERROR,
"PREP_CMD: unknown cmd- %#x\n", cmd_no); "PREP_CMD: unknown cmd- %#x\n", cmd_no);
......
...@@ -1170,6 +1170,22 @@ static int mwifiex_ret_pkt_aggr_ctrl(struct mwifiex_private *priv, ...@@ -1170,6 +1170,22 @@ static int mwifiex_ret_pkt_aggr_ctrl(struct mwifiex_private *priv,
return 0; return 0;
} }
static int mwifiex_ret_get_chan_info(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
struct mwifiex_channel_band *channel_band)
{
struct host_cmd_ds_sta_configure *sta_cfg_cmd = &resp->params.sta_cfg;
struct host_cmd_tlv_channel_band *tlv_band_channel;
tlv_band_channel =
(struct host_cmd_tlv_channel_band *)sta_cfg_cmd->tlv_buffer;
memcpy(&channel_band->band_config, &tlv_band_channel->band_config,
sizeof(struct mwifiex_band_config));
channel_band->channel = tlv_band_channel->channel;
return 0;
}
/* /*
* This function handles the command responses. * This function handles the command responses.
* *
...@@ -1393,6 +1409,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, ...@@ -1393,6 +1409,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
case HostCmd_CMD_CHAN_REGION_CFG: case HostCmd_CMD_CHAN_REGION_CFG:
ret = mwifiex_ret_chan_region_cfg(priv, resp); ret = mwifiex_ret_chan_region_cfg(priv, resp);
break; break;
case HostCmd_CMD_STA_CONFIGURE:
ret = mwifiex_ret_get_chan_info(priv, resp, data_buf);
break;
default: default:
mwifiex_dbg(adapter, ERROR, mwifiex_dbg(adapter, ERROR,
"CMD_RESP: unknown cmd response %#x\n", "CMD_RESP: unknown cmd response %#x\n",
......
...@@ -1481,3 +1481,15 @@ int mwifiex_get_wakeup_reason(struct mwifiex_private *priv, u16 action, ...@@ -1481,3 +1481,15 @@ int mwifiex_get_wakeup_reason(struct mwifiex_private *priv, u16 action,
return status; return status;
} }
int mwifiex_get_chan_info(struct mwifiex_private *priv,
struct mwifiex_channel_band *channel_band)
{
int status = 0;
status = mwifiex_send_cmd(priv, HostCmd_CMD_STA_CONFIGURE,
HostCmd_ACT_GEN_GET, 0, channel_band,
MWIFIEX_SYNC_CMD);
return status;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册