mwifiex: add support for Marvell sd8797 device
[deliverable/linux.git] / drivers / net / wireless / mwifiex / sta_ioctl.c
index c34ff8c4f4f82adb471524df463b5d8c5e24fb5a..4b6f5539657d6cd250c07939cda005c02e66fba0 100644 (file)
@@ -55,7 +55,9 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)
 {
        bool cancel_flag = false;
        int status = adapter->cmd_wait_q.status;
+       struct cmd_ctrl_node *cmd_queued = adapter->cmd_queued;
 
+       adapter->cmd_queued = NULL;
        dev_dbg(adapter->dev, "cmd pending\n");
        atomic_inc(&adapter->cmd_pending);
 
@@ -64,8 +66,8 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)
 
        /* Wait for completion */
        wait_event_interruptible(adapter->cmd_wait_q.wait,
-                                       adapter->cmd_wait_q.condition);
-       if (!adapter->cmd_wait_q.condition)
+                                       *(cmd_queued->condition));
+       if (!*(cmd_queued->condition))
                cancel_flag = true;
 
        if (cancel_flag) {
@@ -141,91 +143,147 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
        return ret;
 }
 
+/*
+ * This function fills bss descriptor structure using provided
+ * information.
+ */
+int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
+                             u8 *bssid, s32 rssi, u8 *ie_buf,
+                             size_t ie_len, u16 beacon_period,
+                             u16 cap_info_bitmap, u8 band,
+                             struct mwifiex_bssdescriptor *bss_desc)
+{
+       int ret;
+
+       memcpy(bss_desc->mac_address, bssid, ETH_ALEN);
+       bss_desc->rssi = rssi;
+       bss_desc->beacon_buf = ie_buf;
+       bss_desc->beacon_buf_size = ie_len;
+       bss_desc->beacon_period = beacon_period;
+       bss_desc->cap_info_bitmap = cap_info_bitmap;
+       bss_desc->bss_band = band;
+       if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) {
+               dev_dbg(priv->adapter->dev, "info: InterpretIE: AP WEP enabled\n");
+               bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP;
+       } else {
+               bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL;
+       }
+       if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_IBSS)
+               bss_desc->bss_mode = NL80211_IFTYPE_ADHOC;
+       else
+               bss_desc->bss_mode = NL80211_IFTYPE_STATION;
+
+       ret = mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc,
+                                             ie_buf, ie_len);
+
+       return ret;
+}
+
 /*
  * In Ad-Hoc mode, the IBSS is created if not found in scan list.
  * In both Ad-Hoc and infra mode, an deauthentication is performed
  * first.
  */
-int mwifiex_bss_start(struct mwifiex_private *priv,
-                     struct mwifiex_ssid_bssid *ssid_bssid)
+int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
+                     struct mwifiex_802_11_ssid *req_ssid)
 {
        int ret;
        struct mwifiex_adapter *adapter = priv->adapter;
-       s32 i = -1;
+       struct mwifiex_bssdescriptor *bss_desc = NULL;
+       u8 *beacon_ie = NULL;
 
        priv->scan_block = false;
-       if (!ssid_bssid)
-               return -1;
+
+       if (bss) {
+               /* Allocate and fill new bss descriptor */
+               bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor),
+                               GFP_KERNEL);
+               if (!bss_desc) {
+                       dev_err(priv->adapter->dev, " failed to alloc bss_desc\n");
+                       return -ENOMEM;
+               }
+
+               beacon_ie = kmemdup(bss->information_elements,
+                                       bss->len_beacon_ies, GFP_KERNEL);
+               if (!beacon_ie) {
+                       kfree(bss_desc);
+                       dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n");
+                       return -ENOMEM;
+               }
+
+               ret = mwifiex_fill_new_bss_desc(priv, bss->bssid, bss->signal,
+                                               beacon_ie, bss->len_beacon_ies,
+                                               bss->beacon_interval,
+                                               bss->capability,
+                                               *(u8 *)bss->priv, bss_desc);
+               if (ret)
+                       goto done;
+       }
 
        if (priv->bss_mode == NL80211_IFTYPE_STATION) {
                /* Infra mode */
                ret = mwifiex_deauthenticate(priv, NULL);
                if (ret)
-                       return ret;
+                       goto done;
 
-               /* Search for the requested SSID in the scan table */
-               if (ssid_bssid->ssid.ssid_len)
-                       i = mwifiex_find_ssid_in_list(priv, &ssid_bssid->ssid,
-                                               NULL, NL80211_IFTYPE_STATION);
-               else
-                       i = mwifiex_find_bssid_in_list(priv,
-                                               (u8 *) &ssid_bssid->bssid,
-                                               NL80211_IFTYPE_STATION);
-               if (i < 0)
-                       return -1;
+               ret = mwifiex_check_network_compatibility(priv, bss_desc);
+               if (ret)
+                       goto done;
 
-               dev_dbg(adapter->dev,
-                       "info: SSID found in scan list ... associating...\n");
+               dev_dbg(adapter->dev, "info: SSID found in scan list ... "
+                                     "associating...\n");
+
+               if (!netif_queue_stopped(priv->netdev))
+                       netif_stop_queue(priv->netdev);
 
                /* Clear any past association response stored for
                 * application retrieval */
                priv->assoc_rsp_size = 0;
-               ret = mwifiex_associate(priv, &adapter->scan_table[i]);
-               if (ret)
-                       return ret;
+               ret = mwifiex_associate(priv, bss_desc);
+               if (bss)
+                       cfg80211_put_bss(bss);
        } else {
                /* Adhoc mode */
                /* If the requested SSID matches current SSID, return */
-               if (ssid_bssid->ssid.ssid_len &&
+               if (bss_desc && bss_desc->ssid.ssid_len &&
                    (!mwifiex_ssid_cmp
                     (&priv->curr_bss_params.bss_descriptor.ssid,
-                     &ssid_bssid->ssid)))
+                     &bss_desc->ssid))) {
+                       kfree(bss_desc);
+                       kfree(beacon_ie);
                        return 0;
+               }
 
                /* Exit Adhoc mode first */
                dev_dbg(adapter->dev, "info: Sending Adhoc Stop\n");
                ret = mwifiex_deauthenticate(priv, NULL);
                if (ret)
