aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwifiex/cfg80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/mwifiex/cfg80211.c')
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c209
1 files changed, 44 insertions, 165 deletions
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 352d2c5da1f..6fd53e4e3fe 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -547,7 +547,7 @@ mwifiex_dump_station_info(struct mwifiex_private *priv,
547 sinfo->tx_bytes = priv->stats.tx_bytes; 547 sinfo->tx_bytes = priv->stats.tx_bytes;
548 sinfo->rx_packets = priv->stats.rx_packets; 548 sinfo->rx_packets = priv->stats.rx_packets;
549 sinfo->tx_packets = priv->stats.tx_packets; 549 sinfo->tx_packets = priv->stats.tx_packets;
550 sinfo->signal = priv->w_stats.qual.level; 550 sinfo->signal = priv->qual_level;
551 sinfo->txrate.legacy = rate.rate; 551 sinfo->txrate.legacy = rate.rate;
552 552
553 return ret; 553 return ret;
@@ -793,139 +793,6 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)
793} 793}
794 794
795/* 795/*
796 * This function informs the CFG802.11 subsystem of a new BSS connection.
797 *
798 * The following information are sent to the CFG802.11 subsystem
799 * to register the new BSS connection. If we do not register the new BSS,
800 * a kernel panic will result.
801 * - MAC address
802 * - Capabilities
803 * - Beacon period
804 * - RSSI value
805 * - Channel
806 * - Supported rates IE
807 * - Extended capabilities IE
808 * - DS parameter set IE
809 * - HT Capability IE
810 * - Vendor Specific IE (221)
811 * - WPA IE
812 * - RSN IE
813 */
814static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv,
815 struct mwifiex_802_11_ssid *ssid)
816{
817 struct mwifiex_bssdescriptor *scan_table;
818 int i, j;
819 struct ieee80211_channel *chan;
820 u8 *ie, *ie_buf;
821 u32 ie_len;
822 u8 *beacon;
823 int beacon_size;
824 u8 element_id, element_len;
825
826#define MAX_IE_BUF 2048
827 ie_buf = kzalloc(MAX_IE_BUF, GFP_KERNEL);
828 if (!ie_buf) {
829 dev_err(priv->adapter->dev, "%s: failed to alloc ie_buf\n",
830 __func__);
831 return -ENOMEM;
832 }
833
834 scan_table = priv->adapter->scan_table;
835 for (i = 0; i < priv->adapter->num_in_scan_table; i++) {
836 if (ssid) {
837 /* Inform specific BSS only */
838 if (memcmp(ssid->ssid, scan_table[i].ssid.ssid,
839 ssid->ssid_len))
840 continue;
841 }
842 memset(ie_buf, 0, MAX_IE_BUF);
843 ie_buf[0] = WLAN_EID_SSID;
844 ie_buf[1] = scan_table[i].ssid.ssid_len;
845 memcpy(&ie_buf[sizeof(struct ieee_types_header)],
846 scan_table[i].ssid.ssid, ie_buf[1]);
847
848 ie = ie_buf + ie_buf[1] + sizeof(struct ieee_types_header);
849 ie_len = ie_buf[1] + sizeof(struct ieee_types_header);
850
851 ie[0] = WLAN_EID_SUPP_RATES;
852
853 for (j = 0; j < sizeof(scan_table[i].supported_rates); j++) {
854 if (!scan_table[i].supported_rates[j])
855 break;
856 else
857 ie[j + sizeof(struct ieee_types_header)] =
858 scan_table[i].supported_rates[j];
859 }
860
861 ie[1] = j;
862 ie_len += ie[1] + sizeof(struct ieee_types_header);
863
864 beacon = scan_table[i].beacon_buf;
865 beacon_size = scan_table[i].beacon_buf_size;
866
867 /* Skip time stamp, beacon interval and capability */
868
869 if (beacon) {
870 beacon += sizeof(scan_table[i].beacon_period)
871 + sizeof(scan_table[i].time_stamp) +
872 +sizeof(scan_table[i].cap_info_bitmap);
873
874 beacon_size -= sizeof(scan_table[i].beacon_period)
875 + sizeof(scan_table[i].time_stamp)
876 + sizeof(scan_table[i].cap_info_bitmap);
877 }
878
879 while (beacon_size >= sizeof(struct ieee_types_header)) {
880 ie = ie_buf + ie_len;
881 element_id = *beacon;
882 element_len = *(beacon + 1);
883 if (beacon_size < (int) element_len +
884 sizeof(struct ieee_types_header)) {
885 dev_err(priv->adapter->dev, "%s: in processing"
886 " IE, bytes left < IE length\n",
887 __func__);
888 break;
889 }
890 switch (element_id) {
891 case WLAN_EID_EXT_CAPABILITY:
892 case WLAN_EID_DS_PARAMS:
893 case WLAN_EID_HT_CAPABILITY:
894 case WLAN_EID_VENDOR_SPECIFIC:
895 case WLAN_EID_RSN:
896 case WLAN_EID_BSS_AC_ACCESS_DELAY:
897 ie[0] = element_id;
898 ie[1] = element_len;
899 memcpy(&ie[sizeof(struct ieee_types_header)],
900 (u8 *) beacon
901 + sizeof(struct ieee_types_header),
902 element_len);
903 ie_len += ie[1] +
904 sizeof(struct ieee_types_header);
905 break;
906 default:
907 break;
908 }
909 beacon += element_len +
910 sizeof(struct ieee_types_header);
911 beacon_size -= element_len +
912 sizeof(struct ieee_types_header);
913 }
914 chan = ieee80211_get_channel(priv->wdev->wiphy,
915 scan_table[i].freq);
916 cfg80211_inform_bss(priv->wdev->wiphy, chan,
917 scan_table[i].mac_address,
918 0, scan_table[i].cap_info_bitmap,
919 scan_table[i].beacon_period,
920 ie_buf, ie_len,
921 scan_table[i].rssi, GFP_KERNEL);
922 }
923
924 kfree(ie_buf);
925 return 0;
926}
927
928/*
929 * This function connects with a BSS. 796 * This function connects with a BSS.
930 * 797 *
931 * This function handles both Infra and Ad-Hoc modes. It also performs 798 * This function handles both Infra and Ad-Hoc modes. It also performs
@@ -937,8 +804,7 @@ static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv,
937 * For Infra mode, the function returns failure if the specified SSID 804 * For Infra mode, the function returns failure if the specified SSID
938 * is not found in scan table. However, for Ad-Hoc mode, it can create 805 * is not found in scan table. However, for Ad-Hoc mode, it can create
939 * the IBSS if it does not exist. On successful completion in either case, 806 * the IBSS if it does not exist. On successful completion in either case,
940 * the function notifies the CFG802.11 subsystem of the new BSS connection, 807 * the function notifies the CFG802.11 subsystem of the new BSS connection.
941 * otherwise the kernel will panic.
942 */ 808 */
943static int 809static int
944mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, 810mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
@@ -946,11 +812,11 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
946 struct cfg80211_connect_params *sme, bool privacy) 812 struct cfg80211_connect_params *sme, bool privacy)
947{ 813{
948 struct mwifiex_802_11_ssid req_ssid; 814 struct mwifiex_802_11_ssid req_ssid;
949 struct mwifiex_ssid_bssid ssid_bssid;
950 int ret, auth_type = 0; 815 int ret, auth_type = 0;
816 struct cfg80211_bss *bss = NULL;
817 u8 is_scanning_required = 0;
951 818
952 memset(&req_ssid, 0, sizeof(struct mwifiex_802_11_ssid)); 819 memset(&req_ssid, 0, sizeof(struct mwifiex_802_11_ssid));
953 memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid));
954 820
955 req_ssid.ssid_len = ssid_len; 821 req_ssid.ssid_len = ssid_len;
956 if (ssid_len > IEEE80211_MAX_SSID_LEN) { 822 if (ssid_len > IEEE80211_MAX_SSID_LEN) {
@@ -1028,30 +894,48 @@ done:
1028 return -EFAULT; 894 return -EFAULT;
1029 } 895 }
1030 896
897 /*
898 * Scan entries are valid for some time (15 sec). So we can save one
899 * active scan time if we just try cfg80211_get_bss first. If it fails
900 * then request scan and cfg80211_get_bss() again for final output.
901 */
902 while (1) {
903 if (is_scanning_required) {
904 /* Do specific SSID scanning */
905 if (mwifiex_request_scan(priv, &req_ssid)) {
906 dev_err(priv->adapter->dev, "scan error\n");
907 return -EFAULT;
908 }
909 }
1031 910
1032 memcpy(&ssid_bssid.ssid, &req_ssid, sizeof(struct mwifiex_802_11_ssid)); 911 /* Find the BSS we want using available scan results */
1033 912 if (mode == NL80211_IFTYPE_ADHOC)
1034 if (mode != NL80211_IFTYPE_ADHOC) { 913 bss = cfg80211_get_bss(priv->wdev->wiphy, channel,
1035 if (mwifiex_find_best_bss(priv, &ssid_bssid)) 914 bssid, ssid, ssid_len,
1036 return -EFAULT; 915 WLAN_CAPABILITY_IBSS,
1037 /* Inform the BSS information to kernel, otherwise 916 WLAN_CAPABILITY_IBSS);
1038 * kernel will give a panic after successful assoc */ 917 else
1039 if (mwifiex_inform_bss_from_scan_result(priv, &req_ssid)) 918 bss = cfg80211_get_bss(priv->wdev->wiphy, channel,
1040 return -EFAULT; 919 bssid, ssid, ssid_len,
920 WLAN_CAPABILITY_ESS,
921 WLAN_CAPABILITY_ESS);
922
923 if (!bss) {
924 if (is_scanning_required) {
925 dev_warn(priv->adapter->dev, "assoc: requested "
926 "bss not found in scan results\n");
927 break;
928 }
929 is_scanning_required = 1;
930 } else {
931 dev_dbg(priv->adapter->dev, "info: trying to associate to %s and bssid %pM\n",
932 (char *) req_ssid.ssid, bss->bssid);
933 memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN);
934 break;
935 }
1041 } 936 }
1042 937
1043 dev_dbg(priv->adapter->dev, "info: trying to associate to %s and bssid %pM\n", 938 if (mwifiex_bss_start(priv, bss, &req_ssid))
1044 (char *) req_ssid.ssid, ssid_bssid.bssid);
1045
1046 memcpy(&priv->cfg_bssid, ssid_bssid.bssid, 6);
1047
1048 /* Connect to BSS by ESSID */
1049 memset(&ssid_bssid.bssid, 0, ETH_ALEN);
1050
1051 if (!netif_queue_stopped(priv->netdev))
1052 netif_stop_queue(priv->netdev);
1053
1054 if (mwifiex_bss_start(priv, &ssid_bssid))
1055 return -EFAULT; 939 return -EFAULT;
1056 940
1057 if (mode == NL80211_IFTYPE_ADHOC) { 941 if (mode == NL80211_IFTYPE_ADHOC) {
@@ -1416,13 +1300,8 @@ mwifiex_cfg80211_results(struct work_struct *work)
1416 MWIFIEX_SCAN_TYPE_ACTIVE; 1300 MWIFIEX_SCAN_TYPE_ACTIVE;
1417 scan_req->chan_list[i].scan_time = 0; 1301 scan_req->chan_list[i].scan_time = 0;
1418 } 1302 }
1419 if (mwifiex_set_user_scan_ioctl(priv, scan_req)) { 1303 if (mwifiex_set_user_scan_ioctl(priv, scan_req))
1420 ret = -EFAULT; 1304 ret = -EFAULT;
1421 goto done;
1422 }
1423 if (mwifiex_inform_bss_from_scan_result(priv, NULL))
1424 ret = -EFAULT;
1425done:
1426 priv->scan_result_status = ret; 1305 priv->scan_result_status = ret;
1427 dev_dbg(priv->adapter->dev, "info: %s: sending scan results\n", 1306 dev_dbg(priv->adapter->dev, "info: %s: sending scan results\n",
1428 __func__); 1307 __func__);