mwifiex: get_channel from firmware
authorGanapathi Bhat <gbhat@marvell.com>
Fri, 9 Mar 2018 18:15:26 +0000 (23:45 +0530)
committerKalle Valo <kvalo@codeaurora.org>
Tue, 13 Mar 2018 16:53:47 +0000 (18:53 +0200)
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: Cathy Luo <cluo@marvell.com>
Signed-off-by: Ganapathi Bhat <gbhat@marvell.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/marvell/mwifiex/cfg80211.c
drivers/net/wireless/marvell/mwifiex/decl.h
drivers/net/wireless/marvell/mwifiex/fw.h
drivers/net/wireless/marvell/mwifiex/main.h
drivers/net/wireless/marvell/mwifiex/sta_cmd.c
drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
drivers/net/wireless/marvell/mwifiex/sta_ioctl.c

index ce4432c535f0543757345d352f32a5b08972c4ba..7f7e9de2db1c52968e4aa5712e7cbf0e87e30a30 100644 (file)
@@ -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
  */
-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) {
-       case IEEE80211_HT_PARAM_CHA_SEC_NONE:
-               return NL80211_CHAN_HT20;
-       case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
-               return NL80211_CHAN_HT40PLUS;
-       case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
-               return NL80211_CHAN_HT40MINUS;
-       default:
-               return NL80211_CHAN_HT20;
+       struct mwifiex_channel_band channel_band;
+       int ret;
+
+       ret = mwifiex_get_chan_info(priv, &channel_band);
+
+       if (!ret) {
+               switch (channel_band.band_config.chan_width) {
+               case CHAN_BW_20MHZ:
+                       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,
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
        struct mwifiex_bssdescriptor *curr_bss;
        struct ieee80211_channel *chan;
-       u8 second_chan_offset;
        enum nl80211_channel_type chan_type;
        enum nl80211_band band;
        int freq;
@@ -3954,10 +3967,7 @@ static int mwifiex_cfg80211_get_channel(struct wiphy *wiphy,
                chan = ieee80211_get_channel(wiphy, freq);
 
                if (priv->ht_param_present) {
-                       second_chan_offset = priv->assoc_resp_ht_param &
-                                       IEEE80211_HT_PARAM_CHA_SEC_OFFSET;
-                       chan_type = mwifiex_sec_chan_offset_to_chan_type
-                                                       (second_chan_offset);
+                       chan_type = mwifiex_get_chan_type(priv);
                        cfg80211_chandef_create(chandef, chan, chan_type);
                } else {
                        cfg80211_chandef_create(chandef, chan,
index 188e4c3708363ea29915c478796c046d1ac9d15a..46696ea0b23e8260f3029c0cb1b9f0de3d5928de 100644 (file)
@@ -294,4 +294,21 @@ enum rdwr_status {
        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_ */
index 9c2cdef540742670fe4da7adc05d93c1dd15e435..c5dc518f768b5373bb4e111c389fdf1c7e6335df 100644 (file)
@@ -411,6 +411,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
 #define HostCmd_CMD_TDLS_OPER                         0x0122
 #define HostCmd_CMD_FW_DUMP_EVENT                    0x0125
 #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_PACKET_AGGR_CTRL                 0x0251
 
@@ -2285,6 +2286,11 @@ struct host_cmd_ds_pkt_aggr_ctrl {
        __le16 tx_aggr_align;
 } __packed;
 
+struct host_cmd_ds_sta_configure {
+       __le16 action;
+       u8 tlv_buffer[0];
+} __packed;
+
 struct host_cmd_ds_command {
        __le16 command;
        __le16 size;
@@ -2361,6 +2367,7 @@ struct host_cmd_ds_command {
                struct host_cmd_ds_gtk_rekey_params rekey;
                struct host_cmd_ds_chan_region_cfg reg_cfg;
                struct host_cmd_ds_pkt_aggr_ctrl pkt_aggr_ctrl;
+               struct host_cmd_ds_sta_configure sta_cfg;
        } params;
 } __packed;
 
index 58e6ae5415e7b48dd6dab37931d159c258d29215..9bde181700dc25de9a6303f749b91383454fa41d 100644 (file)
@@ -517,6 +517,18 @@ enum mwifiex_iface_work_flags {
        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_adapter *adapter;
        u8 bss_type;
@@ -1557,7 +1569,7 @@ int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
                                        struct mwifiex_bssdescriptor *bss_desc);
 
 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,
                                              const char *name,
@@ -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 cmd_type,
                              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,
                              struct host_cmd_ds_command *resp,
                              struct host_cmd_ds_wakeup_reason *wakeup_reason);
index 211e47d8b3181ddab78d90f293953eaf714b3d2b..4ed10cf82f9a4c7459e6429087eca637470afd40 100644 (file)
@@ -1898,6 +1898,25 @@ static int mwifiex_cmd_get_wakeup_reason(struct mwifiex_private *priv,
        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 */
 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,
                cmd_ptr->command = cpu_to_le16(cmd_no);
                cmd_ptr->size = cpu_to_le16(S_DS_GEN);
                break;
+       case HostCmd_CMD_STA_CONFIGURE:
+               ret = mwifiex_cmd_get_chan_info(cmd_ptr, cmd_action);
+               break;
        default:
                mwifiex_dbg(priv->adapter, ERROR,
                            "PREP_CMD: unknown cmd- %#x\n", cmd_no);
index 1bd4e13b8449a51ce0a6e789b5b02a8761334322..69e3b624adbb9432fe49de863de2d0e95418c739 100644 (file)
@@ -1170,6 +1170,22 @@ static int mwifiex_ret_pkt_aggr_ctrl(struct mwifiex_private *priv,
        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.
  *
@@ -1393,6 +1409,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
        case HostCmd_CMD_CHAN_REGION_CFG:
                ret = mwifiex_ret_chan_region_cfg(priv, resp);
                break;
+       case HostCmd_CMD_STA_CONFIGURE:
+               ret = mwifiex_ret_get_chan_info(priv, resp, data_buf);
+               break;
        default:
                mwifiex_dbg(adapter, ERROR,
                            "CMD_RESP: unknown cmd response %#x\n",
index ed66f12d3301d33bf7271384ecdd6a7399261df2..5414b755cf8225829e86b0bb26390e7635fadf73 100644 (file)
@@ -1481,3 +1481,15 @@ int mwifiex_get_wakeup_reason(struct mwifiex_private *priv, u16 action,
 
        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;
+}