-                       return ret;
+                       goto done;
 
                priv->adhoc_is_link_sensed = false;
 
-               /* Search for the requested network in the scan table */
-               if (ssid_bssid->ssid.ssid_len)
-                       i = mwifiex_find_ssid_in_list(priv,
-                                                     &ssid_bssid->ssid, NULL,
-                                                     NL80211_IFTYPE_ADHOC);
-               else
-                       i = mwifiex_find_bssid_in_list(priv,
-                                                      (u8 *)&ssid_bssid->bssid,
-                                                      NL80211_IFTYPE_ADHOC);
+               ret = mwifiex_check_network_compatibility(priv, bss_desc);
+
+               if (!netif_queue_stopped(priv->netdev))
+                       netif_stop_queue(priv->netdev);
 
-               if (i >= 0) {
+               if (!ret) {
                        dev_dbg(adapter->dev, "info: network found in scan"
                                                        " list. Joining...\n");
-                       ret = mwifiex_adhoc_join(priv, &adapter->scan_table[i]);
-                       if (ret)
-                               return ret;
+                       ret = mwifiex_adhoc_join(priv, bss_desc);
+                       if (bss)
+                               cfg80211_put_bss(bss);
                } else {
                        dev_dbg(adapter->dev, "info: Network not found in "
                                "the list, creating adhoc with ssid = %s\n",
-                              ssid_bssid->ssid.ssid);
-                       ret = mwifiex_adhoc_start(priv, &ssid_bssid->ssid);
-                       if (ret)
-                               return ret;
+                               req_ssid->ssid);
+                       ret = mwifiex_adhoc_start(priv, req_ssid);
                }
        }
 
+done:
+       kfree(bss_desc);
+       kfree(beacon_ie);
        return ret;
 }
 
@@ -235,8 +293,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv,
  * This function prepares the correct firmware command and
  * issues it.
  */
