]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/net/wireless/mwifiex/scan.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[karo-tx-linux.git] / drivers / net / wireless / mwifiex / scan.c
index ca64d4c941127511bde59dd76d8b2c47299db47b..3a17821157d77c1503ab636fafc8d244ae538def 100644 (file)
@@ -1755,6 +1755,7 @@ static void mwifiex_complete_scan(struct mwifiex_private *priv)
 {
        struct mwifiex_adapter *adapter = priv->adapter;
 
+       adapter->survey_idx = 0;
        if (adapter->curr_cmd->wait_q_enabled) {
                adapter->cmd_wait_q.status = 0;
                if (!priv->scan_request) {
@@ -1976,10 +1977,53 @@ int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
        return 0;
 }
 
+static void
+mwifiex_update_chan_statistics(struct mwifiex_private *priv,
+                              struct mwifiex_ietypes_chanstats *tlv_stat)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       u8 i, num_chan;
+       struct mwifiex_fw_chan_stats *fw_chan_stats;
+       struct mwifiex_chan_stats chan_stats;
+
+       fw_chan_stats = (void *)((u8 *)tlv_stat +
+                             sizeof(struct mwifiex_ie_types_header));
+       num_chan = le16_to_cpu(tlv_stat->header.len) /
+                                             sizeof(struct mwifiex_chan_stats);
+
+       for (i = 0 ; i < num_chan; i++) {
+               chan_stats.chan_num = fw_chan_stats->chan_num;
+               chan_stats.bandcfg = fw_chan_stats->bandcfg;
+               chan_stats.flags = fw_chan_stats->flags;
+               chan_stats.noise = fw_chan_stats->noise;
+               chan_stats.total_bss = le16_to_cpu(fw_chan_stats->total_bss);
+               chan_stats.cca_scan_dur =
+                                      le16_to_cpu(fw_chan_stats->cca_scan_dur);
+               chan_stats.cca_busy_dur =
+                                      le16_to_cpu(fw_chan_stats->cca_busy_dur);
+               dev_dbg(adapter->dev,
+                       "chan=%d, noise=%d, total_network=%d scan_duration=%d, busy_duration=%d\n",
+                       chan_stats.chan_num,
+                       chan_stats.noise,
+                       chan_stats.total_bss,
+                       chan_stats.cca_scan_dur,
+                       chan_stats.cca_busy_dur);
+               memcpy(&adapter->chan_stats[adapter->survey_idx++], &chan_stats,
+                      sizeof(struct mwifiex_chan_stats));
+               fw_chan_stats++;
+       }
+}
+
 /* This function handles the command response of extended scan */
-int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv)
+int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
+                               struct host_cmd_ds_command *resp)
 {
        struct mwifiex_adapter *adapter = priv->adapter;
+       struct host_cmd_ds_802_11_scan_ext *ext_scan_resp;
+       struct mwifiex_ie_types_header *tlv;
+       struct mwifiex_ietypes_chanstats *tlv_stat;
+       u16 buf_left, type, len;
+
        struct host_cmd_ds_command *cmd_ptr;
        struct cmd_ctrl_node *cmd_node;
        unsigned long cmd_flags, scan_flags;
@@ -1987,6 +2031,36 @@ int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv)
 
        dev_dbg(priv->adapter->dev, "info: EXT scan returns successfully\n");
 
+       ext_scan_resp = &resp->params.ext_scan;
+
+       tlv = (void *)ext_scan_resp->tlv_buffer;
+       buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN
+                                             - 1);
+
+       while (buf_left >= sizeof(struct mwifiex_ie_types_header)) {
+               type = le16_to_cpu(tlv->type);
+               len = le16_to_cpu(tlv->len);
+
+               if (buf_left < (sizeof(struct mwifiex_ie_types_header) + len)) {
+                       dev_err(adapter->dev,
+                               "error processing scan response TLVs");
+                       break;
+               }
+
+               switch (type) {
+               case TLV_TYPE_CHANNEL_STATS:
+                       tlv_stat = (void *)tlv;
+                       mwifiex_update_chan_statistics(priv, tlv_stat);
+                       break;
+               default:
+                       break;
+               }
+
+               buf_left -= len + sizeof(struct mwifiex_ie_types_header);
+               tlv = (void *)((u8 *)tlv + len +
+                              sizeof(struct mwifiex_ie_types_header));
+       }
+
        spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_flags);
        spin_lock_irqsave(&adapter->scan_pending_q_lock, scan_flags);
        if (list_empty(&adapter->scan_pending_q)) {