-int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
-                         int cmd_type, struct mwifiex_ds_hs_cfg *hs_cfg)
+static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
+                                int cmd_type, struct mwifiex_ds_hs_cfg *hs_cfg)
 
 {
        struct mwifiex_adapter *adapter = priv->adapter;
@@ -376,7 +434,6 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv,
 {
        struct mwifiex_adapter *adapter = priv->adapter;
        struct mwifiex_bssdescriptor *bss_desc;
-       s32 tbl_idx;
 
        if (!info)
                return -1;
@@ -394,17 +451,6 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv,
 
        info->region_code = adapter->region_code;
 
-       /* Scan table index if connected */
-       info->scan_table_idx = 0;
-       if (priv->media_connected) {
-               tbl_idx =
-                       mwifiex_find_ssid_in_list(priv, &bss_desc->ssid,
-                                                 bss_desc->mac_address,
-                                                 priv->bss_mode);
-               if (tbl_idx >= 0)
-                       info->scan_table_idx = tbl_idx;
-       }
-
        info->media_connected = priv->media_connected;
 
        info->max_power_level = priv->max_tx_power_level;
@@ -585,50 +631,6 @@ static int mwifiex_bss_ioctl_ibss_channel(struct mwifiex_private *priv,
                                    action, 0, channel);
 }
 
-/*
- * IOCTL request handler to find a particular BSS.
- *
- * The BSS can be searched with either a BSSID or a SSID. If none of
- * these are provided, just the best BSS (best RSSI) is returned.
- */
-int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *priv,
-                              struct mwifiex_ssid_bssid *ssid_bssid)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct mwifiex_bssdescriptor *bss_desc;
-       u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
-       u8 mac[ETH_ALEN];
-       int i = 0;
-
-       if (memcmp(ssid_bssid->bssid, zero_mac, sizeof(zero_mac))) {
-               i = mwifiex_find_bssid_in_list(priv,
-                                              (u8 *) ssid_bssid->bssid,
-                                              priv->bss_mode);
-               if (i < 0) {
-                       memcpy(mac, ssid_bssid->bssid, sizeof(mac));
-                       dev_err(adapter->dev, "cannot find bssid %pM\n", mac);
-                       return -1;
-               }
-               bss_desc = &adapter->scan_table[i];
-               memcpy(&ssid_bssid->ssid, &bss_desc->ssid,
-                               sizeof(struct mwifiex_802_11_ssid));
-       } else if (ssid_bssid->ssid.ssid_len) {
-               i = mwifiex_find_ssid_in_list(priv, &ssid_bssid->ssid, NULL,
-                                             priv->bss_mode);
-               if (i < 0) {
-                       dev_err(adapter->dev, "cannot find ssid %s\n",
-                                       ssid_bssid->ssid.ssid);
-                       return -1;
-               }
-               bss_desc = &adapter->scan_table[i];
-               memcpy(ssid_bssid->bssid, bss_desc->mac_address, ETH_ALEN);
-       } else {
-               return mwifiex_find_best_network(priv, ssid_bssid);
-       }
-
-       return 0;
-}
-
 /*
  * IOCTL request handler to change Ad-Hoc channel.
  *
@@ -653,6 +655,9 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel)
        struct mwifiex_bss_info bss_info;
        struct mwifiex_ssid_bssid ssid_bssid;
        u16 curr_chan = 0;
+       struct cfg80211_bss *bss = NULL;
+       struct ieee80211_channel *chan;
+       enum ieee80211_band band;
 
        memset(&bss_info, 0, sizeof(bss_info));
 
@@ -688,12 +693,20 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel)
                ret = -1;
                goto done;
        }
-       /* Start/Join Adhoc network */
-       memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid));
-       memcpy(&ssid_bssid.ssid, &bss_info.ssid,
-              sizeof(struct mwifiex_802_11_ssid));
 
-       ret = mwifiex_bss_start(priv, &ssid_bssid);
+       band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
+       chan = __ieee80211_get_channel(priv->wdev->wiphy,
+                       ieee80211_channel_to_frequency(channel, band));
+
+       /* Find the BSS we want using available scan results */
+       bss = cfg80211_get_bss(priv->wdev->wiphy, chan, bss_info.bssid,
+                              bss_info.ssid.ssid, bss_info.ssid.ssid_len,
+                              WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
+       if (!bss)
+               wiphy_warn(priv->wdev->wiphy, "assoc: bss %pM not in scan results\n",
+                         bss_info.bssid);
+
+       ret = mwifiex_bss_start(priv, bss, &bss_info.ssid);
 done:
        return ret;
 }
@@ -709,51 +722,9 @@ done:
 static int mwifiex_rate_ioctl_get_rate_value(struct mwifiex_private *priv,
                                             struct mwifiex_rate_cfg *rate_cfg)
 {
-       struct mwifiex_adapter *adapter = priv->adapter;
-
        rate_cfg->is_rate_auto = priv->is_data_rate_auto;
-       if (!priv->media_connected) {
-               switch (adapter->config_bands) {
-               case BAND_B:
-                       /* Return the lowest supported rate for B band */
-                       rate_cfg->rate = supported_rates_b[0] & 0x7f;
-                       break;
-               case BAND_G:
-               case BAND_G | BAND_GN:
-                       /* Return the lowest supported rate for G band */
-                       rate_cfg->rate = supported_rates_g[0] & 0x7f;
-                       break;
-               case BAND_B | BAND_G:
-               case BAND_A | BAND_B | BAND_G:
-               case BAND_A | BAND_B:
-               case BAND_A | BAND_B | BAND_G | BAND_AN | BAND_GN:
-               case BAND_B | BAND_G | BAND_GN:
-                       /* Return the lowest supported rate for BG band */
-                       rate_cfg->rate = supported_rates_bg[0] & 0x7f;
-                       break;
-               case BAND_A:
-               case BAND_A | BAND_G:
-               case BAND_A | BAND_G | BAND_AN | BAND_GN:
-               case BAND_A | BAND_AN:
-                       /* Return the lowest supported rate for A band */
-                       rate_cfg->rate = supported_rates_a[0] & 0x7f;
-                       break;
-               case BAND_GN:
-                       /* Return the lowest supported rate for N band */
-                       rate_cfg->rate = supported_rates_n[0] & 0x7f;
-                       break;
-               default:
-                       dev_warn(adapter->dev, "invalid band %#x\n",
-                              adapter->config_bands);
-                       break;
-               }
-       } else {
-               return mwifiex_send_cmd_sync(priv,
-                                           HostCmd_CMD_802_11_TX_RATE_QUERY,
-                                           HostCmd_ACT_GEN_GET, 0, NULL);
-       }
-
-       return 0;
+       return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_TX_RATE_QUERY,
+                                    HostCmd_ACT_GEN_GET, 0, NULL);
 }
 
 /*
@@ -794,7 +765,7 @@ static int mwifiex_rate_ioctl_set_rate_value(struct mwifiex_private *priv,
                        if ((rate[i] & 0x7f) == (rate_cfg->rate & 0x7f))
                                break;
                }
-               if (!rate[i] || (i == MWIFIEX_SUPPORTED_RATES)) {
+               if ((i == MWIFIEX_SUPPORTED_RATES) || !rate[i]) {
                        dev_err(adapter->dev, "fixed data rate %#x is out "
                               "of range\n", rate_cfg->rate);
                        return -1;
@@ -860,10 +831,10 @@ int mwifiex_drv_get_data_rate(struct mwifiex_private *priv,
        ret = mwifiex_rate_ioctl_cfg(priv, rate);
 
        if (!ret) {
-               if (rate && rate->is_rate_auto)
-                       rate->rate = mwifiex_index_to_data_rate(priv->tx_rate,
-                                                       priv->tx_htinfo);
-               else if (rate)
+               if (rate->is_rate_auto)
+                       rate->rate = mwifiex_index_to_data_rate(priv,
+                                       priv->tx_rate, priv->tx_htinfo);
+               else
                        rate->rate = priv->data_rate;
        } else {
                ret = -1;
@@ -1280,9 +1251,9 @@ int mwifiex_get_signal_info(struct mwifiex_private *priv,
 
        if (!status) {
                if (signal->selector & BCN_RSSI_AVG_MASK)
-                       priv->w_stats.qual.level = signal->bcn_rssi_avg;
+                       priv->qual_level = signal->bcn_rssi_avg;
                if (signal->selector & BCN_NF_AVG_MASK)
-                       priv->w_stats.qual.noise = signal->bcn_nf_avg;
+                       priv->qual_noise = signal->bcn_nf_avg;
        }
 
        return status;
@@ -1341,18 +1312,8 @@ int
 mwifiex_get_stats_info(struct mwifiex_private *priv,
                       struct mwifiex_ds_get_stats *log)
 {
-       int ret;
-
-       ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_GET_LOG,
+       return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_GET_LOG,
                                    HostCmd_ACT_GEN_GET, 0, log);
-
-       if (!ret) {
-               priv->w_stats.discard.fragment = log->fcs_error;
-               priv->w_stats.discard.retries = log->retry;
-               priv->w_stats.discard.misc = log->ack_failure;
-       }
-
-       return ret;
 }
 
 /*
@@ -1594,7 +1555,7 @@ mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len)
 {
        struct mwifiex_ds_misc_gen_ie gen_ie;
 
-       if (ie_len > IW_CUSTOM_MAX)
+       if (ie_len > IEEE_MAX_IE_SIZE)
                return -EFAULT;
 
        gen_ie.type = MWIFIEX_IE_TYPE_GEN_IE;
This page took 0.032705 seconds and 5 git commands to generate.