diff options
| author | John W. Linville <linville@tuxdriver.com> | 2012-05-22 15:18:06 -0400 |
|---|---|---|
| committer | John W. Linville <linville@tuxdriver.com> | 2012-05-22 15:18:06 -0400 |
| commit | a0d0d1685f9763ab26a394df3ab84026b39a06a7 (patch) | |
| tree | 4165dc6fd3266977ab4b3fa3b379c47597f97d88 /drivers/net/wireless | |
| parent | 31a67102f4762df5544bc2dfb34a931233d2a5b2 (diff) | |
| parent | 05f8f25276ea8c7d41b3649890d6eaf179e67a81 (diff) | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next
Diffstat (limited to 'drivers/net/wireless')
90 files changed, 3463 insertions, 4494 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 28a65d3a03d..b869a358ce4 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
| @@ -693,8 +693,8 @@ ath6kl_add_bss_if_needed(struct ath6kl_vif *vif, | |||
| 693 | ie, 2 + vif->ssid_len + beacon_ie_len, | 693 | ie, 2 + vif->ssid_len + beacon_ie_len, |
| 694 | 0, GFP_KERNEL); | 694 | 0, GFP_KERNEL); |
| 695 | if (bss) | 695 | if (bss) |
| 696 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "added bss %pM to " | 696 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, |
| 697 | "cfg80211\n", bssid); | 697 | "added bss %pM to cfg80211\n", bssid); |
| 698 | kfree(ie); | 698 | kfree(ie); |
| 699 | } else | 699 | } else |
| 700 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss\n"); | 700 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss\n"); |
| @@ -882,6 +882,32 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason, | |||
| 882 | vif->sme_state = SME_DISCONNECTED; | 882 | vif->sme_state = SME_DISCONNECTED; |
| 883 | } | 883 | } |
| 884 | 884 | ||
| 885 | static int ath6kl_set_probed_ssids(struct ath6kl *ar, | ||
| 886 | struct ath6kl_vif *vif, | ||
| 887 | struct cfg80211_ssid *ssids, int n_ssids) | ||
| 888 | { | ||
| 889 | u8 i; | ||
| 890 | |||
| 891 | if (n_ssids > MAX_PROBED_SSID_INDEX) | ||
| 892 | return -EINVAL; | ||
| 893 | |||
| 894 | for (i = 0; i < n_ssids; i++) { | ||
| 895 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i, | ||
| 896 | ssids[i].ssid_len ? | ||
| 897 | SPECIFIC_SSID_FLAG : ANY_SSID_FLAG, | ||
| 898 | ssids[i].ssid_len, | ||
| 899 | ssids[i].ssid); | ||
| 900 | } | ||
| 901 | |||
| 902 | /* Make sure no old entries are left behind */ | ||
| 903 | for (i = n_ssids; i < MAX_PROBED_SSID_INDEX; i++) { | ||
| 904 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i, | ||
| 905 | DISABLE_SSID_FLAG, 0, NULL); | ||
| 906 | } | ||
| 907 | |||
| 908 | return 0; | ||
| 909 | } | ||
| 910 | |||
| 885 | static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, | 911 | static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, |
| 886 | struct cfg80211_scan_request *request) | 912 | struct cfg80211_scan_request *request) |
| 887 | { | 913 | { |
| @@ -899,36 +925,25 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, | |||
| 899 | 925 | ||
| 900 | if (!ar->usr_bss_filter) { | 926 | if (!ar->usr_bss_filter) { |
| 901 | clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags); | 927 | clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags); |
| 902 | ret = ath6kl_wmi_bssfilter_cmd( | 928 | ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, |
| 903 | ar->wmi, vif->fw_vif_idx, | 929 | ALL_BSS_FILTER, 0); |
| 904 | (test_bit(CONNECTED, &vif->flags) ? | ||
| 905 | ALL_BUT_BSS_FILTER : ALL_BSS_FILTER), 0); | ||
| 906 | if (ret) { | 930 | if (ret) { |
| 907 | ath6kl_err("couldn't set bss filtering\n"); | 931 | ath6kl_err("couldn't set bss filtering\n"); |
| 908 | return ret; | 932 | return ret; |
| 909 | } | 933 | } |
| 910 | } | 934 | } |
| 911 | 935 | ||
| 912 | if (request->n_ssids && request->ssids[0].ssid_len) { | 936 | ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, |
| 913 | u8 i; | 937 | request->n_ssids); |
| 914 | 938 | if (ret < 0) | |
| 915 | if (request->n_ssids > (MAX_PROBED_SSID_INDEX - 1)) | 939 | return ret; |
| 916 | request->n_ssids = MAX_PROBED_SSID_INDEX - 1; | ||
| 917 | |||
| 918 | for (i = 0; i < request->n_ssids; i++) | ||
| 919 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, | ||
| 920 | i + 1, SPECIFIC_SSID_FLAG, | ||
| 921 | request->ssids[i].ssid_len, | ||
| 922 | request->ssids[i].ssid); | ||
| 923 | } | ||
| 924 | 940 | ||
| 925 | /* this also clears IE in fw if it's not set */ | 941 | /* this also clears IE in fw if it's not set */ |
| 926 | ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx, | 942 | ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx, |
| 927 | WMI_FRAME_PROBE_REQ, | 943 | WMI_FRAME_PROBE_REQ, |
| 928 | request->ie, request->ie_len); | 944 | request->ie, request->ie_len); |
| 929 | if (ret) { | 945 | if (ret) { |
| 930 | ath6kl_err("failed to set Probe Request appie for " | 946 | ath6kl_err("failed to set Probe Request appie for scan"); |
| 931 | "scan"); | ||
| 932 | return ret; | 947 | return ret; |
| 933 | } | 948 | } |
| 934 | 949 | ||
| @@ -945,8 +960,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, | |||
| 945 | 960 | ||
| 946 | channels = kzalloc(n_channels * sizeof(u16), GFP_KERNEL); | 961 | channels = kzalloc(n_channels * sizeof(u16), GFP_KERNEL); |
| 947 | if (channels == NULL) { | 962 | if (channels == NULL) { |
| 948 | ath6kl_warn("failed to set scan channels, " | 963 | ath6kl_warn("failed to set scan channels, scan all channels"); |
| 949 | "scan all channels"); | ||
| 950 | n_channels = 0; | 964 | n_channels = 0; |
| 951 | } | 965 | } |
| 952 | 966 | ||
| @@ -1018,6 +1032,20 @@ out: | |||
| 1018 | vif->scan_req = NULL; | 1032 | vif->scan_req = NULL; |
| 1019 | } | 1033 | } |
| 1020 | 1034 | ||
| 1035 | void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq, | ||
| 1036 | enum wmi_phy_mode mode) | ||
| 1037 | { | ||
| 1038 | enum nl80211_channel_type type; | ||
| 1039 | |||
| 1040 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, | ||
| 1041 | "channel switch notify nw_type %d freq %d mode %d\n", | ||
| 1042 | vif->nw_type, freq, mode); | ||
| 1043 | |||
| 1044 | type = (mode == WMI_11G_HT20) ? NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT; | ||
| 1045 | |||
| 1046 | cfg80211_ch_switch_notify(vif->ndev, freq, type); | ||
| 1047 | } | ||
| 1048 | |||
| 1021 | static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | 1049 | static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, |
| 1022 | u8 key_index, bool pairwise, | 1050 | u8 key_index, bool pairwise, |
| 1023 | const u8 *mac_addr, | 1051 | const u8 *mac_addr, |
| @@ -1111,9 +1139,8 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
| 1111 | ar->ap_mode_bkey.key_len = key->key_len; | 1139 | ar->ap_mode_bkey.key_len = key->key_len; |
| 1112 | memcpy(ar->ap_mode_bkey.key, key->key, key->key_len); | 1140 | memcpy(ar->ap_mode_bkey.key, key->key, key->key_len); |
| 1113 | if (!test_bit(CONNECTED, &vif->flags)) { | 1141 | if (!test_bit(CONNECTED, &vif->flags)) { |
| 1114 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay initial group " | 1142 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, |
| 1115 | "key configuration until AP mode has been " | 1143 | "Delay initial group key configuration until AP mode has been started\n"); |
| 1116 | "started\n"); | ||
| 1117 | /* | 1144 | /* |
| 1118 | * The key will be set in ath6kl_connect_ap_mode() once | 1145 | * The key will be set in ath6kl_connect_ap_mode() once |
| 1119 | * the connected event is received from the target. | 1146 | * the connected event is received from the target. |
| @@ -1129,8 +1156,8 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
| 1129 | * the AP mode has properly started | 1156 | * the AP mode has properly started |
| 1130 | * (ath6kl_install_statioc_wep_keys). | 1157 | * (ath6kl_install_statioc_wep_keys). |
| 1131 | */ | 1158 | */ |
| 1132 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay WEP key configuration " | 1159 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, |
| 1133 | "until AP mode has been started\n"); | 1160 | "Delay WEP key configuration until AP mode has been started\n"); |
| 1134 | vif->wep_key_list[key_index].key_len = key->key_len; | 1161 | vif->wep_key_list[key_index].key_len = key->key_len; |
| 1135 | memcpy(vif->wep_key_list[key_index].key, key->key, | 1162 | memcpy(vif->wep_key_list[key_index].key, key->key, |
| 1136 | key->key_len); | 1163 | key->key_len); |
| @@ -1962,8 +1989,7 @@ static int ath6kl_wow_sta(struct ath6kl *ar, struct ath6kl_vif *vif) | |||
| 1962 | sizeof(discvr_pattern), discvr_offset, | 1989 | sizeof(discvr_pattern), discvr_offset, |
| 1963 | discvr_pattern, discvr_mask); | 1990 | discvr_pattern, discvr_mask); |
| 1964 | if (ret) { | 1991 | if (ret) { |
| 1965 | ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR " | 1992 | ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR pattern\n"); |
| 1966 | "pattern\n"); | ||
| 1967 | return ret; | 1993 | return ret; |
| 1968 | } | 1994 | } |
| 1969 | } | 1995 | } |
| @@ -2031,6 +2057,10 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) | |||
| 2031 | u8 index = 0; | 2057 | u8 index = 0; |
| 2032 | __be32 ips[MAX_IP_ADDRS]; | 2058 | __be32 ips[MAX_IP_ADDRS]; |
| 2033 | 2059 | ||
| 2060 | /* The FW currently can't support multi-vif WoW properly. */ | ||
| 2061 | if (ar->num_vif > 1) | ||
| 2062 | return -EIO; | ||
| 2063 | |||
| 2034 | vif = ath6kl_vif_first(ar); | 2064 | vif = ath6kl_vif_first(ar); |
| 2035 | if (!vif) | 2065 | if (!vif) |
| 2036 | return -EIO; | 2066 | return -EIO; |
| @@ -2044,6 +2074,13 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) | |||
| 2044 | if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST)) | 2074 | if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST)) |
| 2045 | return -EINVAL; | 2075 | return -EINVAL; |
| 2046 | 2076 | ||
| 2077 | if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags)) { | ||
| 2078 | ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, | ||
| 2079 | vif->fw_vif_idx, false); | ||
| 2080 | if (ret) | ||
| 2081 | return ret; | ||
| 2082 | } | ||
| 2083 | |||
| 2047 | /* Clear existing WOW patterns */ | 2084 | /* Clear existing WOW patterns */ |
| 2048 | for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++) | 2085 | for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++) |
| 2049 | ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx, | 2086 | ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx, |
| @@ -2147,8 +2184,8 @@ static int ath6kl_wow_resume(struct ath6kl *ar) | |||
| 2147 | ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx, | 2184 | ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx, |
| 2148 | ATH6KL_HOST_MODE_AWAKE); | 2185 | ATH6KL_HOST_MODE_AWAKE); |
| 2149 | if (ret) { | 2186 | if (ret) { |
| 2150 | ath6kl_warn("Failed to configure host sleep mode for " | 2187 | ath6kl_warn("Failed to configure host sleep mode for wow resume: %d\n", |
| 2151 | "wow resume: %d\n", ret); | 2188 | ret); |
| 2152 | ar->state = ATH6KL_STATE_WOW; | 2189 | ar->state = ATH6KL_STATE_WOW; |
| 2153 | return ret; | 2190 | return ret; |
| 2154 | } | 2191 | } |
| @@ -2172,6 +2209,13 @@ static int ath6kl_wow_resume(struct ath6kl *ar) | |||
| 2172 | 2209 | ||
| 2173 | ar->state = ATH6KL_STATE_ON; | 2210 | ar->state = ATH6KL_STATE_ON; |
| 2174 | 2211 | ||
| 2212 | if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags)) { | ||
| 2213 | ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, | ||
| 2214 | vif->fw_vif_idx, true); | ||
| 2215 | if (ret) | ||
| 2216 | return ret; | ||
| 2217 | } | ||
| 2218 | |||
| 2175 | netif_wake_queue(vif->ndev); | 2219 | netif_wake_queue(vif->ndev); |
| 2176 | 2220 | ||
| 2177 | return 0; | 2221 | return 0; |
| @@ -2186,8 +2230,10 @@ static int ath6kl_cfg80211_deepsleep_suspend(struct ath6kl *ar) | |||
| 2186 | if (!vif) | 2230 | if (!vif) |
| 2187 | return -EIO; | 2231 | return -EIO; |
| 2188 | 2232 | ||
| 2189 | if (!ath6kl_cfg80211_ready(vif)) | 2233 | if (!test_bit(WMI_READY, &ar->flag)) { |
| 2234 | ath6kl_err("deepsleep failed as wmi is not ready\n"); | ||
| 2190 | return -EIO; | 2235 | return -EIO; |
| 2236 | } | ||
| 2191 | 2237 | ||
| 2192 | ath6kl_cfg80211_stop_all(ar); | 2238 | ath6kl_cfg80211_stop_all(ar); |
| 2193 | 2239 | ||
| @@ -2447,6 +2493,24 @@ static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum ieee80211_band band, | |||
| 2447 | band, htcap); | 2493 | band, htcap); |
| 2448 | } | 2494 | } |
| 2449 | 2495 | ||
| 2496 | static int ath6kl_restore_htcap(struct ath6kl_vif *vif) | ||
| 2497 | { | ||
| 2498 | struct wiphy *wiphy = vif->ar->wiphy; | ||
| 2499 | int band, ret = 0; | ||
| 2500 | |||
| 2501 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
| 2502 | if (!wiphy->bands[band]) | ||
| 2503 | continue; | ||
| 2504 | |||
| 2505 | ret = ath6kl_set_htcap(vif, band, | ||
| 2506 | wiphy->bands[band]->ht_cap.ht_supported); | ||
| 2507 | if (ret) | ||
| 2508 | return ret; | ||
| 2509 | } | ||
| 2510 | |||
| 2511 | return ret; | ||
| 2512 | } | ||
| 2513 | |||
| 2450 | static bool ath6kl_is_p2p_ie(const u8 *pos) | 2514 | static bool ath6kl_is_p2p_ie(const u8 *pos) |
| 2451 | { | 2515 | { |
| 2452 | return pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && | 2516 | return pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && |
| @@ -2568,28 +2632,34 @@ static int ath6kl_get_rsn_capab(struct cfg80211_beacon_data *beacon, | |||
| 2568 | /* skip element id and length */ | 2632 | /* skip element id and length */ |
| 2569 | rsn_ie += 2; | 2633 | rsn_ie += 2; |
| 2570 | 2634 | ||
| 2571 | /* skip version, group cipher */ | 2635 | /* skip version */ |
| 2572 | if (rsn_ie_len < 6) | 2636 | if (rsn_ie_len < 2) |
| 2573 | return -EINVAL; | 2637 | return -EINVAL; |
| 2574 | rsn_ie += 6; | 2638 | rsn_ie += 2; |
| 2575 | rsn_ie_len -= 6; | 2639 | rsn_ie_len -= 2; |
| 2640 | |||
| 2641 | /* skip group cipher suite */ | ||
| 2642 | if (rsn_ie_len < 4) | ||
| 2643 | return 0; | ||
| 2644 | rsn_ie += 4; | ||
| 2645 | rsn_ie_len -= 4; | ||
| 2576 | 2646 | ||
| 2577 | /* skip pairwise cipher suite */ | 2647 | /* skip pairwise cipher suite */ |
| 2578 | if (rsn_ie_len < 2) | 2648 | if (rsn_ie_len < 2) |
| 2579 | return -EINVAL; | 2649 | return 0; |
| 2580 | cnt = *((u16 *) rsn_ie); | 2650 | cnt = get_unaligned_le16(rsn_ie); |
| 2581 | rsn_ie += (2 + cnt * 4); | 2651 | rsn_ie += (2 + cnt * 4); |
| 2582 | rsn_ie_len -= (2 + cnt * 4); | 2652 | rsn_ie_len -= (2 + cnt * 4); |
| 2583 | 2653 | ||
| 2584 | /* skip akm suite */ | 2654 | /* skip akm suite */ |
| 2585 | if (rsn_ie_len < 2) | 2655 | if (rsn_ie_len < 2) |
| 2586 | return -EINVAL; | 2656 | return 0; |
| 2587 | cnt = *((u16 *) rsn_ie); | 2657 | cnt = get_unaligned_le16(rsn_ie); |
| 2588 | rsn_ie += (2 + cnt * 4); | 2658 | rsn_ie += (2 + cnt * 4); |
| 2589 | rsn_ie_len -= (2 + cnt * 4); | 2659 | rsn_ie_len -= (2 + cnt * 4); |
| 2590 | 2660 | ||
| 2591 | if (rsn_ie_len < 2) | 2661 | if (rsn_ie_len < 2) |
| 2592 | return -EINVAL; | 2662 | return 0; |
| 2593 | 2663 | ||
| 2594 | memcpy(rsn_capab, rsn_ie, 2); | 2664 | memcpy(rsn_capab, rsn_ie, 2); |
| 2595 | 2665 | ||
| @@ -2766,6 +2836,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
| 2766 | return res; | 2836 | return res; |
| 2767 | } | 2837 | } |
| 2768 | 2838 | ||
| 2839 | memcpy(&vif->profile, &p, sizeof(p)); | ||
| 2769 | res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p); | 2840 | res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p); |
| 2770 | if (res < 0) | 2841 | if (res < 0) |
| 2771 | return res; | 2842 | return res; |
| @@ -2801,13 +2872,7 @@ static int ath6kl_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
| 2801 | clear_bit(CONNECTED, &vif->flags); | 2872 | clear_bit(CONNECTED, &vif->flags); |
| 2802 | 2873 | ||
| 2803 | /* Restore ht setting in firmware */ | 2874 | /* Restore ht setting in firmware */ |
| 2804 | if (ath6kl_set_htcap(vif, IEEE80211_BAND_2GHZ, true)) | 2875 | return ath6kl_restore_htcap(vif); |
| 2805 | return -EIO; | ||
| 2806 | |||
| 2807 | if (ath6kl_set_htcap(vif, IEEE80211_BAND_5GHZ, true)) | ||
| 2808 | return -EIO; | ||
| 2809 | |||
| 2810 | return 0; | ||
| 2811 | } | 2876 | } |
| 2812 | 2877 | ||
| 2813 | static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | 2878 | static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; |
| @@ -3081,7 +3146,6 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, | |||
| 3081 | struct ath6kl_vif *vif = netdev_priv(dev); | 3146 | struct ath6kl_vif *vif = netdev_priv(dev); |
| 3082 | u16 interval; | 3147 | u16 interval; |
| 3083 | int ret; | 3148 | int ret; |
| 3084 | u8 i; | ||
| 3085 | 3149 | ||
| 3086 | if (ar->state != ATH6KL_STATE_ON) | 3150 | if (ar->state != ATH6KL_STATE_ON) |
| 3087 | return -EIO; | 3151 | return -EIO; |
| @@ -3089,29 +3153,23 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, | |||
| 3089 | if (vif->sme_state != SME_DISCONNECTED) | 3153 | if (vif->sme_state != SME_DISCONNECTED) |
| 3090 | return -EBUSY; | 3154 | return -EBUSY; |
| 3091 | 3155 | ||
| 3156 | /* The FW currently can't support multi-vif WoW properly. */ | ||
| 3157 | if (ar->num_vif > 1) | ||
| 3158 | return -EIO; | ||
| 3159 | |||
| 3092 | ath6kl_cfg80211_scan_complete_event(vif, true); | 3160 | ath6kl_cfg80211_scan_complete_event(vif, true); |
| 3093 | 3161 | ||
| 3094 | for (i = 0; i < ar->wiphy->max_sched_scan_ssids; i++) { | 3162 | ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, |
| 3095 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, | 3163 | request->n_ssids); |
| 3096 | i, DISABLE_SSID_FLAG, | 3164 | if (ret < 0) |
| 3097 | 0, NULL); | 3165 | return ret; |
| 3098 | } | ||
| 3099 | 3166 | ||
| 3100 | /* fw uses seconds, also make sure that it's >0 */ | 3167 | /* fw uses seconds, also make sure that it's >0 */ |
| 3101 | interval = max_t(u16, 1, request->interval / 1000); | 3168 | interval = max_t(u16, 1, request->interval / 1000); |
| 3102 | 3169 | ||
| 3103 | ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, | 3170 | ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, |
| 3104 | interval, interval, | 3171 | interval, interval, |
| 3105 | 10, 0, 0, 0, 3, 0, 0, 0); | 3172 | vif->bg_scan_period, 0, 0, 0, 3, 0, 0, 0); |
| 3106 | |||
| 3107 | if (request->n_ssids && request->ssids[0].ssid_len) { | ||
| 3108 | for (i = 0; i < request->n_ssids; i++) { | ||
| 3109 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, | ||
| 3110 | i, SPECIFIC_SSID_FLAG, | ||
| 3111 | request->ssids[i].ssid_len, | ||
| 3112 | request->ssids[i].ssid); | ||
| 3113 | } | ||
| 3114 | } | ||
| 3115 | 3173 | ||
| 3116 | ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx, | 3174 | ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx, |
| 3117 | ATH6KL_WOW_MODE_ENABLE, | 3175 | ATH6KL_WOW_MODE_ENABLE, |
| @@ -3271,8 +3329,7 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar) | |||
| 3271 | ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode; | 3329 | ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode; |
| 3272 | 3330 | ||
| 3273 | if (ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER) != 0) | 3331 | if (ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER) != 0) |
| 3274 | ath6kl_warn("ath6kl_deep_sleep_enable: " | 3332 | ath6kl_warn("ath6kl_deep_sleep_enable: wmi_powermode_cmd failed\n"); |
| 3275 | "wmi_powermode_cmd failed\n"); | ||
| 3276 | return; | 3333 | return; |
| 3277 | } | 3334 | } |
| 3278 | 3335 | ||
| @@ -3352,6 +3409,7 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, | |||
| 3352 | vif->next_mode = nw_type; | 3409 | vif->next_mode = nw_type; |
| 3353 | vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL; | 3410 | vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL; |
| 3354 | vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME; | 3411 | vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME; |
| 3412 | vif->bg_scan_period = 0; | ||
| 3355 | vif->htcap.ht_enable = true; | 3413 | vif->htcap.ht_enable = true; |
| 3356 | 3414 | ||
| 3357 | memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); | 3415 | memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); |
| @@ -3393,6 +3451,7 @@ err: | |||
| 3393 | int ath6kl_cfg80211_init(struct ath6kl *ar) | 3451 | int ath6kl_cfg80211_init(struct ath6kl *ar) |
| 3394 | { | 3452 | { |
| 3395 | struct wiphy *wiphy = ar->wiphy; | 3453 | struct wiphy *wiphy = ar->wiphy; |
| 3454 | bool band_2gig = false, band_5gig = false, ht = false; | ||
| 3396 | int ret; | 3455 | int ret; |
| 3397 | 3456 | ||
| 3398 | wiphy->mgmt_stypes = ath6kl_mgmt_stypes; | 3457 | wiphy->mgmt_stypes = ath6kl_mgmt_stypes; |
| @@ -3413,8 +3472,46 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) | |||
| 3413 | /* max num of ssids that can be probed during scanning */ | 3472 | /* max num of ssids that can be probed during scanning */ |
| 3414 | wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX; | 3473 | wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX; |
| 3415 | wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */ | 3474 | wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */ |
| 3416 | wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; | 3475 | switch (ar->hw.cap) { |
| 3417 | wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz; | 3476 | case WMI_11AN_CAP: |
| 3477 | ht = true; | ||
| 3478 | case WMI_11A_CAP: | ||
| 3479 | band_5gig = true; | ||
| 3480 | break; | ||
| 3481 | case WMI_11GN_CAP: | ||
| 3482 | ht = true; | ||
| 3483 | case WMI_11G_CAP: | ||
| 3484 | band_2gig = true; | ||
| 3485 | break; | ||
| 3486 | case WMI_11AGN_CAP: | ||
| 3487 | ht = true; | ||
| 3488 | case WMI_11AG_CAP: | ||
| 3489 | band_2gig = true; | ||
| 3490 | band_5gig = true; | ||
| 3491 | break; | ||
| 3492 | default: | ||
| 3493 | ath6kl_err("invalid phy capability!\n"); | ||
| 3494 | return -EINVAL; | ||
| 3495 | } | ||
| 3496 | |||
| 3497 | /* | ||
| 3498 | * Even if the fw has HT support, advertise HT cap only when | ||
| 3499 | * the firmware has support to override RSN capability, otherwise | ||
| 3500 | * 4-way handshake would fail. | ||
| 3501 | */ | ||
| 3502 | if (!(ht && | ||
| 3503 | test_bit(ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE, | ||
| 3504 | ar->fw_capabilities))) { | ||
| 3505 | ath6kl_band_2ghz.ht_cap.cap = 0; | ||
| 3506 | ath6kl_band_2ghz.ht_cap.ht_supported = false; | ||
| 3507 | ath6kl_band_5ghz.ht_cap.cap = 0; | ||
| 3508 | ath6kl_band_5ghz.ht_cap.ht_supported = false; | ||
| 3509 | } | ||
| 3510 | if (band_2gig) | ||
| 3511 | wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; | ||
| 3512 | if (band_5gig) | ||
| 3513 | wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz; | ||
| 3514 | |||
| 3418 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 3515 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
| 3419 | 3516 | ||
| 3420 | wiphy->cipher_suites = cipher_suites; | 3517 | wiphy->cipher_suites = cipher_suites; |
| @@ -3430,7 +3527,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) | |||
| 3430 | wiphy->wowlan.pattern_min_len = 1; | 3527 | wiphy->wowlan.pattern_min_len = 1; |
| 3431 | wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; | 3528 | wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; |
| 3432 | 3529 | ||
| 3433 | wiphy->max_sched_scan_ssids = 10; | 3530 | wiphy->max_sched_scan_ssids = MAX_PROBED_SSID_INDEX; |
| 3434 | 3531 | ||
| 3435 | ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | | 3532 | ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | |
| 3436 | WIPHY_FLAG_HAVE_AP_SME | | 3533 | WIPHY_FLAG_HAVE_AP_SME | |
| @@ -3447,8 +3544,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) | |||
| 3447 | ar->wiphy->probe_resp_offload = | 3544 | ar->wiphy->probe_resp_offload = |
| 3448 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | | 3545 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | |
| 3449 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | | 3546 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | |
| 3450 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P | | 3547 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; |
| 3451 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U; | ||
| 3452 | 3548 | ||
| 3453 | ret = wiphy_register(wiphy); | 3549 | ret = wiphy_register(wiphy); |
| 3454 | if (ret < 0) { | 3550 | if (ret < 0) { |
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h index c5def436417..5ea8cbb79f4 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.h +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h | |||
| @@ -28,6 +28,8 @@ enum ath6kl_cfg_suspend_mode { | |||
| 28 | struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, | 28 | struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, |
| 29 | enum nl80211_iftype type, | 29 | enum nl80211_iftype type, |
| 30 | u8 fw_vif_idx, u8 nw_type); | 30 | u8 fw_vif_idx, u8 nw_type); |
| 31 | void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq, | ||
| 32 | enum wmi_phy_mode mode); | ||
| 31 | void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted); | 33 | void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted); |
| 32 | 34 | ||
| 33 | void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, | 35 | void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, |
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 9d67964a51d..4d9c6f14269 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h | |||
| @@ -126,9 +126,9 @@ struct ath6kl_fw_ie { | |||
| 126 | #define AR6003_HW_2_0_FIRMWARE_FILE "athwlan.bin.z77" | 126 | #define AR6003_HW_2_0_FIRMWARE_FILE "athwlan.bin.z77" |
| 127 | #define AR6003_HW_2_0_TCMD_FIRMWARE_FILE "athtcmd_ram.bin" | 127 | #define AR6003_HW_2_0_TCMD_FIRMWARE_FILE "athtcmd_ram.bin" |
| 128 | #define AR6003_HW_2_0_PATCH_FILE "data.patch.bin" | 128 | #define AR6003_HW_2_0_PATCH_FILE "data.patch.bin" |
| 129 | #define AR6003_HW_2_0_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.bin" | 129 | #define AR6003_HW_2_0_BOARD_DATA_FILE AR6003_HW_2_0_FW_DIR "/bdata.bin" |
| 130 | #define AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE \ | 130 | #define AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE \ |
| 131 | "ath6k/AR6003/hw2.0/bdata.SD31.bin" | 131 | AR6003_HW_2_0_FW_DIR "/bdata.SD31.bin" |
| 132 | 132 | ||
| 133 | /* AR6003 3.0 definitions */ | 133 | /* AR6003 3.0 definitions */ |
| 134 | #define AR6003_HW_2_1_1_VERSION 0x30000582 | 134 | #define AR6003_HW_2_1_1_VERSION 0x30000582 |
| @@ -139,25 +139,33 @@ struct ath6kl_fw_ie { | |||
| 139 | #define AR6003_HW_2_1_1_UTF_FIRMWARE_FILE "utf.bin" | 139 | #define AR6003_HW_2_1_1_UTF_FIRMWARE_FILE "utf.bin" |
| 140 | #define AR6003_HW_2_1_1_TESTSCRIPT_FILE "nullTestFlow.bin" | 140 | #define AR6003_HW_2_1_1_TESTSCRIPT_FILE "nullTestFlow.bin" |
| 141 | #define AR6003_HW_2_1_1_PATCH_FILE "data.patch.bin" | 141 | #define AR6003_HW_2_1_1_PATCH_FILE "data.patch.bin" |
| 142 | #define AR6003_HW_2_1_1_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.bin" | 142 | #define AR6003_HW_2_1_1_BOARD_DATA_FILE AR6003_HW_2_1_1_FW_DIR "/bdata.bin" |
| 143 | #define AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE \ | 143 | #define AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE \ |
| 144 | "ath6k/AR6003/hw2.1.1/bdata.SD31.bin" | 144 | AR6003_HW_2_1_1_FW_DIR "/bdata.SD31.bin" |
| 145 | 145 | ||
| 146 | /* AR6004 1.0 definitions */ | 146 | /* AR6004 1.0 definitions */ |
| 147 | #define AR6004_HW_1_0_VERSION 0x30000623 | 147 | #define AR6004_HW_1_0_VERSION 0x30000623 |
| 148 | #define AR6004_HW_1_0_FW_DIR "ath6k/AR6004/hw1.0" | 148 | #define AR6004_HW_1_0_FW_DIR "ath6k/AR6004/hw1.0" |
| 149 | #define AR6004_HW_1_0_FIRMWARE_FILE "fw.ram.bin" | 149 | #define AR6004_HW_1_0_FIRMWARE_FILE "fw.ram.bin" |
| 150 | #define AR6004_HW_1_0_BOARD_DATA_FILE "ath6k/AR6004/hw1.0/bdata.bin" | 150 | #define AR6004_HW_1_0_BOARD_DATA_FILE AR6004_HW_1_0_FW_DIR "/bdata.bin" |
| 151 | #define AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE \ | 151 | #define AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE \ |
| 152 | "ath6k/AR6004/hw1.0/bdata.DB132.bin" | 152 | AR6004_HW_1_0_FW_DIR "/bdata.DB132.bin" |
| 153 | 153 | ||
| 154 | /* AR6004 1.1 definitions */ | 154 | /* AR6004 1.1 definitions */ |
| 155 | #define AR6004_HW_1_1_VERSION 0x30000001 | 155 | #define AR6004_HW_1_1_VERSION 0x30000001 |
| 156 | #define AR6004_HW_1_1_FW_DIR "ath6k/AR6004/hw1.1" | 156 | #define AR6004_HW_1_1_FW_DIR "ath6k/AR6004/hw1.1" |
| 157 | #define AR6004_HW_1_1_FIRMWARE_FILE "fw.ram.bin" | 157 | #define AR6004_HW_1_1_FIRMWARE_FILE "fw.ram.bin" |
| 158 | #define AR6004_HW_1_1_BOARD_DATA_FILE "ath6k/AR6004/hw1.1/bdata.bin" | 158 | #define AR6004_HW_1_1_BOARD_DATA_FILE AR6004_HW_1_1_FW_DIR "/bdata.bin" |
| 159 | #define AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE \ | 159 | #define AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE \ |
| 160 | "ath6k/AR6004/hw1.1/bdata.DB132.bin" | 160 | AR6004_HW_1_1_FW_DIR "/bdata.DB132.bin" |
| 161 | |||
| 162 | /* AR6004 1.2 definitions */ | ||
| 163 | #define AR6004_HW_1_2_VERSION 0x300007e8 | ||
| 164 | #define AR6004_HW_1_2_FW_DIR "ath6k/AR6004/hw1.2" | ||
| 165 | #define AR6004_HW_1_2_FIRMWARE_FILE "fw.ram.bin" | ||
| 166 | #define AR6004_HW_1_2_BOARD_DATA_FILE AR6004_HW_1_2_FW_DIR "/bdata.bin" | ||
| 167 | #define AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE \ | ||
| 168 | AR6004_HW_1_2_FW_DIR "/bdata.bin" | ||
| 161 | 169 | ||
| 162 | /* Per STA data, used in AP mode */ | 170 | /* Per STA data, used in AP mode */ |
| 163 | #define STA_PS_AWAKE BIT(0) | 171 | #define STA_PS_AWAKE BIT(0) |
| @@ -502,6 +510,8 @@ enum ath6kl_vif_state { | |||
| 502 | WLAN_ENABLED, | 510 | WLAN_ENABLED, |
| 503 | STATS_UPDATE_PEND, | 511 | STATS_UPDATE_PEND, |
| 504 | HOST_SLEEP_MODE_CMD_PROCESSED, | 512 | HOST_SLEEP_MODE_CMD_PROCESSED, |
| 513 | NETDEV_MCAST_ALL_ON, | ||
| 514 | NETDEV_MCAST_ALL_OFF, | ||
| 505 | }; | 515 | }; |
| 506 | 516 | ||
| 507 | struct ath6kl_vif { | 517 | struct ath6kl_vif { |
| @@ -549,9 +559,11 @@ struct ath6kl_vif { | |||
| 549 | u16 assoc_bss_beacon_int; | 559 | u16 assoc_bss_beacon_int; |
| 550 | u16 listen_intvl_t; | 560 | u16 listen_intvl_t; |
| 551 | u16 bmiss_time_t; | 561 | u16 bmiss_time_t; |
| 562 | u16 bg_scan_period; | ||
| 552 | u8 assoc_bss_dtim_period; | 563 | u8 assoc_bss_dtim_period; |
| 553 | struct net_device_stats net_stats; | 564 | struct net_device_stats net_stats; |
| 554 | struct target_stats target_stats; | 565 | struct target_stats target_stats; |
| 566 | struct wmi_connect_cmd profile; | ||
| 555 | 567 | ||
| 556 | struct list_head mc_filter; | 568 | struct list_head mc_filter; |
| 557 | }; | 569 | }; |
| @@ -640,6 +652,7 @@ struct ath6kl { | |||
| 640 | u8 sta_list_index; | 652 | u8 sta_list_index; |
| 641 | struct ath6kl_req_key ap_mode_bkey; | 653 | struct ath6kl_req_key ap_mode_bkey; |
| 642 | struct sk_buff_head mcastpsq; | 654 | struct sk_buff_head mcastpsq; |
| 655 | u32 want_ch_switch; | ||
| 643 | 656 | ||
| 644 | /* | 657 | /* |
| 645 | * FIXME: protects access to mcastpsq but is actually useless as | 658 | * FIXME: protects access to mcastpsq but is actually useless as |
| @@ -672,6 +685,7 @@ struct ath6kl { | |||
| 672 | u32 refclk_hz; | 685 | u32 refclk_hz; |
| 673 | u32 uarttx_pin; | 686 | u32 uarttx_pin; |
| 674 | u32 testscript_addr; | 687 | u32 testscript_addr; |
| 688 | enum wmi_phy_cap cap; | ||
| 675 | 689 | ||
| 676 | struct ath6kl_hw_fw { | 690 | struct ath6kl_hw_fw { |
| 677 | const char *dir; | 691 | const char *dir; |
| @@ -805,7 +819,8 @@ void aggr_reset_state(struct aggr_info_conn *aggr_conn); | |||
| 805 | struct ath6kl_sta *ath6kl_find_sta(struct ath6kl_vif *vif, u8 *node_addr); | 819 | struct ath6kl_sta *ath6kl_find_sta(struct ath6kl_vif *vif, u8 *node_addr); |
| 806 | struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid); | 820 | struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid); |
| 807 | 821 | ||
| 808 | void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver); | 822 | void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver, |
| 823 | enum wmi_phy_cap cap); | ||
| 809 | int ath6kl_control_tx(void *devt, struct sk_buff *skb, | 824 | int ath6kl_control_tx(void *devt, struct sk_buff *skb, |
| 810 | enum htc_endpoint_id eid); | 825 | enum htc_endpoint_id eid); |
| 811 | void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, | 826 | void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, |
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index 1b76aff7850..15cfe30e54f 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c | |||
| @@ -401,8 +401,10 @@ static ssize_t ath6kl_fwlog_block_read(struct file *file, | |||
| 401 | 401 | ||
| 402 | ret = wait_for_completion_interruptible( | 402 | ret = wait_for_completion_interruptible( |
| 403 | &ar->debug.fwlog_completion); | 403 | &ar->debug.fwlog_completion); |
| 404 | if (ret == -ERESTARTSYS) | 404 | if (ret == -ERESTARTSYS) { |
| 405 | vfree(buf); | ||
| 405 | return ret; | 406 | return ret; |
| 407 | } | ||
| 406 | 408 | ||
| 407 | spin_lock(&ar->debug.fwlog_queue.lock); | 409 | spin_lock(&ar->debug.fwlog_queue.lock); |
| 408 | } | 410 | } |
| @@ -1570,10 +1572,15 @@ static ssize_t ath6kl_bgscan_int_write(struct file *file, | |||
| 1570 | size_t count, loff_t *ppos) | 1572 | size_t count, loff_t *ppos) |
| 1571 | { | 1573 | { |
| 1572 | struct ath6kl *ar = file->private_data; | 1574 | struct ath6kl *ar = file->private_data; |
| 1575 | struct ath6kl_vif *vif; | ||
| 1573 | u16 bgscan_int; | 1576 | u16 bgscan_int; |
| 1574 | char buf[32]; | 1577 | char buf[32]; |
| 1575 | ssize_t len; | 1578 | ssize_t len; |
| 1576 | 1579 | ||
| 1580 | vif = ath6kl_vif_first(ar); | ||
| 1581 | if (!vif) | ||
| 1582 | return -EIO; | ||
| 1583 | |||
| 1577 | len = min(count, sizeof(buf) - 1); | 1584 | len = min(count, sizeof(buf) - 1); |
| 1578 | if (copy_from_user(buf, user_buf, len)) | 1585 | if (copy_from_user(buf, user_buf, len)) |
| 1579 | return -EFAULT; | 1586 | return -EFAULT; |
| @@ -1585,6 +1592,8 @@ static ssize_t ath6kl_bgscan_int_write(struct file *file, | |||
| 1585 | if (bgscan_int == 0) | 1592 | if (bgscan_int == 0) |
| 1586 | bgscan_int = 0xffff; | 1593 | bgscan_int = 0xffff; |
| 1587 | 1594 | ||
| 1595 | vif->bg_scan_period = bgscan_int; | ||
| 1596 | |||
| 1588 | ath6kl_wmi_scanparams_cmd(ar->wmi, 0, 0, 0, bgscan_int, 0, 0, 0, 3, | 1597 | ath6kl_wmi_scanparams_cmd(ar->wmi, 0, 0, 0, bgscan_int, 0, 0, 0, 3, |
| 1589 | 0, 0, 0); | 1598 | 0, 0, 0); |
| 1590 | 1599 | ||
| @@ -1809,6 +1818,7 @@ int ath6kl_debug_init_fs(struct ath6kl *ar) | |||
| 1809 | void ath6kl_debug_cleanup(struct ath6kl *ar) | 1818 | void ath6kl_debug_cleanup(struct ath6kl *ar) |
| 1810 | { | 1819 | { |
| 1811 | skb_queue_purge(&ar->debug.fwlog_queue); | 1820 | skb_queue_purge(&ar->debug.fwlog_queue); |
| 1821 | complete(&ar->debug.fwlog_completion); | ||
| 1812 | kfree(ar->debug.roam_tbl); | 1822 | kfree(ar->debug.roam_tbl); |
| 1813 | } | 1823 | } |
| 1814 | 1824 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/htc_mbox.c b/drivers/net/wireless/ath/ath6kl/htc_mbox.c index 065e61516d7..2798624d3a9 100644 --- a/drivers/net/wireless/ath/ath6kl/htc_mbox.c +++ b/drivers/net/wireless/ath/ath6kl/htc_mbox.c | |||
| @@ -83,10 +83,7 @@ static void ath6kl_credit_init(struct ath6kl_htc_credit_info *cred_info, | |||
| 83 | * never goes inactive EVER. | 83 | * never goes inactive EVER. |
| 84 | */ | 84 | */ |
| 85 | cur_ep_dist->dist_flags |= HTC_EP_ACTIVE; | 85 | cur_ep_dist->dist_flags |= HTC_EP_ACTIVE; |
| 86 | } else if (cur_ep_dist->svc_id == WMI_DATA_BK_SVC) | 86 | } |
| 87 | /* this is the lowest priority data endpoint */ | ||
| 88 | /* FIXME: this looks fishy, check */ | ||
| 89 | cred_info->lowestpri_ep_dist = cur_ep_dist->list; | ||
| 90 | 87 | ||
| 91 | /* | 88 | /* |
| 92 | * Streams have to be created (explicit | implicit) for all | 89 | * Streams have to be created (explicit | implicit) for all |
| @@ -100,6 +97,13 @@ static void ath6kl_credit_init(struct ath6kl_htc_credit_info *cred_info, | |||
| 100 | */ | 97 | */ |
| 101 | } | 98 | } |
| 102 | 99 | ||
| 100 | /* | ||
| 101 | * For ath6kl_credit_seek function, | ||
| 102 | * it use list_for_each_entry_reverse to walk around the whole ep list. | ||
| 103 | * Therefore assign this lowestpri_ep_dist after walk around the ep_list | ||
| 104 | */ | ||
| 105 | cred_info->lowestpri_ep_dist = cur_ep_dist->list; | ||
| 106 | |||
| 103 | WARN_ON(cred_info->cur_free_credits <= 0); | 107 | WARN_ON(cred_info->cur_free_credits <= 0); |
| 104 | 108 | ||
| 105 | list_for_each_entry(cur_ep_dist, ep_list, list) { | 109 | list_for_each_entry(cur_ep_dist, ep_list, list) { |
| @@ -758,7 +762,7 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint, | |||
| 758 | u32 txb_mask; | 762 | u32 txb_mask; |
| 759 | u8 ac = WMM_NUM_AC; | 763 | u8 ac = WMM_NUM_AC; |
| 760 | 764 | ||
| 761 | if ((HTC_CTRL_RSVD_SVC != endpoint->svc_id) || | 765 | if ((HTC_CTRL_RSVD_SVC != endpoint->svc_id) && |
| 762 | (WMI_CONTROL_SVC != endpoint->svc_id)) | 766 | (WMI_CONTROL_SVC != endpoint->svc_id)) |
| 763 | ac = target->dev->ar->ep2ac_map[endpoint->eid]; | 767 | ac = target->dev->ar->ep2ac_map[endpoint->eid]; |
| 764 | 768 | ||
| @@ -793,16 +797,17 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint, | |||
| 793 | * itself | 797 | * itself |
| 794 | */ | 798 | */ |
| 795 | txb_mask = ((1 << ac) - 1); | 799 | txb_mask = ((1 << ac) - 1); |
| 796 | /* | 800 | |
| 797 | * when the scatter request resources drop below a | 801 | /* |
| 798 | * certain threshold, disable Tx bundling for all | 802 | * when the scatter request resources drop below a |
| 799 | * AC's with priority lower than the current requesting | 803 | * certain threshold, disable Tx bundling for all |
| 800 | * AC. Otherwise re-enable Tx bundling for them | 804 | * AC's with priority lower than the current requesting |
| 801 | */ | 805 | * AC. Otherwise re-enable Tx bundling for them |
| 802 | if (scat_req->scat_q_depth < ATH6KL_SCATTER_REQS) | 806 | */ |
| 803 | target->tx_bndl_mask &= ~txb_mask; | 807 | if (scat_req->scat_q_depth < ATH6KL_SCATTER_REQS) |
| 804 | else | 808 | target->tx_bndl_mask &= ~txb_mask; |
| 805 | target->tx_bndl_mask |= txb_mask; | 809 | else |
| 810 | target->tx_bndl_mask |= txb_mask; | ||
| 806 | } | 811 | } |
| 807 | 812 | ||
| 808 | ath6kl_dbg(ATH6KL_DBG_HTC, "htc tx pkts to scatter: %d\n", | 813 | ath6kl_dbg(ATH6KL_DBG_HTC, "htc tx pkts to scatter: %d\n", |
| @@ -849,6 +854,7 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target, | |||
| 849 | int bundle_sent; | 854 | int bundle_sent; |
| 850 | int n_pkts_bundle; | 855 | int n_pkts_bundle; |
| 851 | u8 ac = WMM_NUM_AC; | 856 | u8 ac = WMM_NUM_AC; |
| 857 | int status; | ||
| 852 | 858 | ||
| 853 | spin_lock_bh(&target->tx_lock); | 859 | spin_lock_bh(&target->tx_lock); |
| 854 | 860 | ||
| @@ -866,7 +872,7 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target, | |||
| 866 | */ | 872 | */ |
| 867 | INIT_LIST_HEAD(&txq); | 873 | INIT_LIST_HEAD(&txq); |
| 868 | 874 | ||
| 869 | if ((HTC_CTRL_RSVD_SVC != endpoint->svc_id) || | 875 | if ((HTC_CTRL_RSVD_SVC != endpoint->svc_id) && |
| 870 | (WMI_CONTROL_SVC != endpoint->svc_id)) | 876 | (WMI_CONTROL_SVC != endpoint->svc_id)) |
| 871 | ac = target->dev->ar->ep2ac_map[endpoint->eid]; | 877 | ac = target->dev->ar->ep2ac_map[endpoint->eid]; |
| 872 | 878 | ||
| @@ -910,7 +916,12 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target, | |||
| 910 | 916 | ||
| 911 | ath6kl_htc_tx_prep_pkt(packet, packet->info.tx.flags, | 917 | ath6kl_htc_tx_prep_pkt(packet, packet->info.tx.flags, |
| 912 | 0, packet->info.tx.seqno); | 918 | 0, packet->info.tx.seqno); |
| 913 | ath6kl_htc_tx_issue(target, packet); | 919 | status = ath6kl_htc_tx_issue(target, packet); |
| 920 | |||
| 921 | if (status) { | ||
| 922 | packet->status = status; | ||
| 923 | packet->completion(packet->context, packet); | ||
| 924 | } | ||
| 914 | } | 925 | } |
| 915 | 926 | ||
| 916 | spin_lock_bh(&target->tx_lock); | 927 | spin_lock_bh(&target->tx_lock); |
diff --git a/drivers/net/wireless/ath/ath6kl/htc_pipe.c b/drivers/net/wireless/ath/ath6kl/htc_pipe.c index b277b344688..f9626c72369 100644 --- a/drivers/net/wireless/ath/ath6kl/htc_pipe.c +++ b/drivers/net/wireless/ath/ath6kl/htc_pipe.c | |||
| @@ -108,8 +108,6 @@ static void get_htc_packet_credit_based(struct htc_target *target, | |||
| 108 | 108 | ||
| 109 | /* get packet at head, but don't remove it */ | 109 | /* get packet at head, but don't remove it */ |
| 110 | packet = list_first_entry(&ep->txq, struct htc_packet, list); | 110 | packet = list_first_entry(&ep->txq, struct htc_packet, list); |
| 111 | if (packet == NULL) | ||
| 112 | break; | ||
| 113 | 111 | ||
| 114 | ath6kl_dbg(ATH6KL_DBG_HTC, | 112 | ath6kl_dbg(ATH6KL_DBG_HTC, |
| 115 | "%s: got head packet:0x%p , queue depth: %d\n", | 113 | "%s: got head packet:0x%p , queue depth: %d\n", |
| @@ -803,8 +801,6 @@ static int htc_send_packets_multiple(struct htc_target *target, | |||
| 803 | 801 | ||
| 804 | /* get first packet to find out which ep the packets will go into */ | 802 | /* get first packet to find out which ep the packets will go into */ |
| 805 | packet = list_first_entry(pkt_queue, struct htc_packet, list); | 803 | packet = list_first_entry(pkt_queue, struct htc_packet, list); |
| 806 | if (packet == NULL) | ||
| 807 | return -EINVAL; | ||
| 808 | 804 | ||
| 809 | if (packet->endpoint >= ENDPOINT_MAX) { | 805 | if (packet->endpoint >= ENDPOINT_MAX) { |
| 810 | WARN_ON_ONCE(1); | 806 | WARN_ON_ONCE(1); |
| @@ -1382,6 +1378,9 @@ static int ath6kl_htc_pipe_conn_service(struct htc_target *target, | |||
| 1382 | /* copy all the callbacks */ | 1378 | /* copy all the callbacks */ |
| 1383 | ep->ep_cb = conn_req->ep_cb; | 1379 | ep->ep_cb = conn_req->ep_cb; |
| 1384 | 1380 | ||
| 1381 | /* initialize tx_drop_packet_threshold */ | ||
| 1382 | ep->tx_drop_packet_threshold = MAX_HI_COOKIE_NUM; | ||
| 1383 | |||
| 1385 | status = ath6kl_hif_pipe_map_service(ar, ep->svc_id, | 1384 | status = ath6kl_hif_pipe_map_service(ar, ep->svc_id, |
| 1386 | &ep->pipe.pipeid_ul, | 1385 | &ep->pipe.pipeid_ul, |
| 1387 | &ep->pipe.pipeid_dl); | 1386 | &ep->pipe.pipeid_dl); |
| @@ -1636,10 +1635,6 @@ static int ath6kl_htc_pipe_add_rxbuf_multiple(struct htc_target *target, | |||
| 1636 | return -EINVAL; | 1635 | return -EINVAL; |
| 1637 | 1636 | ||
| 1638 | first = list_first_entry(pkt_queue, struct htc_packet, list); | 1637 | first = list_first_entry(pkt_queue, struct htc_packet, list); |
| 1639 | if (first == NULL) { | ||
| 1640 | WARN_ON_ONCE(1); | ||
| 1641 | return -EINVAL; | ||
| 1642 | } | ||
| 1643 | 1638 | ||
| 1644 | if (first->endpoint >= ENDPOINT_MAX) { | 1639 | if (first->endpoint >= ENDPOINT_MAX) { |
| 1645 | WARN_ON_ONCE(1); | 1640 | WARN_ON_ONCE(1); |
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 29ef50ea07d..7eb0515f458 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c | |||
| @@ -119,6 +119,24 @@ static const struct ath6kl_hw hw_list[] = { | |||
| 119 | .fw_board = AR6004_HW_1_1_BOARD_DATA_FILE, | 119 | .fw_board = AR6004_HW_1_1_BOARD_DATA_FILE, |
| 120 | .fw_default_board = AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE, | 120 | .fw_default_board = AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE, |
| 121 | }, | 121 | }, |
| 122 | { | ||
| 123 | .id = AR6004_HW_1_2_VERSION, | ||
| 124 | .name = "ar6004 hw 1.2", | ||
| 125 | .dataset_patch_addr = 0x436ecc, | ||
| 126 | .app_load_addr = 0x1234, | ||
| 127 | .board_ext_data_addr = 0x437000, | ||
| 128 | .reserved_ram_size = 9216, | ||
| 129 | .board_addr = 0x435c00, | ||
| 130 | .refclk_hz = 40000000, | ||
| 131 | .uarttx_pin = 11, | ||
| 132 | |||
| 133 | .fw = { | ||
| 134 | .dir = AR6004_HW_1_2_FW_DIR, | ||
| 135 | .fw = AR6004_HW_1_2_FIRMWARE_FILE, | ||
| 136 | }, | ||
| 137 | .fw_board = AR6004_HW_1_2_BOARD_DATA_FILE, | ||
| 138 | .fw_default_board = AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE, | ||
| 139 | }, | ||
| 122 | }; | 140 | }; |
| 123 | 141 | ||
| 124 | /* | 142 | /* |
| @@ -445,9 +463,9 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx) | |||
| 445 | P2P_FLAG_MACADDR_REQ | | 463 | P2P_FLAG_MACADDR_REQ | |
| 446 | P2P_FLAG_HMODEL_REQ); | 464 | P2P_FLAG_HMODEL_REQ); |
| 447 | if (ret) { | 465 | if (ret) { |
| 448 | ath6kl_dbg(ATH6KL_DBG_TRC, "failed to request P2P " | 466 | ath6kl_dbg(ATH6KL_DBG_TRC, |
| 449 | "capabilities (%d) - assuming P2P not " | 467 | "failed to request P2P capabilities (%d) - assuming P2P not supported\n", |
| 450 | "supported\n", ret); | 468 | ret); |
| 451 | ar->p2p = false; | 469 | ar->p2p = false; |
| 452 | } | 470 | } |
| 453 | } | 471 | } |
| @@ -456,8 +474,9 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx) | |||
| 456 | /* Enable Probe Request reporting for P2P */ | 474 | /* Enable Probe Request reporting for P2P */ |
| 457 | ret = ath6kl_wmi_probe_report_req_cmd(ar->wmi, idx, true); | 475 | ret = ath6kl_wmi_probe_report_req_cmd(ar->wmi, idx, true); |
| 458 | if (ret) { | 476 | if (ret) { |
| 459 | ath6kl_dbg(ATH6KL_DBG_TRC, "failed to enable Probe " | 477 | ath6kl_dbg(ATH6KL_DBG_TRC, |
| 460 | "Request reporting (%d)\n", ret); | 478 | "failed to enable Probe Request reporting (%d)\n", |
| 479 | ret); | ||
| 461 | } | 480 | } |
| 462 | } | 481 | } |
| 463 | 482 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 4d818f96c41..e5524470529 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c | |||
| @@ -421,8 +421,8 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel) | |||
| 421 | if (!ik->valid) | 421 | if (!ik->valid) |
| 422 | break; | 422 | break; |
| 423 | 423 | ||
| 424 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed addkey for " | 424 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, |
| 425 | "the initial group key for AP mode\n"); | 425 | "Delayed addkey for the initial group key for AP mode\n"); |
| 426 | memset(key_rsc, 0, sizeof(key_rsc)); | 426 | memset(key_rsc, 0, sizeof(key_rsc)); |
| 427 | res = ath6kl_wmi_addkey_cmd( | 427 | res = ath6kl_wmi_addkey_cmd( |
| 428 | ar->wmi, vif->fw_vif_idx, ik->key_index, ik->key_type, | 428 | ar->wmi, vif->fw_vif_idx, ik->key_index, ik->key_type, |
| @@ -430,12 +430,19 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel) | |||
| 430 | ik->key, | 430 | ik->key, |
| 431 | KEY_OP_INIT_VAL, NULL, SYNC_BOTH_WMIFLAG); | 431 | KEY_OP_INIT_VAL, NULL, SYNC_BOTH_WMIFLAG); |
| 432 | if (res) { | 432 | if (res) { |
| 433 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed " | 433 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, |
| 434 | "addkey failed: %d\n", res); | 434 | "Delayed addkey failed: %d\n", res); |
| 435 | } | 435 | } |
| 436 | break; | 436 | break; |
| 437 | } | 437 | } |
| 438 | 438 | ||
| 439 | if (ar->want_ch_switch & (1 << vif->fw_vif_idx)) { | ||
| 440 | ar->want_ch_switch &= ~(1 << vif->fw_vif_idx); | ||
| 441 | /* we actually don't know the phymode, default to HT20 */ | ||
| 442 | ath6kl_cfg80211_ch_switch_notify(vif, channel, | ||
| 443 | WMI_11G_HT20); | ||
| 444 | } | ||
| 445 | |||
| 439 | ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, NONE_BSS_FILTER, 0); | 446 | ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, NONE_BSS_FILTER, 0); |
| 440 | set_bit(CONNECTED, &vif->flags); | 447 | set_bit(CONNECTED, &vif->flags); |
| 441 | netif_carrier_on(vif->ndev); | 448 | netif_carrier_on(vif->ndev); |
| @@ -541,7 +548,8 @@ void ath6kl_disconnect(struct ath6kl_vif *vif) | |||
| 541 | 548 | ||
| 542 | /* WMI Event handlers */ | 549 | /* WMI Event handlers */ |
| 543 | 550 | ||
| 544 | void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver) | 551 | void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver, |
| 552 | enum wmi_phy_cap cap) | ||
| 545 | { | 553 | { |
| 546 | struct ath6kl *ar = devt; | 554 | struct ath6kl *ar = devt; |
| 547 | 555 | ||
| @@ -551,6 +559,7 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver) | |||
| 551 | 559 | ||
| 552 | ar->version.wlan_ver = sw_ver; | 560 | ar->version.wlan_ver = sw_ver; |
| 553 | ar->version.abi_ver = abi_ver; | 561 | ar->version.abi_ver = abi_ver; |
| 562 | ar->hw.cap = cap; | ||
| 554 | 563 | ||
| 555 | snprintf(ar->wiphy->fw_version, | 564 | snprintf(ar->wiphy->fw_version, |
| 556 | sizeof(ar->wiphy->fw_version), | 565 | sizeof(ar->wiphy->fw_version), |
| @@ -584,6 +593,45 @@ void ath6kl_scan_complete_evt(struct ath6kl_vif *vif, int status) | |||
| 584 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "scan complete: %d\n", status); | 593 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "scan complete: %d\n", status); |
| 585 | } | 594 | } |
| 586 | 595 | ||
| 596 | static int ath6kl_commit_ch_switch(struct ath6kl_vif *vif, u16 channel) | ||
| 597 | { | ||
| 598 | |||
| 599 | struct ath6kl *ar = vif->ar; | ||
| 600 | |||
| 601 | vif->next_chan = channel; | ||
| 602 | vif->profile.ch = cpu_to_le16(channel); | ||
| 603 | |||
| 604 | switch (vif->nw_type) { | ||
| 605 | case AP_NETWORK: | ||
| 606 | return ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, | ||
| 607 | &vif->profile); | ||
| 608 | default: | ||
| 609 | ath6kl_err("won't switch channels nw_type=%d\n", vif->nw_type); | ||
| 610 | return -ENOTSUPP; | ||
| 611 | } | ||
| 612 | } | ||
| 613 | |||
| 614 | static void ath6kl_check_ch_switch(struct ath6kl *ar, u16 channel) | ||
| 615 | { | ||
| 616 | |||
| 617 | struct ath6kl_vif *vif; | ||
| 618 | int res = 0; | ||
| 619 | |||
| 620 | if (!ar->want_ch_switch) | ||
| 621 | return; | ||
| 622 | |||
| 623 | spin_lock_bh(&ar->list_lock); | ||
| 624 | list_for_each_entry(vif, &ar->vif_list, list) { | ||
| 625 | if (ar->want_ch_switch & (1 << vif->fw_vif_idx)) | ||
| 626 | res = ath6kl_commit_ch_switch(vif, channel); | ||
| 627 | |||
| 628 | if (res) | ||
| 629 | ath6kl_err("channel switch failed nw_type %d res %d\n", | ||
| 630 | vif->nw_type, res); | ||
| 631 | } | ||
| 632 | spin_unlock_bh(&ar->list_lock); | ||
| 633 | } | ||
| 634 | |||
| 587 | void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid, | 635 | void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid, |
| 588 | u16 listen_int, u16 beacon_int, | 636 | u16 listen_int, u16 beacon_int, |
| 589 | enum network_type net_type, u8 beacon_ie_len, | 637 | enum network_type net_type, u8 beacon_ie_len, |
| @@ -601,9 +649,11 @@ void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid, | |||
| 601 | memcpy(vif->bssid, bssid, sizeof(vif->bssid)); | 649 | memcpy(vif->bssid, bssid, sizeof(vif->bssid)); |
| 602 | vif->bss_ch = channel; | 650 | vif->bss_ch = channel; |
| 603 | 651 | ||
| 604 | if ((vif->nw_type == INFRA_NETWORK)) | 652 | if ((vif->nw_type == INFRA_NETWORK)) { |
| 605 | ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx, | 653 | ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx, |
| 606 | vif->listen_intvl_t, 0); | 654 | vif->listen_intvl_t, 0); |
| 655 | ath6kl_check_ch_switch(ar, channel); | ||
| 656 | } | ||
| 607 | 657 | ||
| 608 | netif_wake_queue(vif->ndev); | 658 | netif_wake_queue(vif->ndev); |
| 609 | 659 | ||
| @@ -926,6 +976,11 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid, | |||
| 926 | struct ath6kl *ar = vif->ar; | 976 | struct ath6kl *ar = vif->ar; |
| 927 | 977 | ||
| 928 | if (vif->nw_type == AP_NETWORK) { | 978 | if (vif->nw_type == AP_NETWORK) { |
| 979 | /* disconnect due to other STA vif switching channels */ | ||
| 980 | if (reason == BSS_DISCONNECTED && | ||
| 981 | prot_reason_status == WMI_AP_REASON_STA_ROAM) | ||
| 982 | ar->want_ch_switch |= 1 << vif->fw_vif_idx; | ||
| 983 | |||
| 929 | if (!ath6kl_remove_sta(ar, bssid, prot_reason_status)) | 984 | if (!ath6kl_remove_sta(ar, bssid, prot_reason_status)) |
| 930 | return; | 985 | return; |
| 931 | 986 | ||
| @@ -1090,7 +1145,7 @@ static int ath6kl_set_features(struct net_device *dev, | |||
| 1090 | static void ath6kl_set_multicast_list(struct net_device *ndev) | 1145 | static void ath6kl_set_multicast_list(struct net_device *ndev) |
| 1091 | { | 1146 | { |
| 1092 | struct ath6kl_vif *vif = netdev_priv(ndev); | 1147 | struct ath6kl_vif *vif = netdev_priv(ndev); |
| 1093 | bool mc_all_on = false, mc_all_off = false; | 1148 | bool mc_all_on = false; |
| 1094 | int mc_count = netdev_mc_count(ndev); | 1149 | int mc_count = netdev_mc_count(ndev); |
| 1095 | struct netdev_hw_addr *ha; | 1150 | struct netdev_hw_addr *ha; |
| 1096 | bool found; | 1151 | bool found; |
| @@ -1102,24 +1157,41 @@ static void ath6kl_set_multicast_list(struct net_device *ndev) | |||
| 1102 | !test_bit(WLAN_ENABLED, &vif->flags)) | 1157 | !test_bit(WLAN_ENABLED, &vif->flags)) |
| 1103 | return; | 1158 | return; |
| 1104 | 1159 | ||
| 1160 | /* Enable multicast-all filter. */ | ||
| 1105 | mc_all_on = !!(ndev->flags & IFF_PROMISC) || | 1161 | mc_all_on = !!(ndev->flags & IFF_PROMISC) || |
| 1106 | !!(ndev->flags & IFF_ALLMULTI) || | 1162 | !!(ndev->flags & IFF_ALLMULTI) || |
| 1107 | !!(mc_count > ATH6K_MAX_MC_FILTERS_PER_LIST); | 1163 | !!(mc_count > ATH6K_MAX_MC_FILTERS_PER_LIST); |
| 1108 | 1164 | ||
| 1109 | mc_all_off = !(ndev->flags & IFF_MULTICAST) || mc_count == 0; | 1165 | if (mc_all_on) |
| 1166 | set_bit(NETDEV_MCAST_ALL_ON, &vif->flags); | ||
| 1167 | else | ||
| 1168 | clear_bit(NETDEV_MCAST_ALL_ON, &vif->flags); | ||
| 1169 | |||
| 1170 | mc_all_on = mc_all_on || (vif->ar->state == ATH6KL_STATE_ON); | ||
| 1110 | 1171 | ||
| 1111 | if (mc_all_on || mc_all_off) { | 1172 | if (!(ndev->flags & IFF_MULTICAST)) { |
| 1112 | /* Enable/disable all multicast */ | 1173 | mc_all_on = false; |
| 1113 | ath6kl_dbg(ATH6KL_DBG_TRC, "%s multicast filter\n", | 1174 | set_bit(NETDEV_MCAST_ALL_OFF, &vif->flags); |
| 1114 | mc_all_on ? "enabling" : "disabling"); | 1175 | } else { |
| 1115 | ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, vif->fw_vif_idx, | 1176 | clear_bit(NETDEV_MCAST_ALL_OFF, &vif->flags); |
| 1177 | } | ||
| 1178 | |||
| 1179 | /* Enable/disable "multicast-all" filter*/ | ||
| 1180 | ath6kl_dbg(ATH6KL_DBG_TRC, "%s multicast-all filter\n", | ||
| 1181 | mc_all_on ? "enabling" : "disabling"); | ||
| 1182 | |||
| 1183 | ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, vif->fw_vif_idx, | ||
| 1116 | mc_all_on); | 1184 | mc_all_on); |
| 1117 | if (ret) | 1185 | if (ret) { |
| 1118 | ath6kl_warn("Failed to %s multicast receive\n", | 1186 | ath6kl_warn("Failed to %s multicast-all receive\n", |
| 1119 | mc_all_on ? "enable" : "disable"); | 1187 | mc_all_on ? "enable" : "disable"); |
| 1120 | return; | 1188 | return; |
| 1121 | } | 1189 | } |
| 1122 | 1190 | ||
| 1191 | if (test_bit(NETDEV_MCAST_ALL_ON, &vif->flags)) | ||
| 1192 | return; | ||
| 1193 | |||
| 1194 | /* Keep the driver and firmware mcast list in sync. */ | ||
| 1123 | list_for_each_entry_safe(mc_filter, tmp, &vif->mc_filter, list) { | 1195 | list_for_each_entry_safe(mc_filter, tmp, &vif->mc_filter, list) { |
| 1124 | found = false; | 1196 | found = false; |
| 1125 | netdev_for_each_mc_addr(ha, ndev) { | 1197 | netdev_for_each_mc_addr(ha, ndev) { |
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 44ea7a74210..05b95405f7b 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c | |||
| @@ -552,7 +552,7 @@ static int ath6kl_sdio_write_async(struct ath6kl *ar, u32 address, u8 *buffer, | |||
| 552 | 552 | ||
| 553 | bus_req = ath6kl_sdio_alloc_busreq(ar_sdio); | 553 | bus_req = ath6kl_sdio_alloc_busreq(ar_sdio); |
| 554 | 554 | ||
| 555 | if (!bus_req) | 555 | if (WARN_ON_ONCE(!bus_req)) |
| 556 | return -ENOMEM; | 556 | return -ENOMEM; |
| 557 | 557 | ||
| 558 | bus_req->address = address; | 558 | bus_req->address = address; |
| @@ -915,6 +915,9 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) | |||
| 915 | } | 915 | } |
| 916 | 916 | ||
| 917 | cut_pwr: | 917 | cut_pwr: |
| 918 | if (func->card && func->card->host) | ||
| 919 | func->card->host->pm_flags &= ~MMC_PM_KEEP_POWER; | ||
| 920 | |||
| 918 | return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_CUTPOWER, NULL); | 921 | return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_CUTPOWER, NULL); |
| 919 | } | 922 | } |
| 920 | 923 | ||
| @@ -985,9 +988,8 @@ static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr) | |||
| 985 | } | 988 | } |
| 986 | 989 | ||
| 987 | if (status) { | 990 | if (status) { |
| 988 | ath6kl_err("%s: failed to write initial bytes of 0x%x " | 991 | ath6kl_err("%s: failed to write initial bytes of 0x%x to window reg: 0x%X\n", |
| 989 | "to window reg: 0x%X\n", __func__, | 992 | __func__, addr, reg_addr); |
| 990 | addr, reg_addr); | ||
| 991 | return status; | 993 | return status; |
| 992 | } | 994 | } |
| 993 | 995 | ||
| @@ -1076,8 +1078,8 @@ static int ath6kl_sdio_bmi_credits(struct ath6kl *ar) | |||
| 1076 | (u8 *)&ar->bmi.cmd_credits, 4, | 1078 | (u8 *)&ar->bmi.cmd_credits, 4, |
| 1077 | HIF_RD_SYNC_BYTE_INC); | 1079 | HIF_RD_SYNC_BYTE_INC); |
| 1078 | if (ret) { | 1080 | if (ret) { |
| 1079 | ath6kl_err("Unable to decrement the command credit " | 1081 | ath6kl_err("Unable to decrement the command credit count register: %d\n", |
| 1080 | "count register: %d\n", ret); | 1082 | ret); |
| 1081 | return ret; | 1083 | return ret; |
| 1082 | } | 1084 | } |
| 1083 | 1085 | ||
| @@ -1457,3 +1459,6 @@ MODULE_FIRMWARE(AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE); | |||
| 1457 | MODULE_FIRMWARE(AR6004_HW_1_1_FW_DIR "/" AR6004_HW_1_1_FIRMWARE_FILE); | 1459 | MODULE_FIRMWARE(AR6004_HW_1_1_FW_DIR "/" AR6004_HW_1_1_FIRMWARE_FILE); |
| 1458 | MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE); | 1460 | MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE); |
| 1459 | MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE); | 1461 | MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE); |
| 1462 | MODULE_FIRMWARE(AR6004_HW_1_2_FW_DIR "/" AR6004_HW_1_2_FIRMWARE_FILE); | ||
| 1463 | MODULE_FIRMWARE(AR6004_HW_1_2_BOARD_DATA_FILE); | ||
| 1464 | MODULE_FIRMWARE(AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE); | ||
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index 82f2f5cb475..67206aedea6 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c | |||
| @@ -362,15 +362,11 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) | |||
| 362 | skb, skb->data, skb->len); | 362 | skb, skb->data, skb->len); |
| 363 | 363 | ||
| 364 | /* If target is not associated */ | 364 | /* If target is not associated */ |
| 365 | if (!test_bit(CONNECTED, &vif->flags)) { | 365 | if (!test_bit(CONNECTED, &vif->flags)) |
| 366 | dev_kfree_skb(skb); | 366 | goto fail_tx; |
| 367 | return 0; | ||
| 368 | } | ||
| 369 | 367 | ||
| 370 | if (WARN_ON_ONCE(ar->state != ATH6KL_STATE_ON)) { | 368 | if (WARN_ON_ONCE(ar->state != ATH6KL_STATE_ON)) |
| 371 | dev_kfree_skb(skb); | 369 | goto fail_tx; |
| 372 | return 0; | ||
| 373 | } | ||
| 374 | 370 | ||
| 375 | if (!test_bit(WMI_READY, &ar->flag)) | 371 | if (!test_bit(WMI_READY, &ar->flag)) |
| 376 | goto fail_tx; | 372 | goto fail_tx; |
diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c index ec7f1f5fd1c..dfbbe9e7ff7 100644 --- a/drivers/net/wireless/ath/ath6kl/usb.c +++ b/drivers/net/wireless/ath/ath6kl/usb.c | |||
| @@ -1037,6 +1037,14 @@ static void ath6kl_usb_stop(struct ath6kl *ar) | |||
| 1037 | hif_stop(ar); | 1037 | hif_stop(ar); |
| 1038 | } | 1038 | } |
| 1039 | 1039 | ||
| 1040 | static void ath6kl_usb_cleanup_scatter(struct ath6kl *ar) | ||
| 1041 | { | ||
| 1042 | /* | ||
| 1043 | * USB doesn't support it. Just return. | ||
| 1044 | */ | ||
| 1045 | return; | ||
| 1046 | } | ||
| 1047 | |||
| 1040 | static const struct ath6kl_hif_ops ath6kl_usb_ops = { | 1048 | static const struct ath6kl_hif_ops ath6kl_usb_ops = { |
| 1041 | .diag_read32 = ath6kl_usb_diag_read32, | 1049 | .diag_read32 = ath6kl_usb_diag_read32, |
| 1042 | .diag_write32 = ath6kl_usb_diag_write32, | 1050 | .diag_write32 = ath6kl_usb_diag_write32, |
| @@ -1049,6 +1057,7 @@ static const struct ath6kl_hif_ops ath6kl_usb_ops = { | |||
| 1049 | .pipe_get_default = ath6kl_usb_get_default_pipe, | 1057 | .pipe_get_default = ath6kl_usb_get_default_pipe, |
| 1050 | .pipe_map_service = ath6kl_usb_map_service_pipe, | 1058 | .pipe_map_service = ath6kl_usb_map_service_pipe, |
| 1051 | .pipe_get_free_queue_number = ath6kl_usb_get_free_queue_number, | 1059 | .pipe_get_free_queue_number = ath6kl_usb_get_free_queue_number, |
| 1060 | .cleanup_scatter = ath6kl_usb_cleanup_scatter, | ||
| 1052 | }; | 1061 | }; |
| 1053 | 1062 | ||
| 1054 | /* ath6kl usb driver registered functions */ | 1063 | /* ath6kl usb driver registered functions */ |
| @@ -1207,3 +1216,6 @@ MODULE_FIRMWARE(AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE); | |||
| 1207 | MODULE_FIRMWARE(AR6004_HW_1_1_FIRMWARE_FILE); | 1216 | MODULE_FIRMWARE(AR6004_HW_1_1_FIRMWARE_FILE); |
| 1208 | MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE); | 1217 | MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE); |
| 1209 | MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE); | 1218 | MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE); |
| 1219 | MODULE_FIRMWARE(AR6004_HW_1_2_FIRMWARE_FILE); | ||
| 1220 | MODULE_FIRMWARE(AR6004_HW_1_2_BOARD_DATA_FILE); | ||
| 1221 | MODULE_FIRMWARE(AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE); | ||
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 7c8a9977faf..ee8ec2394c2 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | */ | 16 | */ |
| 17 | 17 | ||
| 18 | #include <linux/ip.h> | 18 | #include <linux/ip.h> |
| 19 | #include <linux/in.h> | ||
| 19 | #include "core.h" | 20 | #include "core.h" |
| 20 | #include "debug.h" | 21 | #include "debug.h" |
| 21 | #include "testmode.h" | 22 | #include "testmode.h" |
| @@ -289,6 +290,13 @@ int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, u8 if_idx, | |||
| 289 | layer2_priority); | 290 | layer2_priority); |
| 290 | } else | 291 | } else |
| 291 | usr_pri = layer2_priority & 0x7; | 292 | usr_pri = layer2_priority & 0x7; |
| 293 | |||
| 294 | /* | ||
| 295 | * Queue the EAPOL frames in the same WMM_AC_VO queue | ||
| 296 | * as that of management frames. | ||
| 297 | */ | ||
| 298 | if (skb->protocol == cpu_to_be16(ETH_P_PAE)) | ||
| 299 | usr_pri = WMI_VOICE_USER_PRIORITY; | ||
| 292 | } | 300 | } |
| 293 | 301 | ||
| 294 | /* | 302 | /* |
| @@ -460,8 +468,9 @@ static int ath6kl_wmi_remain_on_chnl_event_rx(struct wmi *wmi, u8 *datap, | |||
| 460 | freq, dur); | 468 | freq, dur); |
| 461 | chan = ieee80211_get_channel(ar->wiphy, freq); | 469 | chan = ieee80211_get_channel(ar->wiphy, freq); |
| 462 | if (!chan) { | 470 | if (!chan) { |
| 463 | ath6kl_dbg(ATH6KL_DBG_WMI, "remain_on_chnl: Unknown channel " | 471 | ath6kl_dbg(ATH6KL_DBG_WMI, |
| 464 | "(freq=%u)\n", freq); | 472 | "remain_on_chnl: Unknown channel (freq=%u)\n", |
| 473 | freq); | ||
| 465 | return -EINVAL; | 474 | return -EINVAL; |
| 466 | } | 475 | } |
| 467 | id = vif->last_roc_id; | 476 | id = vif->last_roc_id; |
| @@ -488,12 +497,14 @@ static int ath6kl_wmi_cancel_remain_on_chnl_event_rx(struct wmi *wmi, | |||
| 488 | ev = (struct wmi_cancel_remain_on_chnl_event *) datap; | 497 | ev = (struct wmi_cancel_remain_on_chnl_event *) datap; |
| 489 | freq = le32_to_cpu(ev->freq); | 498 | freq = le32_to_cpu(ev->freq); |
| 490 | dur = le32_to_cpu(ev->duration); | 499 | dur = le32_to_cpu(ev->duration); |
| 491 | ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl: freq=%u dur=%u " | 500 | ath6kl_dbg(ATH6KL_DBG_WMI, |
| 492 | "status=%u\n", freq, dur, ev->status); | 501 | "cancel_remain_on_chnl: freq=%u dur=%u status=%u\n", |
| 502 | freq, dur, ev->status); | ||
| 493 | chan = ieee80211_get_channel(ar->wiphy, freq); | 503 | chan = ieee80211_get_channel(ar->wiphy, freq); |
| 494 | if (!chan) { | 504 | if (!chan) { |
| 495 | ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl: Unknown " | 505 | ath6kl_dbg(ATH6KL_DBG_WMI, |
| 496 | "channel (freq=%u)\n", freq); | 506 | "cancel_remain_on_chnl: Unknown channel (freq=%u)\n", |
| 507 | freq); | ||
| 497 | return -EINVAL; | 508 | return -EINVAL; |
| 498 | } | 509 | } |
| 499 | if (vif->last_cancel_roc_id && | 510 | if (vif->last_cancel_roc_id && |
| @@ -548,12 +559,12 @@ static int ath6kl_wmi_rx_probe_req_event_rx(struct wmi *wmi, u8 *datap, int len, | |||
| 548 | freq = le32_to_cpu(ev->freq); | 559 | freq = le32_to_cpu(ev->freq); |
| 549 | dlen = le16_to_cpu(ev->len); | 560 | dlen = le16_to_cpu(ev->len); |
| 550 | if (datap + len < ev->data + dlen) { | 561 | if (datap + len < ev->data + dlen) { |
| 551 | ath6kl_err("invalid wmi_p2p_rx_probe_req_event: " | 562 | ath6kl_err("invalid wmi_p2p_rx_probe_req_event: len=%d dlen=%u\n", |
| 552 | "len=%d dlen=%u\n", len, dlen); | 563 | len, dlen); |
| 553 | return -EINVAL; | 564 | return -EINVAL; |
| 554 | } | 565 | } |
| 555 | ath6kl_dbg(ATH6KL_DBG_WMI, "rx_probe_req: len=%u freq=%u " | 566 | ath6kl_dbg(ATH6KL_DBG_WMI, |
| 556 | "probe_req_report=%d\n", | 567 | "rx_probe_req: len=%u freq=%u probe_req_report=%d\n", |
| 557 | dlen, freq, vif->probe_req_report); | 568 | dlen, freq, vif->probe_req_report); |
| 558 | 569 | ||
| 559 | if (vif->probe_req_report || vif->nw_type == AP_NETWORK) | 570 | if (vif->probe_req_report || vif->nw_type == AP_NETWORK) |
| @@ -592,8 +603,8 @@ static int ath6kl_wmi_rx_action_event_rx(struct wmi *wmi, u8 *datap, int len, | |||
| 592 | freq = le32_to_cpu(ev->freq); | 603 | freq = le32_to_cpu(ev->freq); |
| 593 | dlen = le16_to_cpu(ev->len); | 604 | dlen = le16_to_cpu(ev->len); |
| 594 | if (datap + len < ev->data + dlen) { | 605 | if (datap + len < ev->data + dlen) { |
| 595 | ath6kl_err("invalid wmi_rx_action_event: " | 606 | ath6kl_err("invalid wmi_rx_action_event: len=%d dlen=%u\n", |
| 596 | "len=%d dlen=%u\n", len, dlen); | 607 | len, dlen); |
| 597 | return -EINVAL; | 608 | return -EINVAL; |
| 598 | } | 609 | } |
| 599 | ath6kl_dbg(ATH6KL_DBG_WMI, "rx_action: len=%u freq=%u\n", dlen, freq); | 610 | ath6kl_dbg(ATH6KL_DBG_WMI, "rx_action: len=%u freq=%u\n", dlen, freq); |
| @@ -687,7 +698,7 @@ static int ath6kl_wmi_ready_event_rx(struct wmi *wmi, u8 *datap, int len) | |||
| 687 | 698 | ||
| 688 | ath6kl_ready_event(wmi->parent_dev, ev->mac_addr, | 699 | ath6kl_ready_event(wmi->parent_dev, ev->mac_addr, |
| 689 | le32_to_cpu(ev->sw_version), | 700 | le32_to_cpu(ev->sw_version), |
| 690 | le32_to_cpu(ev->abi_version)); | 701 | le32_to_cpu(ev->abi_version), ev->phy_cap); |
| 691 | 702 | ||
| 692 | return 0; | 703 | return 0; |
| 693 | } | 704 | } |
| @@ -777,16 +788,15 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len, | |||
| 777 | /* AP mode start/STA connected event */ | 788 | /* AP mode start/STA connected event */ |
| 778 | struct net_device *dev = vif->ndev; | 789 | struct net_device *dev = vif->ndev; |
| 779 | if (memcmp(dev->dev_addr, ev->u.ap_bss.bssid, ETH_ALEN) == 0) { | 790 | if (memcmp(dev->dev_addr, ev->u.ap_bss.bssid, ETH_ALEN) == 0) { |
| 780 | ath6kl_dbg(ATH6KL_DBG_WMI, "%s: freq %d bssid %pM " | 791 | ath6kl_dbg(ATH6KL_DBG_WMI, |
| 781 | "(AP started)\n", | 792 | "%s: freq %d bssid %pM (AP started)\n", |
| 782 | __func__, le16_to_cpu(ev->u.ap_bss.ch), | 793 | __func__, le16_to_cpu(ev->u.ap_bss.ch), |
| 783 | ev->u.ap_bss.bssid); | 794 | ev->u.ap_bss.bssid); |
| 784 | ath6kl_connect_ap_mode_bss( | 795 | ath6kl_connect_ap_mode_bss( |
| 785 | vif, le16_to_cpu(ev->u.ap_bss.ch)); | 796 | vif, le16_to_cpu(ev->u.ap_bss.ch)); |
| 786 | } else { | 797 | } else { |
| 787 | ath6kl_dbg(ATH6KL_DBG_WMI, "%s: aid %u mac_addr %pM " | 798 | ath6kl_dbg(ATH6KL_DBG_WMI, |
| 788 | "auth=%u keymgmt=%u cipher=%u apsd_info=%u " | 799 | "%s: aid %u mac_addr %pM auth=%u keymgmt=%u cipher=%u apsd_info=%u (STA connected)\n", |
| 789 | "(STA connected)\n", | ||
| 790 | __func__, ev->u.ap_sta.aid, | 800 | __func__, ev->u.ap_sta.aid, |
| 791 | ev->u.ap_sta.mac_addr, | 801 | ev->u.ap_sta.mac_addr, |
| 792 | ev->u.ap_sta.auth, | 802 | ev->u.ap_sta.auth, |
| @@ -1229,8 +1239,9 @@ static int ath6kl_wmi_neighbor_report_event_rx(struct wmi *wmi, u8 *datap, | |||
| 1229 | ev = (struct wmi_neighbor_report_event *) datap; | 1239 | ev = (struct wmi_neighbor_report_event *) datap; |
| 1230 | if (sizeof(*ev) + ev->num_neighbors * sizeof(struct wmi_neighbor_info) | 1240 | if (sizeof(*ev) + ev->num_neighbors * sizeof(struct wmi_neighbor_info) |
| 1231 | > len) { | 1241 | > len) { |
| 1232 | ath6kl_dbg(ATH6KL_DBG_WMI, "truncated neighbor event " | 1242 | ath6kl_dbg(ATH6KL_DBG_WMI, |
| 1233 | "(num=%d len=%d)\n", ev->num_neighbors, len); | 1243 | "truncated neighbor event (num=%d len=%d)\n", |
| 1244 | ev->num_neighbors, len); | ||
| 1234 | return -EINVAL; | 1245 | return -EINVAL; |
| 1235 | } | 1246 | } |
| 1236 | for (i = 0; i < ev->num_neighbors; i++) { | 1247 | for (i = 0; i < ev->num_neighbors; i++) { |
| @@ -1814,12 +1825,14 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx, | |||
| 1814 | u32 home_dwell_time, u32 force_scan_interval, | 1825 | u32 home_dwell_time, u32 force_scan_interval, |
| 1815 | s8 num_chan, u16 *ch_list, u32 no_cck, u32 *rates) | 1826 | s8 num_chan, u16 *ch_list, u32 no_cck, u32 *rates) |
| 1816 | { | 1827 | { |
| 1828 | struct ieee80211_supported_band *sband; | ||
| 1817 | struct sk_buff *skb; | 1829 | struct sk_buff *skb; |
| 1818 | struct wmi_begin_scan_cmd *sc; | 1830 | struct wmi_begin_scan_cmd *sc; |
| 1819 | s8 size; | 1831 | s8 size, *supp_rates; |
| 1820 | int i, band, ret; | 1832 | int i, band, ret; |
| 1821 | struct ath6kl *ar = wmi->parent_dev; | 1833 | struct ath6kl *ar = wmi->parent_dev; |
| 1822 | int num_rates; | 1834 | int num_rates; |
| 1835 | u32 ratemask; | ||
| 1823 | 1836 | ||
| 1824 | size = sizeof(struct wmi_begin_scan_cmd); | 1837 | size = sizeof(struct wmi_begin_scan_cmd); |
| 1825 | 1838 | ||
| @@ -1846,10 +1859,13 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx, | |||
| 1846 | sc->num_ch = num_chan; | 1859 | sc->num_ch = num_chan; |
| 1847 | 1860 | ||
| 1848 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 1861 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
| 1849 | struct ieee80211_supported_band *sband = | 1862 | sband = ar->wiphy->bands[band]; |
| 1850 | ar->wiphy->bands[band]; | 1863 | |
| 1851 | u32 ratemask = rates[band]; | 1864 | if (!sband) |
| 1852 | u8 *supp_rates = sc->supp_rates[band].rates; | 1865 | continue; |
| 1866 | |||
| 1867 | ratemask = rates[band]; | ||
| 1868 | supp_rates = sc->supp_rates[band].rates; | ||
| 1853 | num_rates = 0; | 1869 | num_rates = 0; |
| 1854 | 1870 | ||
| 1855 | for (i = 0; i < sband->n_bitrates; i++) { | 1871 | for (i = 0; i < sband->n_bitrates; i++) { |
| @@ -2129,8 +2145,8 @@ int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index, | |||
| 2129 | struct wmi_add_cipher_key_cmd *cmd; | 2145 | struct wmi_add_cipher_key_cmd *cmd; |
| 2130 | int ret; | 2146 | int ret; |
| 2131 | 2147 | ||
| 2132 | ath6kl_dbg(ATH6KL_DBG_WMI, "addkey cmd: key_index=%u key_type=%d " | 2148 | ath6kl_dbg(ATH6KL_DBG_WMI, |
| 2133 | "key_usage=%d key_len=%d key_op_ctrl=%d\n", | 2149 | "addkey cmd: key_index=%u key_type=%d key_usage=%d key_len=%d key_op_ctrl=%d\n", |
| 2134 | key_index, key_type, key_usage, key_len, key_op_ctrl); | 2150 | key_index, key_type, key_usage, key_len, key_op_ctrl); |
| 2135 | 2151 | ||
| 2136 | if ((key_index > WMI_MAX_KEY_INDEX) || (key_len > WMI_MAX_KEY_LEN) || | 2152 | if ((key_index > WMI_MAX_KEY_INDEX) || (key_len > WMI_MAX_KEY_LEN) || |
| @@ -3047,8 +3063,8 @@ int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, u8 if_idx, | |||
| 3047 | 3063 | ||
| 3048 | res = ath6kl_wmi_cmd_send(wmip, if_idx, skb, WMI_AP_CONFIG_COMMIT_CMDID, | 3064 | res = ath6kl_wmi_cmd_send(wmip, if_idx, skb, WMI_AP_CONFIG_COMMIT_CMDID, |
| 3049 | NO_SYNC_WMIFLAG); | 3065 | NO_SYNC_WMIFLAG); |
| 3050 | ath6kl_dbg(ATH6KL_DBG_WMI, "%s: nw_type=%u auth_mode=%u ch=%u " | 3066 | ath6kl_dbg(ATH6KL_DBG_WMI, |
| 3051 | "ctrl_flags=0x%x-> res=%d\n", | 3067 | "%s: nw_type=%u auth_mode=%u ch=%u ctrl_flags=0x%x-> res=%d\n", |
| 3052 | __func__, p->nw_type, p->auth_mode, le16_to_cpu(p->ch), | 3068 | __func__, p->nw_type, p->auth_mode, le16_to_cpu(p->ch), |
| 3053 | le32_to_cpu(p->ctrl_flags), res); | 3069 | le32_to_cpu(p->ctrl_flags), res); |
| 3054 | return res; | 3070 | return res; |
| @@ -3208,8 +3224,9 @@ int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type, | |||
| 3208 | if (!skb) | 3224 | if (!skb) |
| 3209 | return -ENOMEM; | 3225 | return -ENOMEM; |
| 3210 | 3226 | ||
| 3211 | ath6kl_dbg(ATH6KL_DBG_WMI, "set_appie_cmd: mgmt_frm_type=%u " | 3227 | ath6kl_dbg(ATH6KL_DBG_WMI, |
| 3212 | "ie_len=%u\n", mgmt_frm_type, ie_len); | 3228 | "set_appie_cmd: mgmt_frm_type=%u ie_len=%u\n", |
| 3229 | mgmt_frm_type, ie_len); | ||
| 3213 | p = (struct wmi_set_appie_cmd *) skb->data; | 3230 | p = (struct wmi_set_appie_cmd *) skb->data; |
| 3214 | p->mgmt_frm_type = mgmt_frm_type; | 3231 | p->mgmt_frm_type = mgmt_frm_type; |
| 3215 | p->ie_len = ie_len; | 3232 | p->ie_len = ie_len; |
| @@ -3310,8 +3327,9 @@ static int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id, | |||
| 3310 | wmi->last_mgmt_tx_frame = buf; | 3327 | wmi->last_mgmt_tx_frame = buf; |
| 3311 | wmi->last_mgmt_tx_frame_len = data_len; | 3328 | wmi->last_mgmt_tx_frame_len = data_len; |
| 3312 | 3329 | ||
| 3313 | ath6kl_dbg(ATH6KL_DBG_WMI, "send_action_cmd: id=%u freq=%u wait=%u " | 3330 | ath6kl_dbg(ATH6KL_DBG_WMI, |
| 3314 | "len=%u\n", id, freq, wait, data_len); | 3331 | "send_action_cmd: id=%u freq=%u wait=%u len=%u\n", |
| 3332 | id, freq, wait, data_len); | ||
| 3315 | p = (struct wmi_send_action_cmd *) skb->data; | 3333 | p = (struct wmi_send_action_cmd *) skb->data; |
| 3316 | p->id = cpu_to_le32(id); | 3334 | p->id = cpu_to_le32(id); |
| 3317 | p->freq = cpu_to_le32(freq); | 3335 | p->freq = cpu_to_le32(freq); |
| @@ -3348,8 +3366,9 @@ static int __ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id, | |||
| 3348 | wmi->last_mgmt_tx_frame = buf; | 3366 | wmi->last_mgmt_tx_frame = buf; |
| 3349 | wmi->last_mgmt_tx_frame_len = data_len; | 3367 | wmi->last_mgmt_tx_frame_len = data_len; |
| 3350 | 3368 | ||
| 3351 | ath6kl_dbg(ATH6KL_DBG_WMI, "send_action_cmd: id=%u freq=%u wait=%u " | 3369 | ath6kl_dbg(ATH6KL_DBG_WMI, |
| 3352 | "len=%u\n", id, freq, wait, data_len); | 3370 | "send_action_cmd: id=%u freq=%u wait=%u len=%u\n", |
| 3371 | id, freq, wait, data_len); | ||
| 3353 | p = (struct wmi_send_mgmt_cmd *) skb->data; | 3372 | p = (struct wmi_send_mgmt_cmd *) skb->data; |
| 3354 | p->id = cpu_to_le32(id); | 3373 | p->id = cpu_to_le32(id); |
| 3355 | p->freq = cpu_to_le32(freq); | 3374 | p->freq = cpu_to_le32(freq); |
| @@ -3402,8 +3421,9 @@ int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u8 if_idx, u32 freq, | |||
| 3402 | if (!skb) | 3421 | if (!skb) |
| 3403 | return -ENOMEM; | 3422 | return -ENOMEM; |
| 3404 | 3423 | ||
| 3405 | ath6kl_dbg(ATH6KL_DBG_WMI, "send_probe_response_cmd: freq=%u dst=%pM " | 3424 | ath6kl_dbg(ATH6KL_DBG_WMI, |
| 3406 | "len=%u\n", freq, dst, data_len); | 3425 | "send_probe_response_cmd: freq=%u dst=%pM len=%u\n", |
| 3426 | freq, dst, data_len); | ||
| 3407 | p = (struct wmi_p2p_probe_response_cmd *) skb->data; | 3427 | p = (struct wmi_p2p_probe_response_cmd *) skb->data; |
| 3408 | p->freq = cpu_to_le32(freq); | 3428 | p->freq = cpu_to_le32(freq); |
| 3409 | memcpy(p->destination_addr, dst, ETH_ALEN); | 3429 | memcpy(p->destination_addr, dst, ETH_ALEN); |
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index d3d2ab5c168..9076bec3a2b 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h | |||
| @@ -106,6 +106,8 @@ struct wmi_data_sync_bufs { | |||
| 106 | #define WMM_AC_VI 2 /* video */ | 106 | #define WMM_AC_VI 2 /* video */ |
| 107 | #define WMM_AC_VO 3 /* voice */ | 107 | #define WMM_AC_VO 3 /* voice */ |
| 108 | 108 | ||
| 109 | #define WMI_VOICE_USER_PRIORITY 0x7 | ||
| 110 | |||
| 109 | struct wmi { | 111 | struct wmi { |
| 110 | u16 stream_exist_for_ac[WMM_NUM_AC]; | 112 | u16 stream_exist_for_ac[WMM_NUM_AC]; |
| 111 | u8 fat_pipe_exist; | 113 | u8 fat_pipe_exist; |
| @@ -1151,6 +1153,7 @@ enum wmi_phy_mode { | |||
| 1151 | WMI_11AG_MODE = 0x3, | 1153 | WMI_11AG_MODE = 0x3, |
| 1152 | WMI_11B_MODE = 0x4, | 1154 | WMI_11B_MODE = 0x4, |
| 1153 | WMI_11GONLY_MODE = 0x5, | 1155 | WMI_11GONLY_MODE = 0x5, |
| 1156 | WMI_11G_HT20 = 0x6, | ||
| 1154 | }; | 1157 | }; |
| 1155 | 1158 | ||
| 1156 | #define WMI_MAX_CHANNELS 32 | 1159 | #define WMI_MAX_CHANNELS 32 |
| @@ -1416,6 +1419,16 @@ struct wmi_ready_event_2 { | |||
| 1416 | u8 phy_cap; | 1419 | u8 phy_cap; |
| 1417 | } __packed; | 1420 | } __packed; |
| 1418 | 1421 | ||
| 1422 | /* WMI_PHY_CAPABILITY */ | ||
| 1423 | enum wmi_phy_cap { | ||
| 1424 | WMI_11A_CAP = 0x01, | ||
| 1425 | WMI_11G_CAP = 0x02, | ||
| 1426 | WMI_11AG_CAP = 0x03, | ||
| 1427 | WMI_11AN_CAP = 0x04, | ||
| 1428 | WMI_11GN_CAP = 0x05, | ||
| 1429 | WMI_11AGN_CAP = 0x06, | ||
| 1430 | }; | ||
| 1431 | |||
| 1419 | /* Connect Event */ | 1432 | /* Connect Event */ |
| 1420 | struct wmi_connect_event { | 1433 | struct wmi_connect_event { |
| 1421 | union { | 1434 | union { |
| @@ -1468,6 +1481,17 @@ enum wmi_disconnect_reason { | |||
| 1468 | IBSS_MERGE = 0xe, | 1481 | IBSS_MERGE = 0xe, |
| 1469 | }; | 1482 | }; |
| 1470 | 1483 | ||
| 1484 | /* AP mode disconnect proto_reasons */ | ||
| 1485 | enum ap_disconnect_reason { | ||
| 1486 | WMI_AP_REASON_STA_LEFT = 101, | ||
| 1487 | WMI_AP_REASON_FROM_HOST = 102, | ||
| 1488 | WMI_AP_REASON_COMM_TIMEOUT = 103, | ||
| 1489 | WMI_AP_REASON_MAX_STA = 104, | ||
| 1490 | WMI_AP_REASON_ACL = 105, | ||
| 1491 | WMI_AP_REASON_STA_ROAM = 106, | ||
| 1492 | WMI_AP_REASON_DFS_CHANNEL = 107, | ||
| 1493 | }; | ||
| 1494 | |||
| 1471 | #define ATH6KL_COUNTRY_RD_SHIFT 16 | 1495 | #define ATH6KL_COUNTRY_RD_SHIFT 16 |
| 1472 | 1496 | ||
| 1473 | struct ath6kl_wmi_regdomain { | 1497 | struct ath6kl_wmi_regdomain { |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index a0387a027db..9fdd70fcaf5 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c | |||
| @@ -892,34 +892,6 @@ static void ar9003_hw_tx_iq_cal_reload(struct ath_hw *ah) | |||
| 892 | AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1); | 892 | AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1); |
| 893 | } | 893 | } |
| 894 | 894 | ||
| 895 | static bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan) | ||
| 896 | { | ||
| 897 | struct ath9k_rtt_hist *hist; | ||
| 898 | u32 *table; | ||
| 899 | int i; | ||
| 900 | bool restore; | ||
| 901 | |||
| 902 | if (!ah->caldata) | ||
| 903 | return false; | ||
| 904 | |||
| 905 | hist = &ah->caldata->rtt_hist; | ||
| 906 | if (!hist->num_readings) | ||
| 907 | return false; | ||
| 908 | |||
| 909 | ar9003_hw_rtt_enable(ah); | ||
| 910 | ar9003_hw_rtt_set_mask(ah, 0x00); | ||
| 911 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { | ||
| 912 | if (!(ah->rxchainmask & (1 << i))) | ||
| 913 | continue; | ||
| 914 | table = &hist->table[i][hist->num_readings][0]; | ||
| 915 | ar9003_hw_rtt_load_hist(ah, i, table); | ||
| 916 | } | ||
| 917 | restore = ar9003_hw_rtt_force_restore(ah); | ||
| 918 | ar9003_hw_rtt_disable(ah); | ||
| 919 | |||
| 920 | return restore; | ||
| 921 | } | ||
| 922 | |||
| 923 | static bool ar9003_hw_init_cal(struct ath_hw *ah, | 895 | static bool ar9003_hw_init_cal(struct ath_hw *ah, |
| 924 | struct ath9k_channel *chan) | 896 | struct ath9k_channel *chan) |
| 925 | { | 897 | { |
| @@ -942,9 +914,10 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
| 942 | if (!ar9003_hw_rtt_restore(ah, chan)) | 914 | if (!ar9003_hw_rtt_restore(ah, chan)) |
| 943 | run_rtt_cal = true; | 915 | run_rtt_cal = true; |
| 944 | 916 | ||
| 945 | ath_dbg(common, CALIBRATE, "RTT restore %s\n", | 917 | if (run_rtt_cal) |
| 946 | run_rtt_cal ? "failed" : "succeed"); | 918 | ath_dbg(common, CALIBRATE, "RTT calibration to be done\n"); |
| 947 | } | 919 | } |
| 920 | |||
| 948 | run_agc_cal = run_rtt_cal; | 921 | run_agc_cal = run_rtt_cal; |
| 949 | 922 | ||
| 950 | if (run_rtt_cal) { | 923 | if (run_rtt_cal) { |
| @@ -1069,17 +1042,14 @@ skip_tx_iqcal: | |||
| 1069 | #undef CL_TAB_ENTRY | 1042 | #undef CL_TAB_ENTRY |
| 1070 | 1043 | ||
| 1071 | if (run_rtt_cal && caldata) { | 1044 | if (run_rtt_cal && caldata) { |
| 1072 | struct ath9k_rtt_hist *hist = &caldata->rtt_hist; | 1045 | if (is_reusable) { |
| 1073 | if (is_reusable && (hist->num_readings < RTT_HIST_MAX)) { | 1046 | if (!ath9k_hw_rfbus_req(ah)) |
| 1074 | u32 *table; | 1047 | ath_err(ath9k_hw_common(ah), |
| 1048 | "Could not stop baseband\n"); | ||
| 1049 | else | ||
| 1050 | ar9003_hw_rtt_fill_hist(ah); | ||
| 1075 | 1051 | ||
| 1076 | hist->num_readings++; | 1052 | ath9k_hw_rfbus_done(ah); |
| 1077 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { | ||
| 1078 | if (!(ah->rxchainmask & (1 << i))) | ||
| 1079 | continue; | ||
| 1080 | table = &hist->table[i][hist->num_readings][0]; | ||
| 1081 | ar9003_hw_rtt_fill_hist(ah, i, table); | ||
| 1082 | } | ||
| 1083 | } | 1053 | } |
| 1084 | 1054 | ||
| 1085 | ar9003_hw_rtt_disable(ah); | 1055 | ar9003_hw_rtt_disable(ah); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/drivers/net/wireless/ath/ath9k/ar9003_mci.c index 3cac293a284..ffbb180f91e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mci.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.c | |||
| @@ -756,7 +756,7 @@ int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 756 | if (caldata) { | 756 | if (caldata) { |
| 757 | caldata->done_txiqcal_once = false; | 757 | caldata->done_txiqcal_once = false; |
| 758 | caldata->done_txclcal_once = false; | 758 | caldata->done_txclcal_once = false; |
| 759 | caldata->rtt_hist.num_readings = 0; | 759 | caldata->rtt_done = false; |
| 760 | } | 760 | } |
| 761 | 761 | ||
| 762 | if (!ath9k_hw_init_cal(ah, chan)) | 762 | if (!ath9k_hw_init_cal(ah, chan)) |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_rtt.c b/drivers/net/wireless/ath/ath9k/ar9003_rtt.c index 458bedf0b0a..74de3539c2c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_rtt.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_rtt.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | #include "hw.h" | 17 | #include "hw.h" |
| 18 | #include "hw-ops.h" | ||
| 18 | #include "ar9003_phy.h" | 19 | #include "ar9003_phy.h" |
| 19 | #include "ar9003_rtt.h" | 20 | #include "ar9003_rtt.h" |
| 20 | 21 | ||
| @@ -69,7 +70,7 @@ bool ar9003_hw_rtt_force_restore(struct ath_hw *ah) | |||
| 69 | } | 70 | } |
| 70 | 71 | ||
| 71 | static void ar9003_hw_rtt_load_hist_entry(struct ath_hw *ah, u8 chain, | 72 | static void ar9003_hw_rtt_load_hist_entry(struct ath_hw *ah, u8 chain, |
| 72 | u32 index, u32 data28) | 73 | u32 index, u32 data28) |
| 73 | { | 74 | { |
| 74 | u32 val; | 75 | u32 val; |
| 75 | 76 | ||
| @@ -100,12 +101,21 @@ static void ar9003_hw_rtt_load_hist_entry(struct ath_hw *ah, u8 chain, | |||
| 100 | RTT_ACCESS_TIMEOUT); | 101 | RTT_ACCESS_TIMEOUT); |
| 101 | } | 102 | } |
| 102 | 103 | ||
| 103 | void ar9003_hw_rtt_load_hist(struct ath_hw *ah, u8 chain, u32 *table) | 104 | void ar9003_hw_rtt_load_hist(struct ath_hw *ah) |
| 104 | { | 105 | { |
| 105 | int i; | 106 | int chain, i; |
| 106 | 107 | ||
| 107 | for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) | 108 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { |
| 108 | ar9003_hw_rtt_load_hist_entry(ah, chain, i, table[i]); | 109 | if (!(ah->rxchainmask & (1 << chain))) |
| 110 | continue; | ||
| 111 | for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) { | ||
| 112 | ar9003_hw_rtt_load_hist_entry(ah, chain, i, | ||
| 113 | ah->caldata->rtt_table[chain][i]); | ||
| 114 | ath_dbg(ath9k_hw_common(ah), CALIBRATE, | ||
| 115 | "Load RTT value at idx %d, chain %d: 0x%x\n", | ||
| 116 | i, chain, ah->caldata->rtt_table[chain][i]); | ||
| 117 | } | ||
| 118 | } | ||
| 109 | } | 119 | } |
| 110 | 120 | ||
| 111 | static int ar9003_hw_rtt_fill_hist_entry(struct ath_hw *ah, u8 chain, u32 index) | 121 | static int ar9003_hw_rtt_fill_hist_entry(struct ath_hw *ah, u8 chain, u32 index) |
| @@ -128,27 +138,71 @@ static int ar9003_hw_rtt_fill_hist_entry(struct ath_hw *ah, u8 chain, u32 index) | |||
| 128 | RTT_ACCESS_TIMEOUT)) | 138 | RTT_ACCESS_TIMEOUT)) |
| 129 | return RTT_BAD_VALUE; | 139 | return RTT_BAD_VALUE; |
| 130 | 140 | ||
| 131 | val = REG_READ(ah, AR_PHY_RTT_TABLE_SW_INTF_1_B(chain)); | 141 | val = MS(REG_READ(ah, AR_PHY_RTT_TABLE_SW_INTF_1_B(chain)), |
| 142 | AR_PHY_RTT_SW_RTT_TABLE_DATA); | ||
| 143 | |||
| 132 | 144 | ||
| 133 | return val; | 145 | return val; |
| 134 | } | 146 | } |
| 135 | 147 | ||
| 136 | void ar9003_hw_rtt_fill_hist(struct ath_hw *ah, u8 chain, u32 *table) | 148 | void ar9003_hw_rtt_fill_hist(struct ath_hw *ah) |
| 137 | { | 149 | { |
| 138 | int i; | 150 | int chain, i; |
| 151 | |||
| 152 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { | ||
| 153 | if (!(ah->rxchainmask & (1 << chain))) | ||
| 154 | continue; | ||
| 155 | for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) { | ||
| 156 | ah->caldata->rtt_table[chain][i] = | ||
| 157 | ar9003_hw_rtt_fill_hist_entry(ah, chain, i); | ||
| 158 | ath_dbg(ath9k_hw_common(ah), CALIBRATE, | ||
| 159 | "RTT value at idx %d, chain %d is: 0x%x\n", | ||
| 160 | i, chain, ah->caldata->rtt_table[chain][i]); | ||
| 161 | } | ||
| 162 | } | ||
| 139 | 163 | ||
| 140 | for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) | 164 | ah->caldata->rtt_done = true; |
| 141 | table[i] = ar9003_hw_rtt_fill_hist_entry(ah, chain, i); | ||
| 142 | } | 165 | } |
| 143 | 166 | ||
| 144 | void ar9003_hw_rtt_clear_hist(struct ath_hw *ah) | 167 | void ar9003_hw_rtt_clear_hist(struct ath_hw *ah) |
| 145 | { | 168 | { |
| 146 | int i, j; | 169 | int chain, i; |
| 147 | 170 | ||
| 148 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { | 171 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { |
| 149 | if (!(ah->rxchainmask & (1 << i))) | 172 | if (!(ah->rxchainmask & (1 << chain))) |
| 150 | continue; | 173 | continue; |
| 151 | for (j = 0; j < MAX_RTT_TABLE_ENTRY; j++) | 174 | for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) |
| 152 | ar9003_hw_rtt_load_hist_entry(ah, i, j, 0); | 175 | ar9003_hw_rtt_load_hist_entry(ah, chain, i, 0); |
| 153 | } | 176 | } |
| 177 | |||
| 178 | if (ah->caldata) | ||
| 179 | ah->caldata->rtt_done = false; | ||
| 180 | } | ||
| 181 | |||
| 182 | bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan) | ||
| 183 | { | ||
| 184 | bool restore; | ||
| 185 | |||
| 186 | if (!ah->caldata) | ||
| 187 | return false; | ||
| 188 | |||
| 189 | if (!ah->caldata->rtt_done) | ||
| 190 | return false; | ||
| 191 | |||
| 192 | ar9003_hw_rtt_enable(ah); | ||
| 193 | ar9003_hw_rtt_set_mask(ah, 0x10); | ||
| 194 | |||
| 195 | if (!ath9k_hw_rfbus_req(ah)) { | ||
| 196 | ath_err(ath9k_hw_common(ah), "Could not stop baseband\n"); | ||
| 197 | restore = false; | ||
| 198 | goto fail; | ||
| 199 | } | ||
| 200 | |||
| 201 | ar9003_hw_rtt_load_hist(ah); | ||
| 202 | restore = ar9003_hw_rtt_force_restore(ah); | ||
| 203 | |||
| 204 | fail: | ||
| 205 | ath9k_hw_rfbus_done(ah); | ||
| 206 | ar9003_hw_rtt_disable(ah); | ||
| 207 | return restore; | ||
| 154 | } | 208 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_rtt.h b/drivers/net/wireless/ath/ath9k/ar9003_rtt.h index 030758d087d..a43b30d723a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_rtt.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_rtt.h | |||
| @@ -21,8 +21,9 @@ void ar9003_hw_rtt_enable(struct ath_hw *ah); | |||
| 21 | void ar9003_hw_rtt_disable(struct ath_hw *ah); | 21 | void ar9003_hw_rtt_disable(struct ath_hw *ah); |
| 22 | void ar9003_hw_rtt_set_mask(struct ath_hw *ah, u32 rtt_mask); | 22 | void ar9003_hw_rtt_set_mask(struct ath_hw *ah, u32 rtt_mask); |
| 23 | bool ar9003_hw_rtt_force_restore(struct ath_hw *ah); | 23 | bool ar9003_hw_rtt_force_restore(struct ath_hw *ah); |
| 24 | void ar9003_hw_rtt_load_hist(struct ath_hw *ah, u8 chain, u32 *table); | 24 | void ar9003_hw_rtt_load_hist(struct ath_hw *ah); |
| 25 | void ar9003_hw_rtt_fill_hist(struct ath_hw *ah, u8 chain, u32 *table); | 25 | void ar9003_hw_rtt_fill_hist(struct ath_hw *ah); |
| 26 | void ar9003_hw_rtt_clear_hist(struct ath_hw *ah); | 26 | void ar9003_hw_rtt_clear_hist(struct ath_hw *ah); |
| 27 | bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan); | ||
| 27 | 28 | ||
| 28 | #endif | 29 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index f84477c5ebb..abe05ec85d5 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
| @@ -1702,10 +1702,10 @@ static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan) | |||
| 1702 | * For AR9462, make sure that calibration data for | 1702 | * For AR9462, make sure that calibration data for |
| 1703 | * re-using are present. | 1703 | * re-using are present. |
| 1704 | */ | 1704 | */ |
| 1705 | if (AR_SREV_9462(ah) && (!ah->caldata || | 1705 | if (AR_SREV_9462(ah) && (ah->caldata && |
| 1706 | !ah->caldata->done_txiqcal_once || | 1706 | (!ah->caldata->done_txiqcal_once || |
| 1707 | !ah->caldata->done_txclcal_once || | 1707 | !ah->caldata->done_txclcal_once || |
| 1708 | !ah->caldata->rtt_hist.num_readings)) | 1708 | !ah->caldata->rtt_done))) |
| 1709 | goto fail; | 1709 | goto fail; |
| 1710 | 1710 | ||
| 1711 | ath_dbg(common, RESET, "FastChannelChange for %d -> %d\n", | 1711 | ath_dbg(common, RESET, "FastChannelChange for %d -> %d\n", |
| @@ -1941,7 +1941,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 1941 | if (caldata) { | 1941 | if (caldata) { |
| 1942 | caldata->done_txiqcal_once = false; | 1942 | caldata->done_txiqcal_once = false; |
| 1943 | caldata->done_txclcal_once = false; | 1943 | caldata->done_txclcal_once = false; |
| 1944 | caldata->rtt_hist.num_readings = 0; | ||
| 1945 | } | 1944 | } |
| 1946 | if (!ath9k_hw_init_cal(ah, chan)) | 1945 | if (!ath9k_hw_init_cal(ah, chan)) |
| 1947 | return -EIO; | 1946 | return -EIO; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 828b9bbc456..b620c557c2a 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
| @@ -348,12 +348,6 @@ enum ath9k_int { | |||
| 348 | CHANNEL_HT40MINUS) | 348 | CHANNEL_HT40MINUS) |
| 349 | 349 | ||
| 350 | #define MAX_RTT_TABLE_ENTRY 6 | 350 | #define MAX_RTT_TABLE_ENTRY 6 |
| 351 | #define RTT_HIST_MAX 3 | ||
| 352 | struct ath9k_rtt_hist { | ||
| 353 | u32 table[AR9300_MAX_CHAINS][RTT_HIST_MAX][MAX_RTT_TABLE_ENTRY]; | ||
| 354 | u8 num_readings; | ||
| 355 | }; | ||
| 356 | |||
| 357 | #define MAX_IQCAL_MEASUREMENT 8 | 351 | #define MAX_IQCAL_MEASUREMENT 8 |
| 358 | #define MAX_CL_TAB_ENTRY 16 | 352 | #define MAX_CL_TAB_ENTRY 16 |
| 359 | 353 | ||
| @@ -363,6 +357,7 @@ struct ath9k_hw_cal_data { | |||
| 363 | int32_t CalValid; | 357 | int32_t CalValid; |
| 364 | int8_t iCoff; | 358 | int8_t iCoff; |
| 365 | int8_t qCoff; | 359 | int8_t qCoff; |
| 360 | bool rtt_done; | ||
| 366 | bool paprd_done; | 361 | bool paprd_done; |
| 367 | bool nfcal_pending; | 362 | bool nfcal_pending; |
| 368 | bool nfcal_interference; | 363 | bool nfcal_interference; |
| @@ -373,8 +368,8 @@ struct ath9k_hw_cal_data { | |||
| 373 | u32 num_measures[AR9300_MAX_CHAINS]; | 368 | u32 num_measures[AR9300_MAX_CHAINS]; |
| 374 | int tx_corr_coeff[MAX_IQCAL_MEASUREMENT][AR9300_MAX_CHAINS]; | 369 | int tx_corr_coeff[MAX_IQCAL_MEASUREMENT][AR9300_MAX_CHAINS]; |
| 375 | u32 tx_clcal[AR9300_MAX_CHAINS][MAX_CL_TAB_ENTRY]; | 370 | u32 tx_clcal[AR9300_MAX_CHAINS][MAX_CL_TAB_ENTRY]; |
| 371 | u32 rtt_table[AR9300_MAX_CHAINS][MAX_RTT_TABLE_ENTRY]; | ||
| 376 | struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; | 372 | struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; |
| 377 | struct ath9k_rtt_hist rtt_hist; | ||
| 378 | }; | 373 | }; |
| 379 | 374 | ||
| 380 | struct ath9k_channel { | 375 | struct ath9k_channel { |
diff --git a/drivers/net/wireless/b43/bus.c b/drivers/net/wireless/b43/bus.c index 424692df239..565fdbdd691 100644 --- a/drivers/net/wireless/b43/bus.c +++ b/drivers/net/wireless/b43/bus.c | |||
| @@ -107,11 +107,9 @@ struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core) | |||
| 107 | dev->dma_dev = core->dma_dev; | 107 | dev->dma_dev = core->dma_dev; |
| 108 | dev->irq = core->irq; | 108 | dev->irq = core->irq; |
| 109 | 109 | ||
| 110 | /* | ||
| 111 | dev->board_vendor = core->bus->boardinfo.vendor; | 110 | dev->board_vendor = core->bus->boardinfo.vendor; |
| 112 | dev->board_type = core->bus->boardinfo.type; | 111 | dev->board_type = core->bus->boardinfo.type; |
| 113 | dev->board_rev = core->bus->boardinfo.rev; | 112 | dev->board_rev = core->bus->sprom.board_rev; |
| 114 | */ | ||
| 115 | 113 | ||
| 116 | dev->chip_id = core->bus->chipinfo.id; | 114 | dev->chip_id = core->bus->chipinfo.id; |
| 117 | dev->chip_rev = core->bus->chipinfo.rev; | 115 | dev->chip_rev = core->bus->chipinfo.rev; |
| @@ -210,7 +208,7 @@ struct b43_bus_dev *b43_bus_dev_ssb_init(struct ssb_device *sdev) | |||
| 210 | 208 | ||
| 211 | dev->board_vendor = sdev->bus->boardinfo.vendor; | 209 | dev->board_vendor = sdev->bus->boardinfo.vendor; |
| 212 | dev->board_type = sdev->bus->boardinfo.type; | 210 | dev->board_type = sdev->bus->boardinfo.type; |
| 213 | dev->board_rev = sdev->bus->boardinfo.rev; | 211 | dev->board_rev = sdev->bus->sprom.board_rev; |
| 214 | 212 | ||
| 215 | dev->chip_id = sdev->bus->chip_id; | 213 | dev->chip_id = sdev->bus->chip_id; |
| 216 | dev->chip_rev = sdev->bus->chip_rev; | 214 | dev->chip_rev = sdev->bus->chip_rev; |
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index b5f1b91002b..777cd74921d 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c | |||
| @@ -1109,7 +1109,7 @@ static bool b43_dma_translation_in_low_word(struct b43_wldev *dev, | |||
| 1109 | #ifdef CONFIG_B43_SSB | 1109 | #ifdef CONFIG_B43_SSB |
| 1110 | if (dev->dev->bus_type == B43_BUS_SSB && | 1110 | if (dev->dev->bus_type == B43_BUS_SSB && |
| 1111 | dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI && | 1111 | dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI && |
| 1112 | !(dev->dev->sdev->bus->host_pci->is_pcie && | 1112 | !(pci_is_pcie(dev->dev->sdev->bus->host_pci) && |
| 1113 | ssb_read32(dev->dev->sdev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64)) | 1113 | ssb_read32(dev->dev->sdev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64)) |
| 1114 | return 1; | 1114 | return 1; |
| 1115 | #endif | 1115 | #endif |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 617afc8211b..5a39b226b2e 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
| @@ -5243,10 +5243,10 @@ static void b43_sprom_fixup(struct ssb_bus *bus) | |||
| 5243 | 5243 | ||
| 5244 | /* boardflags workarounds */ | 5244 | /* boardflags workarounds */ |
| 5245 | if (bus->boardinfo.vendor == SSB_BOARDVENDOR_DELL && | 5245 | if (bus->boardinfo.vendor == SSB_BOARDVENDOR_DELL && |
| 5246 | bus->chip_id == 0x4301 && bus->boardinfo.rev == 0x74) | 5246 | bus->chip_id == 0x4301 && bus->sprom.board_rev == 0x74) |
| 5247 | bus->sprom.boardflags_lo |= B43_BFL_BTCOEXIST; | 5247 | bus->sprom.boardflags_lo |= B43_BFL_BTCOEXIST; |
| 5248 | if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE && | 5248 | if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE && |
| 5249 | bus->boardinfo.type == 0x4E && bus->boardinfo.rev > 0x40) | 5249 | bus->boardinfo.type == 0x4E && bus->sprom.board_rev > 0x40) |
| 5250 | bus->sprom.boardflags_lo |= B43_BFL_PACTRL; | 5250 | bus->sprom.boardflags_lo |= B43_BFL_PACTRL; |
| 5251 | if (bus->bustype == SSB_BUSTYPE_PCI) { | 5251 | if (bus->bustype == SSB_BUSTYPE_PCI) { |
| 5252 | pdev = bus->host_pci; | 5252 | pdev = bus->host_pci; |
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 1be214b815f..cd9c9bc186d 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
| @@ -1573,8 +1573,6 @@ static void b43legacy_request_firmware(struct work_struct *work) | |||
| 1573 | const char *filename; | 1573 | const char *filename; |
| 1574 | int err; | 1574 | int err; |
| 1575 | 1575 | ||
| 1576 | /* do dummy read */ | ||
| 1577 | ssb_read32(dev->dev, SSB_TMSHIGH); | ||
| 1578 | if (!fw->ucode) { | 1576 | if (!fw->ucode) { |
| 1579 | if (rev == 2) | 1577 | if (rev == 2) |
| 1580 | filename = "ucode2"; | 1578 | filename = "ucode2"; |
| @@ -3781,7 +3779,7 @@ static void b43legacy_sprom_fixup(struct ssb_bus *bus) | |||
| 3781 | /* boardflags workarounds */ | 3779 | /* boardflags workarounds */ |
| 3782 | if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE && | 3780 | if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE && |
| 3783 | bus->boardinfo.type == 0x4E && | 3781 | bus->boardinfo.type == 0x4E && |
| 3784 | bus->boardinfo.rev > 0x40) | 3782 | bus->sprom.board_rev > 0x40) |
| 3785 | bus->sprom.boardflags_lo |= B43legacy_BFL_PACTRL; | 3783 | bus->sprom.boardflags_lo |= B43legacy_BFL_PACTRL; |
| 3786 | } | 3784 | } |
| 3787 | 3785 | ||
diff --git a/drivers/net/wireless/b43legacy/phy.c b/drivers/net/wireless/b43legacy/phy.c index 950334197f4..995c7d0c212 100644 --- a/drivers/net/wireless/b43legacy/phy.c +++ b/drivers/net/wireless/b43legacy/phy.c | |||
| @@ -408,7 +408,7 @@ static void b43legacy_phy_setupg(struct b43legacy_wldev *dev) | |||
| 408 | 408 | ||
| 409 | if (is_bcm_board_vendor(dev) && | 409 | if (is_bcm_board_vendor(dev) && |
| 410 | (dev->dev->bus->boardinfo.type == 0x0416) && | 410 | (dev->dev->bus->boardinfo.type == 0x0416) && |
| 411 | (dev->dev->bus->boardinfo.rev == 0x0017)) | 411 | (dev->dev->bus->sprom.board_rev == 0x0017)) |
| 412 | return; | 412 | return; |
| 413 | 413 | ||
| 414 | b43legacy_ilt_write(dev, 0x5001, 0x0002); | 414 | b43legacy_ilt_write(dev, 0x5001, 0x0002); |
| @@ -424,7 +424,7 @@ static void b43legacy_phy_setupg(struct b43legacy_wldev *dev) | |||
| 424 | 424 | ||
| 425 | if (is_bcm_board_vendor(dev) && | 425 | if (is_bcm_board_vendor(dev) && |
| 426 | (dev->dev->bus->boardinfo.type == 0x0416) && | 426 | (dev->dev->bus->boardinfo.type == 0x0416) && |
| 427 | (dev->dev->bus->boardinfo.rev == 0x0017)) | 427 | (dev->dev->bus->sprom.board_rev == 0x0017)) |
| 428 | return; | 428 | return; |
| 429 | 429 | ||
| 430 | b43legacy_ilt_write(dev, 0x0401, 0x0002); | 430 | b43legacy_ilt_write(dev, 0x0401, 0x0002); |
diff --git a/drivers/net/wireless/b43legacy/radio.c b/drivers/net/wireless/b43legacy/radio.c index fcbafcd603c..89617769039 100644 --- a/drivers/net/wireless/b43legacy/radio.c +++ b/drivers/net/wireless/b43legacy/radio.c | |||
| @@ -1998,7 +1998,7 @@ u16 b43legacy_default_radio_attenuation(struct b43legacy_wldev *dev) | |||
| 1998 | if (phy->type == B43legacy_PHYTYPE_G) { | 1998 | if (phy->type == B43legacy_PHYTYPE_G) { |
| 1999 | if (is_bcm_board_vendor(dev) && | 1999 | if (is_bcm_board_vendor(dev) && |
| 2000 | dev->dev->bus->boardinfo.type == 0x421 && | 2000 | dev->dev->bus->boardinfo.type == 0x421 && |
| 2001 | dev->dev->bus->boardinfo.rev >= 30) | 2001 | dev->dev->bus->sprom.board_rev >= 30) |
| 2002 | att = 3; | 2002 | att = 3; |
| 2003 | else if (is_bcm_board_vendor(dev) && | 2003 | else if (is_bcm_board_vendor(dev) && |
| 2004 | dev->dev->bus->boardinfo.type == 0x416) | 2004 | dev->dev->bus->boardinfo.type == 0x416) |
| @@ -2008,7 +2008,7 @@ u16 b43legacy_default_radio_attenuation(struct b43legacy_wldev *dev) | |||
| 2008 | } else { | 2008 | } else { |
| 2009 | if (is_bcm_board_vendor(dev) && | 2009 | if (is_bcm_board_vendor(dev) && |
| 2010 | dev->dev->bus->boardinfo.type == 0x421 && | 2010 | dev->dev->bus->boardinfo.type == 0x421 && |
| 2011 | dev->dev->bus->boardinfo.rev >= 30) | 2011 | dev->dev->bus->sprom.board_rev >= 30) |
| 2012 | att = 7; | 2012 | att = 7; |
| 2013 | else | 2013 | else |
| 2014 | att = 6; | 2014 | att = 6; |
| @@ -2018,7 +2018,7 @@ u16 b43legacy_default_radio_attenuation(struct b43legacy_wldev *dev) | |||
| 2018 | if (phy->type == B43legacy_PHYTYPE_G) { | 2018 | if (phy->type == B43legacy_PHYTYPE_G) { |
| 2019 | if (is_bcm_board_vendor(dev) && | 2019 | if (is_bcm_board_vendor(dev) && |
| 2020 | dev->dev->bus->boardinfo.type == 0x421 && | 2020 | dev->dev->bus->boardinfo.type == 0x421 && |
| 2021 | dev->dev->bus->boardinfo.rev >= 30) | 2021 | dev->dev->bus->sprom.board_rev >= 30) |
| 2022 | att = 3; | 2022 | att = 3; |
| 2023 | else if (is_bcm_board_vendor(dev) && | 2023 | else if (is_bcm_board_vendor(dev) && |
| 2024 | dev->dev->bus->boardinfo.type == | 2024 | dev->dev->bus->boardinfo.type == |
| @@ -2052,9 +2052,9 @@ u16 b43legacy_default_radio_attenuation(struct b43legacy_wldev *dev) | |||
| 2052 | } | 2052 | } |
| 2053 | if (is_bcm_board_vendor(dev) && | 2053 | if (is_bcm_board_vendor(dev) && |
| 2054 | dev->dev->bus->boardinfo.type == 0x421) { | 2054 | dev->dev->bus->boardinfo.type == 0x421) { |
| 2055 | if (dev->dev->bus->boardinfo.rev < 0x43) | 2055 | if (dev->dev->bus->sprom.board_rev < 0x43) |
| 2056 | att = 2; | 2056 | att = 2; |
| 2057 | else if (dev->dev->bus->boardinfo.rev < 0x51) | 2057 | else if (dev->dev->bus->sprom.board_rev < 0x51) |
| 2058 | att = 3; | 2058 | att = 3; |
| 2059 | } | 2059 | } |
| 2060 | if (att == 0xFFFF) | 2060 | if (att == 0xFFFF) |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 4add7da2468..e2480d19627 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
| @@ -85,18 +85,15 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) | |||
| 85 | sdiodev->irq_wake = true; | 85 | sdiodev->irq_wake = true; |
| 86 | 86 | ||
| 87 | /* must configure SDIO_CCCR_IENx to enable irq */ | 87 | /* must configure SDIO_CCCR_IENx to enable irq */ |
| 88 | data = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_0, | 88 | data = brcmf_sdio_regrb(sdiodev, SDIO_CCCR_IENx, &ret); |
| 89 | SDIO_CCCR_IENx, &ret); | ||
| 90 | data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1; | 89 | data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1; |
| 91 | brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_IENx, | 90 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret); |
| 92 | data, &ret); | ||
| 93 | 91 | ||
| 94 | /* redirect, configure ane enable io for interrupt signal */ | 92 | /* redirect, configure ane enable io for interrupt signal */ |
| 95 | data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE; | 93 | data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE; |
| 96 | if (sdiodev->irq_flags | IRQF_TRIGGER_HIGH) | 94 | if (sdiodev->irq_flags | IRQF_TRIGGER_HIGH) |
| 97 | data |= SDIO_SEPINT_ACT_HI; | 95 | data |= SDIO_SEPINT_ACT_HI; |
| 98 | brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_BRCM_SEPINT, | 96 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret); |
| 99 | data, &ret); | ||
| 100 | 97 | ||
| 101 | return 0; | 98 | return 0; |
| 102 | } | 99 | } |
| @@ -105,9 +102,8 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev) | |||
| 105 | { | 102 | { |
| 106 | brcmf_dbg(TRACE, "Entering\n"); | 103 | brcmf_dbg(TRACE, "Entering\n"); |
| 107 | 104 | ||
| 108 | brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_BRCM_SEPINT, | 105 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL); |
| 109 | 0, NULL); | 106 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL); |
| 110 | brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_IENx, 0, NULL); | ||
| 111 | 107 | ||
| 112 | if (sdiodev->irq_wake) { | 108 | if (sdiodev->irq_wake) { |
| 113 | disable_irq_wake(sdiodev->irq); | 109 | disable_irq_wake(sdiodev->irq); |
| @@ -158,153 +154,147 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev) | |||
| 158 | } | 154 | } |
| 159 | #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ | 155 | #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ |
| 160 | 156 | ||
| 161 | u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr, | ||
| 162 | int *err) | ||
| 163 | { | ||
| 164 | int status; | ||
| 165 | s32 retry = 0; | ||
| 166 | u8 data = 0; | ||
| 167 | |||
| 168 | do { | ||
| 169 | if (retry) /* wait for 1 ms till bus get settled down */ | ||
| 170 | udelay(1000); | ||
| 171 | status = brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, fnc_num, | ||
| 172 | addr, (u8 *) &data); | ||
| 173 | } while (status != 0 | ||
| 174 | && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT)); | ||
| 175 | if (err) | ||
| 176 | *err = status; | ||
| 177 | |||
| 178 | brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n", | ||
| 179 | fnc_num, addr, data); | ||
| 180 | |||
| 181 | return data; | ||
| 182 | } | ||
| 183 | |||
| 184 | void | ||
| 185 | brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr, | ||
| 186 | u8 data, int *err) | ||
| 187 | { | ||
| 188 | int status; | ||
| 189 | s32 retry = 0; | ||
| 190 | |||
| 191 | do { | ||
| 192 | if (retry) /* wait for 1 ms till bus get settled down */ | ||
| 193 | udelay(1000); | ||
| 194 | status = brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, fnc_num, | ||
| 195 | addr, (u8 *) &data); | ||
| 196 | } while (status != 0 | ||
| 197 | && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT)); | ||
| 198 | if (err) | ||
| 199 | *err = status; | ||
| 200 | |||
| 201 | brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n", | ||
| 202 | fnc_num, addr, data); | ||
| 203 | } | ||
| 204 | |||
| 205 | int | 157 | int |
| 206 | brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) | 158 | brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) |
| 207 | { | 159 | { |
| 208 | int err = 0; | 160 | int err = 0, i; |
| 209 | brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW, | 161 | u8 addr[3]; |
| 210 | (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err); | 162 | s32 retry; |
| 211 | if (!err) | 163 | |
| 212 | brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, | 164 | addr[0] = (address >> 8) & SBSDIO_SBADDRLOW_MASK; |
| 213 | SBSDIO_FUNC1_SBADDRMID, | 165 | addr[1] = (address >> 16) & SBSDIO_SBADDRMID_MASK; |
| 214 | (address >> 16) & SBSDIO_SBADDRMID_MASK, | 166 | addr[2] = (address >> 24) & SBSDIO_SBADDRHIGH_MASK; |
| 215 | &err); | 167 | |
| 216 | if (!err) | 168 | for (i = 0; i < 3; i++) { |
| 217 | brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, | 169 | retry = 0; |
| 218 | SBSDIO_FUNC1_SBADDRHIGH, | 170 | do { |
| 219 | (address >> 24) & SBSDIO_SBADDRHIGH_MASK, | 171 | if (retry) |
| 220 | &err); | 172 | usleep_range(1000, 2000); |
| 173 | err = brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, | ||
| 174 | SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW + i, | ||
| 175 | &addr[i]); | ||
| 176 | } while (err != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); | ||
| 177 | |||
| 178 | if (err) { | ||
| 179 | brcmf_dbg(ERROR, "failed at addr:0x%0x\n", | ||
| 180 | SBSDIO_FUNC1_SBADDRLOW + i); | ||
| 181 | break; | ||
| 182 | } | ||
| 183 | } | ||
| 221 | 184 | ||
| 222 | return err; | 185 | return err; |
| 223 | } | 186 | } |
| 224 | 187 | ||
| 225 | u32 brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size) | 188 | static int |
| 189 | brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | ||
| 190 | void *data, bool write) | ||
| 226 | { | 191 | { |
| 227 | int status; | 192 | u8 func_num, reg_size; |
| 228 | u32 word = 0; | 193 | u32 bar; |
| 229 | uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; | 194 | s32 retry = 0; |
| 230 | 195 | int ret; | |
| 231 | brcmf_dbg(INFO, "fun = 1, addr = 0x%x\n", addr); | ||
| 232 | |||
| 233 | if (bar0 != sdiodev->sbwad) { | ||
| 234 | if (brcmf_sdcard_set_sbaddr_window(sdiodev, bar0)) | ||
| 235 | return 0xFFFFFFFF; | ||
| 236 | 196 | ||
| 237 | sdiodev->sbwad = bar0; | 197 | /* |
| 198 | * figure out how to read the register based on address range | ||
| 199 | * 0x00 ~ 0x7FF: function 0 CCCR and FBR | ||
| 200 | * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers | ||
| 201 | * The rest: function 1 silicon backplane core registers | ||
| 202 | */ | ||
| 203 | if ((addr & ~REG_F0_REG_MASK) == 0) { | ||
| 204 | func_num = SDIO_FUNC_0; | ||
| 205 | reg_size = 1; | ||
| 206 | } else if ((addr & ~REG_F1_MISC_MASK) == 0) { | ||
| 207 | func_num = SDIO_FUNC_1; | ||
| 208 | reg_size = 1; | ||
| 209 | } else { | ||
| 210 | func_num = SDIO_FUNC_1; | ||
| 211 | reg_size = 4; | ||
| 212 | |||
| 213 | /* Set the window for SB core register */ | ||
| 214 | bar = addr & ~SBSDIO_SB_OFT_ADDR_MASK; | ||
| 215 | if (bar != sdiodev->sbwad) { | ||
| 216 | ret = brcmf_sdcard_set_sbaddr_window(sdiodev, bar); | ||
| 217 | if (ret != 0) { | ||
| 218 | memset(data, 0xFF, reg_size); | ||
| 219 | return ret; | ||
| 220 | } | ||
| 221 | sdiodev->sbwad = bar; | ||
| 222 | } | ||
| 223 | addr &= SBSDIO_SB_OFT_ADDR_MASK; | ||
| 224 | addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; | ||
| 238 | } | 225 | } |
| 239 | 226 | ||
| 240 | addr &= SBSDIO_SB_OFT_ADDR_MASK; | 227 | do { |
| 241 | if (size == 4) | 228 | if (!write) |
| 242 | addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; | 229 | memset(data, 0, reg_size); |
| 230 | if (retry) /* wait for 1 ms till bus get settled down */ | ||
| 231 | usleep_range(1000, 2000); | ||
| 232 | if (reg_size == 1) | ||
| 233 | ret = brcmf_sdioh_request_byte(sdiodev, write, | ||
| 234 | func_num, addr, data); | ||
| 235 | else | ||
| 236 | ret = brcmf_sdioh_request_word(sdiodev, write, | ||
| 237 | func_num, addr, data, 4); | ||
| 238 | } while (ret != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); | ||
| 243 | 239 | ||
| 244 | status = brcmf_sdioh_request_word(sdiodev, SDIOH_READ, SDIO_FUNC_1, | 240 | if (ret != 0) |
| 245 | addr, &word, size); | 241 | brcmf_dbg(ERROR, "failed with %d\n", ret); |
| 246 | 242 | ||
| 247 | sdiodev->regfail = (status != 0); | 243 | return ret; |
| 244 | } | ||
| 248 | 245 | ||
| 249 | brcmf_dbg(INFO, "u32data = 0x%x\n", word); | 246 | u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) |
| 247 | { | ||
| 248 | u8 data; | ||
| 249 | int retval; | ||
| 250 | 250 | ||
| 251 | /* if ok, return appropriately masked word */ | 251 | brcmf_dbg(INFO, "addr:0x%08x\n", addr); |
| 252 | if (status == 0) { | 252 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false); |
| 253 | switch (size) { | 253 | brcmf_dbg(INFO, "data:0x%02x\n", data); |
| 254 | case sizeof(u8): | ||
| 255 | return word & 0xff; | ||
| 256 | case sizeof(u16): | ||
| 257 | return word & 0xffff; | ||
| 258 | case sizeof(u32): | ||
| 259 | return word; | ||
| 260 | default: | ||
| 261 | sdiodev->regfail = true; | ||
| 262 | 254 | ||
| 263 | } | 255 | if (ret) |
| 264 | } | 256 | *ret = retval; |
| 265 | 257 | ||
| 266 | /* otherwise, bad sdio access or invalid size */ | 258 | return data; |
| 267 | brcmf_dbg(ERROR, "error reading addr 0x%04x size %d\n", addr, size); | ||
| 268 | return 0xFFFFFFFF; | ||
| 269 | } | 259 | } |
| 270 | 260 | ||
| 271 | u32 brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size, | 261 | u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) |
| 272 | u32 data) | ||
| 273 | { | 262 | { |
| 274 | int status; | 263 | u32 data; |
| 275 | uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; | 264 | int retval; |
| 276 | int err = 0; | ||
| 277 | 265 | ||
| 278 | brcmf_dbg(INFO, "fun = 1, addr = 0x%x, uint%ddata = 0x%x\n", | 266 | brcmf_dbg(INFO, "addr:0x%08x\n", addr); |
| 279 | addr, size * 8, data); | 267 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false); |
| 268 | brcmf_dbg(INFO, "data:0x%08x\n", data); | ||
| 280 | 269 | ||
| 281 | if (bar0 != sdiodev->sbwad) { | 270 | if (ret) |
| 282 | err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); | 271 | *ret = retval; |
| 283 | if (err) | ||
| 284 | return err; | ||
| 285 | 272 | ||
| 286 | sdiodev->sbwad = bar0; | 273 | return data; |
| 287 | } | 274 | } |
| 288 | 275 | ||
| 289 | addr &= SBSDIO_SB_OFT_ADDR_MASK; | 276 | void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, |
| 290 | if (size == 4) | 277 | u8 data, int *ret) |
| 291 | addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; | 278 | { |
| 292 | status = | 279 | int retval; |
| 293 | brcmf_sdioh_request_word(sdiodev, SDIOH_WRITE, SDIO_FUNC_1, | ||
| 294 | addr, &data, size); | ||
| 295 | sdiodev->regfail = (status != 0); | ||
| 296 | 280 | ||
| 297 | if (status == 0) | 281 | brcmf_dbg(INFO, "addr:0x%08x, data:0x%02x\n", addr, data); |
| 298 | return 0; | 282 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true); |
| 299 | 283 | ||
| 300 | brcmf_dbg(ERROR, "error writing 0x%08x to addr 0x%04x size %d\n", | 284 | if (ret) |
| 301 | data, addr, size); | 285 | *ret = retval; |
| 302 | return 0xFFFFFFFF; | ||
| 303 | } | 286 | } |
| 304 | 287 | ||
| 305 | bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev) | 288 | void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, |
| 289 | u32 data, int *ret) | ||
| 306 | { | 290 | { |
| 307 | return sdiodev->regfail; | 291 | int retval; |
| 292 | |||
| 293 | brcmf_dbg(INFO, "addr:0x%08x, data:0x%08x\n", addr, data); | ||
| 294 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true); | ||
| 295 | |||
| 296 | if (ret) | ||
| 297 | *ret = retval; | ||
| 308 | } | 298 | } |
| 309 | 299 | ||
| 310 | static int brcmf_sdcard_recv_prepare(struct brcmf_sdio_dev *sdiodev, uint fn, | 300 | static int brcmf_sdcard_recv_prepare(struct brcmf_sdio_dev *sdiodev, uint fn, |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index dd07d33a927..82f51dbd0d6 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | |||
| @@ -346,43 +346,17 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, | |||
| 346 | return status; | 346 | return status; |
| 347 | } | 347 | } |
| 348 | 348 | ||
| 349 | /* Read client card reg */ | ||
| 350 | static int | ||
| 351 | brcmf_sdioh_card_regread(struct brcmf_sdio_dev *sdiodev, int func, u32 regaddr, | ||
| 352 | int regsize, u32 *data) | ||
| 353 | { | ||
| 354 | |||
| 355 | if ((func == 0) || (regsize == 1)) { | ||
| 356 | u8 temp = 0; | ||
| 357 | |||
| 358 | brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, func, regaddr, | ||
| 359 | &temp); | ||
| 360 | *data = temp; | ||
| 361 | *data &= 0xff; | ||
| 362 | brcmf_dbg(DATA, "byte read data=0x%02x\n", *data); | ||
| 363 | } else { | ||
| 364 | brcmf_sdioh_request_word(sdiodev, SDIOH_READ, func, regaddr, | ||
| 365 | data, regsize); | ||
| 366 | if (regsize == 2) | ||
| 367 | *data &= 0xffff; | ||
| 368 | |||
| 369 | brcmf_dbg(DATA, "word read data=0x%08x\n", *data); | ||
| 370 | } | ||
| 371 | |||
| 372 | return SUCCESS; | ||
| 373 | } | ||
| 374 | |||
| 375 | static int brcmf_sdioh_get_cisaddr(struct brcmf_sdio_dev *sdiodev, u32 regaddr) | 349 | static int brcmf_sdioh_get_cisaddr(struct brcmf_sdio_dev *sdiodev, u32 regaddr) |
| 376 | { | 350 | { |
| 377 | /* read 24 bits and return valid 17 bit addr */ | 351 | /* read 24 bits and return valid 17 bit addr */ |
| 378 | int i; | 352 | int i, ret; |
| 379 | u32 scratch, regdata; | 353 | u32 scratch, regdata; |
| 380 | __le32 scratch_le; | 354 | __le32 scratch_le; |
| 381 | u8 *ptr = (u8 *)&scratch_le; | 355 | u8 *ptr = (u8 *)&scratch_le; |
| 382 | 356 | ||
| 383 | for (i = 0; i < 3; i++) { | 357 | for (i = 0; i < 3; i++) { |
| 384 | if ((brcmf_sdioh_card_regread(sdiodev, 0, regaddr, 1, | 358 | regdata = brcmf_sdio_regrl(sdiodev, regaddr, &ret); |
| 385 | ®data)) != SUCCESS) | 359 | if (ret != 0) |
| 386 | brcmf_dbg(ERROR, "Can't read!\n"); | 360 | brcmf_dbg(ERROR, "Can't read!\n"); |
| 387 | 361 | ||
| 388 | *ptr++ = (u8) regdata; | 362 | *ptr++ = (u8) regdata; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 149ee67beb2..1dbf2be478c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
| @@ -629,43 +629,29 @@ static bool data_ok(struct brcmf_sdio *bus) | |||
| 629 | * Reads a register in the SDIO hardware block. This block occupies a series of | 629 | * Reads a register in the SDIO hardware block. This block occupies a series of |
| 630 | * adresses on the 32 bit backplane bus. | 630 | * adresses on the 32 bit backplane bus. |
| 631 | */ | 631 | */ |
| 632 | static void | 632 | static int |
| 633 | r_sdreg32(struct brcmf_sdio *bus, u32 *regvar, u32 reg_offset, u32 *retryvar) | 633 | r_sdreg32(struct brcmf_sdio *bus, u32 *regvar, u32 offset) |
| 634 | { | 634 | { |
| 635 | u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); | 635 | u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); |
| 636 | *retryvar = 0; | 636 | int ret; |
| 637 | do { | 637 | |
| 638 | *regvar = brcmf_sdcard_reg_read(bus->sdiodev, | 638 | *regvar = brcmf_sdio_regrl(bus->sdiodev, |
| 639 | bus->ci->c_inf[idx].base + reg_offset, | 639 | bus->ci->c_inf[idx].base + offset, &ret); |
| 640 | sizeof(u32)); | 640 | |
| 641 | } while (brcmf_sdcard_regfail(bus->sdiodev) && | 641 | return ret; |
| 642 | (++(*retryvar) <= retry_limit)); | ||
| 643 | if (*retryvar) { | ||
| 644 | bus->regfails += (*retryvar-1); | ||
| 645 | if (*retryvar > retry_limit) { | ||
| 646 | brcmf_dbg(ERROR, "FAILED READ %Xh\n", reg_offset); | ||
| 647 | *regvar = 0; | ||
| 648 | } | ||
| 649 | } | ||
| 650 | } | 642 | } |
| 651 | 643 | ||
| 652 | static void | 644 | static int |
| 653 | w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset, u32 *retryvar) | 645 | w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset) |
| 654 | { | 646 | { |
| 655 | u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); | 647 | u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); |
| 656 | *retryvar = 0; | 648 | int ret; |
| 657 | do { | 649 | |
| 658 | brcmf_sdcard_reg_write(bus->sdiodev, | 650 | brcmf_sdio_regwl(bus->sdiodev, |
| 659 | bus->ci->c_inf[idx].base + reg_offset, | 651 | bus->ci->c_inf[idx].base + reg_offset, |
| 660 | sizeof(u32), regval); | 652 | regval, &ret); |
| 661 | } while (brcmf_sdcard_regfail(bus->sdiodev) && | 653 | |
| 662 | (++(*retryvar) <= retry_limit)); | 654 | return ret; |
| 663 | if (*retryvar) { | ||
| 664 | bus->regfails += (*retryvar-1); | ||
| 665 | if (*retryvar > retry_limit) | ||
| 666 | brcmf_dbg(ERROR, "FAILED REGISTER WRITE %Xh\n", | ||
| 667 | reg_offset); | ||
| 668 | } | ||
| 669 | } | 655 | } |
| 670 | 656 | ||
| 671 | #define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND) | 657 | #define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND) |
| @@ -697,16 +683,16 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | |||
| 697 | clkreq = | 683 | clkreq = |
| 698 | bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ; | 684 | bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ; |
| 699 | 685 | ||
| 700 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 686 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, |
| 701 | SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err); | 687 | clkreq, &err); |
| 702 | if (err) { | 688 | if (err) { |
| 703 | brcmf_dbg(ERROR, "HT Avail request error: %d\n", err); | 689 | brcmf_dbg(ERROR, "HT Avail request error: %d\n", err); |
| 704 | return -EBADE; | 690 | return -EBADE; |
| 705 | } | 691 | } |
| 706 | 692 | ||
| 707 | /* Check current status */ | 693 | /* Check current status */ |
| 708 | clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, | 694 | clkctl = brcmf_sdio_regrb(bus->sdiodev, |
| 709 | SBSDIO_FUNC1_CHIPCLKCSR, &err); | 695 | SBSDIO_FUNC1_CHIPCLKCSR, &err); |
| 710 | if (err) { | 696 | if (err) { |
| 711 | brcmf_dbg(ERROR, "HT Avail read error: %d\n", err); | 697 | brcmf_dbg(ERROR, "HT Avail read error: %d\n", err); |
| 712 | return -EBADE; | 698 | return -EBADE; |
| @@ -715,9 +701,8 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | |||
| 715 | /* Go to pending and await interrupt if appropriate */ | 701 | /* Go to pending and await interrupt if appropriate */ |
| 716 | if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) { | 702 | if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) { |
| 717 | /* Allow only clock-available interrupt */ | 703 | /* Allow only clock-available interrupt */ |
| 718 | devctl = brcmf_sdcard_cfg_read(bus->sdiodev, | 704 | devctl = brcmf_sdio_regrb(bus->sdiodev, |
| 719 | SDIO_FUNC_1, | 705 | SBSDIO_DEVICE_CTL, &err); |
| 720 | SBSDIO_DEVICE_CTL, &err); | ||
| 721 | if (err) { | 706 | if (err) { |
| 722 | brcmf_dbg(ERROR, "Devctl error setting CA: %d\n", | 707 | brcmf_dbg(ERROR, "Devctl error setting CA: %d\n", |
| 723 | err); | 708 | err); |
| @@ -725,30 +710,28 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | |||
| 725 | } | 710 | } |
| 726 | 711 | ||
| 727 | devctl |= SBSDIO_DEVCTL_CA_INT_ONLY; | 712 | devctl |= SBSDIO_DEVCTL_CA_INT_ONLY; |
| 728 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 713 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, |
| 729 | SBSDIO_DEVICE_CTL, devctl, &err); | 714 | devctl, &err); |
| 730 | brcmf_dbg(INFO, "CLKCTL: set PENDING\n"); | 715 | brcmf_dbg(INFO, "CLKCTL: set PENDING\n"); |
| 731 | bus->clkstate = CLK_PENDING; | 716 | bus->clkstate = CLK_PENDING; |
| 732 | 717 | ||
| 733 | return 0; | 718 | return 0; |
| 734 | } else if (bus->clkstate == CLK_PENDING) { | 719 | } else if (bus->clkstate == CLK_PENDING) { |
| 735 | /* Cancel CA-only interrupt filter */ | 720 | /* Cancel CA-only interrupt filter */ |
| 736 | devctl = | 721 | devctl = brcmf_sdio_regrb(bus->sdiodev, |
| 737 | brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, | ||
| 738 | SBSDIO_DEVICE_CTL, &err); | 722 | SBSDIO_DEVICE_CTL, &err); |
| 739 | devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; | 723 | devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; |
| 740 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 724 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, |
| 741 | SBSDIO_DEVICE_CTL, devctl, &err); | 725 | devctl, &err); |
| 742 | } | 726 | } |
| 743 | 727 | ||
| 744 | /* Otherwise, wait here (polling) for HT Avail */ | 728 | /* Otherwise, wait here (polling) for HT Avail */ |
| 745 | timeout = jiffies + | 729 | timeout = jiffies + |
| 746 | msecs_to_jiffies(PMU_MAX_TRANSITION_DLY/1000); | 730 | msecs_to_jiffies(PMU_MAX_TRANSITION_DLY/1000); |
| 747 | while (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { | 731 | while (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { |
| 748 | clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, | 732 | clkctl = brcmf_sdio_regrb(bus->sdiodev, |
| 749 | SDIO_FUNC_1, | 733 | SBSDIO_FUNC1_CHIPCLKCSR, |
| 750 | SBSDIO_FUNC1_CHIPCLKCSR, | 734 | &err); |
| 751 | &err); | ||
| 752 | if (time_after(jiffies, timeout)) | 735 | if (time_after(jiffies, timeout)) |
| 753 | break; | 736 | break; |
| 754 | else | 737 | else |
| @@ -781,17 +764,16 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | |||
| 781 | 764 | ||
| 782 | if (bus->clkstate == CLK_PENDING) { | 765 | if (bus->clkstate == CLK_PENDING) { |
| 783 | /* Cancel CA-only interrupt filter */ | 766 | /* Cancel CA-only interrupt filter */ |
| 784 | devctl = brcmf_sdcard_cfg_read(bus->sdiodev, | 767 | devctl = brcmf_sdio_regrb(bus->sdiodev, |
| 785 | SDIO_FUNC_1, | 768 | SBSDIO_DEVICE_CTL, &err); |
| 786 | SBSDIO_DEVICE_CTL, &err); | ||
| 787 | devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; | 769 | devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; |
| 788 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 770 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, |
| 789 | SBSDIO_DEVICE_CTL, devctl, &err); | 771 | devctl, &err); |
| 790 | } | 772 | } |
| 791 | 773 | ||
| 792 | bus->clkstate = CLK_SDONLY; | 774 | bus->clkstate = CLK_SDONLY; |
| 793 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 775 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, |
| 794 | SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err); | 776 | clkreq, &err); |
| 795 | brcmf_dbg(INFO, "CLKCTL: turned OFF\n"); | 777 | brcmf_dbg(INFO, "CLKCTL: turned OFF\n"); |
| 796 | if (err) { | 778 | if (err) { |
| 797 | brcmf_dbg(ERROR, "Failed access turning clock off: %d\n", | 779 | brcmf_dbg(ERROR, "Failed access turning clock off: %d\n", |
| @@ -874,7 +856,7 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok) | |||
| 874 | 856 | ||
| 875 | static int brcmf_sdbrcm_bussleep(struct brcmf_sdio *bus, bool sleep) | 857 | static int brcmf_sdbrcm_bussleep(struct brcmf_sdio *bus, bool sleep) |
| 876 | { | 858 | { |
| 877 | uint retries = 0; | 859 | int ret; |
| 878 | 860 | ||
| 879 | brcmf_dbg(INFO, "request %s (currently %s)\n", | 861 | brcmf_dbg(INFO, "request %s (currently %s)\n", |
| 880 | sleep ? "SLEEP" : "WAKE", | 862 | sleep ? "SLEEP" : "WAKE", |
| @@ -894,22 +876,20 @@ static int brcmf_sdbrcm_bussleep(struct brcmf_sdio *bus, bool sleep) | |||
| 894 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | 876 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); |
| 895 | 877 | ||
| 896 | /* Tell device to start using OOB wakeup */ | 878 | /* Tell device to start using OOB wakeup */ |
| 897 | w_sdreg32(bus, SMB_USE_OOB, | 879 | ret = w_sdreg32(bus, SMB_USE_OOB, |
| 898 | offsetof(struct sdpcmd_regs, tosbmailbox), &retries); | 880 | offsetof(struct sdpcmd_regs, tosbmailbox)); |
| 899 | if (retries > retry_limit) | 881 | if (ret != 0) |
| 900 | brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"); | 882 | brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"); |
| 901 | 883 | ||
| 902 | /* Turn off our contribution to the HT clock request */ | 884 | /* Turn off our contribution to the HT clock request */ |
| 903 | brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); | 885 | brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); |
| 904 | 886 | ||
| 905 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 887 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, |
| 906 | SBSDIO_FUNC1_CHIPCLKCSR, | 888 | SBSDIO_FORCE_HW_CLKREQ_OFF, NULL); |
| 907 | SBSDIO_FORCE_HW_CLKREQ_OFF, NULL); | ||
| 908 | 889 | ||
| 909 | /* Isolate the bus */ | 890 | /* Isolate the bus */ |
| 910 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 891 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, |
| 911 | SBSDIO_DEVICE_CTL, | 892 | SBSDIO_DEVCTL_PADS_ISO, NULL); |
| 912 | SBSDIO_DEVCTL_PADS_ISO, NULL); | ||
| 913 | 893 | ||
| 914 | /* Change state */ | 894 | /* Change state */ |
| 915 | bus->sleeping = true; | 895 | bus->sleeping = true; |
| @@ -917,21 +897,20 @@ static int brcmf_sdbrcm_bussleep(struct brcmf_sdio *bus, bool sleep) | |||
| 917 | } else { | 897 | } else { |
| 918 | /* Waking up: bus power up is ok, set local state */ | 898 | /* Waking up: bus power up is ok, set local state */ |
| 919 | 899 | ||
| 920 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 900 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, |
| 921 | SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); | 901 | 0, NULL); |
| 922 | 902 | ||
| 923 | /* Make sure the controller has the bus up */ | 903 | /* Make sure the controller has the bus up */ |
| 924 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | 904 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); |
| 925 | 905 | ||
| 926 | /* Send misc interrupt to indicate OOB not needed */ | 906 | /* Send misc interrupt to indicate OOB not needed */ |
| 927 | w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, tosbmailboxdata), | 907 | ret = w_sdreg32(bus, 0, |
| 928 | &retries); | 908 | offsetof(struct sdpcmd_regs, tosbmailboxdata)); |
| 929 | if (retries <= retry_limit) | 909 | if (ret == 0) |
| 930 | w_sdreg32(bus, SMB_DEV_INT, | 910 | ret = w_sdreg32(bus, SMB_DEV_INT, |
| 931 | offsetof(struct sdpcmd_regs, tosbmailbox), | 911 | offsetof(struct sdpcmd_regs, tosbmailbox)); |
| 932 | &retries); | 912 | |
| 933 | 913 | if (ret != 0) | |
| 934 | if (retries > retry_limit) | ||
| 935 | brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"); | 914 | brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"); |
| 936 | 915 | ||
| 937 | /* Make sure we have SD bus access */ | 916 | /* Make sure we have SD bus access */ |
| @@ -955,17 +934,17 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus) | |||
| 955 | u32 intstatus = 0; | 934 | u32 intstatus = 0; |
| 956 | u32 hmb_data; | 935 | u32 hmb_data; |
| 957 | u8 fcbits; | 936 | u8 fcbits; |
| 958 | uint retries = 0; | 937 | int ret; |
| 959 | 938 | ||
| 960 | brcmf_dbg(TRACE, "Enter\n"); | 939 | brcmf_dbg(TRACE, "Enter\n"); |
| 961 | 940 | ||
| 962 | /* Read mailbox data and ack that we did so */ | 941 | /* Read mailbox data and ack that we did so */ |
| 963 | r_sdreg32(bus, &hmb_data, | 942 | ret = r_sdreg32(bus, &hmb_data, |
| 964 | offsetof(struct sdpcmd_regs, tohostmailboxdata), &retries); | 943 | offsetof(struct sdpcmd_regs, tohostmailboxdata)); |
| 965 | 944 | ||
| 966 | if (retries <= retry_limit) | 945 | if (ret == 0) |
| 967 | w_sdreg32(bus, SMB_INT_ACK, | 946 | w_sdreg32(bus, SMB_INT_ACK, |
| 968 | offsetof(struct sdpcmd_regs, tosbmailbox), &retries); | 947 | offsetof(struct sdpcmd_regs, tosbmailbox)); |
| 969 | bus->f1regdata += 2; | 948 | bus->f1regdata += 2; |
| 970 | 949 | ||
| 971 | /* Dongle recomposed rx frames, accept them again */ | 950 | /* Dongle recomposed rx frames, accept them again */ |
| @@ -1040,17 +1019,16 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) | |||
| 1040 | if (abort) | 1019 | if (abort) |
| 1041 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); | 1020 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); |
| 1042 | 1021 | ||
| 1043 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 1022 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, |
| 1044 | SBSDIO_FUNC1_FRAMECTRL, | 1023 | SFC_RF_TERM, &err); |
| 1045 | SFC_RF_TERM, &err); | ||
| 1046 | bus->f1regdata++; | 1024 | bus->f1regdata++; |
| 1047 | 1025 | ||
| 1048 | /* Wait until the packet has been flushed (device/FIFO stable) */ | 1026 | /* Wait until the packet has been flushed (device/FIFO stable) */ |
| 1049 | for (lastrbc = retries = 0xffff; retries > 0; retries--) { | 1027 | for (lastrbc = retries = 0xffff; retries > 0; retries--) { |
| 1050 | hi = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, | 1028 | hi = brcmf_sdio_regrb(bus->sdiodev, |
| 1051 | SBSDIO_FUNC1_RFRAMEBCHI, NULL); | 1029 | SBSDIO_FUNC1_RFRAMEBCHI, &err); |
| 1052 | lo = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, | 1030 | lo = brcmf_sdio_regrb(bus->sdiodev, |
| 1053 | SBSDIO_FUNC1_RFRAMEBCLO, NULL); | 1031 | SBSDIO_FUNC1_RFRAMEBCLO, &err); |
| 1054 | bus->f1regdata += 2; | 1032 | bus->f1regdata += 2; |
| 1055 | 1033 | ||
| 1056 | if ((hi == 0) && (lo == 0)) | 1034 | if ((hi == 0) && (lo == 0)) |
| @@ -1070,11 +1048,11 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) | |||
| 1070 | 1048 | ||
| 1071 | if (rtx) { | 1049 | if (rtx) { |
| 1072 | bus->rxrtx++; | 1050 | bus->rxrtx++; |
| 1073 | w_sdreg32(bus, SMB_NAK, | 1051 | err = w_sdreg32(bus, SMB_NAK, |
| 1074 | offsetof(struct sdpcmd_regs, tosbmailbox), &retries); | 1052 | offsetof(struct sdpcmd_regs, tosbmailbox)); |
| 1075 | 1053 | ||
| 1076 | bus->f1regdata++; | 1054 | bus->f1regdata++; |
| 1077 | if (retries <= retry_limit) | 1055 | if (err == 0) |
| 1078 | bus->rxskip = true; | 1056 | bus->rxskip = true; |
| 1079 | } | 1057 | } |
| 1080 | 1058 | ||
| @@ -1082,7 +1060,7 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) | |||
| 1082 | bus->nextlen = 0; | 1060 | bus->nextlen = 0; |
| 1083 | 1061 | ||
| 1084 | /* If we can't reach the device, signal failure */ | 1062 | /* If we can't reach the device, signal failure */ |
| 1085 | if (err || brcmf_sdcard_regfail(bus->sdiodev)) | 1063 | if (err) |
| 1086 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 1064 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
| 1087 | } | 1065 | } |
| 1088 | 1066 | ||
| @@ -2178,21 +2156,16 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, | |||
| 2178 | bus->tx_sderrs++; | 2156 | bus->tx_sderrs++; |
| 2179 | 2157 | ||
| 2180 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); | 2158 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); |
| 2181 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 2159 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, |
| 2182 | SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, | 2160 | SFC_WF_TERM, NULL); |
| 2183 | NULL); | ||
| 2184 | bus->f1regdata++; | 2161 | bus->f1regdata++; |
| 2185 | 2162 | ||
| 2186 | for (i = 0; i < 3; i++) { | 2163 | for (i = 0; i < 3; i++) { |
| 2187 | u8 hi, lo; | 2164 | u8 hi, lo; |
| 2188 | hi = brcmf_sdcard_cfg_read(bus->sdiodev, | 2165 | hi = brcmf_sdio_regrb(bus->sdiodev, |
| 2189 | SDIO_FUNC_1, | 2166 | SBSDIO_FUNC1_WFRAMEBCHI, NULL); |
| 2190 | SBSDIO_FUNC1_WFRAMEBCHI, | 2167 | lo = brcmf_sdio_regrb(bus->sdiodev, |
| 2191 | NULL); | 2168 | SBSDIO_FUNC1_WFRAMEBCLO, NULL); |
| 2192 | lo = brcmf_sdcard_cfg_read(bus->sdiodev, | ||
| 2193 | SDIO_FUNC_1, | ||
| 2194 | SBSDIO_FUNC1_WFRAMEBCLO, | ||
| 2195 | NULL); | ||
| 2196 | bus->f1regdata += 2; | 2169 | bus->f1regdata += 2; |
| 2197 | if ((hi == 0) && (lo == 0)) | 2170 | if ((hi == 0) && (lo == 0)) |
| 2198 | break; | 2171 | break; |
| @@ -2219,7 +2192,6 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes) | |||
| 2219 | { | 2192 | { |
| 2220 | struct sk_buff *pkt; | 2193 | struct sk_buff *pkt; |
| 2221 | u32 intstatus = 0; | 2194 | u32 intstatus = 0; |
| 2222 | uint retries = 0; | ||
| 2223 | int ret = 0, prec_out; | 2195 | int ret = 0, prec_out; |
| 2224 | uint cnt = 0; | 2196 | uint cnt = 0; |
| 2225 | uint datalen; | 2197 | uint datalen; |
| @@ -2249,11 +2221,11 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes) | |||
| 2249 | /* In poll mode, need to check for other events */ | 2221 | /* In poll mode, need to check for other events */ |
| 2250 | if (!bus->intr && cnt) { | 2222 | if (!bus->intr && cnt) { |
| 2251 | /* Check device status, signal pending interrupt */ | 2223 | /* Check device status, signal pending interrupt */ |
| 2252 | r_sdreg32(bus, &intstatus, | 2224 | ret = r_sdreg32(bus, &intstatus, |
| 2253 | offsetof(struct sdpcmd_regs, intstatus), | 2225 | offsetof(struct sdpcmd_regs, |
| 2254 | &retries); | 2226 | intstatus)); |
| 2255 | bus->f2txdata++; | 2227 | bus->f2txdata++; |
| 2256 | if (brcmf_sdcard_regfail(bus->sdiodev)) | 2228 | if (ret != 0) |
| 2257 | break; | 2229 | break; |
| 2258 | if (intstatus & bus->hostintmask) | 2230 | if (intstatus & bus->hostintmask) |
| 2259 | bus->ipend = true; | 2231 | bus->ipend = true; |
| @@ -2275,7 +2247,6 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev) | |||
| 2275 | { | 2247 | { |
| 2276 | u32 local_hostintmask; | 2248 | u32 local_hostintmask; |
| 2277 | u8 saveclk; | 2249 | u8 saveclk; |
| 2278 | uint retries; | ||
| 2279 | int err; | 2250 | int err; |
| 2280 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 2251 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
| 2281 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 2252 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
| @@ -2303,7 +2274,7 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev) | |||
| 2303 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | 2274 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); |
| 2304 | 2275 | ||
| 2305 | /* Disable and clear interrupts at the chip level also */ | 2276 | /* Disable and clear interrupts at the chip level also */ |
| 2306 | w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask), &retries); | 2277 | w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask)); |
| 2307 | local_hostintmask = bus->hostintmask; | 2278 | local_hostintmask = bus->hostintmask; |
| 2308 | bus->hostintmask = 0; | 2279 | bus->hostintmask = 0; |
| 2309 | 2280 | ||
| @@ -2311,24 +2282,23 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev) | |||
| 2311 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 2282 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
| 2312 | 2283 | ||
| 2313 | /* Force clocks on backplane to be sure F2 interrupt propagates */ | 2284 | /* Force clocks on backplane to be sure F2 interrupt propagates */ |
| 2314 | saveclk = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, | 2285 | saveclk = brcmf_sdio_regrb(bus->sdiodev, |
| 2315 | SBSDIO_FUNC1_CHIPCLKCSR, &err); | 2286 | SBSDIO_FUNC1_CHIPCLKCSR, &err); |
| 2316 | if (!err) { | 2287 | if (!err) { |
| 2317 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 2288 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, |
| 2318 | SBSDIO_FUNC1_CHIPCLKCSR, | 2289 | (saveclk | SBSDIO_FORCE_HT), &err); |
| 2319 | (saveclk | SBSDIO_FORCE_HT), &err); | ||
| 2320 | } | 2290 | } |
| 2321 | if (err) | 2291 | if (err) |
| 2322 | brcmf_dbg(ERROR, "Failed to force clock for F2: err %d\n", err); | 2292 | brcmf_dbg(ERROR, "Failed to force clock for F2: err %d\n", err); |
| 2323 | 2293 | ||
| 2324 | /* Turn off the bus (F2), free any pending packets */ | 2294 | /* Turn off the bus (F2), free any pending packets */ |
| 2325 | brcmf_dbg(INTR, "disable SDIO interrupts\n"); | 2295 | brcmf_dbg(INTR, "disable SDIO interrupts\n"); |
| 2326 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx, | 2296 | brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx, SDIO_FUNC_ENABLE_1, |
| 2327 | SDIO_FUNC_ENABLE_1, NULL); | 2297 | NULL); |
| 2328 | 2298 | ||
| 2329 | /* Clear any pending interrupts now that F2 is disabled */ | 2299 | /* Clear any pending interrupts now that F2 is disabled */ |
| 2330 | w_sdreg32(bus, local_hostintmask, | 2300 | w_sdreg32(bus, local_hostintmask, |
| 2331 | offsetof(struct sdpcmd_regs, intstatus), &retries); | 2301 | offsetof(struct sdpcmd_regs, intstatus)); |
| 2332 | 2302 | ||
| 2333 | /* Turn off the backplane clock (only) */ | 2303 | /* Turn off the backplane clock (only) */ |
| 2334 | brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); | 2304 | brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); |
| @@ -2373,12 +2343,12 @@ static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus) | |||
| 2373 | static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | 2343 | static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) |
| 2374 | { | 2344 | { |
| 2375 | u32 intstatus, newstatus = 0; | 2345 | u32 intstatus, newstatus = 0; |
| 2376 | uint retries = 0; | ||
| 2377 | uint rxlimit = bus->rxbound; /* Rx frames to read before resched */ | 2346 | uint rxlimit = bus->rxbound; /* Rx frames to read before resched */ |
| 2378 | uint txlimit = bus->txbound; /* Tx frames to send before resched */ | 2347 | uint txlimit = bus->txbound; /* Tx frames to send before resched */ |
| 2379 | uint framecnt = 0; /* Temporary counter of tx/rx frames */ | 2348 | uint framecnt = 0; /* Temporary counter of tx/rx frames */ |
| 2380 | bool rxdone = true; /* Flag for no more read data */ | 2349 | bool rxdone = true; /* Flag for no more read data */ |
| 2381 | bool resched = false; /* Flag indicating resched wanted */ | 2350 | bool resched = false; /* Flag indicating resched wanted */ |
| 2351 | int err; | ||
| 2382 | 2352 | ||
| 2383 | brcmf_dbg(TRACE, "Enter\n"); | 2353 | brcmf_dbg(TRACE, "Enter\n"); |
| 2384 | 2354 | ||
| @@ -2389,13 +2359,12 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
| 2389 | 2359 | ||
| 2390 | /* If waiting for HTAVAIL, check status */ | 2360 | /* If waiting for HTAVAIL, check status */ |
| 2391 | if (bus->clkstate == CLK_PENDING) { | 2361 | if (bus->clkstate == CLK_PENDING) { |
| 2392 | int err; | ||
| 2393 | u8 clkctl, devctl = 0; | 2362 | u8 clkctl, devctl = 0; |
| 2394 | 2363 | ||
| 2395 | #ifdef DEBUG | 2364 | #ifdef DEBUG |
| 2396 | /* Check for inconsistent device control */ | 2365 | /* Check for inconsistent device control */ |
| 2397 | devctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, | 2366 | devctl = brcmf_sdio_regrb(bus->sdiodev, |
| 2398 | SBSDIO_DEVICE_CTL, &err); | 2367 | SBSDIO_DEVICE_CTL, &err); |
| 2399 | if (err) { | 2368 | if (err) { |
| 2400 | brcmf_dbg(ERROR, "error reading DEVCTL: %d\n", err); | 2369 | brcmf_dbg(ERROR, "error reading DEVCTL: %d\n", err); |
| 2401 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 2370 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
| @@ -2403,8 +2372,8 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
| 2403 | #endif /* DEBUG */ | 2372 | #endif /* DEBUG */ |
| 2404 | 2373 | ||
| 2405 | /* Read CSR, if clock on switch to AVAIL, else ignore */ | 2374 | /* Read CSR, if clock on switch to AVAIL, else ignore */ |
| 2406 | clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, | 2375 | clkctl = brcmf_sdio_regrb(bus->sdiodev, |
| 2407 | SBSDIO_FUNC1_CHIPCLKCSR, &err); | 2376 | SBSDIO_FUNC1_CHIPCLKCSR, &err); |
| 2408 | if (err) { | 2377 | if (err) { |
| 2409 | brcmf_dbg(ERROR, "error reading CSR: %d\n", | 2378 | brcmf_dbg(ERROR, "error reading CSR: %d\n", |
| 2410 | err); | 2379 | err); |
| @@ -2415,17 +2384,16 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
| 2415 | devctl, clkctl); | 2384 | devctl, clkctl); |
| 2416 | 2385 | ||
| 2417 | if (SBSDIO_HTAV(clkctl)) { | 2386 | if (SBSDIO_HTAV(clkctl)) { |
| 2418 | devctl = brcmf_sdcard_cfg_read(bus->sdiodev, | 2387 | devctl = brcmf_sdio_regrb(bus->sdiodev, |
| 2419 | SDIO_FUNC_1, | 2388 | SBSDIO_DEVICE_CTL, &err); |
| 2420 | SBSDIO_DEVICE_CTL, &err); | ||
| 2421 | if (err) { | 2389 | if (err) { |
| 2422 | brcmf_dbg(ERROR, "error reading DEVCTL: %d\n", | 2390 | brcmf_dbg(ERROR, "error reading DEVCTL: %d\n", |
| 2423 | err); | 2391 | err); |
| 2424 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 2392 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
| 2425 | } | 2393 | } |
| 2426 | devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; | 2394 | devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; |
| 2427 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 2395 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, |
| 2428 | SBSDIO_DEVICE_CTL, devctl, &err); | 2396 | devctl, &err); |
| 2429 | if (err) { | 2397 | if (err) { |
| 2430 | brcmf_dbg(ERROR, "error writing DEVCTL: %d\n", | 2398 | brcmf_dbg(ERROR, "error writing DEVCTL: %d\n", |
| 2431 | err); | 2399 | err); |
| @@ -2447,17 +2415,17 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
| 2447 | /* Pending interrupt indicates new device status */ | 2415 | /* Pending interrupt indicates new device status */ |
| 2448 | if (bus->ipend) { | 2416 | if (bus->ipend) { |
| 2449 | bus->ipend = false; | 2417 | bus->ipend = false; |
| 2450 | r_sdreg32(bus, &newstatus, | 2418 | err = r_sdreg32(bus, &newstatus, |
| 2451 | offsetof(struct sdpcmd_regs, intstatus), &retries); | 2419 | offsetof(struct sdpcmd_regs, intstatus)); |
| 2452 | bus->f1regdata++; | 2420 | bus->f1regdata++; |
| 2453 | if (brcmf_sdcard_regfail(bus->sdiodev)) | 2421 | if (err != 0) |
| 2454 | newstatus = 0; | 2422 | newstatus = 0; |
| 2455 | newstatus &= bus->hostintmask; | 2423 | newstatus &= bus->hostintmask; |
| 2456 | bus->fcstate = !!(newstatus & I_HMB_FC_STATE); | 2424 | bus->fcstate = !!(newstatus & I_HMB_FC_STATE); |
| 2457 | if (newstatus) { | 2425 | if (newstatus) { |
| 2458 | w_sdreg32(bus, newstatus, | 2426 | err = w_sdreg32(bus, newstatus, |
| 2459 | offsetof(struct sdpcmd_regs, intstatus), | 2427 | offsetof(struct sdpcmd_regs, |
| 2460 | &retries); | 2428 | intstatus)); |
| 2461 | bus->f1regdata++; | 2429 | bus->f1regdata++; |
| 2462 | } | 2430 | } |
| 2463 | } | 2431 | } |
| @@ -2472,11 +2440,11 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
| 2472 | */ | 2440 | */ |
| 2473 | if (intstatus & I_HMB_FC_CHANGE) { | 2441 | if (intstatus & I_HMB_FC_CHANGE) { |
| 2474 | intstatus &= ~I_HMB_FC_CHANGE; | 2442 | intstatus &= ~I_HMB_FC_CHANGE; |
| 2475 | w_sdreg32(bus, I_HMB_FC_CHANGE, | 2443 | err = w_sdreg32(bus, I_HMB_FC_CHANGE, |
| 2476 | offsetof(struct sdpcmd_regs, intstatus), &retries); | 2444 | offsetof(struct sdpcmd_regs, intstatus)); |
| 2477 | 2445 | ||
| 2478 | r_sdreg32(bus, &newstatus, | 2446 | err = r_sdreg32(bus, &newstatus, |
| 2479 | offsetof(struct sdpcmd_regs, intstatus), &retries); | 2447 | offsetof(struct sdpcmd_regs, intstatus)); |
| 2480 | bus->f1regdata += 2; | 2448 | bus->f1regdata += 2; |
| 2481 | bus->fcstate = | 2449 | bus->fcstate = |
| 2482 | !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE)); | 2450 | !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE)); |
| @@ -2546,21 +2514,18 @@ clkwait: | |||
| 2546 | 2514 | ||
| 2547 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); | 2515 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); |
| 2548 | 2516 | ||
| 2549 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 2517 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, |
| 2550 | SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, | 2518 | SFC_WF_TERM, &err); |
| 2551 | NULL); | ||
| 2552 | bus->f1regdata++; | 2519 | bus->f1regdata++; |
| 2553 | 2520 | ||
| 2554 | for (i = 0; i < 3; i++) { | 2521 | for (i = 0; i < 3; i++) { |
| 2555 | u8 hi, lo; | 2522 | u8 hi, lo; |
| 2556 | hi = brcmf_sdcard_cfg_read(bus->sdiodev, | 2523 | hi = brcmf_sdio_regrb(bus->sdiodev, |
| 2557 | SDIO_FUNC_1, | 2524 | SBSDIO_FUNC1_WFRAMEBCHI, |
| 2558 | SBSDIO_FUNC1_WFRAMEBCHI, | 2525 | &err); |
| 2559 | NULL); | 2526 | lo = brcmf_sdio_regrb(bus->sdiodev, |
| 2560 | lo = brcmf_sdcard_cfg_read(bus->sdiodev, | 2527 | SBSDIO_FUNC1_WFRAMEBCLO, |
| 2561 | SDIO_FUNC_1, | 2528 | &err); |
| 2562 | SBSDIO_FUNC1_WFRAMEBCLO, | ||
| 2563 | NULL); | ||
| 2564 | bus->f1regdata += 2; | 2529 | bus->f1regdata += 2; |
| 2565 | if ((hi == 0) && (lo == 0)) | 2530 | if ((hi == 0) && (lo == 0)) |
| 2566 | break; | 2531 | break; |
| @@ -2587,10 +2552,8 @@ clkwait: | |||
| 2587 | else await next interrupt */ | 2552 | else await next interrupt */ |
| 2588 | /* On failed register access, all bets are off: | 2553 | /* On failed register access, all bets are off: |
| 2589 | no resched or interrupts */ | 2554 | no resched or interrupts */ |
| 2590 | if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) || | 2555 | if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) || (err != 0)) { |
| 2591 | brcmf_sdcard_regfail(bus->sdiodev)) { | 2556 | brcmf_dbg(ERROR, "failed backplane access over SDIO, halting operation\n"); |
| 2592 | brcmf_dbg(ERROR, "failed backplane access over SDIO, halting operation %d\n", | ||
| 2593 | brcmf_sdcard_regfail(bus->sdiodev)); | ||
| 2594 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 2557 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
| 2595 | bus->intstatus = 0; | 2558 | bus->intstatus = 0; |
| 2596 | } else if (bus->clkstate == CLK_PENDING) { | 2559 | } else if (bus->clkstate == CLK_PENDING) { |
| @@ -2886,19 +2849,16 @@ static int brcmf_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len) | |||
| 2886 | 2849 | ||
| 2887 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); | 2850 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); |
| 2888 | 2851 | ||
| 2889 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 2852 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, |
| 2890 | SBSDIO_FUNC1_FRAMECTRL, | 2853 | SFC_WF_TERM, NULL); |
| 2891 | SFC_WF_TERM, NULL); | ||
| 2892 | bus->f1regdata++; | 2854 | bus->f1regdata++; |
| 2893 | 2855 | ||
| 2894 | for (i = 0; i < 3; i++) { | 2856 | for (i = 0; i < 3; i++) { |
| 2895 | u8 hi, lo; | 2857 | u8 hi, lo; |
| 2896 | hi = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, | 2858 | hi = brcmf_sdio_regrb(bus->sdiodev, |
| 2897 | SBSDIO_FUNC1_WFRAMEBCHI, | 2859 | SBSDIO_FUNC1_WFRAMEBCHI, NULL); |
| 2898 | NULL); | 2860 | lo = brcmf_sdio_regrb(bus->sdiodev, |
| 2899 | lo = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, | 2861 | SBSDIO_FUNC1_WFRAMEBCLO, NULL); |
| 2900 | SBSDIO_FUNC1_WFRAMEBCLO, | ||
| 2901 | NULL); | ||
| 2902 | bus->f1regdata += 2; | 2862 | bus->f1regdata += 2; |
| 2903 | if (hi == 0 && lo == 0) | 2863 | if (hi == 0 && lo == 0) |
| 2904 | break; | 2864 | break; |
| @@ -3188,7 +3148,6 @@ static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus) | |||
| 3188 | 3148 | ||
| 3189 | static int brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter) | 3149 | static int brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter) |
| 3190 | { | 3150 | { |
| 3191 | uint retries; | ||
| 3192 | int bcmerror = 0; | 3151 | int bcmerror = 0; |
| 3193 | struct chip_info *ci = bus->ci; | 3152 | struct chip_info *ci = bus->ci; |
| 3194 | 3153 | ||
| @@ -3222,7 +3181,7 @@ static int brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter) | |||
| 3222 | } | 3181 | } |
| 3223 | 3182 | ||
| 3224 | w_sdreg32(bus, 0xFFFFFFFF, | 3183 | w_sdreg32(bus, 0xFFFFFFFF, |
| 3225 | offsetof(struct sdpcmd_regs, intstatus), &retries); | 3184 | offsetof(struct sdpcmd_regs, intstatus)); |
| 3226 | 3185 | ||
| 3227 | ci->resetcore(bus->sdiodev, ci, BCMA_CORE_ARM_CM3); | 3186 | ci->resetcore(bus->sdiodev, ci, BCMA_CORE_ARM_CM3); |
| 3228 | 3187 | ||
| @@ -3444,7 +3403,6 @@ static int brcmf_sdbrcm_bus_init(struct device *dev) | |||
| 3444 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 3403 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
| 3445 | struct brcmf_sdio *bus = sdiodev->bus; | 3404 | struct brcmf_sdio *bus = sdiodev->bus; |
| 3446 | unsigned long timeout; | 3405 | unsigned long timeout; |
| 3447 | uint retries = 0; | ||
| 3448 | u8 ready, enable; | 3406 | u8 ready, enable; |
| 3449 | int err, ret = 0; | 3407 | int err, ret = 0; |
| 3450 | u8 saveclk; | 3408 | u8 saveclk; |
| @@ -3472,13 +3430,11 @@ static int brcmf_sdbrcm_bus_init(struct device *dev) | |||
| 3472 | goto exit; | 3430 | goto exit; |
| 3473 | 3431 | ||
| 3474 | /* Force clocks on backplane to be sure F2 interrupt propagates */ | 3432 | /* Force clocks on backplane to be sure F2 interrupt propagates */ |
| 3475 | saveclk = | 3433 | saveclk = brcmf_sdio_regrb(bus->sdiodev, |
| 3476 | brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, | 3434 | SBSDIO_FUNC1_CHIPCLKCSR, &err); |
| 3477 | SBSDIO_FUNC1_CHIPCLKCSR, &err); | ||
| 3478 | if (!err) { | 3435 | if (!err) { |
| 3479 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 3436 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, |
| 3480 | SBSDIO_FUNC1_CHIPCLKCSR, | 3437 | (saveclk | SBSDIO_FORCE_HT), &err); |
| 3481 | (saveclk | SBSDIO_FORCE_HT), &err); | ||
| 3482 | } | 3438 | } |
| 3483 | if (err) { | 3439 | if (err) { |
| 3484 | brcmf_dbg(ERROR, "Failed to force clock for F2: err %d\n", err); | 3440 | brcmf_dbg(ERROR, "Failed to force clock for F2: err %d\n", err); |
| @@ -3487,17 +3443,16 @@ static int brcmf_sdbrcm_bus_init(struct device *dev) | |||
| 3487 | 3443 | ||
| 3488 | /* Enable function 2 (frame transfers) */ | 3444 | /* Enable function 2 (frame transfers) */ |
| 3489 | w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT, | 3445 | w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT, |
| 3490 | offsetof(struct sdpcmd_regs, tosbmailboxdata), &retries); | 3446 | offsetof(struct sdpcmd_regs, tosbmailboxdata)); |
| 3491 | enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2); | 3447 | enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2); |
| 3492 | 3448 | ||
| 3493 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx, | 3449 | brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx, enable, NULL); |
| 3494 | enable, NULL); | ||
| 3495 | 3450 | ||
| 3496 | timeout = jiffies + msecs_to_jiffies(BRCMF_WAIT_F2RDY); | 3451 | timeout = jiffies + msecs_to_jiffies(BRCMF_WAIT_F2RDY); |
| 3497 | ready = 0; | 3452 | ready = 0; |
| 3498 | while (enable != ready) { | 3453 | while (enable != ready) { |
| 3499 | ready = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_0, | 3454 | ready = brcmf_sdio_regrb(bus->sdiodev, |
| 3500 | SDIO_CCCR_IORx, NULL); | 3455 | SDIO_CCCR_IORx, NULL); |
| 3501 | if (time_after(jiffies, timeout)) | 3456 | if (time_after(jiffies, timeout)) |
| 3502 | break; | 3457 | break; |
| 3503 | else if (time_after(jiffies, timeout - BRCMF_WAIT_F2RDY + 50)) | 3458 | else if (time_after(jiffies, timeout - BRCMF_WAIT_F2RDY + 50)) |
| @@ -3512,21 +3467,18 @@ static int brcmf_sdbrcm_bus_init(struct device *dev) | |||
| 3512 | /* Set up the interrupt mask and enable interrupts */ | 3467 | /* Set up the interrupt mask and enable interrupts */ |
| 3513 | bus->hostintmask = HOSTINTMASK; | 3468 | bus->hostintmask = HOSTINTMASK; |
| 3514 | w_sdreg32(bus, bus->hostintmask, | 3469 | w_sdreg32(bus, bus->hostintmask, |
| 3515 | offsetof(struct sdpcmd_regs, hostintmask), &retries); | 3470 | offsetof(struct sdpcmd_regs, hostintmask)); |
| 3516 | 3471 | ||
| 3517 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 3472 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_WATERMARK, 8, &err); |
| 3518 | SBSDIO_WATERMARK, 8, &err); | ||
| 3519 | } else { | 3473 | } else { |
| 3520 | /* Disable F2 again */ | 3474 | /* Disable F2 again */ |
| 3521 | enable = SDIO_FUNC_ENABLE_1; | 3475 | enable = SDIO_FUNC_ENABLE_1; |
| 3522 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, | 3476 | brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx, enable, NULL); |
| 3523 | SDIO_CCCR_IOEx, enable, NULL); | ||
| 3524 | ret = -ENODEV; | 3477 | ret = -ENODEV; |
| 3525 | } | 3478 | } |
| 3526 | 3479 | ||
| 3527 | /* Restore previous clock setting */ | 3480 | /* Restore previous clock setting */ |
| 3528 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 3481 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err); |
| 3529 | SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err); | ||
| 3530 | 3482 | ||
| 3531 | if (ret == 0) { | 3483 | if (ret == 0) { |
| 3532 | ret = brcmf_sdio_intr_register(bus->sdiodev); | 3484 | ret = brcmf_sdio_intr_register(bus->sdiodev); |
| @@ -3606,9 +3558,9 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | |||
| 3606 | 3558 | ||
| 3607 | if (!bus->dpc_sched) { | 3559 | if (!bus->dpc_sched) { |
| 3608 | u8 devpend; | 3560 | u8 devpend; |
| 3609 | devpend = brcmf_sdcard_cfg_read(bus->sdiodev, | 3561 | devpend = brcmf_sdio_regrb(bus->sdiodev, |
| 3610 | SDIO_FUNC_0, SDIO_CCCR_INTx, | 3562 | SDIO_CCCR_INTx, |
| 3611 | NULL); | 3563 | NULL); |
| 3612 | intstatus = | 3564 | intstatus = |
| 3613 | devpend & (INTR_STATUS_FUNC1 | | 3565 | devpend & (INTR_STATUS_FUNC1 | |
| 3614 | INTR_STATUS_FUNC2); | 3566 | INTR_STATUS_FUNC2); |
| @@ -3732,24 +3684,18 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva) | |||
| 3732 | 3684 | ||
| 3733 | bus->alp_only = true; | 3685 | bus->alp_only = true; |
| 3734 | 3686 | ||
| 3735 | /* Return the window to backplane enumeration space for core access */ | ||
| 3736 | if (brcmf_sdcard_set_sbaddr_window(bus->sdiodev, SI_ENUM_BASE)) | ||
| 3737 | brcmf_dbg(ERROR, "FAILED to return to SI_ENUM_BASE\n"); | ||
| 3738 | |||
| 3739 | pr_debug("F1 signature read @0x18000000=0x%4x\n", | 3687 | pr_debug("F1 signature read @0x18000000=0x%4x\n", |
| 3740 | brcmf_sdcard_reg_read(bus->sdiodev, SI_ENUM_BASE, 4)); | 3688 | brcmf_sdio_regrl(bus->sdiodev, SI_ENUM_BASE, NULL)); |
| 3741 | 3689 | ||
| 3742 | /* | 3690 | /* |
| 3743 | * Force PLL off until brcmf_sdio_chip_attach() | 3691 | * Force PLL off until brcmf_sdio_chip_attach() |
| 3744 | * programs PLL control regs | 3692 | * programs PLL control regs |
| 3745 | */ | 3693 | */ |
| 3746 | 3694 | ||
| 3747 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 3695 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, |
| 3748 | SBSDIO_FUNC1_CHIPCLKCSR, | 3696 | BRCMF_INIT_CLKCTL1, &err); |
| 3749 | BRCMF_INIT_CLKCTL1, &err); | ||
| 3750 | if (!err) | 3697 | if (!err) |
| 3751 | clkctl = | 3698 | clkctl = brcmf_sdio_regrb(bus->sdiodev, |
| 3752 | brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, | ||
| 3753 | SBSDIO_FUNC1_CHIPCLKCSR, &err); | 3699 | SBSDIO_FUNC1_CHIPCLKCSR, &err); |
| 3754 | 3700 | ||
| 3755 | if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) { | 3701 | if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) { |
| @@ -3782,9 +3728,8 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva) | |||
| 3782 | idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); | 3728 | idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); |
| 3783 | reg_addr = bus->ci->c_inf[idx].base + | 3729 | reg_addr = bus->ci->c_inf[idx].base + |
| 3784 | offsetof(struct sdpcmd_regs, corecontrol); | 3730 | offsetof(struct sdpcmd_regs, corecontrol); |
| 3785 | reg_val = brcmf_sdcard_reg_read(bus->sdiodev, reg_addr, sizeof(u32)); | 3731 | reg_val = brcmf_sdio_regrl(bus->sdiodev, reg_addr, NULL); |
| 3786 | brcmf_sdcard_reg_write(bus->sdiodev, reg_addr, sizeof(u32), | 3732 | brcmf_sdio_regwl(bus->sdiodev, reg_addr, reg_val | CC_BPRESEN, NULL); |
| 3787 | reg_val | CC_BPRESEN); | ||
| 3788 | 3733 | ||
| 3789 | brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN); | 3734 | brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN); |
| 3790 | 3735 | ||
| @@ -3809,16 +3754,15 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus) | |||
| 3809 | brcmf_dbg(TRACE, "Enter\n"); | 3754 | brcmf_dbg(TRACE, "Enter\n"); |
| 3810 | 3755 | ||
| 3811 | /* Disable F2 to clear any intermediate frame state on the dongle */ | 3756 | /* Disable F2 to clear any intermediate frame state on the dongle */ |
| 3812 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx, | 3757 | brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx, |
| 3813 | SDIO_FUNC_ENABLE_1, NULL); | 3758 | SDIO_FUNC_ENABLE_1, NULL); |
| 3814 | 3759 | ||
| 3815 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 3760 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
| 3816 | bus->sleeping = false; | 3761 | bus->sleeping = false; |
| 3817 | bus->rxflow = false; | 3762 | bus->rxflow = false; |
| 3818 | 3763 | ||
| 3819 | /* Done with backplane-dependent accesses, can drop clock... */ | 3764 | /* Done with backplane-dependent accesses, can drop clock... */ |
| 3820 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 3765 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); |
| 3821 | SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); | ||
| 3822 | 3766 | ||
| 3823 | /* ...and initialize clock/power states */ | 3767 | /* ...and initialize clock/power states */ |
| 3824 | bus->clkstate = CLK_SDONLY; | 3768 | bus->clkstate = CLK_SDONLY; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c index 1534efc2163..f8e1f1c84d0 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c | |||
| @@ -93,8 +93,9 @@ brcmf_sdio_sb_corerev(struct brcmf_sdio_dev *sdiodev, | |||
| 93 | 93 | ||
| 94 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); | 94 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); |
| 95 | 95 | ||
| 96 | regdata = brcmf_sdcard_reg_read(sdiodev, | 96 | regdata = brcmf_sdio_regrl(sdiodev, |
| 97 | CORE_SB(ci->c_inf[idx].base, sbidhigh), 4); | 97 | CORE_SB(ci->c_inf[idx].base, sbidhigh), |
| 98 | NULL); | ||
| 98 | return SBCOREREV(regdata); | 99 | return SBCOREREV(regdata); |
| 99 | } | 100 | } |
| 100 | 101 | ||
| @@ -118,8 +119,9 @@ brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev *sdiodev, | |||
| 118 | 119 | ||
| 119 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); | 120 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); |
| 120 | 121 | ||
| 121 | regdata = brcmf_sdcard_reg_read(sdiodev, | 122 | regdata = brcmf_sdio_regrl(sdiodev, |
| 122 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); | 123 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), |
| 124 | NULL); | ||
| 123 | regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT | | 125 | regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT | |
| 124 | SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK); | 126 | SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK); |
| 125 | return (SSB_TMSLOW_CLOCK == regdata); | 127 | return (SSB_TMSLOW_CLOCK == regdata); |
| @@ -135,13 +137,13 @@ brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev, | |||
| 135 | 137 | ||
| 136 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); | 138 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); |
| 137 | 139 | ||
| 138 | regdata = brcmf_sdcard_reg_read(sdiodev, | 140 | regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, |
| 139 | ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4); | 141 | NULL); |
| 140 | ret = (regdata & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) == BCMA_IOCTL_CLK; | 142 | ret = (regdata & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) == BCMA_IOCTL_CLK; |
| 141 | 143 | ||
| 142 | regdata = brcmf_sdcard_reg_read(sdiodev, | 144 | regdata = brcmf_sdio_regrl(sdiodev, |
| 143 | ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, | 145 | ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, |
| 144 | 4); | 146 | NULL); |
| 145 | ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0); | 147 | ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0); |
| 146 | 148 | ||
| 147 | return ret; | 149 | return ret; |
| @@ -151,84 +153,85 @@ static void | |||
| 151 | brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev, | 153 | brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev, |
| 152 | struct chip_info *ci, u16 coreid) | 154 | struct chip_info *ci, u16 coreid) |
| 153 | { | 155 | { |
| 154 | u32 regdata; | 156 | u32 regdata, base; |
| 155 | u8 idx; | 157 | u8 idx; |
| 156 | 158 | ||
| 157 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); | 159 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); |
| 160 | base = ci->c_inf[idx].base; | ||
| 158 | 161 | ||
| 159 | regdata = brcmf_sdcard_reg_read(sdiodev, | 162 | regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL); |
| 160 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); | ||
| 161 | if (regdata & SSB_TMSLOW_RESET) | 163 | if (regdata & SSB_TMSLOW_RESET) |
| 162 | return; | 164 | return; |
| 163 | 165 | ||
| 164 | regdata = brcmf_sdcard_reg_read(sdiodev, | 166 | regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL); |
| 165 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); | ||
| 166 | if ((regdata & SSB_TMSLOW_CLOCK) != 0) { | 167 | if ((regdata & SSB_TMSLOW_CLOCK) != 0) { |
| 167 | /* | 168 | /* |
| 168 | * set target reject and spin until busy is clear | 169 | * set target reject and spin until busy is clear |
| 169 | * (preserve core-specific bits) | 170 | * (preserve core-specific bits) |
| 170 | */ | 171 | */ |
| 171 | regdata = brcmf_sdcard_reg_read(sdiodev, | 172 | regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow), |
| 172 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); | 173 | NULL); |
| 173 | brcmf_sdcard_reg_write(sdiodev, | 174 | brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbtmstatelow), |
| 174 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), | 175 | regdata | SSB_TMSLOW_REJECT, NULL); |
| 175 | 4, regdata | SSB_TMSLOW_REJECT); | 176 | |
| 176 | 177 | regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow), | |
| 177 | regdata = brcmf_sdcard_reg_read(sdiodev, | 178 | NULL); |
| 178 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); | ||
| 179 | udelay(1); | 179 | udelay(1); |
| 180 | SPINWAIT((brcmf_sdcard_reg_read(sdiodev, | 180 | SPINWAIT((brcmf_sdio_regrl(sdiodev, |
| 181 | CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4) & | 181 | CORE_SB(base, sbtmstatehigh), |
| 182 | NULL) & | ||
| 182 | SSB_TMSHIGH_BUSY), 100000); | 183 | SSB_TMSHIGH_BUSY), 100000); |
| 183 | 184 | ||
| 184 | regdata = brcmf_sdcard_reg_read(sdiodev, | 185 | regdata = brcmf_sdio_regrl(sdiodev, |
| 185 | CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4); | 186 | CORE_SB(base, sbtmstatehigh), |
| 187 | NULL); | ||
| 186 | if (regdata & SSB_TMSHIGH_BUSY) | 188 | if (regdata & SSB_TMSHIGH_BUSY) |
| 187 | brcmf_dbg(ERROR, "core state still busy\n"); | 189 | brcmf_dbg(ERROR, "core state still busy\n"); |
| 188 | 190 | ||
| 189 | regdata = brcmf_sdcard_reg_read(sdiodev, | 191 | regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbidlow), |
| 190 | CORE_SB(ci->c_inf[idx].base, sbidlow), 4); | 192 | NULL); |
| 191 | if (regdata & SSB_IDLOW_INITIATOR) { | 193 | if (regdata & SSB_IDLOW_INITIATOR) { |
| 192 | regdata = brcmf_sdcard_reg_read(sdiodev, | 194 | regdata = brcmf_sdio_regrl(sdiodev, |
| 193 | CORE_SB(ci->c_inf[idx].base, sbimstate), 4) | | 195 | CORE_SB(base, sbimstate), |
| 194 | SSB_IMSTATE_REJECT; | 196 | NULL); |
| 195 | brcmf_sdcard_reg_write(sdiodev, | 197 | regdata |= SSB_IMSTATE_REJECT; |
| 196 | CORE_SB(ci->c_inf[idx].base, sbimstate), 4, | 198 | brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbimstate), |
| 197 | regdata); | 199 | regdata, NULL); |
| 198 | regdata = brcmf_sdcard_reg_read(sdiodev, | 200 | regdata = brcmf_sdio_regrl(sdiodev, |
| 199 | CORE_SB(ci->c_inf[idx].base, sbimstate), 4); | 201 | CORE_SB(base, sbimstate), |
| 202 | NULL); | ||
| 200 | udelay(1); | 203 | udelay(1); |
| 201 | SPINWAIT((brcmf_sdcard_reg_read(sdiodev, | 204 | SPINWAIT((brcmf_sdio_regrl(sdiodev, |
| 202 | CORE_SB(ci->c_inf[idx].base, sbimstate), 4) & | 205 | CORE_SB(base, sbimstate), |
| 206 | NULL) & | ||
| 203 | SSB_IMSTATE_BUSY), 100000); | 207 | SSB_IMSTATE_BUSY), 100000); |
| 204 | } | 208 | } |
| 205 | 209 | ||
| 206 | /* set reset and reject while enabling the clocks */ | 210 | /* set reset and reject while enabling the clocks */ |
| 207 | brcmf_sdcard_reg_write(sdiodev, | 211 | regdata = SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | |
| 208 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4, | 212 | SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET; |
| 209 | (SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | | 213 | brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbtmstatelow), |
| 210 | SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET)); | 214 | regdata, NULL); |
| 211 | regdata = brcmf_sdcard_reg_read(sdiodev, | 215 | regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow), |
| 212 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); | 216 | NULL); |
| 213 | udelay(10); | 217 | udelay(10); |
| 214 | 218 | ||
| 215 | /* clear the initiator reject bit */ | 219 | /* clear the initiator reject bit */ |
| 216 | regdata = brcmf_sdcard_reg_read(sdiodev, | 220 | regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbidlow), |
| 217 | CORE_SB(ci->c_inf[idx].base, sbidlow), 4); | 221 | NULL); |
| 218 | if (regdata & SSB_IDLOW_INITIATOR) { | 222 | if (regdata & SSB_IDLOW_INITIATOR) { |
| 219 | regdata = brcmf_sdcard_reg_read(sdiodev, | 223 | regdata = brcmf_sdio_regrl(sdiodev, |
| 220 | CORE_SB(ci->c_inf[idx].base, sbimstate), 4) & | 224 | CORE_SB(base, sbimstate), |
| 221 | ~SSB_IMSTATE_REJECT; | 225 | NULL); |
| 222 | brcmf_sdcard_reg_write(sdiodev, | 226 | regdata &= ~SSB_IMSTATE_REJECT; |
| 223 | CORE_SB(ci->c_inf[idx].base, sbimstate), 4, | 227 | brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbimstate), |
| 224 | regdata); | 228 | regdata, NULL); |
| 225 | } | 229 | } |
| 226 | } | 230 | } |
| 227 | 231 | ||
| 228 | /* leave reset and reject asserted */ | 232 | /* leave reset and reject asserted */ |
| 229 | brcmf_sdcard_reg_write(sdiodev, | 233 | brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbtmstatelow), |
| 230 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4, | 234 | (SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET), NULL); |
| 231 | (SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET)); | ||
| 232 | udelay(1); | 235 | udelay(1); |
| 233 | } | 236 | } |
| 234 | 237 | ||
| @@ -242,20 +245,19 @@ brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev, | |||
| 242 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); | 245 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); |
| 243 | 246 | ||
| 244 | /* if core is already in reset, just return */ | 247 | /* if core is already in reset, just return */ |
| 245 | regdata = brcmf_sdcard_reg_read(sdiodev, | 248 | regdata = brcmf_sdio_regrl(sdiodev, |
| 246 | ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, | 249 | ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, |
| 247 | 4); | 250 | NULL); |
| 248 | if ((regdata & BCMA_RESET_CTL_RESET) != 0) | 251 | if ((regdata & BCMA_RESET_CTL_RESET) != 0) |
| 249 | return; | 252 | return; |
| 250 | 253 | ||
| 251 | brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | 254 | brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, 0, NULL); |
| 252 | 4, 0); | 255 | regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, |
| 253 | regdata = brcmf_sdcard_reg_read(sdiodev, | 256 | NULL); |
| 254 | ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4); | ||
| 255 | udelay(10); | 257 | udelay(10); |
| 256 | 258 | ||
| 257 | brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, | 259 | brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, |
| 258 | 4, BCMA_RESET_CTL_RESET); | 260 | BCMA_RESET_CTL_RESET, NULL); |
| 259 | udelay(1); | 261 | udelay(1); |
| 260 | } | 262 | } |
| 261 | 263 | ||
| @@ -279,41 +281,47 @@ brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev, | |||
| 279 | * set reset while enabling the clock and | 281 | * set reset while enabling the clock and |
| 280 | * forcing them on throughout the core | 282 | * forcing them on throughout the core |
| 281 | */ | 283 | */ |
| 282 | brcmf_sdcard_reg_write(sdiodev, | 284 | brcmf_sdio_regwl(sdiodev, |
| 283 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4, | 285 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), |
| 284 | SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET); | 286 | SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET, |
| 285 | regdata = brcmf_sdcard_reg_read(sdiodev, | 287 | NULL); |
| 286 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); | 288 | regdata = brcmf_sdio_regrl(sdiodev, |
| 289 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), | ||
| 290 | NULL); | ||
| 287 | udelay(1); | 291 | udelay(1); |
| 288 | 292 | ||
| 289 | /* clear any serror */ | 293 | /* clear any serror */ |
| 290 | regdata = brcmf_sdcard_reg_read(sdiodev, | 294 | regdata = brcmf_sdio_regrl(sdiodev, |
| 291 | CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4); | 295 | CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), |
| 296 | NULL); | ||
| 292 | if (regdata & SSB_TMSHIGH_SERR) | 297 | if (regdata & SSB_TMSHIGH_SERR) |
| 293 | brcmf_sdcard_reg_write(sdiodev, | 298 | brcmf_sdio_regwl(sdiodev, |
| 294 | CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4, 0); | 299 | CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), |
| 300 | 0, NULL); | ||
| 295 | 301 | ||
| 296 | regdata = brcmf_sdcard_reg_read(sdiodev, | 302 | regdata = brcmf_sdio_regrl(sdiodev, |
| 297 | CORE_SB(ci->c_inf[idx].base, sbimstate), 4); | 303 | CORE_SB(ci->c_inf[idx].base, sbimstate), |
| 304 | NULL); | ||
| 298 | if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO)) | 305 | if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO)) |
| 299 | brcmf_sdcard_reg_write(sdiodev, | 306 | brcmf_sdio_regwl(sdiodev, |
| 300 | CORE_SB(ci->c_inf[idx].base, sbimstate), 4, | 307 | CORE_SB(ci->c_inf[idx].base, sbimstate), |
| 301 | regdata & ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO)); | 308 | regdata & ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO), |
| 309 | NULL); | ||
| 302 | 310 | ||
| 303 | /* clear reset and allow it to propagate throughout the core */ | 311 | /* clear reset and allow it to propagate throughout the core */ |
| 304 | brcmf_sdcard_reg_write(sdiodev, | 312 | brcmf_sdio_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow), |
| 305 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4, | 313 | SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK, NULL); |
| 306 | SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK); | 314 | regdata = brcmf_sdio_regrl(sdiodev, |
| 307 | regdata = brcmf_sdcard_reg_read(sdiodev, | 315 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), |
| 308 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); | 316 | NULL); |
| 309 | udelay(1); | 317 | udelay(1); |
| 310 | 318 | ||
| 311 | /* leave clock enabled */ | 319 | /* leave clock enabled */ |
| 312 | brcmf_sdcard_reg_write(sdiodev, | 320 | brcmf_sdio_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow), |
| 313 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), | 321 | SSB_TMSLOW_CLOCK, NULL); |
| 314 | 4, SSB_TMSLOW_CLOCK); | 322 | regdata = brcmf_sdio_regrl(sdiodev, |
| 315 | regdata = brcmf_sdcard_reg_read(sdiodev, | 323 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), |
| 316 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); | 324 | NULL); |
| 317 | udelay(1); | 325 | udelay(1); |
| 318 | } | 326 | } |
| 319 | 327 | ||
| @@ -330,18 +338,18 @@ brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev, | |||
| 330 | brcmf_sdio_ai_coredisable(sdiodev, ci, coreid); | 338 | brcmf_sdio_ai_coredisable(sdiodev, ci, coreid); |
| 331 | 339 | ||
| 332 | /* now do initialization sequence */ | 340 | /* now do initialization sequence */ |
| 333 | brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | 341 | brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, |
| 334 | 4, BCMA_IOCTL_FGC | BCMA_IOCTL_CLK); | 342 | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL); |
| 335 | regdata = brcmf_sdcard_reg_read(sdiodev, | 343 | regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, |
| 336 | ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4); | 344 | NULL); |
| 337 | brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, | 345 | brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, |
| 338 | 4, 0); | 346 | 0, NULL); |
| 339 | udelay(1); | 347 | udelay(1); |
| 340 | 348 | ||
| 341 | brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | 349 | brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, |
| 342 | 4, BCMA_IOCTL_CLK); | 350 | BCMA_IOCTL_CLK, NULL); |
| 343 | regdata = brcmf_sdcard_reg_read(sdiodev, | 351 | regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, |
| 344 | ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4); | 352 | NULL); |
| 345 | udelay(1); | 353 | udelay(1); |
| 346 | } | 354 | } |
| 347 | 355 | ||
| @@ -358,8 +366,9 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev, | |||
| 358 | */ | 366 | */ |
| 359 | ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON; | 367 | ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON; |
| 360 | ci->c_inf[0].base = regs; | 368 | ci->c_inf[0].base = regs; |
| 361 | regdata = brcmf_sdcard_reg_read(sdiodev, | 369 | regdata = brcmf_sdio_regrl(sdiodev, |
| 362 | CORE_CC_REG(ci->c_inf[0].base, chipid), 4); | 370 | CORE_CC_REG(ci->c_inf[0].base, chipid), |
| 371 | NULL); | ||
| 363 | ci->chip = regdata & CID_ID_MASK; | 372 | ci->chip = regdata & CID_ID_MASK; |
| 364 | ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT; | 373 | ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT; |
| 365 | ci->socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT; | 374 | ci->socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT; |
| @@ -428,8 +437,7 @@ brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev) | |||
| 428 | 437 | ||
| 429 | /* Try forcing SDIO core to do ALPAvail request only */ | 438 | /* Try forcing SDIO core to do ALPAvail request only */ |
| 430 | clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ; | 439 | clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ; |
| 431 | brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, | 440 | brcmf_sdio_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); |
| 432 | SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); | ||
| 433 | if (err) { | 441 | if (err) { |
| 434 | brcmf_dbg(ERROR, "error writing for HT off\n"); | 442 | brcmf_dbg(ERROR, "error writing for HT off\n"); |
| 435 | return err; | 443 | return err; |
| @@ -437,8 +445,8 @@ brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev) | |||
| 437 | 445 | ||
| 438 | /* If register supported, wait for ALPAvail and then force ALP */ | 446 | /* If register supported, wait for ALPAvail and then force ALP */ |
| 439 | /* This may take up to 15 milliseconds */ | 447 | /* This may take up to 15 milliseconds */ |
| 440 | clkval = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_1, | 448 | clkval = brcmf_sdio_regrb(sdiodev, |
| 441 | SBSDIO_FUNC1_CHIPCLKCSR, NULL); | 449 | SBSDIO_FUNC1_CHIPCLKCSR, NULL); |
| 442 | 450 | ||
| 443 | if ((clkval & ~SBSDIO_AVBITS) != clkset) { | 451 | if ((clkval & ~SBSDIO_AVBITS) != clkset) { |
| 444 | brcmf_dbg(ERROR, "ChipClkCSR access: wrote 0x%02x read 0x%02x\n", | 452 | brcmf_dbg(ERROR, "ChipClkCSR access: wrote 0x%02x read 0x%02x\n", |
| @@ -446,8 +454,8 @@ brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev) | |||
| 446 | return -EACCES; | 454 | return -EACCES; |
| 447 | } | 455 | } |
| 448 | 456 | ||
| 449 | SPINWAIT(((clkval = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_1, | 457 | SPINWAIT(((clkval = brcmf_sdio_regrb(sdiodev, |
| 450 | SBSDIO_FUNC1_CHIPCLKCSR, NULL)), | 458 | SBSDIO_FUNC1_CHIPCLKCSR, NULL)), |
| 451 | !SBSDIO_ALPAV(clkval)), | 459 | !SBSDIO_ALPAV(clkval)), |
| 452 | PMU_MAX_TRANSITION_DLY); | 460 | PMU_MAX_TRANSITION_DLY); |
| 453 | if (!SBSDIO_ALPAV(clkval)) { | 461 | if (!SBSDIO_ALPAV(clkval)) { |
| @@ -457,13 +465,11 @@ brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev) | |||
| 457 | } | 465 | } |
| 458 | 466 | ||
| 459 | clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP; | 467 | clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP; |
| 460 | brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, | 468 | brcmf_sdio_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); |
| 461 | SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); | ||
| 462 | udelay(65); | 469 | udelay(65); |
| 463 | 470 | ||
| 464 | /* Also, disable the extra SDIO pull-ups */ | 471 | /* Also, disable the extra SDIO pull-ups */ |
| 465 | brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, | 472 | brcmf_sdio_regwb(sdiodev, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL); |
| 466 | SBSDIO_FUNC1_SDIOPULLUP, 0, NULL); | ||
| 467 | 473 | ||
| 468 | return 0; | 474 | return 0; |
| 469 | } | 475 | } |
| @@ -472,18 +478,22 @@ static void | |||
| 472 | brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev, | 478 | brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev, |
| 473 | struct chip_info *ci) | 479 | struct chip_info *ci) |
| 474 | { | 480 | { |
| 481 | u32 base = ci->c_inf[0].base; | ||
| 482 | |||
| 475 | /* get chipcommon rev */ | 483 | /* get chipcommon rev */ |
| 476 | ci->c_inf[0].rev = ci->corerev(sdiodev, ci, ci->c_inf[0].id); | 484 | ci->c_inf[0].rev = ci->corerev(sdiodev, ci, ci->c_inf[0].id); |
| 477 | 485 | ||
| 478 | /* get chipcommon capabilites */ | 486 | /* get chipcommon capabilites */ |
| 479 | ci->c_inf[0].caps = | 487 | ci->c_inf[0].caps = brcmf_sdio_regrl(sdiodev, |
| 480 | brcmf_sdcard_reg_read(sdiodev, | 488 | CORE_CC_REG(base, capabilities), |
| 481 | CORE_CC_REG(ci->c_inf[0].base, capabilities), 4); | 489 | NULL); |
| 482 | 490 | ||
| 483 | /* get pmu caps & rev */ | 491 | /* get pmu caps & rev */ |
| 484 | if (ci->c_inf[0].caps & CC_CAP_PMU) { | 492 | if (ci->c_inf[0].caps & CC_CAP_PMU) { |
| 485 | ci->pmucaps = brcmf_sdcard_reg_read(sdiodev, | 493 | ci->pmucaps = |
| 486 | CORE_CC_REG(ci->c_inf[0].base, pmucapabilities), 4); | 494 | brcmf_sdio_regrl(sdiodev, |
| 495 | CORE_CC_REG(base, pmucapabilities), | ||
| 496 | NULL); | ||
| 487 | ci->pmurev = ci->pmucaps & PCAP_REV_MASK; | 497 | ci->pmurev = ci->pmucaps & PCAP_REV_MASK; |
| 488 | } | 498 | } |
| 489 | 499 | ||
| @@ -523,10 +533,10 @@ int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev, | |||
| 523 | 533 | ||
| 524 | brcmf_sdio_chip_buscoresetup(sdiodev, ci); | 534 | brcmf_sdio_chip_buscoresetup(sdiodev, ci); |
| 525 | 535 | ||
| 526 | brcmf_sdcard_reg_write(sdiodev, | 536 | brcmf_sdio_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopullup), |
| 527 | CORE_CC_REG(ci->c_inf[0].base, gpiopullup), 4, 0); | 537 | 0, NULL); |
| 528 | brcmf_sdcard_reg_write(sdiodev, | 538 | brcmf_sdio_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopulldown), |
| 529 | CORE_CC_REG(ci->c_inf[0].base, gpiopulldown), 4, 0); | 539 | 0, NULL); |
| 530 | 540 | ||
| 531 | *ci_ptr = ci; | 541 | *ci_ptr = ci; |
| 532 | return 0; | 542 | return 0; |
| @@ -562,6 +572,7 @@ brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, | |||
| 562 | u32 str_mask = 0; | 572 | u32 str_mask = 0; |
| 563 | u32 str_shift = 0; | 573 | u32 str_shift = 0; |
| 564 | char chn[8]; | 574 | char chn[8]; |
| 575 | u32 base = ci->c_inf[0].base; | ||
| 565 | 576 | ||
| 566 | if (!(ci->c_inf[0].caps & CC_CAP_PMU)) | 577 | if (!(ci->c_inf[0].caps & CC_CAP_PMU)) |
| 567 | return; | 578 | return; |
| @@ -591,17 +602,17 @@ brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, | |||
| 591 | } | 602 | } |
| 592 | } | 603 | } |
| 593 | 604 | ||
| 594 | brcmf_sdcard_reg_write(sdiodev, | 605 | brcmf_sdio_regwl(sdiodev, CORE_CC_REG(base, chipcontrol_addr), |
| 595 | CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr), | 606 | 1, NULL); |
| 596 | 4, 1); | 607 | cc_data_temp = |
| 597 | cc_data_temp = brcmf_sdcard_reg_read(sdiodev, | 608 | brcmf_sdio_regrl(sdiodev, |
| 598 | CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr), 4); | 609 | CORE_CC_REG(base, chipcontrol_addr), |
| 610 | NULL); | ||
| 599 | cc_data_temp &= ~str_mask; | 611 | cc_data_temp &= ~str_mask; |
| 600 | drivestrength_sel <<= str_shift; | 612 | drivestrength_sel <<= str_shift; |
| 601 | cc_data_temp |= drivestrength_sel; | 613 | cc_data_temp |= drivestrength_sel; |
| 602 | brcmf_sdcard_reg_write(sdiodev, | 614 | brcmf_sdio_regwl(sdiodev, CORE_CC_REG(base, chipcontrol_addr), |
| 603 | CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr), | 615 | cc_data_temp, NULL); |
| 604 | 4, cc_data_temp); | ||
| 605 | 616 | ||
| 606 | brcmf_dbg(INFO, "SDIO: %dmA drive strength selected, set to 0x%08x\n", | 617 | brcmf_dbg(INFO, "SDIO: %dmA drive strength selected, set to 0x%08x\n", |
| 607 | drivestrength, cc_data_temp); | 618 | drivestrength, cc_data_temp); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h index 7010eaf71f9..29bf78d264e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h | |||
| @@ -40,6 +40,10 @@ | |||
| 40 | /* Maximum number of I/O funcs */ | 40 | /* Maximum number of I/O funcs */ |
| 41 | #define SDIOD_MAX_IOFUNCS 7 | 41 | #define SDIOD_MAX_IOFUNCS 7 |
| 42 | 42 | ||
| 43 | /* mask of register map */ | ||
| 44 | #define REG_F0_REG_MASK 0x7FF | ||
| 45 | #define REG_F1_MISC_MASK 0x1FFFF | ||
| 46 | |||
| 43 | /* as of sdiod rev 0, supports 3 functions */ | 47 | /* as of sdiod rev 0, supports 3 functions */ |
| 44 | #define SBSDIO_NUM_FUNCTION 3 | 48 | #define SBSDIO_NUM_FUNCTION 3 |
| 45 | 49 | ||
| @@ -142,7 +146,6 @@ struct brcmf_sdio_dev { | |||
| 142 | u8 num_funcs; /* Supported funcs on client */ | 146 | u8 num_funcs; /* Supported funcs on client */ |
| 143 | u32 func_cis_ptr[SDIOD_MAX_IOFUNCS]; | 147 | u32 func_cis_ptr[SDIOD_MAX_IOFUNCS]; |
| 144 | u32 sbwad; /* Save backplane window address */ | 148 | u32 sbwad; /* Save backplane window address */ |
| 145 | bool regfail; /* status of last reg_r/w call */ | ||
| 146 | void *bus; | 149 | void *bus; |
| 147 | atomic_t suspend; /* suspend flag */ | 150 | atomic_t suspend; /* suspend flag */ |
| 148 | wait_queue_head_t request_byte_wait; | 151 | wait_queue_head_t request_byte_wait; |
| @@ -164,31 +167,13 @@ struct brcmf_sdio_dev { | |||
| 164 | extern int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev); | 167 | extern int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev); |
| 165 | extern int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev); | 168 | extern int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev); |
| 166 | 169 | ||
| 167 | /* Access SDIO address space (e.g. CCCR) using CMD52 (single-byte interface). | 170 | /* sdio device register access interface */ |
| 168 | * fn: function number | 171 | extern u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret); |
| 169 | * addr: unmodified SDIO-space address | 172 | extern u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret); |
| 170 | * data: data byte to write | 173 | extern void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, |
| 171 | * err: pointer to error code (or NULL) | 174 | u8 data, int *ret); |
| 172 | */ | 175 | extern void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, |
| 173 | extern u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint func, | 176 | u32 data, int *ret); |
| 174 | u32 addr, int *err); | ||
| 175 | extern void brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint func, | ||
| 176 | u32 addr, u8 data, int *err); | ||
| 177 | |||
| 178 | /* Synchronous access to device (client) core registers via CMD53 to F1. | ||
| 179 | * addr: backplane address (i.e. >= regsva from attach) | ||
| 180 | * size: register width in bytes (2 or 4) | ||
| 181 | * data: data for register write | ||
| 182 | */ | ||
| 183 | extern u32 | ||
| 184 | brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size); | ||
| 185 | |||
| 186 | extern u32 | ||
| 187 | brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size, | ||
| 188 | u32 data); | ||
| 189 | |||
| 190 | /* Indicate if last reg read/write failed */ | ||
| 191 | extern bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev); | ||
| 192 | 177 | ||
| 193 | /* Buffer transfer to/from device (client) core via cmd53. | 178 | /* Buffer transfer to/from device (client) core via cmd53. |
| 194 | * fn: function number | 179 | * fn: function number |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/Makefile b/drivers/net/wireless/brcm80211/brcmsmac/Makefile index c2eb2d0af38..e227c4c68ef 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/Makefile +++ b/drivers/net/wireless/brcm80211/brcmsmac/Makefile | |||
| @@ -39,10 +39,7 @@ BRCMSMAC_OFILES := \ | |||
| 39 | phy/phytbl_lcn.o \ | 39 | phy/phytbl_lcn.o \ |
| 40 | phy/phytbl_n.o \ | 40 | phy/phytbl_n.o \ |
| 41 | phy/phy_qmath.o \ | 41 | phy/phy_qmath.o \ |
| 42 | otp.o \ | ||
| 43 | srom.o \ | ||
| 44 | dma.o \ | 42 | dma.o \ |
| 45 | nicpci.o \ | ||
| 46 | brcms_trace_events.o | 43 | brcms_trace_events.o |
| 47 | 44 | ||
| 48 | MODULEPFX := brcmsmac | 45 | MODULEPFX := brcmsmac |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c index c93ea35bcee..6d8b7213643 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c | |||
| @@ -19,7 +19,6 @@ | |||
| 19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
| 20 | 20 | ||
| 21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
| 22 | #include <linux/pci.h> | ||
| 23 | 22 | ||
| 24 | #include <defs.h> | 23 | #include <defs.h> |
| 25 | #include <chipcommon.h> | 24 | #include <chipcommon.h> |
| @@ -29,8 +28,6 @@ | |||
| 29 | #include "types.h" | 28 | #include "types.h" |
| 30 | #include "pub.h" | 29 | #include "pub.h" |
| 31 | #include "pmu.h" | 30 | #include "pmu.h" |
| 32 | #include "srom.h" | ||
| 33 | #include "nicpci.h" | ||
| 34 | #include "aiutils.h" | 31 | #include "aiutils.h" |
| 35 | 32 | ||
| 36 | /* slow_clk_ctl */ | 33 | /* slow_clk_ctl */ |
| @@ -321,7 +318,6 @@ | |||
| 321 | #define IS_SIM(chippkg) \ | 318 | #define IS_SIM(chippkg) \ |
| 322 | ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID)) | 319 | ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID)) |
| 323 | 320 | ||
| 324 | #define PCI(sih) (ai_get_buscoretype(sih) == PCI_CORE_ID) | ||
| 325 | #define PCIE(sih) (ai_get_buscoretype(sih) == PCIE_CORE_ID) | 321 | #define PCIE(sih) (ai_get_buscoretype(sih) == PCIE_CORE_ID) |
| 326 | 322 | ||
| 327 | #define PCI_FORCEHT(sih) (PCIE(sih) && (ai_get_chip_id(sih) == BCM4716_CHIP_ID)) | 323 | #define PCI_FORCEHT(sih) (PCIE(sih) && (ai_get_chip_id(sih) == BCM4716_CHIP_ID)) |
| @@ -454,36 +450,9 @@ struct aidmp { | |||
| 454 | u32 componentid3; /* 0xffc */ | 450 | u32 componentid3; /* 0xffc */ |
| 455 | }; | 451 | }; |
| 456 | 452 | ||
| 457 | /* return true if PCIE capability exists in the pci config space */ | ||
| 458 | static bool ai_ispcie(struct si_info *sii) | ||
| 459 | { | ||
| 460 | u8 cap_ptr; | ||
| 461 | |||
| 462 | cap_ptr = | ||
| 463 | pcicore_find_pci_capability(sii->pcibus, PCI_CAP_ID_EXP, NULL, | ||
| 464 | NULL); | ||
| 465 | if (!cap_ptr) | ||
| 466 | return false; | ||
| 467 | |||
| 468 | return true; | ||
| 469 | } | ||
| 470 | |||
| 471 | static bool ai_buscore_prep(struct si_info *sii) | ||
| 472 | { | ||
| 473 | /* kludge to enable the clock on the 4306 which lacks a slowclock */ | ||
| 474 | if (!ai_ispcie(sii)) | ||
| 475 | ai_clkctl_xtal(&sii->pub, XTAL | PLL, ON); | ||
| 476 | return true; | ||
| 477 | } | ||
| 478 | |||
| 479 | static bool | 453 | static bool |
| 480 | ai_buscore_setup(struct si_info *sii, struct bcma_device *cc) | 454 | ai_buscore_setup(struct si_info *sii, struct bcma_device *cc) |
| 481 | { | 455 | { |
| 482 | struct bcma_device *pci = NULL; | ||
| 483 | struct bcma_device *pcie = NULL; | ||
| 484 | struct bcma_device *core; | ||
| 485 | |||
| 486 | |||
| 487 | /* no cores found, bail out */ | 456 | /* no cores found, bail out */ |
| 488 | if (cc->bus->nr_cores == 0) | 457 | if (cc->bus->nr_cores == 0) |
| 489 | return false; | 458 | return false; |
| @@ -492,8 +461,7 @@ ai_buscore_setup(struct si_info *sii, struct bcma_device *cc) | |||
| 492 | sii->pub.ccrev = cc->id.rev; | 461 | sii->pub.ccrev = cc->id.rev; |
| 493 | 462 | ||
| 494 | /* get chipcommon chipstatus */ | 463 | /* get chipcommon chipstatus */ |
| 495 | if (ai_get_ccrev(&sii->pub) >= 11) | 464 | sii->chipst = bcma_read32(cc, CHIPCREGOFFS(chipstatus)); |
| 496 | sii->chipst = bcma_read32(cc, CHIPCREGOFFS(chipstatus)); | ||
| 497 | 465 | ||
| 498 | /* get chipcommon capabilites */ | 466 | /* get chipcommon capabilites */ |
| 499 | sii->pub.cccaps = bcma_read32(cc, CHIPCREGOFFS(capabilities)); | 467 | sii->pub.cccaps = bcma_read32(cc, CHIPCREGOFFS(capabilities)); |
| @@ -506,64 +474,18 @@ ai_buscore_setup(struct si_info *sii, struct bcma_device *cc) | |||
| 506 | } | 474 | } |
| 507 | 475 | ||
| 508 | /* figure out buscore */ | 476 | /* figure out buscore */ |
| 509 | list_for_each_entry(core, &cc->bus->cores, list) { | 477 | sii->buscore = ai_findcore(&sii->pub, PCIE_CORE_ID, 0); |
| 510 | uint cid, crev; | ||
| 511 | |||
| 512 | cid = core->id.id; | ||
| 513 | crev = core->id.rev; | ||
| 514 | |||
| 515 | if (cid == PCI_CORE_ID) { | ||
| 516 | pci = core; | ||
| 517 | } else if (cid == PCIE_CORE_ID) { | ||
| 518 | pcie = core; | ||
| 519 | } | ||
| 520 | } | ||
| 521 | |||
| 522 | if (pci && pcie) { | ||
| 523 | if (ai_ispcie(sii)) | ||
| 524 | pci = NULL; | ||
| 525 | else | ||
| 526 | pcie = NULL; | ||
| 527 | } | ||
| 528 | if (pci) { | ||
| 529 | sii->buscore = pci; | ||
| 530 | } else if (pcie) { | ||
| 531 | sii->buscore = pcie; | ||
| 532 | } | ||
| 533 | |||
| 534 | /* fixup necessary chip/core configurations */ | ||
| 535 | if (!sii->pch) { | ||
| 536 | sii->pch = pcicore_init(&sii->pub, sii->icbus->drv_pci.core); | ||
| 537 | if (sii->pch == NULL) | ||
| 538 | return false; | ||
| 539 | } | ||
| 540 | if (ai_pci_fixcfg(&sii->pub)) | ||
| 541 | return false; | ||
| 542 | 478 | ||
| 543 | return true; | 479 | return true; |
| 544 | } | 480 | } |
| 545 | 481 | ||
| 546 | /* | ||
| 547 | * get boardtype and boardrev | ||
| 548 | */ | ||
| 549 | static __used void ai_nvram_process(struct si_info *sii) | ||
| 550 | { | ||
| 551 | uint w = 0; | ||
| 552 | |||
| 553 | /* do a pci config read to get subsystem id and subvendor id */ | ||
| 554 | pci_read_config_dword(sii->pcibus, PCI_SUBSYSTEM_VENDOR_ID, &w); | ||
| 555 | |||
| 556 | sii->pub.boardvendor = w & 0xffff; | ||
| 557 | sii->pub.boardtype = (w >> 16) & 0xffff; | ||
| 558 | } | ||
| 559 | |||
| 560 | static struct si_info *ai_doattach(struct si_info *sii, | 482 | static struct si_info *ai_doattach(struct si_info *sii, |
| 561 | struct bcma_bus *pbus) | 483 | struct bcma_bus *pbus) |
| 562 | { | 484 | { |
| 563 | struct si_pub *sih = &sii->pub; | 485 | struct si_pub *sih = &sii->pub; |
| 564 | u32 w, savewin; | 486 | u32 w, savewin; |
| 565 | struct bcma_device *cc; | 487 | struct bcma_device *cc; |
| 566 | uint socitype; | 488 | struct ssb_sprom *sprom = &pbus->sprom; |
| 567 | 489 | ||
| 568 | savewin = 0; | 490 | savewin = 0; |
| 569 | 491 | ||
| @@ -573,38 +495,15 @@ static struct si_info *ai_doattach(struct si_info *sii, | |||
| 573 | /* switch to Chipcommon core */ | 495 | /* switch to Chipcommon core */ |
| 574 | cc = pbus->drv_cc.core; | 496 | cc = pbus->drv_cc.core; |
| 575 | 497 | ||
| 576 | /* bus/core/clk setup for register access */ | 498 | sih->chip = pbus->chipinfo.id; |
| 577 | if (!ai_buscore_prep(sii)) | 499 | sih->chiprev = pbus->chipinfo.rev; |
| 578 | return NULL; | 500 | sih->chippkg = pbus->chipinfo.pkg; |
| 501 | sih->boardvendor = pbus->boardinfo.vendor; | ||
| 502 | sih->boardtype = pbus->boardinfo.type; | ||
| 579 | 503 | ||
| 580 | /* | ||
| 581 | * ChipID recognition. | ||
| 582 | * We assume we can read chipid at offset 0 from the regs arg. | ||
| 583 | * If we add other chiptypes (or if we need to support old sdio | ||
| 584 | * hosts w/o chipcommon), some way of recognizing them needs to | ||
| 585 | * be added here. | ||
| 586 | */ | ||
| 587 | w = bcma_read32(cc, CHIPCREGOFFS(chipid)); | ||
| 588 | socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT; | ||
| 589 | /* Might as wll fill in chip id rev & pkg */ | ||
| 590 | sih->chip = w & CID_ID_MASK; | ||
| 591 | sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT; | ||
| 592 | sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT; | ||
| 593 | |||
| 594 | /* scan for cores */ | ||
| 595 | if (socitype != SOCI_AI) | ||
| 596 | return NULL; | ||
| 597 | |||
| 598 | SI_MSG("Found chip type AI (0x%08x)\n", w); | ||
| 599 | if (!ai_buscore_setup(sii, cc)) | 504 | if (!ai_buscore_setup(sii, cc)) |
| 600 | goto exit; | 505 | goto exit; |
| 601 | 506 | ||
| 602 | /* Init nvram from sprom/otp if they exist */ | ||
| 603 | if (srom_var_init(&sii->pub)) | ||
| 604 | goto exit; | ||
| 605 | |||
| 606 | ai_nvram_process(sii); | ||
| 607 | |||
| 608 | /* === NVRAM, clock is ready === */ | 507 | /* === NVRAM, clock is ready === */ |
| 609 | bcma_write32(cc, CHIPCREGOFFS(gpiopullup), 0); | 508 | bcma_write32(cc, CHIPCREGOFFS(gpiopullup), 0); |
| 610 | bcma_write32(cc, CHIPCREGOFFS(gpiopulldown), 0); | 509 | bcma_write32(cc, CHIPCREGOFFS(gpiopulldown), 0); |
| @@ -617,15 +516,13 @@ static struct si_info *ai_doattach(struct si_info *sii, | |||
| 617 | } | 516 | } |
| 618 | 517 | ||
| 619 | /* setup the GPIO based LED powersave register */ | 518 | /* setup the GPIO based LED powersave register */ |
| 620 | w = getintvar(sih, BRCMS_SROM_LEDDC); | 519 | w = (sprom->leddc_on_time << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) | |
| 520 | (sprom->leddc_off_time << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT); | ||
| 621 | if (w == 0) | 521 | if (w == 0) |
| 622 | w = DEFAULT_GPIOTIMERVAL; | 522 | w = DEFAULT_GPIOTIMERVAL; |
| 623 | ai_cc_reg(sih, offsetof(struct chipcregs, gpiotimerval), | 523 | ai_cc_reg(sih, offsetof(struct chipcregs, gpiotimerval), |
| 624 | ~0, w); | 524 | ~0, w); |
| 625 | 525 | ||
| 626 | if (PCIE(sih)) | ||
| 627 | pcicore_attach(sii->pch, SI_DOATTACH); | ||
| 628 | |||
| 629 | if (ai_get_chip_id(sih) == BCM43224_CHIP_ID) { | 526 | if (ai_get_chip_id(sih) == BCM43224_CHIP_ID) { |
| 630 | /* | 527 | /* |
| 631 | * enable 12 mA drive strenth for 43224 and | 528 | * enable 12 mA drive strenth for 43224 and |
| @@ -659,9 +556,6 @@ static struct si_info *ai_doattach(struct si_info *sii, | |||
| 659 | return sii; | 556 | return sii; |
| 660 | 557 | ||
| 661 | exit: | 558 | exit: |
| 662 | if (sii->pch) | ||
| 663 | pcicore_deinit(sii->pch); | ||
| 664 | sii->pch = NULL; | ||
| 665 | 559 | ||
| 666 | return NULL; | 560 | return NULL; |
| 667 | } | 561 | } |
| @@ -700,11 +594,6 @@ void ai_detach(struct si_pub *sih) | |||
| 700 | if (sii == NULL) | 594 | if (sii == NULL) |
| 701 | return; | 595 | return; |
| 702 | 596 | ||
| 703 | if (sii->pch) | ||
| 704 | pcicore_deinit(sii->pch); | ||
| 705 | sii->pch = NULL; | ||
| 706 | |||
| 707 | srom_free_vars(sih); | ||
| 708 | kfree(sii); | 597 | kfree(sii); |
| 709 | } | 598 | } |
| 710 | 599 | ||
| @@ -755,21 +644,7 @@ uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val) | |||
| 755 | /* return the slow clock source - LPO, XTAL, or PCI */ | 644 | /* return the slow clock source - LPO, XTAL, or PCI */ |
| 756 | static uint ai_slowclk_src(struct si_pub *sih, struct bcma_device *cc) | 645 | static uint ai_slowclk_src(struct si_pub *sih, struct bcma_device *cc) |
| 757 | { | 646 | { |
| 758 | struct si_info *sii; | 647 | return SCC_SS_XTAL; |
| 759 | u32 val; | ||
| 760 | |||
| 761 | sii = (struct si_info *)sih; | ||
| 762 | if (ai_get_ccrev(&sii->pub) < 6) { | ||
| 763 | pci_read_config_dword(sii->pcibus, PCI_GPIO_OUT, | ||
| 764 | &val); | ||
| 765 | if (val & PCI_CFG_GPIO_SCS) | ||
| 766 | return SCC_SS_PCI; | ||
| 767 | return SCC_SS_XTAL; | ||
| 768 | } else if (ai_get_ccrev(&sii->pub) < 10) { | ||
| 769 | return bcma_read32(cc, CHIPCREGOFFS(slow_clk_ctl)) & | ||
| 770 | SCC_SS_MASK; | ||
| 771 | } else /* Insta-clock */ | ||
| 772 | return SCC_SS_XTAL; | ||
| 773 | } | 648 | } |
| 774 | 649 | ||
| 775 | /* | 650 | /* |
| @@ -779,36 +654,12 @@ static uint ai_slowclk_src(struct si_pub *sih, struct bcma_device *cc) | |||
| 779 | static uint ai_slowclk_freq(struct si_pub *sih, bool max_freq, | 654 | static uint ai_slowclk_freq(struct si_pub *sih, bool max_freq, |
| 780 | struct bcma_device *cc) | 655 | struct bcma_device *cc) |
| 781 | { | 656 | { |
| 782 | u32 slowclk; | ||
| 783 | uint div; | 657 | uint div; |
| 784 | 658 | ||
| 785 | slowclk = ai_slowclk_src(sih, cc); | 659 | /* Chipc rev 10 is InstaClock */ |
| 786 | if (ai_get_ccrev(sih) < 6) { | 660 | div = bcma_read32(cc, CHIPCREGOFFS(system_clk_ctl)); |
| 787 | if (slowclk == SCC_SS_PCI) | 661 | div = 4 * ((div >> SYCC_CD_SHIFT) + 1); |
| 788 | return max_freq ? (PCIMAXFREQ / 64) | 662 | return max_freq ? XTALMAXFREQ : (XTALMINFREQ / div); |
| 789 | : (PCIMINFREQ / 64); | ||
| 790 | else | ||
| 791 | return max_freq ? (XTALMAXFREQ / 32) | ||
| 792 | : (XTALMINFREQ / 32); | ||
| 793 | } else if (ai_get_ccrev(sih) < 10) { | ||
| 794 | div = 4 * | ||
| 795 | (((bcma_read32(cc, CHIPCREGOFFS(slow_clk_ctl)) & | ||
| 796 | SCC_CD_MASK) >> SCC_CD_SHIFT) + 1); | ||
| 797 | if (slowclk == SCC_SS_LPO) | ||
| 798 | return max_freq ? LPOMAXFREQ : LPOMINFREQ; | ||
| 799 | else if (slowclk == SCC_SS_XTAL) | ||
| 800 | return max_freq ? (XTALMAXFREQ / div) | ||
| 801 | : (XTALMINFREQ / div); | ||
| 802 | else if (slowclk == SCC_SS_PCI) | ||
| 803 | return max_freq ? (PCIMAXFREQ / div) | ||
| 804 | : (PCIMINFREQ / div); | ||
| 805 | } else { | ||
| 806 | /* Chipc rev 10 is InstaClock */ | ||
| 807 | div = bcma_read32(cc, CHIPCREGOFFS(system_clk_ctl)); | ||
| 808 | div = 4 * ((div >> SYCC_CD_SHIFT) + 1); | ||
| 809 | return max_freq ? XTALMAXFREQ : (XTALMINFREQ / div); | ||
| 810 | } | ||
| 811 | return 0; | ||
| 812 | } | 663 | } |
| 813 | 664 | ||
| 814 | static void | 665 | static void |
| @@ -831,8 +682,7 @@ ai_clkctl_setdelay(struct si_pub *sih, struct bcma_device *cc) | |||
| 831 | 682 | ||
| 832 | /* Starting with 4318 it is ILP that is used for the delays */ | 683 | /* Starting with 4318 it is ILP that is used for the delays */ |
| 833 | slowmaxfreq = | 684 | slowmaxfreq = |
| 834 | ai_slowclk_freq(sih, | 685 | ai_slowclk_freq(sih, false, cc); |
| 835 | (ai_get_ccrev(sih) >= 10) ? false : true, cc); | ||
| 836 | 686 | ||
| 837 | pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; | 687 | pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; |
| 838 | fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000; | 688 | fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000; |
| @@ -854,9 +704,8 @@ void ai_clkctl_init(struct si_pub *sih) | |||
| 854 | return; | 704 | return; |
| 855 | 705 | ||
| 856 | /* set all Instaclk chip ILP to 1 MHz */ | 706 | /* set all Instaclk chip ILP to 1 MHz */ |
| 857 | if (ai_get_ccrev(sih) >= 10) | 707 | bcma_maskset32(cc, CHIPCREGOFFS(system_clk_ctl), SYCC_CD_MASK, |
| 858 | bcma_maskset32(cc, CHIPCREGOFFS(system_clk_ctl), SYCC_CD_MASK, | 708 | (ILP_DIV_1MHZ << SYCC_CD_SHIFT)); |
| 859 | (ILP_DIV_1MHZ << SYCC_CD_SHIFT)); | ||
| 860 | 709 | ||
| 861 | ai_clkctl_setdelay(sih, cc); | 710 | ai_clkctl_setdelay(sih, cc); |
| 862 | } | 711 | } |
| @@ -891,140 +740,6 @@ u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih) | |||
| 891 | return fpdelay; | 740 | return fpdelay; |
| 892 | } | 741 | } |
| 893 | 742 | ||
| 894 | /* turn primary xtal and/or pll off/on */ | ||
| 895 | int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on) | ||
| 896 | { | ||
| 897 | struct si_info *sii; | ||
| 898 | u32 in, out, outen; | ||
| 899 | |||
| 900 | sii = (struct si_info *)sih; | ||
| 901 | |||
| 902 | /* pcie core doesn't have any mapping to control the xtal pu */ | ||
| 903 | if (PCIE(sih)) | ||
| 904 | return -1; | ||
| 905 | |||
| 906 | pci_read_config_dword(sii->pcibus, PCI_GPIO_IN, &in); | ||
| 907 | pci_read_config_dword(sii->pcibus, PCI_GPIO_OUT, &out); | ||
| 908 | pci_read_config_dword(sii->pcibus, PCI_GPIO_OUTEN, &outen); | ||
| 909 | |||
| 910 | /* | ||
| 911 | * Avoid glitching the clock if GPRS is already using it. | ||
| 912 | * We can't actually read the state of the PLLPD so we infer it | ||
| 913 | * by the value of XTAL_PU which *is* readable via gpioin. | ||
| 914 | */ | ||
| 915 | if (on && (in & PCI_CFG_GPIO_XTAL)) | ||
| 916 | return 0; | ||
| 917 | |||
| 918 | if (what & XTAL) | ||
| 919 | outen |= PCI_CFG_GPIO_XTAL; | ||
| 920 | if (what & PLL) | ||
| 921 | outen |= PCI_CFG_GPIO_PLL; | ||
| 922 | |||
| 923 | if (on) { | ||
| 924 | /* turn primary xtal on */ | ||
| 925 | if (what & XTAL) { | ||
| 926 | out |= PCI_CFG_GPIO_XTAL; | ||
| 927 | if (what & PLL) | ||
| 928 | out |= PCI_CFG_GPIO_PLL; | ||
| 929 | pci_write_config_dword(sii->pcibus, | ||
| 930 | PCI_GPIO_OUT, out); | ||
| 931 | pci_write_config_dword(sii->pcibus, | ||
| 932 | PCI_GPIO_OUTEN, outen); | ||
| 933 | udelay(XTAL_ON_DELAY); | ||
| 934 | } | ||
| 935 | |||
| 936 | /* turn pll on */ | ||
| 937 | if (what & PLL) { | ||
| 938 | out &= ~PCI_CFG_GPIO_PLL; | ||
| 939 | pci_write_config_dword(sii->pcibus, | ||
| 940 | PCI_GPIO_OUT, out); | ||
| 941 | mdelay(2); | ||
| 942 | } | ||
| 943 | } else { | ||
| 944 | if (what & XTAL) | ||
| 945 | out &= ~PCI_CFG_GPIO_XTAL; | ||
| 946 | if (what & PLL) | ||
| 947 | out |= PCI_CFG_GPIO_PLL; | ||
| 948 | pci_write_config_dword(sii->pcibus, | ||
| 949 | PCI_GPIO_OUT, out); | ||
| 950 | pci_write_config_dword(sii->pcibus, | ||
| 951 | PCI_GPIO_OUTEN, outen); | ||
| 952 | } | ||
| 953 | |||
| 954 | return 0; | ||
| 955 | } | ||
| 956 | |||
| 957 | /* clk control mechanism through chipcommon, no policy checking */ | ||
| 958 | static bool _ai_clkctl_cc(struct si_info *sii, uint mode) | ||
| 959 | { | ||
| 960 | struct bcma_device *cc; | ||
| 961 | u32 scc; | ||
| 962 | |||
| 963 | /* chipcommon cores prior to rev6 don't support dynamic clock control */ | ||
| 964 | if (ai_get_ccrev(&sii->pub) < 6) | ||
| 965 | return false; | ||
| 966 | |||
| 967 | cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0); | ||
| 968 | |||
| 969 | if (!(ai_get_cccaps(&sii->pub) & CC_CAP_PWR_CTL) && | ||
| 970 | (ai_get_ccrev(&sii->pub) < 20)) | ||
| 971 | return mode == CLK_FAST; | ||
| 972 | |||
| 973 | switch (mode) { | ||
| 974 | case CLK_FAST: /* FORCEHT, fast (pll) clock */ | ||
| 975 | if (ai_get_ccrev(&sii->pub) < 10) { | ||
| 976 | /* | ||
| 977 | * don't forget to force xtal back | ||
| 978 | * on before we clear SCC_DYN_XTAL.. | ||
| 979 | */ | ||
| 980 | ai_clkctl_xtal(&sii->pub, XTAL, ON); | ||
| 981 | bcma_maskset32(cc, CHIPCREGOFFS(slow_clk_ctl), | ||
| 982 | (SCC_XC | SCC_FS | SCC_IP), SCC_IP); | ||
| 983 | } else if (ai_get_ccrev(&sii->pub) < 20) { | ||
| 984 | bcma_set32(cc, CHIPCREGOFFS(system_clk_ctl), SYCC_HR); | ||
| 985 | } else { | ||
| 986 | bcma_set32(cc, CHIPCREGOFFS(clk_ctl_st), CCS_FORCEHT); | ||
| 987 | } | ||
| 988 | |||
| 989 | /* wait for the PLL */ | ||
| 990 | if (ai_get_cccaps(&sii->pub) & CC_CAP_PMU) { | ||
| 991 | u32 htavail = CCS_HTAVAIL; | ||
| 992 | SPINWAIT(((bcma_read32(cc, CHIPCREGOFFS(clk_ctl_st)) & | ||
| 993 | htavail) == 0), PMU_MAX_TRANSITION_DLY); | ||
| 994 | } else { | ||
| 995 | udelay(PLL_DELAY); | ||
| 996 | } | ||
| 997 | break; | ||
| 998 | |||
| 999 | case CLK_DYNAMIC: /* enable dynamic clock control */ | ||
| 1000 | if (ai_get_ccrev(&sii->pub) < 10) { | ||
| 1001 | scc = bcma_read32(cc, CHIPCREGOFFS(slow_clk_ctl)); | ||
| 1002 | scc &= ~(SCC_FS | SCC_IP | SCC_XC); | ||
| 1003 | if ((scc & SCC_SS_MASK) != SCC_SS_XTAL) | ||
| 1004 | scc |= SCC_XC; | ||
| 1005 | bcma_write32(cc, CHIPCREGOFFS(slow_clk_ctl), scc); | ||
| 1006 | |||
| 1007 | /* | ||
| 1008 | * for dynamic control, we have to | ||
| 1009 | * release our xtal_pu "force on" | ||
| 1010 | */ | ||
| 1011 | if (scc & SCC_XC) | ||
| 1012 | ai_clkctl_xtal(&sii->pub, XTAL, OFF); | ||
| 1013 | } else if (ai_get_ccrev(&sii->pub) < 20) { | ||
| 1014 | /* Instaclock */ | ||
| 1015 | bcma_mask32(cc, CHIPCREGOFFS(system_clk_ctl), ~SYCC_HR); | ||
| 1016 | } else { | ||
| 1017 | bcma_mask32(cc, CHIPCREGOFFS(clk_ctl_st), ~CCS_FORCEHT); | ||
| 1018 | } | ||
| 1019 | break; | ||
| 1020 | |||
| 1021 | default: | ||
| 1022 | break; | ||
| 1023 | } | ||
| 1024 | |||
| 1025 | return mode == CLK_FAST; | ||
| 1026 | } | ||
| 1027 | |||
| 1028 | /* | 743 | /* |
| 1029 | * clock control policy function throught chipcommon | 744 | * clock control policy function throught chipcommon |
| 1030 | * | 745 | * |
| @@ -1033,133 +748,53 @@ static bool _ai_clkctl_cc(struct si_info *sii, uint mode) | |||
| 1033 | * this is a wrapper over the next internal function | 748 | * this is a wrapper over the next internal function |
| 1034 | * to allow flexible policy settings for outside caller | 749 | * to allow flexible policy settings for outside caller |
| 1035 | */ | 750 | */ |
| 1036 | bool ai_clkctl_cc(struct si_pub *sih, uint mode) | 751 | bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode) |
| 1037 | { | 752 | { |
| 1038 | struct si_info *sii; | 753 | struct si_info *sii; |
| 754 | struct bcma_device *cc; | ||
| 1039 | 755 | ||
| 1040 | sii = (struct si_info *)sih; | 756 | sii = (struct si_info *)sih; |
| 1041 | 757 | ||
| 1042 | /* chipcommon cores prior to rev6 don't support dynamic clock control */ | ||
| 1043 | if (ai_get_ccrev(sih) < 6) | ||
| 1044 | return false; | ||
| 1045 | |||
| 1046 | if (PCI_FORCEHT(sih)) | 758 | if (PCI_FORCEHT(sih)) |
| 1047 | return mode == CLK_FAST; | 759 | return mode == BCMA_CLKMODE_FAST; |
| 1048 | 760 | ||
| 1049 | return _ai_clkctl_cc(sii, mode); | 761 | cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0); |
| 762 | bcma_core_set_clockmode(cc, mode); | ||
| 763 | return mode == BCMA_CLKMODE_FAST; | ||
| 1050 | } | 764 | } |
| 1051 | 765 | ||
| 1052 | void ai_pci_up(struct si_pub *sih) | 766 | void ai_pci_up(struct si_pub *sih) |
| 1053 | { | 767 | { |
| 1054 | struct si_info *sii; | 768 | struct si_info *sii; |
| 769 | struct bcma_device *cc; | ||
| 1055 | 770 | ||
| 1056 | sii = (struct si_info *)sih; | 771 | sii = (struct si_info *)sih; |
| 1057 | 772 | ||
| 1058 | if (PCI_FORCEHT(sih)) | 773 | if (PCI_FORCEHT(sih)) { |
| 1059 | _ai_clkctl_cc(sii, CLK_FAST); | 774 | cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0); |
| 775 | bcma_core_set_clockmode(cc, BCMA_CLKMODE_FAST); | ||
| 776 | } | ||
| 1060 | 777 | ||
| 1061 | if (PCIE(sih)) | 778 | if (PCIE(sih)) |
| 1062 | pcicore_up(sii->pch, SI_PCIUP); | 779 | bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, true); |
| 1063 | |||
| 1064 | } | ||
| 1065 | |||
| 1066 | /* Unconfigure and/or apply various WARs when system is going to sleep mode */ | ||
| 1067 | void ai_pci_sleep(struct si_pub *sih) | ||
| 1068 | { | ||
| 1069 | struct si_info *sii; | ||
| 1070 | |||
| 1071 | sii = (struct si_info *)sih; | ||
| 1072 | |||
| 1073 | pcicore_sleep(sii->pch); | ||
| 1074 | } | 780 | } |
| 1075 | 781 | ||
| 1076 | /* Unconfigure and/or apply various WARs when going down */ | 782 | /* Unconfigure and/or apply various WARs when going down */ |
| 1077 | void ai_pci_down(struct si_pub *sih) | 783 | void ai_pci_down(struct si_pub *sih) |
| 1078 | { | 784 | { |
| 1079 | struct si_info *sii; | 785 | struct si_info *sii; |
| 786 | struct bcma_device *cc; | ||
| 1080 | 787 | ||
| 1081 | sii = (struct si_info *)sih; | 788 | sii = (struct si_info *)sih; |
| 1082 | 789 | ||
| 1083 | /* release FORCEHT since chip is going to "down" state */ | 790 | /* release FORCEHT since chip is going to "down" state */ |
| 1084 | if (PCI_FORCEHT(sih)) | 791 | if (PCI_FORCEHT(sih)) { |
| 1085 | _ai_clkctl_cc(sii, CLK_DYNAMIC); | 792 | cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0); |
| 1086 | 793 | bcma_core_set_clockmode(cc, BCMA_CLKMODE_DYNAMIC); | |
| 1087 | pcicore_down(sii->pch, SI_PCIDOWN); | ||
| 1088 | } | ||
| 1089 | |||
| 1090 | /* | ||
| 1091 | * Configure the pci core for pci client (NIC) action | ||
| 1092 | * coremask is the bitvec of cores by index to be enabled. | ||
| 1093 | */ | ||
| 1094 | void ai_pci_setup(struct si_pub *sih, uint coremask) | ||
| 1095 | { | ||
| 1096 | struct si_info *sii; | ||
| 1097 | u32 w; | ||
| 1098 | |||
| 1099 | sii = (struct si_info *)sih; | ||
| 1100 | |||
| 1101 | /* | ||
| 1102 | * Enable sb->pci interrupts. Assume | ||
| 1103 | * PCI rev 2.3 support was added in pci core rev 6 and things changed.. | ||
| 1104 | */ | ||
| 1105 | if (PCIE(sih) || (PCI(sih) && (ai_get_buscorerev(sih) >= 6))) { | ||
| 1106 | /* pci config write to set this core bit in PCIIntMask */ | ||
| 1107 | pci_read_config_dword(sii->pcibus, PCI_INT_MASK, &w); | ||
| 1108 | w |= (coremask << PCI_SBIM_SHIFT); | ||
| 1109 | pci_write_config_dword(sii->pcibus, PCI_INT_MASK, w); | ||
| 1110 | } | ||
| 1111 | |||
| 1112 | if (PCI(sih)) { | ||
| 1113 | pcicore_pci_setup(sii->pch); | ||
| 1114 | } | 794 | } |
| 1115 | } | ||
| 1116 | 795 | ||
| 1117 | /* | 796 | if (PCIE(sih)) |
| 1118 | * Fixup SROMless PCI device's configuration. | 797 | bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, false); |
| 1119 | * The current core may be changed upon return. | ||
| 1120 | */ | ||
| 1121 | int ai_pci_fixcfg(struct si_pub *sih) | ||
| 1122 | { | ||
| 1123 | struct si_info *sii = (struct si_info *)sih; | ||
| 1124 | |||
| 1125 | /* Fixup PI in SROM shadow area to enable the correct PCI core access */ | ||
| 1126 | /* check 'pi' is correct and fix it if not */ | ||
| 1127 | pcicore_fixcfg(sii->pch); | ||
| 1128 | pcicore_hwup(sii->pch); | ||
| 1129 | return 0; | ||
| 1130 | } | ||
| 1131 | |||
| 1132 | /* mask&set gpiocontrol bits */ | ||
| 1133 | u32 ai_gpiocontrol(struct si_pub *sih, u32 mask, u32 val, u8 priority) | ||
| 1134 | { | ||
| 1135 | uint regoff; | ||
| 1136 | |||
| 1137 | regoff = offsetof(struct chipcregs, gpiocontrol); | ||
| 1138 | return ai_cc_reg(sih, regoff, mask, val); | ||
| 1139 | } | ||
| 1140 | |||
| 1141 | void ai_chipcontrl_epa4331(struct si_pub *sih, bool on) | ||
| 1142 | { | ||
| 1143 | struct bcma_device *cc; | ||
| 1144 | u32 val; | ||
| 1145 | |||
| 1146 | cc = ai_findcore(sih, CC_CORE_ID, 0); | ||
| 1147 | |||
| 1148 | if (on) { | ||
| 1149 | if (ai_get_chippkg(sih) == 9 || ai_get_chippkg(sih) == 0xb) | ||
| 1150 | /* Ext PA Controls for 4331 12x9 Package */ | ||
| 1151 | bcma_set32(cc, CHIPCREGOFFS(chipcontrol), | ||
| 1152 | CCTRL4331_EXTPA_EN | | ||
| 1153 | CCTRL4331_EXTPA_ON_GPIO2_5); | ||
| 1154 | else | ||
| 1155 | /* Ext PA Controls for 4331 12x12 Package */ | ||
| 1156 | bcma_set32(cc, CHIPCREGOFFS(chipcontrol), | ||
| 1157 | CCTRL4331_EXTPA_EN); | ||
| 1158 | } else { | ||
| 1159 | val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5); | ||
| 1160 | bcma_mask32(cc, CHIPCREGOFFS(chipcontrol), | ||
| 1161 | ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5)); | ||
| 1162 | } | ||
| 1163 | } | 798 | } |
| 1164 | 799 | ||
| 1165 | /* Enable BT-COEX & Ex-PA for 4313 */ | 800 | /* Enable BT-COEX & Ex-PA for 4313 */ |
| @@ -1181,6 +816,9 @@ bool ai_deviceremoved(struct si_pub *sih) | |||
| 1181 | 816 | ||
| 1182 | sii = (struct si_info *)sih; | 817 | sii = (struct si_info *)sih; |
| 1183 | 818 | ||
| 819 | if (sii->icbus->hosttype != BCMA_HOSTTYPE_PCI) | ||
| 820 | return false; | ||
| 821 | |||
| 1184 | pci_read_config_dword(sii->pcibus, PCI_VENDOR_ID, &w); | 822 | pci_read_config_dword(sii->pcibus, PCI_VENDOR_ID, &w); |
| 1185 | if ((w & 0xFFFF) != PCI_VENDOR_ID_BROADCOM) | 823 | if ((w & 0xFFFF) != PCI_VENDOR_ID_BROADCOM) |
| 1186 | return true; | 824 | return true; |
| @@ -1188,45 +826,6 @@ bool ai_deviceremoved(struct si_pub *sih) | |||
| 1188 | return false; | 826 | return false; |
| 1189 | } | 827 | } |
| 1190 | 828 | ||
| 1191 | bool ai_is_sprom_available(struct si_pub *sih) | ||
| 1192 | { | ||
| 1193 | struct si_info *sii = (struct si_info *)sih; | ||
| 1194 | |||
| 1195 | if (ai_get_ccrev(sih) >= 31) { | ||
| 1196 | struct bcma_device *cc; | ||
| 1197 | u32 sromctrl; | ||
| 1198 | |||
| 1199 | if ((ai_get_cccaps(sih) & CC_CAP_SROM) == 0) | ||
| 1200 | return false; | ||
| 1201 | |||
| 1202 | cc = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); | ||
| 1203 | sromctrl = bcma_read32(cc, CHIPCREGOFFS(sromcontrol)); | ||
| 1204 | return sromctrl & SRC_PRESENT; | ||
| 1205 | } | ||
| 1206 | |||
| 1207 | switch (ai_get_chip_id(sih)) { | ||
| 1208 | case BCM4313_CHIP_ID: | ||
| 1209 | return (sii->chipst & CST4313_SPROM_PRESENT) != 0; | ||
| 1210 | default: | ||
| 1211 | return true; | ||
| 1212 | } | ||
| 1213 | } | ||
| 1214 | |||
| 1215 | bool ai_is_otp_disabled(struct si_pub *sih) | ||
| 1216 | { | ||
| 1217 | struct si_info *sii = (struct si_info *)sih; | ||
| 1218 | |||
| 1219 | switch (ai_get_chip_id(sih)) { | ||
| 1220 | case BCM4313_CHIP_ID: | ||
| 1221 | return (sii->chipst & CST4313_OTP_PRESENT) == 0; | ||
| 1222 | /* These chips always have their OTP on */ | ||
| 1223 | case BCM43224_CHIP_ID: | ||
| 1224 | case BCM43225_CHIP_ID: | ||
| 1225 | default: | ||
| 1226 | return false; | ||
| 1227 | } | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | uint ai_get_buscoretype(struct si_pub *sih) | 829 | uint ai_get_buscoretype(struct si_pub *sih) |
| 1231 | { | 830 | { |
| 1232 | struct si_info *sii = (struct si_info *)sih; | 831 | struct si_info *sii = (struct si_info *)sih; |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h index f84c6f78169..d9f04a683bd 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h | |||
| @@ -113,10 +113,6 @@ | |||
| 113 | #define XTAL 0x1 /* primary crystal oscillator (2050) */ | 113 | #define XTAL 0x1 /* primary crystal oscillator (2050) */ |
| 114 | #define PLL 0x2 /* main chip pll */ | 114 | #define PLL 0x2 /* main chip pll */ |
| 115 | 115 | ||
| 116 | /* clkctl clk mode */ | ||
| 117 | #define CLK_FAST 0 /* force fast (pll) clock */ | ||
| 118 | #define CLK_DYNAMIC 2 /* enable dynamic clock control */ | ||
| 119 | |||
| 120 | /* GPIO usage priorities */ | 116 | /* GPIO usage priorities */ |
| 121 | #define GPIO_DRV_PRIORITY 0 /* Driver */ | 117 | #define GPIO_DRV_PRIORITY 0 /* Driver */ |
| 122 | #define GPIO_APP_PRIORITY 1 /* Application */ | 118 | #define GPIO_APP_PRIORITY 1 /* Application */ |
| @@ -172,9 +168,7 @@ struct si_info { | |||
| 172 | struct si_pub pub; /* back plane public state (must be first) */ | 168 | struct si_pub pub; /* back plane public state (must be first) */ |
| 173 | struct bcma_bus *icbus; /* handle to soc interconnect bus */ | 169 | struct bcma_bus *icbus; /* handle to soc interconnect bus */ |
| 174 | struct pci_dev *pcibus; /* handle to pci bus */ | 170 | struct pci_dev *pcibus; /* handle to pci bus */ |
| 175 | struct pcicore_info *pch; /* PCI/E core handle */ | ||
| 176 | struct bcma_device *buscore; | 171 | struct bcma_device *buscore; |
| 177 | struct list_head var_list; /* list of srom variables */ | ||
| 178 | 172 | ||
| 179 | u32 chipst; /* chip status */ | 173 | u32 chipst; /* chip status */ |
| 180 | }; | 174 | }; |
| @@ -197,38 +191,20 @@ extern u32 ai_core_cflags(struct bcma_device *core, u32 mask, u32 val); | |||
| 197 | extern struct si_pub *ai_attach(struct bcma_bus *pbus); | 191 | extern struct si_pub *ai_attach(struct bcma_bus *pbus); |
| 198 | extern void ai_detach(struct si_pub *sih); | 192 | extern void ai_detach(struct si_pub *sih); |
| 199 | extern uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val); | 193 | extern uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val); |
| 200 | extern void ai_pci_setup(struct si_pub *sih, uint coremask); | ||
| 201 | extern void ai_clkctl_init(struct si_pub *sih); | 194 | extern void ai_clkctl_init(struct si_pub *sih); |
| 202 | extern u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih); | 195 | extern u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih); |
| 203 | extern bool ai_clkctl_cc(struct si_pub *sih, uint mode); | 196 | extern bool ai_clkctl_cc(struct si_pub *sih, uint mode); |
| 204 | extern int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on); | ||
| 205 | extern bool ai_deviceremoved(struct si_pub *sih); | 197 | extern bool ai_deviceremoved(struct si_pub *sih); |
| 206 | extern u32 ai_gpiocontrol(struct si_pub *sih, u32 mask, u32 val, | ||
| 207 | u8 priority); | ||
| 208 | |||
| 209 | /* OTP status */ | ||
| 210 | extern bool ai_is_otp_disabled(struct si_pub *sih); | ||
| 211 | |||
| 212 | /* SPROM availability */ | ||
| 213 | extern bool ai_is_sprom_available(struct si_pub *sih); | ||
| 214 | 198 | ||
| 215 | extern void ai_pci_sleep(struct si_pub *sih); | ||
| 216 | extern void ai_pci_down(struct si_pub *sih); | 199 | extern void ai_pci_down(struct si_pub *sih); |
| 217 | extern void ai_pci_up(struct si_pub *sih); | 200 | extern void ai_pci_up(struct si_pub *sih); |
| 218 | extern int ai_pci_fixcfg(struct si_pub *sih); | ||
| 219 | 201 | ||
| 220 | extern void ai_chipcontrl_epa4331(struct si_pub *sih, bool on); | ||
| 221 | /* Enable Ex-PA for 4313 */ | 202 | /* Enable Ex-PA for 4313 */ |
| 222 | extern void ai_epa_4313war(struct si_pub *sih); | 203 | extern void ai_epa_4313war(struct si_pub *sih); |
| 223 | 204 | ||
| 224 | extern uint ai_get_buscoretype(struct si_pub *sih); | 205 | extern uint ai_get_buscoretype(struct si_pub *sih); |
| 225 | extern uint ai_get_buscorerev(struct si_pub *sih); | 206 | extern uint ai_get_buscorerev(struct si_pub *sih); |
| 226 | 207 | ||
| 227 | static inline int ai_get_ccrev(struct si_pub *sih) | ||
| 228 | { | ||
| 229 | return sih->ccrev; | ||
| 230 | } | ||
| 231 | |||
| 232 | static inline u32 ai_get_cccaps(struct si_pub *sih) | 208 | static inline u32 ai_get_cccaps(struct si_pub *sih) |
| 233 | { | 209 | { |
| 234 | return sih->cccaps; | 210 | return sih->cccaps; |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/antsel.c b/drivers/net/wireless/brcm80211/brcmsmac/antsel.c index a47ce25cb9a..55e12c32791 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/antsel.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/antsel.c | |||
| @@ -108,7 +108,7 @@ brcms_c_antsel_init_cfg(struct antsel_info *asi, struct brcms_antselcfg *antsel, | |||
| 108 | struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc) | 108 | struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc) |
| 109 | { | 109 | { |
| 110 | struct antsel_info *asi; | 110 | struct antsel_info *asi; |
| 111 | struct si_pub *sih = wlc->hw->sih; | 111 | struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom; |
| 112 | 112 | ||
| 113 | asi = kzalloc(sizeof(struct antsel_info), GFP_ATOMIC); | 113 | asi = kzalloc(sizeof(struct antsel_info), GFP_ATOMIC); |
| 114 | if (!asi) | 114 | if (!asi) |
| @@ -118,7 +118,7 @@ struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc) | |||
| 118 | asi->pub = wlc->pub; | 118 | asi->pub = wlc->pub; |
| 119 | asi->antsel_type = ANTSEL_NA; | 119 | asi->antsel_type = ANTSEL_NA; |
| 120 | asi->antsel_avail = false; | 120 | asi->antsel_avail = false; |
| 121 | asi->antsel_antswitch = (u8) getintvar(sih, BRCMS_SROM_ANTSWITCH); | 121 | asi->antsel_antswitch = sprom->antswitch; |
| 122 | 122 | ||
| 123 | if ((asi->pub->sromrev >= 4) && (asi->antsel_antswitch != 0)) { | 123 | if ((asi->pub->sromrev >= 4) && (asi->antsel_antswitch != 0)) { |
| 124 | switch (asi->antsel_antswitch) { | 124 | switch (asi->antsel_antswitch) { |
| @@ -128,12 +128,12 @@ struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc) | |||
| 128 | /* 4321/2 board with 2x3 switch logic */ | 128 | /* 4321/2 board with 2x3 switch logic */ |
| 129 | asi->antsel_type = ANTSEL_2x3; | 129 | asi->antsel_type = ANTSEL_2x3; |
| 130 | /* Antenna selection availability */ | 130 | /* Antenna selection availability */ |
| 131 | if (((u16) getintvar(sih, BRCMS_SROM_AA2G) == 7) || | 131 | if ((sprom->ant_available_bg == 7) || |
| 132 | ((u16) getintvar(sih, BRCMS_SROM_AA5G) == 7)) { | 132 | (sprom->ant_available_a == 7)) { |
| 133 | asi->antsel_avail = true; | 133 | asi->antsel_avail = true; |
| 134 | } else if ( | 134 | } else if ( |
| 135 | (u16) getintvar(sih, BRCMS_SROM_AA2G) == 3 || | 135 | sprom->ant_available_bg == 3 || |
| 136 | (u16) getintvar(sih, BRCMS_SROM_AA5G) == 3) { | 136 | sprom->ant_available_a == 3) { |
| 137 | asi->antsel_avail = false; | 137 | asi->antsel_avail = false; |
| 138 | } else { | 138 | } else { |
| 139 | asi->antsel_avail = false; | 139 | asi->antsel_avail = false; |
| @@ -146,8 +146,8 @@ struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc) | |||
| 146 | break; | 146 | break; |
| 147 | } | 147 | } |
| 148 | } else if ((asi->pub->sromrev == 4) && | 148 | } else if ((asi->pub->sromrev == 4) && |
| 149 | ((u16) getintvar(sih, BRCMS_SROM_AA2G) == 7) && | 149 | (sprom->ant_available_bg == 7) && |
| 150 | ((u16) getintvar(sih, BRCMS_SROM_AA5G) == 0)) { | 150 | (sprom->ant_available_a == 0)) { |
| 151 | /* hack to match old 4321CB2 cards with 2of3 antenna switch */ | 151 | /* hack to match old 4321CB2 cards with 2of3 antenna switch */ |
| 152 | asi->antsel_type = ANTSEL_2x3; | 152 | asi->antsel_type = ANTSEL_2x3; |
| 153 | asi->antsel_avail = true; | 153 | asi->antsel_avail = true; |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c index 0efe88e25a9..eb77ac3cfb6 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c | |||
| @@ -1110,7 +1110,7 @@ struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc) | |||
| 1110 | char country_abbrev[BRCM_CNTRY_BUF_SZ]; | 1110 | char country_abbrev[BRCM_CNTRY_BUF_SZ]; |
| 1111 | const struct country_info *country; | 1111 | const struct country_info *country; |
| 1112 | struct brcms_pub *pub = wlc->pub; | 1112 | struct brcms_pub *pub = wlc->pub; |
| 1113 | char *ccode; | 1113 | struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom; |
| 1114 | 1114 | ||
| 1115 | BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); | 1115 | BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); |
| 1116 | 1116 | ||
| @@ -1122,9 +1122,8 @@ struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc) | |||
| 1122 | wlc->cmi = wlc_cm; | 1122 | wlc->cmi = wlc_cm; |
| 1123 | 1123 | ||
| 1124 | /* store the country code for passing up as a regulatory hint */ | 1124 | /* store the country code for passing up as a regulatory hint */ |
| 1125 | ccode = getvar(wlc->hw->sih, BRCMS_SROM_CCODE); | 1125 | if (sprom->alpha2 && brcms_c_country_valid(sprom->alpha2)) |
| 1126 | if (ccode && brcms_c_country_valid(ccode)) | 1126 | strncpy(wlc->pub->srom_ccode, sprom->alpha2, sizeof(sprom->alpha2)); |
| 1127 | strncpy(wlc->pub->srom_ccode, ccode, BRCM_CNTRY_BUF_SZ - 1); | ||
| 1128 | 1127 | ||
| 1129 | /* | 1128 | /* |
| 1130 | * internal country information which must match | 1129 | * internal country information which must match |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index aa15558f75c..50f92a0b7c4 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | #include <linux/bcma/bcma.h> | 25 | #include <linux/bcma/bcma.h> |
| 26 | #include <net/mac80211.h> | 26 | #include <net/mac80211.h> |
| 27 | #include <defs.h> | 27 | #include <defs.h> |
| 28 | #include "nicpci.h" | ||
| 29 | #include "phy/phy_int.h" | 28 | #include "phy/phy_int.h" |
| 30 | #include "d11.h" | 29 | #include "d11.h" |
| 31 | #include "channel.h" | 30 | #include "channel.h" |
| @@ -770,7 +769,7 @@ void brcms_dpc(unsigned long data) | |||
| 770 | * Precondition: Since this function is called in brcms_pci_probe() context, | 769 | * Precondition: Since this function is called in brcms_pci_probe() context, |
| 771 | * no locking is required. | 770 | * no locking is required. |
| 772 | */ | 771 | */ |
| 773 | static int brcms_request_fw(struct brcms_info *wl, struct pci_dev *pdev) | 772 | static int brcms_request_fw(struct brcms_info *wl, struct bcma_device *pdev) |
| 774 | { | 773 | { |
| 775 | int status; | 774 | int status; |
| 776 | struct device *device = &pdev->dev; | 775 | struct device *device = &pdev->dev; |
| @@ -1022,7 +1021,7 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev) | |||
| 1022 | spin_lock_init(&wl->isr_lock); | 1021 | spin_lock_init(&wl->isr_lock); |
| 1023 | 1022 | ||
| 1024 | /* prepare ucode */ | 1023 | /* prepare ucode */ |
| 1025 | if (brcms_request_fw(wl, pdev->bus->host_pci) < 0) { | 1024 | if (brcms_request_fw(wl, pdev) < 0) { |
| 1026 | wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in " | 1025 | wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in " |
| 1027 | "%s\n", KBUILD_MODNAME, "/lib/firmware/brcm"); | 1026 | "%s\n", KBUILD_MODNAME, "/lib/firmware/brcm"); |
| 1028 | brcms_release_fw(wl); | 1027 | brcms_release_fw(wl); |
| @@ -1043,12 +1042,12 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev) | |||
| 1043 | wl->pub->ieee_hw = hw; | 1042 | wl->pub->ieee_hw = hw; |
| 1044 | 1043 | ||
| 1045 | /* register our interrupt handler */ | 1044 | /* register our interrupt handler */ |
| 1046 | if (request_irq(pdev->bus->host_pci->irq, brcms_isr, | 1045 | if (request_irq(pdev->irq, brcms_isr, |
| 1047 | IRQF_SHARED, KBUILD_MODNAME, wl)) { | 1046 | IRQF_SHARED, KBUILD_MODNAME, wl)) { |
| 1048 | wiphy_err(wl->wiphy, "wl%d: request_irq() failed\n", unit); | 1047 | wiphy_err(wl->wiphy, "wl%d: request_irq() failed\n", unit); |
| 1049 | goto fail; | 1048 | goto fail; |
| 1050 | } | 1049 | } |
| 1051 | wl->irq = pdev->bus->host_pci->irq; | 1050 | wl->irq = pdev->irq; |
| 1052 | 1051 | ||
| 1053 | /* register module */ | 1052 | /* register module */ |
| 1054 | brcms_c_module_register(wl->pub, "linux", wl, NULL); | 1053 | brcms_c_module_register(wl->pub, "linux", wl, NULL); |
| @@ -1098,7 +1097,7 @@ static int __devinit brcms_bcma_probe(struct bcma_device *pdev) | |||
| 1098 | 1097 | ||
| 1099 | dev_info(&pdev->dev, "mfg %x core %x rev %d class %d irq %d\n", | 1098 | dev_info(&pdev->dev, "mfg %x core %x rev %d class %d irq %d\n", |
| 1100 | pdev->id.manuf, pdev->id.id, pdev->id.rev, pdev->id.class, | 1099 | pdev->id.manuf, pdev->id.id, pdev->id.rev, pdev->id.class, |
| 1101 | pdev->bus->host_pci->irq); | 1100 | pdev->irq); |
| 1102 | 1101 | ||
| 1103 | if ((pdev->id.manuf != BCMA_MANUF_BCM) || | 1102 | if ((pdev->id.manuf != BCMA_MANUF_BCM) || |
| 1104 | (pdev->id.id != BCMA_CORE_80211)) | 1103 | (pdev->id.id != BCMA_CORE_80211)) |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index b4d92792c50..19db4052c44 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c | |||
| @@ -1219,7 +1219,7 @@ static void brcms_b_wait_for_wake(struct brcms_hardware *wlc_hw) | |||
| 1219 | } | 1219 | } |
| 1220 | 1220 | ||
| 1221 | /* control chip clock to save power, enable dynamic clock or force fast clock */ | 1221 | /* control chip clock to save power, enable dynamic clock or force fast clock */ |
| 1222 | static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode) | 1222 | static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, enum bcma_clkmode mode) |
| 1223 | { | 1223 | { |
| 1224 | if (ai_get_cccaps(wlc_hw->sih) & CC_CAP_PMU) { | 1224 | if (ai_get_cccaps(wlc_hw->sih) & CC_CAP_PMU) { |
| 1225 | /* new chips with PMU, CCS_FORCEHT will distribute the HT clock | 1225 | /* new chips with PMU, CCS_FORCEHT will distribute the HT clock |
| @@ -1229,7 +1229,7 @@ static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode) | |||
| 1229 | */ | 1229 | */ |
| 1230 | 1230 | ||
| 1231 | if (wlc_hw->clk) { | 1231 | if (wlc_hw->clk) { |
| 1232 | if (mode == CLK_FAST) { | 1232 | if (mode == BCMA_CLKMODE_FAST) { |
| 1233 | bcma_set32(wlc_hw->d11core, | 1233 | bcma_set32(wlc_hw->d11core, |
| 1234 | D11REGOFFS(clk_ctl_st), | 1234 | D11REGOFFS(clk_ctl_st), |
| 1235 | CCS_FORCEHT); | 1235 | CCS_FORCEHT); |
| @@ -1260,7 +1260,7 @@ static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode) | |||
| 1260 | ~CCS_FORCEHT); | 1260 | ~CCS_FORCEHT); |
| 1261 | } | 1261 | } |
| 1262 | } | 1262 | } |
| 1263 | wlc_hw->forcefastclk = (mode == CLK_FAST); | 1263 | wlc_hw->forcefastclk = (mode == BCMA_CLKMODE_FAST); |
| 1264 | } else { | 1264 | } else { |
| 1265 | 1265 | ||
| 1266 | /* old chips w/o PMU, force HT through cc, | 1266 | /* old chips w/o PMU, force HT through cc, |
| @@ -1567,7 +1567,7 @@ void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw) | |||
| 1567 | /* request FAST clock if not on */ | 1567 | /* request FAST clock if not on */ |
| 1568 | fastclk = wlc_hw->forcefastclk; | 1568 | fastclk = wlc_hw->forcefastclk; |
| 1569 | if (!fastclk) | 1569 | if (!fastclk) |
| 1570 | brcms_b_clkctl_clk(wlc_hw, CLK_FAST); | 1570 | brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST); |
| 1571 | 1571 | ||
| 1572 | wlc_phy_bw_state_set(wlc_hw->band->pi, bw); | 1572 | wlc_phy_bw_state_set(wlc_hw->band->pi, bw); |
| 1573 | 1573 | ||
| @@ -1576,7 +1576,7 @@ void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw) | |||
| 1576 | 1576 | ||
| 1577 | /* restore the clk */ | 1577 | /* restore the clk */ |
| 1578 | if (!fastclk) | 1578 | if (!fastclk) |
| 1579 | brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); | 1579 | brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_DYNAMIC); |
| 1580 | } | 1580 | } |
| 1581 | 1581 | ||
| 1582 | static void brcms_b_upd_synthpu(struct brcms_hardware *wlc_hw) | 1582 | static void brcms_b_upd_synthpu(struct brcms_hardware *wlc_hw) |
| @@ -1882,27 +1882,20 @@ static bool brcms_c_validboardtype(struct brcms_hardware *wlc_hw) | |||
| 1882 | return true; | 1882 | return true; |
| 1883 | } | 1883 | } |
| 1884 | 1884 | ||
| 1885 | static char *brcms_c_get_macaddr(struct brcms_hardware *wlc_hw) | 1885 | static void brcms_c_get_macaddr(struct brcms_hardware *wlc_hw, u8 etheraddr[ETH_ALEN]) |
| 1886 | { | 1886 | { |
| 1887 | enum brcms_srom_id var_id = BRCMS_SROM_MACADDR; | 1887 | struct ssb_sprom *sprom = &wlc_hw->d11core->bus->sprom; |
| 1888 | char *macaddr; | ||
| 1889 | 1888 | ||
| 1890 | /* If macaddr exists, use it (Sromrev4, CIS, ...). */ | 1889 | /* If macaddr exists, use it (Sromrev4, CIS, ...). */ |
| 1891 | macaddr = getvar(wlc_hw->sih, var_id); | 1890 | if (!is_zero_ether_addr(sprom->il0mac)) { |
| 1892 | if (macaddr != NULL) | 1891 | memcpy(etheraddr, sprom->il0mac, 6); |
| 1893 | return macaddr; | 1892 | return; |
| 1893 | } | ||
| 1894 | 1894 | ||
| 1895 | if (wlc_hw->_nbands > 1) | 1895 | if (wlc_hw->_nbands > 1) |
| 1896 | var_id = BRCMS_SROM_ET1MACADDR; | 1896 | memcpy(etheraddr, sprom->et1mac, 6); |
| 1897 | else | 1897 | else |
| 1898 | var_id = BRCMS_SROM_IL0MACADDR; | 1898 | memcpy(etheraddr, sprom->il0mac, 6); |
| 1899 | |||
| 1900 | macaddr = getvar(wlc_hw->sih, var_id); | ||
| 1901 | if (macaddr == NULL) | ||
| 1902 | wiphy_err(wlc_hw->wlc->wiphy, "wl%d: wlc_get_macaddr: macaddr " | ||
| 1903 | "getvar(%d) not found\n", wlc_hw->unit, var_id); | ||
| 1904 | |||
| 1905 | return macaddr; | ||
| 1906 | } | 1899 | } |
| 1907 | 1900 | ||
| 1908 | /* power both the pll and external oscillator on/off */ | 1901 | /* power both the pll and external oscillator on/off */ |
| @@ -1917,9 +1910,6 @@ static void brcms_b_xtal(struct brcms_hardware *wlc_hw, bool want) | |||
| 1917 | if (!want && wlc_hw->pllreq) | 1910 | if (!want && wlc_hw->pllreq) |
| 1918 | return; | 1911 | return; |
| 1919 | 1912 | ||
| 1920 | if (wlc_hw->sih) | ||
| 1921 | ai_clkctl_xtal(wlc_hw->sih, XTAL | PLL, want); | ||
| 1922 | |||
| 1923 | wlc_hw->sbclk = want; | 1913 | wlc_hw->sbclk = want; |
| 1924 | if (!wlc_hw->sbclk) { | 1914 | if (!wlc_hw->sbclk) { |
| 1925 | wlc_hw->clk = false; | 1915 | wlc_hw->clk = false; |
| @@ -2004,7 +1994,7 @@ void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags) | |||
| 2004 | /* request FAST clock if not on */ | 1994 | /* request FAST clock if not on */ |
| 2005 | fastclk = wlc_hw->forcefastclk; | 1995 | fastclk = wlc_hw->forcefastclk; |
| 2006 | if (!fastclk) | 1996 | if (!fastclk) |
| 2007 | brcms_b_clkctl_clk(wlc_hw, CLK_FAST); | 1997 | brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST); |
| 2008 | 1998 | ||
| 2009 | /* reset the dma engines except first time thru */ | 1999 | /* reset the dma engines except first time thru */ |
| 2010 | if (bcma_core_is_enabled(wlc_hw->d11core)) { | 2000 | if (bcma_core_is_enabled(wlc_hw->d11core)) { |
| @@ -2053,7 +2043,7 @@ void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags) | |||
| 2053 | brcms_c_mctrl_reset(wlc_hw); | 2043 | brcms_c_mctrl_reset(wlc_hw); |
| 2054 | 2044 | ||
| 2055 | if (ai_get_cccaps(wlc_hw->sih) & CC_CAP_PMU) | 2045 | if (ai_get_cccaps(wlc_hw->sih) & CC_CAP_PMU) |
| 2056 | brcms_b_clkctl_clk(wlc_hw, CLK_FAST); | 2046 | brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST); |
| 2057 | 2047 | ||
| 2058 | brcms_b_phy_reset(wlc_hw); | 2048 | brcms_b_phy_reset(wlc_hw); |
| 2059 | 2049 | ||
| @@ -2065,7 +2055,7 @@ void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags) | |||
| 2065 | 2055 | ||
| 2066 | /* restore the clk setting */ | 2056 | /* restore the clk setting */ |
| 2067 | if (!fastclk) | 2057 | if (!fastclk) |
| 2068 | brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); | 2058 | brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_DYNAMIC); |
| 2069 | } | 2059 | } |
| 2070 | 2060 | ||
| 2071 | /* txfifo sizes needs to be modified(increased) since the newer cores | 2061 | /* txfifo sizes needs to be modified(increased) since the newer cores |
| @@ -2218,7 +2208,7 @@ static void brcms_c_gpio_init(struct brcms_c_info *wlc) | |||
| 2218 | gm |= gc |= BOARD_GPIO_PACTRL; | 2208 | gm |= gc |= BOARD_GPIO_PACTRL; |
| 2219 | 2209 | ||
| 2220 | /* apply to gpiocontrol register */ | 2210 | /* apply to gpiocontrol register */ |
| 2221 | ai_gpiocontrol(wlc_hw->sih, gm, gc, GPIO_DRV_PRIORITY); | 2211 | bcma_chipco_gpio_control(&wlc_hw->d11core->bus->drv_cc, gm, gc); |
| 2222 | } | 2212 | } |
| 2223 | 2213 | ||
| 2224 | static void brcms_ucode_write(struct brcms_hardware *wlc_hw, | 2214 | static void brcms_ucode_write(struct brcms_hardware *wlc_hw, |
| @@ -3371,7 +3361,7 @@ static brcms_b_init(struct brcms_hardware *wlc_hw, u16 chanspec) { | |||
| 3371 | /* request FAST clock if not on */ | 3361 | /* request FAST clock if not on */ |
| 3372 | fastclk = wlc_hw->forcefastclk; | 3362 | fastclk = wlc_hw->forcefastclk; |
| 3373 | if (!fastclk) | 3363 | if (!fastclk) |
| 3374 | brcms_b_clkctl_clk(wlc_hw, CLK_FAST); | 3364 | brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST); |
| 3375 | 3365 | ||
| 3376 | /* disable interrupts */ | 3366 | /* disable interrupts */ |
| 3377 | macintmask = brcms_intrsoff(wlc->wl); | 3367 | macintmask = brcms_intrsoff(wlc->wl); |
| @@ -3405,7 +3395,7 @@ static brcms_b_init(struct brcms_hardware *wlc_hw, u16 chanspec) { | |||
| 3405 | 3395 | ||
| 3406 | /* restore the clk */ | 3396 | /* restore the clk */ |
| 3407 | if (!fastclk) | 3397 | if (!fastclk) |
| 3408 | brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); | 3398 | brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_DYNAMIC); |
| 3409 | } | 3399 | } |
| 3410 | 3400 | ||
| 3411 | static void brcms_c_set_phy_chanspec(struct brcms_c_info *wlc, | 3401 | static void brcms_c_set_phy_chanspec(struct brcms_c_info *wlc, |
| @@ -4436,17 +4426,22 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, | |||
| 4436 | uint unit, bool piomode) | 4426 | uint unit, bool piomode) |
| 4437 | { | 4427 | { |
| 4438 | struct brcms_hardware *wlc_hw; | 4428 | struct brcms_hardware *wlc_hw; |
| 4439 | char *macaddr = NULL; | ||
| 4440 | uint err = 0; | 4429 | uint err = 0; |
| 4441 | uint j; | 4430 | uint j; |
| 4442 | bool wme = false; | 4431 | bool wme = false; |
| 4443 | struct shared_phy_params sha_params; | 4432 | struct shared_phy_params sha_params; |
| 4444 | struct wiphy *wiphy = wlc->wiphy; | 4433 | struct wiphy *wiphy = wlc->wiphy; |
| 4445 | struct pci_dev *pcidev = core->bus->host_pci; | 4434 | struct pci_dev *pcidev = core->bus->host_pci; |
| 4435 | struct ssb_sprom *sprom = &core->bus->sprom; | ||
| 4446 | 4436 | ||
| 4447 | BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit, | 4437 | if (core->bus->hosttype == BCMA_HOSTTYPE_PCI) |
| 4448 | pcidev->vendor, | 4438 | BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit, |
| 4449 | pcidev->device); | 4439 | pcidev->vendor, |
| 4440 | pcidev->device); | ||
| 4441 | else | ||
| 4442 | BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit, | ||
| 4443 | core->bus->boardinfo.vendor, | ||
| 4444 | core->bus->boardinfo.type); | ||
| 4450 | 4445 | ||
| 4451 | wme = true; | 4446 | wme = true; |
| 4452 | 4447 | ||
| @@ -4472,7 +4467,8 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, | |||
| 4472 | } | 4467 | } |
| 4473 | 4468 | ||
| 4474 | /* verify again the device is supported */ | 4469 | /* verify again the device is supported */ |
| 4475 | if (!brcms_c_chipmatch(pcidev->vendor, pcidev->device)) { | 4470 | if (core->bus->hosttype == BCMA_HOSTTYPE_PCI && |
| 4471 | !brcms_c_chipmatch(pcidev->vendor, pcidev->device)) { | ||
| 4476 | wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported " | 4472 | wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported " |
| 4477 | "vendor/device (0x%x/0x%x)\n", | 4473 | "vendor/device (0x%x/0x%x)\n", |
| 4478 | unit, pcidev->vendor, pcidev->device); | 4474 | unit, pcidev->vendor, pcidev->device); |
| @@ -4480,8 +4476,13 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, | |||
| 4480 | goto fail; | 4476 | goto fail; |
| 4481 | } | 4477 | } |
| 4482 | 4478 | ||
| 4483 | wlc_hw->vendorid = pcidev->vendor; | 4479 | if (core->bus->hosttype == BCMA_HOSTTYPE_PCI) { |
| 4484 | wlc_hw->deviceid = pcidev->device; | 4480 | wlc_hw->vendorid = pcidev->vendor; |
| 4481 | wlc_hw->deviceid = pcidev->device; | ||
| 4482 | } else { | ||
| 4483 | wlc_hw->vendorid = core->bus->boardinfo.vendor; | ||
| 4484 | wlc_hw->deviceid = core->bus->boardinfo.type; | ||
| 4485 | } | ||
| 4485 | 4486 | ||
| 4486 | wlc_hw->d11core = core; | 4487 | wlc_hw->d11core = core; |
| 4487 | wlc_hw->corerev = core->id.rev; | 4488 | wlc_hw->corerev = core->id.rev; |
| @@ -4501,7 +4502,7 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, | |||
| 4501 | * is still false; But it will be called again inside wlc_corereset, | 4502 | * is still false; But it will be called again inside wlc_corereset, |
| 4502 | * after d11 is out of reset. | 4503 | * after d11 is out of reset. |
| 4503 | */ | 4504 | */ |
| 4504 | brcms_b_clkctl_clk(wlc_hw, CLK_FAST); | 4505 | brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST); |
| 4505 | brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS); | 4506 | brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS); |
| 4506 | 4507 | ||
| 4507 | if (!brcms_b_validate_chip_access(wlc_hw)) { | 4508 | if (!brcms_b_validate_chip_access(wlc_hw)) { |
| @@ -4512,7 +4513,7 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, | |||
| 4512 | } | 4513 | } |
| 4513 | 4514 | ||
| 4514 | /* get the board rev, used just below */ | 4515 | /* get the board rev, used just below */ |
| 4515 | j = getintvar(wlc_hw->sih, BRCMS_SROM_BOARDREV); | 4516 | j = sprom->board_rev; |
| 4516 | /* promote srom boardrev of 0xFF to 1 */ | 4517 | /* promote srom boardrev of 0xFF to 1 */ |
| 4517 | if (j == BOARDREV_PROMOTABLE) | 4518 | if (j == BOARDREV_PROMOTABLE) |
| 4518 | j = BOARDREV_PROMOTED; | 4519 | j = BOARDREV_PROMOTED; |
| @@ -4525,11 +4526,9 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, | |||
| 4525 | err = 15; | 4526 | err = 15; |
| 4526 | goto fail; | 4527 | goto fail; |
| 4527 | } | 4528 | } |
| 4528 | wlc_hw->sromrev = (u8) getintvar(wlc_hw->sih, BRCMS_SROM_REV); | 4529 | wlc_hw->sromrev = sprom->revision; |
| 4529 | wlc_hw->boardflags = (u32) getintvar(wlc_hw->sih, | 4530 | wlc_hw->boardflags = sprom->boardflags_lo + (sprom->boardflags_hi << 16); |
| 4530 | BRCMS_SROM_BOARDFLAGS); | 4531 | wlc_hw->boardflags2 = sprom->boardflags2_lo + (sprom->boardflags2_hi << 16); |
| 4531 | wlc_hw->boardflags2 = (u32) getintvar(wlc_hw->sih, | ||
| 4532 | BRCMS_SROM_BOARDFLAGS2); | ||
| 4533 | 4532 | ||
| 4534 | if (wlc_hw->boardflags & BFL_NOPLLDOWN) | 4533 | if (wlc_hw->boardflags & BFL_NOPLLDOWN) |
| 4535 | brcms_b_pllreq(wlc_hw, true, BRCMS_PLLREQ_SHARED); | 4534 | brcms_b_pllreq(wlc_hw, true, BRCMS_PLLREQ_SHARED); |
| @@ -4702,25 +4701,18 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, | |||
| 4702 | */ | 4701 | */ |
| 4703 | 4702 | ||
| 4704 | /* init etheraddr state variables */ | 4703 | /* init etheraddr state variables */ |
| 4705 | macaddr = brcms_c_get_macaddr(wlc_hw); | 4704 | brcms_c_get_macaddr(wlc_hw, wlc_hw->etheraddr); |
| 4706 | if (macaddr == NULL) { | 4705 | |
| 4707 | wiphy_err(wiphy, "wl%d: brcms_b_attach: macaddr not found\n", | 4706 | if (is_broadcast_ether_addr(wlc_hw->etheraddr) || |
| 4708 | unit); | ||
| 4709 | err = 21; | ||
| 4710 | goto fail; | ||
| 4711 | } | ||
| 4712 | if (!mac_pton(macaddr, wlc_hw->etheraddr) || | ||
| 4713 | is_broadcast_ether_addr(wlc_hw->etheraddr) || | ||
| 4714 | is_zero_ether_addr(wlc_hw->etheraddr)) { | 4707 | is_zero_ether_addr(wlc_hw->etheraddr)) { |
| 4715 | wiphy_err(wiphy, "wl%d: brcms_b_attach: bad macaddr %s\n", | 4708 | wiphy_err(wiphy, "wl%d: brcms_b_attach: bad macaddr\n", |
| 4716 | unit, macaddr); | 4709 | unit); |
| 4717 | err = 22; | 4710 | err = 22; |
| 4718 | goto fail; | 4711 | goto fail; |
| 4719 | } | 4712 | } |
| 4720 | 4713 | ||
| 4721 | BCMMSG(wlc->wiphy, "deviceid 0x%x nbands %d board 0x%x macaddr: %s\n", | 4714 | BCMMSG(wlc->wiphy, "deviceid 0x%x nbands %d board 0x%x\n", |
| 4722 | wlc_hw->deviceid, wlc_hw->_nbands, ai_get_boardtype(wlc_hw->sih), | 4715 | wlc_hw->deviceid, wlc_hw->_nbands, ai_get_boardtype(wlc_hw->sih)); |
| 4723 | macaddr); | ||
| 4724 | 4716 | ||
| 4725 | return err; | 4717 | return err; |
| 4726 | 4718 | ||
| @@ -4770,16 +4762,16 @@ static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc) | |||
| 4770 | int aa; | 4762 | int aa; |
| 4771 | uint unit; | 4763 | uint unit; |
| 4772 | int bandtype; | 4764 | int bandtype; |
| 4773 | struct si_pub *sih = wlc->hw->sih; | 4765 | struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom; |
| 4774 | 4766 | ||
| 4775 | unit = wlc->pub->unit; | 4767 | unit = wlc->pub->unit; |
| 4776 | bandtype = wlc->band->bandtype; | 4768 | bandtype = wlc->band->bandtype; |
| 4777 | 4769 | ||
| 4778 | /* get antennas available */ | 4770 | /* get antennas available */ |
| 4779 | if (bandtype == BRCM_BAND_5G) | 4771 | if (bandtype == BRCM_BAND_5G) |
| 4780 | aa = (s8) getintvar(sih, BRCMS_SROM_AA5G); | 4772 | aa = sprom->ant_available_a; |
| 4781 | else | 4773 | else |
| 4782 | aa = (s8) getintvar(sih, BRCMS_SROM_AA2G); | 4774 | aa = sprom->ant_available_bg; |
| 4783 | 4775 | ||
| 4784 | if ((aa < 1) || (aa > 15)) { | 4776 | if ((aa < 1) || (aa > 15)) { |
| 4785 | wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in" | 4777 | wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in" |
| @@ -4799,9 +4791,9 @@ static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc) | |||
| 4799 | 4791 | ||
| 4800 | /* Compute Antenna Gain */ | 4792 | /* Compute Antenna Gain */ |
| 4801 | if (bandtype == BRCM_BAND_5G) | 4793 | if (bandtype == BRCM_BAND_5G) |
| 4802 | wlc->band->antgain = (s8) getintvar(sih, BRCMS_SROM_AG1); | 4794 | wlc->band->antgain = sprom->antenna_gain.a1; |
| 4803 | else | 4795 | else |
| 4804 | wlc->band->antgain = (s8) getintvar(sih, BRCMS_SROM_AG0); | 4796 | wlc->band->antgain = sprom->antenna_gain.a0; |
| 4805 | 4797 | ||
| 4806 | brcms_c_attach_antgain_init(wlc); | 4798 | brcms_c_attach_antgain_init(wlc); |
| 4807 | 4799 | ||
| @@ -4952,15 +4944,6 @@ static int brcms_b_detach(struct brcms_c_info *wlc) | |||
| 4952 | 4944 | ||
| 4953 | callbacks = 0; | 4945 | callbacks = 0; |
| 4954 | 4946 | ||
| 4955 | if (wlc_hw->sih) { | ||
| 4956 | /* | ||
| 4957 | * detach interrupt sync mechanism since interrupt is disabled | ||
| 4958 | * and per-port interrupt object may has been freed. this must | ||
| 4959 | * be done before sb core switch | ||
| 4960 | */ | ||
| 4961 | ai_pci_sleep(wlc_hw->sih); | ||
| 4962 | } | ||
| 4963 | |||
| 4964 | brcms_b_detach_dmapio(wlc_hw); | 4947 | brcms_b_detach_dmapio(wlc_hw); |
| 4965 | 4948 | ||
| 4966 | band = wlc_hw->band; | 4949 | band = wlc_hw->band; |
| @@ -5047,9 +5030,7 @@ static void brcms_b_hw_up(struct brcms_hardware *wlc_hw) | |||
| 5047 | */ | 5030 | */ |
| 5048 | brcms_b_xtal(wlc_hw, ON); | 5031 | brcms_b_xtal(wlc_hw, ON); |
| 5049 | ai_clkctl_init(wlc_hw->sih); | 5032 | ai_clkctl_init(wlc_hw->sih); |
| 5050 | brcms_b_clkctl_clk(wlc_hw, CLK_FAST); | 5033 | brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST); |
| 5051 | |||
| 5052 | ai_pci_fixcfg(wlc_hw->sih); | ||
| 5053 | 5034 | ||
| 5054 | /* | 5035 | /* |
| 5055 | * TODO: test suspend/resume | 5036 | * TODO: test suspend/resume |
| @@ -5078,8 +5059,6 @@ static void brcms_b_hw_up(struct brcms_hardware *wlc_hw) | |||
| 5078 | 5059 | ||
| 5079 | static int brcms_b_up_prep(struct brcms_hardware *wlc_hw) | 5060 | static int brcms_b_up_prep(struct brcms_hardware *wlc_hw) |
| 5080 | { | 5061 | { |
| 5081 | uint coremask; | ||
| 5082 | |||
| 5083 | BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); | 5062 | BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); |
| 5084 | 5063 | ||
| 5085 | /* | 5064 | /* |
| @@ -5088,15 +5067,14 @@ static int brcms_b_up_prep(struct brcms_hardware *wlc_hw) | |||
| 5088 | */ | 5067 | */ |
| 5089 | brcms_b_xtal(wlc_hw, ON); | 5068 | brcms_b_xtal(wlc_hw, ON); |
| 5090 | ai_clkctl_init(wlc_hw->sih); | 5069 | ai_clkctl_init(wlc_hw->sih); |
| 5091 | brcms_b_clkctl_clk(wlc_hw, CLK_FAST); | 5070 | brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST); |
| 5092 | 5071 | ||
| 5093 | /* | 5072 | /* |
| 5094 | * Configure pci/pcmcia here instead of in brcms_c_attach() | 5073 | * Configure pci/pcmcia here instead of in brcms_c_attach() |
| 5095 | * to allow mfg hotswap: down, hotswap (chip power cycle), up. | 5074 | * to allow mfg hotswap: down, hotswap (chip power cycle), up. |
| 5096 | */ | 5075 | */ |
| 5097 | coremask = (1 << wlc_hw->wlc->core->coreidx); | 5076 | bcma_core_pci_irq_ctl(&wlc_hw->d11core->bus->drv_pci, wlc_hw->d11core, |
| 5098 | 5077 | true); | |
| 5099 | ai_pci_setup(wlc_hw->sih, coremask); | ||
| 5100 | 5078 | ||
| 5101 | /* | 5079 | /* |
| 5102 | * Need to read the hwradio status here to cover the case where the | 5080 | * Need to read the hwradio status here to cover the case where the |
| @@ -5126,7 +5104,7 @@ static int brcms_b_up_finish(struct brcms_hardware *wlc_hw) | |||
| 5126 | wlc_phy_hw_state_upd(wlc_hw->band->pi, true); | 5104 | wlc_phy_hw_state_upd(wlc_hw->band->pi, true); |
| 5127 | 5105 | ||
| 5128 | /* FULLY enable dynamic power control and d11 core interrupt */ | 5106 | /* FULLY enable dynamic power control and d11 core interrupt */ |
| 5129 | brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); | 5107 | brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_DYNAMIC); |
| 5130 | brcms_intrson(wlc_hw->wlc->wl); | 5108 | brcms_intrson(wlc_hw->wlc->wl); |
| 5131 | return 0; | 5109 | return 0; |
| 5132 | } | 5110 | } |
| @@ -5267,7 +5245,7 @@ static int brcms_b_bmac_down_prep(struct brcms_hardware *wlc_hw) | |||
| 5267 | brcms_intrsoff(wlc_hw->wlc->wl); | 5245 | brcms_intrsoff(wlc_hw->wlc->wl); |
| 5268 | 5246 | ||
| 5269 | /* ensure we're running on the pll clock again */ | 5247 | /* ensure we're running on the pll clock again */ |
| 5270 | brcms_b_clkctl_clk(wlc_hw, CLK_FAST); | 5248 | brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST); |
| 5271 | } | 5249 | } |
| 5272 | /* down phy at the last of this stage */ | 5250 | /* down phy at the last of this stage */ |
| 5273 | callbacks += wlc_phy_down(wlc_hw->band->pi); | 5251 | callbacks += wlc_phy_down(wlc_hw->band->pi); |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c b/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c deleted file mode 100644 index 7fad6dc1925..00000000000 --- a/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c +++ /dev/null | |||
| @@ -1,826 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2010 Broadcom Corporation | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/slab.h> | ||
| 18 | #include <linux/delay.h> | ||
| 19 | #include <linux/pci.h> | ||
| 20 | |||
| 21 | #include <defs.h> | ||
| 22 | #include <soc.h> | ||
| 23 | #include <chipcommon.h> | ||
| 24 | #include "aiutils.h" | ||
| 25 | #include "pub.h" | ||
| 26 | #include "nicpci.h" | ||
| 27 | |||
| 28 | /* SPROM offsets */ | ||
| 29 | #define SRSH_ASPM_OFFSET 4 /* word 4 */ | ||
| 30 | #define SRSH_ASPM_ENB 0x18 /* bit 3, 4 */ | ||
| 31 | #define SRSH_ASPM_L1_ENB 0x10 /* bit 4 */ | ||
| 32 | #define SRSH_ASPM_L0s_ENB 0x8 /* bit 3 */ | ||
| 33 | |||
| 34 | #define SRSH_PCIE_MISC_CONFIG 5 /* word 5 */ | ||
| 35 | #define SRSH_L23READY_EXIT_NOPERST 0x8000 /* bit 15 */ | ||
| 36 | #define SRSH_CLKREQ_OFFSET_REV5 20 /* word 20 for srom rev <= 5 */ | ||
| 37 | #define SRSH_CLKREQ_ENB 0x0800 /* bit 11 */ | ||
| 38 | #define SRSH_BD_OFFSET 6 /* word 6 */ | ||
| 39 | |||
| 40 | /* chipcontrol */ | ||
| 41 | #define CHIPCTRL_4321_PLL_DOWN 0x800000/* serdes PLL down override */ | ||
| 42 | |||
| 43 | /* MDIO control */ | ||
| 44 | #define MDIOCTL_DIVISOR_MASK 0x7f /* clock to be used on MDIO */ | ||
| 45 | #define MDIOCTL_DIVISOR_VAL 0x2 | ||
| 46 | #define MDIOCTL_PREAM_EN 0x80 /* Enable preamble sequnce */ | ||
| 47 | #define MDIOCTL_ACCESS_DONE 0x100 /* Transaction complete */ | ||
| 48 | |||
| 49 | /* MDIO Data */ | ||
| 50 | #define MDIODATA_MASK 0x0000ffff /* data 2 bytes */ | ||
| 51 | #define MDIODATA_TA 0x00020000 /* Turnaround */ | ||
| 52 | |||
| 53 | #define MDIODATA_REGADDR_SHF 18 /* Regaddr shift */ | ||
| 54 | #define MDIODATA_REGADDR_MASK 0x007c0000 /* Regaddr Mask */ | ||
| 55 | #define MDIODATA_DEVADDR_SHF 23 /* Physmedia devaddr shift */ | ||
| 56 | #define MDIODATA_DEVADDR_MASK 0x0f800000 | ||
| 57 | /* Physmedia devaddr Mask */ | ||
| 58 | |||
| 59 | /* MDIO Data for older revisions < 10 */ | ||
| 60 | #define MDIODATA_REGADDR_SHF_OLD 18 /* Regaddr shift */ | ||
| 61 | #define MDIODATA_REGADDR_MASK_OLD 0x003c0000 | ||
| 62 | /* Regaddr Mask */ | ||
| 63 | #define MDIODATA_DEVADDR_SHF_OLD 22 /* Physmedia devaddr shift */ | ||
| 64 | #define MDIODATA_DEVADDR_MASK_OLD 0x0fc00000 | ||
| 65 | /* Physmedia devaddr Mask */ | ||
| 66 | |||
| 67 | /* Transactions flags */ | ||
| 68 | #define MDIODATA_WRITE 0x10000000 | ||
| 69 | #define MDIODATA_READ 0x20000000 | ||
| 70 | #define MDIODATA_START 0x40000000 | ||
| 71 | |||
| 72 | #define MDIODATA_DEV_ADDR 0x0 /* dev address for serdes */ | ||
| 73 | #define MDIODATA_BLK_ADDR 0x1F /* blk address for serdes */ | ||
| 74 | |||
| 75 | /* serdes regs (rev < 10) */ | ||
| 76 | #define MDIODATA_DEV_PLL 0x1d /* SERDES PLL Dev */ | ||
| 77 | #define MDIODATA_DEV_TX 0x1e /* SERDES TX Dev */ | ||
| 78 | #define MDIODATA_DEV_RX 0x1f /* SERDES RX Dev */ | ||
| 79 | |||
| 80 | /* SERDES RX registers */ | ||
| 81 | #define SERDES_RX_CTRL 1 /* Rx cntrl */ | ||
| 82 | #define SERDES_RX_TIMER1 2 /* Rx Timer1 */ | ||
| 83 | #define SERDES_RX_CDR 6 /* CDR */ | ||
| 84 | #define SERDES_RX_CDRBW 7 /* CDR BW */ | ||
| 85 | /* SERDES RX control register */ | ||
| 86 | #define SERDES_RX_CTRL_FORCE 0x80 /* rxpolarity_force */ | ||
| 87 | #define SERDES_RX_CTRL_POLARITY 0x40 /* rxpolarity_value */ | ||
| 88 | |||
| 89 | /* SERDES PLL registers */ | ||
| 90 | #define SERDES_PLL_CTRL 1 /* PLL control reg */ | ||
| 91 | #define PLL_CTRL_FREQDET_EN 0x4000 /* bit 14 is FREQDET on */ | ||
| 92 | |||
| 93 | /* Linkcontrol reg offset in PCIE Cap */ | ||
| 94 | #define PCIE_CAP_LINKCTRL_OFFSET 16 /* offset in pcie cap */ | ||
| 95 | #define PCIE_CAP_LCREG_ASPML0s 0x01 /* ASPM L0s in linkctrl */ | ||
| 96 | #define PCIE_CAP_LCREG_ASPML1 0x02 /* ASPM L1 in linkctrl */ | ||
| 97 | #define PCIE_CLKREQ_ENAB 0x100 /* CLKREQ Enab in linkctrl */ | ||
| 98 | |||
| 99 | #define PCIE_ASPM_ENAB 3 /* ASPM L0s & L1 in linkctrl */ | ||
| 100 | #define PCIE_ASPM_L1_ENAB 2 /* ASPM L0s & L1 in linkctrl */ | ||
| 101 | #define PCIE_ASPM_L0s_ENAB 1 /* ASPM L0s & L1 in linkctrl */ | ||
| 102 | #define PCIE_ASPM_DISAB 0 /* ASPM L0s & L1 in linkctrl */ | ||
| 103 | |||
| 104 | /* Power management threshold */ | ||
| 105 | #define PCIE_L1THRESHOLDTIME_MASK 0xFF00 /* bits 8 - 15 */ | ||
| 106 | #define PCIE_L1THRESHOLDTIME_SHIFT 8 /* PCIE_L1THRESHOLDTIME_SHIFT */ | ||
| 107 | #define PCIE_L1THRESHOLD_WARVAL 0x72 /* WAR value */ | ||
| 108 | #define PCIE_ASPMTIMER_EXTEND 0x01000000 | ||
| 109 | /* > rev7: | ||
| 110 | * enable extend ASPM timer | ||
| 111 | */ | ||
| 112 | |||
| 113 | /* different register spaces to access thru pcie indirect access */ | ||
| 114 | #define PCIE_CONFIGREGS 1 /* Access to config space */ | ||
| 115 | #define PCIE_PCIEREGS 2 /* Access to pcie registers */ | ||
| 116 | |||
| 117 | /* PCIE protocol PHY diagnostic registers */ | ||
| 118 | #define PCIE_PLP_STATUSREG 0x204 /* Status */ | ||
| 119 | |||
| 120 | /* Status reg PCIE_PLP_STATUSREG */ | ||
| 121 | #define PCIE_PLP_POLARITYINV_STAT 0x10 | ||
| 122 | |||
| 123 | /* PCIE protocol DLLP diagnostic registers */ | ||
| 124 | #define PCIE_DLLP_LCREG 0x100 /* Link Control */ | ||
| 125 | #define PCIE_DLLP_PMTHRESHREG 0x128 /* Power Management Threshold */ | ||
| 126 | |||
| 127 | /* PCIE protocol TLP diagnostic registers */ | ||
| 128 | #define PCIE_TLP_WORKAROUNDSREG 0x004 /* TLP Workarounds */ | ||
| 129 | |||
| 130 | /* Sonics to PCI translation types */ | ||
| 131 | #define SBTOPCI_PREF 0x4 /* prefetch enable */ | ||
| 132 | #define SBTOPCI_BURST 0x8 /* burst enable */ | ||
| 133 | #define SBTOPCI_RC_READMULTI 0x20 /* memory read multiple */ | ||
| 134 | |||
| 135 | #define PCI_CLKRUN_DSBL 0x8000 /* Bit 15 forceClkrun */ | ||
| 136 | |||
| 137 | /* PCI core index in SROM shadow area */ | ||
| 138 | #define SRSH_PI_OFFSET 0 /* first word */ | ||
| 139 | #define SRSH_PI_MASK 0xf000 /* bit 15:12 */ | ||
| 140 | #define SRSH_PI_SHIFT 12 /* bit 15:12 */ | ||
| 141 | |||
| 142 | #define PCIREGOFFS(field) offsetof(struct sbpciregs, field) | ||
| 143 | #define PCIEREGOFFS(field) offsetof(struct sbpcieregs, field) | ||
| 144 | |||
| 145 | /* Sonics side: PCI core and host control registers */ | ||
| 146 | struct sbpciregs { | ||
| 147 | u32 control; /* PCI control */ | ||
| 148 | u32 PAD[3]; | ||
| 149 | u32 arbcontrol; /* PCI arbiter control */ | ||
| 150 | u32 clkrun; /* Clkrun Control (>=rev11) */ | ||
| 151 | u32 PAD[2]; | ||
| 152 | u32 intstatus; /* Interrupt status */ | ||
| 153 | u32 intmask; /* Interrupt mask */ | ||
| 154 | u32 sbtopcimailbox; /* Sonics to PCI mailbox */ | ||
| 155 | u32 PAD[9]; | ||
| 156 | u32 bcastaddr; /* Sonics broadcast address */ | ||
| 157 | u32 bcastdata; /* Sonics broadcast data */ | ||
| 158 | u32 PAD[2]; | ||
| 159 | u32 gpioin; /* ro: gpio input (>=rev2) */ | ||
| 160 | u32 gpioout; /* rw: gpio output (>=rev2) */ | ||
| 161 | u32 gpioouten; /* rw: gpio output enable (>= rev2) */ | ||
| 162 | u32 gpiocontrol; /* rw: gpio control (>= rev2) */ | ||
| 163 | u32 PAD[36]; | ||
| 164 | u32 sbtopci0; /* Sonics to PCI translation 0 */ | ||
| 165 | u32 sbtopci1; /* Sonics to PCI translation 1 */ | ||
| 166 | u32 sbtopci2; /* Sonics to PCI translation 2 */ | ||
| 167 | u32 PAD[189]; | ||
| 168 | u32 pcicfg[4][64]; /* 0x400 - 0x7FF, PCI Cfg Space (>=rev8) */ | ||
| 169 | u16 sprom[36]; /* SPROM shadow Area */ | ||
| 170 | u32 PAD[46]; | ||
| 171 | }; | ||
| 172 | |||
| 173 | /* SB side: PCIE core and host control registers */ | ||
| 174 | struct sbpcieregs { | ||
| 175 | u32 control; /* host mode only */ | ||
| 176 | u32 PAD[2]; | ||
| 177 | u32 biststatus; /* bist Status: 0x00C */ | ||
| 178 | u32 gpiosel; /* PCIE gpio sel: 0x010 */ | ||
| 179 | u32 gpioouten; /* PCIE gpio outen: 0x14 */ | ||
| 180 | u32 PAD[2]; | ||
| 181 | u32 intstatus; /* Interrupt status: 0x20 */ | ||
| 182 | u32 intmask; /* Interrupt mask: 0x24 */ | ||
| 183 | u32 sbtopcimailbox; /* sb to pcie mailbox: 0x028 */ | ||
| 184 | u32 PAD[53]; | ||
| 185 | u32 sbtopcie0; /* sb to pcie translation 0: 0x100 */ | ||
| 186 | u32 sbtopcie1; /* sb to pcie translation 1: 0x104 */ | ||
| 187 | u32 sbtopcie2; /* sb to pcie translation 2: 0x108 */ | ||
| 188 | u32 PAD[5]; | ||
| 189 | |||
| 190 | /* pcie core supports in direct access to config space */ | ||
| 191 | u32 configaddr; /* pcie config space access: Address field: 0x120 */ | ||
| 192 | u32 configdata; /* pcie config space access: Data field: 0x124 */ | ||
| 193 | |||
| 194 | /* mdio access to serdes */ | ||
| 195 | u32 mdiocontrol; /* controls the mdio access: 0x128 */ | ||
| 196 | u32 mdiodata; /* Data to the mdio access: 0x12c */ | ||
| 197 | |||
| 198 | /* pcie protocol phy/dllp/tlp register indirect access mechanism */ | ||
| 199 | u32 pcieindaddr; /* indirect access to | ||
| 200 | * the internal register: 0x130 | ||
| 201 | */ | ||
| 202 | u32 pcieinddata; /* Data to/from the internal regsiter: 0x134 */ | ||
| 203 | |||
| 204 | u32 clkreqenctrl; /* >= rev 6, Clkreq rdma control : 0x138 */ | ||
| 205 | u32 PAD[177]; | ||
| 206 | u32 pciecfg[4][64]; /* 0x400 - 0x7FF, PCIE Cfg Space */ | ||
| 207 | u16 sprom[64]; /* SPROM shadow Area */ | ||
| 208 | }; | ||
| 209 | |||
| 210 | struct pcicore_info { | ||
| 211 | struct bcma_device *core; | ||
| 212 | struct si_pub *sih; /* System interconnect handle */ | ||
| 213 | struct pci_dev *dev; | ||
| 214 | u8 pciecap_lcreg_offset;/* PCIE capability LCreg offset | ||
| 215 | * in the config space | ||
| 216 | */ | ||
| 217 | bool pcie_pr42767; | ||
| 218 | u8 pcie_polarity; | ||
| 219 | u8 pcie_war_aspm_ovr; /* Override ASPM/Clkreq settings */ | ||
| 220 | |||
| 221 | u8 pmecap_offset; /* PM Capability offset in the config space */ | ||
| 222 | bool pmecap; /* Capable of generating PME */ | ||
| 223 | }; | ||
| 224 | |||
| 225 | #define PCIE_ASPM(sih) \ | ||
| 226 | ((ai_get_buscoretype(sih) == PCIE_CORE_ID) && \ | ||
| 227 | ((ai_get_buscorerev(sih) >= 3) && \ | ||
| 228 | (ai_get_buscorerev(sih) <= 5))) | ||
| 229 | |||
| 230 | |||
| 231 | /* delay needed between the mdio control/ mdiodata register data access */ | ||
| 232 | static void pr28829_delay(void) | ||
| 233 | { | ||
| 234 | udelay(10); | ||
| 235 | } | ||
| 236 | |||
| 237 | /* Initialize the PCI core. | ||
| 238 | * It's caller's responsibility to make sure that this is done only once | ||
| 239 | */ | ||
| 240 | struct pcicore_info *pcicore_init(struct si_pub *sih, struct bcma_device *core) | ||
| 241 | { | ||
| 242 | struct pcicore_info *pi; | ||
| 243 | |||
| 244 | /* alloc struct pcicore_info */ | ||
| 245 | pi = kzalloc(sizeof(struct pcicore_info), GFP_ATOMIC); | ||
| 246 | if (pi == NULL) | ||
| 247 | return NULL; | ||
| 248 | |||
| 249 | pi->sih = sih; | ||
| 250 | pi->dev = core->bus->host_pci; | ||
| 251 | pi->core = core; | ||
| 252 | |||
| 253 | if (core->id.id == PCIE_CORE_ID) { | ||
| 254 | u8 cap_ptr; | ||
| 255 | cap_ptr = pcicore_find_pci_capability(pi->dev, PCI_CAP_ID_EXP, | ||
| 256 | NULL, NULL); | ||
| 257 | pi->pciecap_lcreg_offset = cap_ptr + PCIE_CAP_LINKCTRL_OFFSET; | ||
| 258 | } | ||
| 259 | return pi; | ||
| 260 | } | ||
| 261 | |||
| 262 | void pcicore_deinit(struct pcicore_info *pch) | ||
| 263 | { | ||
| 264 | kfree(pch); | ||
| 265 | } | ||
| 266 | |||
| 267 | /* return cap_offset if requested capability exists in the PCI config space */ | ||
| 268 | /* Note that it's caller's responsibility to make sure it's a pci bus */ | ||
| 269 | u8 | ||
| 270 | pcicore_find_pci_capability(struct pci_dev *dev, u8 req_cap_id, | ||
| 271 | unsigned char *buf, u32 *buflen) | ||
| 272 | { | ||
| 273 | u8 cap_id; | ||
| 274 | u8 cap_ptr = 0; | ||
| 275 | u32 bufsize; | ||
| 276 | u8 byte_val; | ||
| 277 | |||
| 278 | /* check for Header type 0 */ | ||
| 279 | pci_read_config_byte(dev, PCI_HEADER_TYPE, &byte_val); | ||
| 280 | if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL) | ||
| 281 | goto end; | ||
| 282 | |||
| 283 | /* check if the capability pointer field exists */ | ||
| 284 | pci_read_config_byte(dev, PCI_STATUS, &byte_val); | ||
| 285 | if (!(byte_val & PCI_STATUS_CAP_LIST)) | ||
| 286 | goto end; | ||
| 287 | |||
| 288 | pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &cap_ptr); | ||
| 289 | /* check if the capability pointer is 0x00 */ | ||
| 290 | if (cap_ptr == 0x00) | ||
| 291 | goto end; | ||
| 292 | |||
| 293 | /* loop thru the capability list | ||
| 294 | * and see if the pcie capability exists | ||
| 295 | */ | ||
| 296 | |||
| 297 | pci_read_config_byte(dev, cap_ptr, &cap_id); | ||
| 298 | |||
| 299 | while (cap_id != req_cap_id) { | ||
| 300 | pci_read_config_byte(dev, cap_ptr + 1, &cap_ptr); | ||
| 301 | if (cap_ptr == 0x00) | ||
| 302 | break; | ||
| 303 | pci_read_config_byte(dev, cap_ptr, &cap_id); | ||
| 304 | } | ||
| 305 | if (cap_id != req_cap_id) | ||
| 306 | goto end; | ||
| 307 | |||
| 308 | /* found the caller requested capability */ | ||
| 309 | if (buf != NULL && buflen != NULL) { | ||
| 310 | u8 cap_data; | ||
| 311 | |||
| 312 | bufsize = *buflen; | ||
| 313 | if (!bufsize) | ||
| 314 | goto end; | ||
| 315 | *buflen = 0; | ||
| 316 | /* copy the capability data excluding cap ID and next ptr */ | ||
| 317 | cap_data = cap_ptr + 2; | ||
| 318 | if ((bufsize + cap_data) > PCI_SZPCR) | ||
| 319 | bufsize = PCI_SZPCR - cap_data; | ||
| 320 | *buflen = bufsize; | ||
| 321 | while (bufsize--) { | ||
| 322 | pci_read_config_byte(dev, cap_data, buf); | ||
| 323 | cap_data++; | ||
| 324 | buf++; | ||
| 325 | } | ||
| 326 | } | ||
| 327 | end: | ||
| 328 | return cap_ptr; | ||
| 329 | } | ||
| 330 | |||
| 331 | /* ***** Register Access API */ | ||
| 332 | static uint | ||
| 333 | pcie_readreg(struct bcma_device *core, uint addrtype, uint offset) | ||
| 334 | { | ||
| 335 | uint retval = 0xFFFFFFFF; | ||
| 336 | |||
| 337 | switch (addrtype) { | ||
| 338 | case PCIE_CONFIGREGS: | ||
| 339 | bcma_write32(core, PCIEREGOFFS(configaddr), offset); | ||
| 340 | (void)bcma_read32(core, PCIEREGOFFS(configaddr)); | ||
| 341 | retval = bcma_read32(core, PCIEREGOFFS(configdata)); | ||
| 342 | break; | ||
| 343 | case PCIE_PCIEREGS: | ||
| 344 | bcma_write32(core, PCIEREGOFFS(pcieindaddr), offset); | ||
| 345 | (void)bcma_read32(core, PCIEREGOFFS(pcieindaddr)); | ||
| 346 | retval = bcma_read32(core, PCIEREGOFFS(pcieinddata)); | ||
| 347 | break; | ||
| 348 | } | ||
| 349 | |||
| 350 | return retval; | ||
| 351 | } | ||
| 352 | |||
| 353 | static uint pcie_writereg(struct bcma_device *core, uint addrtype, | ||
| 354 | uint offset, uint val) | ||
| 355 | { | ||
| 356 | switch (addrtype) { | ||
| 357 | case PCIE_CONFIGREGS: | ||
| 358 | bcma_write32(core, PCIEREGOFFS(configaddr), offset); | ||
| 359 | bcma_write32(core, PCIEREGOFFS(configdata), val); | ||
| 360 | break; | ||
| 361 | case PCIE_PCIEREGS: | ||
| 362 | bcma_write32(core, PCIEREGOFFS(pcieindaddr), offset); | ||
| 363 | bcma_write32(core, PCIEREGOFFS(pcieinddata), val); | ||
| 364 | break; | ||
| 365 | default: | ||
| 366 | break; | ||
| 367 | } | ||
| 368 | return 0; | ||
| 369 | } | ||
| 370 | |||
| 371 | static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk) | ||
| 372 | { | ||
| 373 | uint mdiodata, i = 0; | ||
| 374 | uint pcie_serdes_spinwait = 200; | ||
| 375 | |||
| 376 | mdiodata = (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA | | ||
| 377 | (MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) | | ||
| 378 | (MDIODATA_BLK_ADDR << MDIODATA_REGADDR_SHF) | | ||
| 379 | (blk << 4)); | ||
| 380 | bcma_write32(pi->core, PCIEREGOFFS(mdiodata), mdiodata); | ||
| 381 | |||
| 382 | pr28829_delay(); | ||
| 383 | /* retry till the transaction is complete */ | ||
| 384 | while (i < pcie_serdes_spinwait) { | ||
| 385 | if (bcma_read32(pi->core, PCIEREGOFFS(mdiocontrol)) & | ||
| 386 | MDIOCTL_ACCESS_DONE) | ||
| 387 | break; | ||
| 388 | |||
| 389 | udelay(1000); | ||
| 390 | i++; | ||
| 391 | } | ||
| 392 | |||
| 393 | if (i >= pcie_serdes_spinwait) | ||
| 394 | return false; | ||
| 395 | |||
| 396 | return true; | ||
| 397 | } | ||
| 398 | |||
| 399 | static int | ||
| 400 | pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write, | ||
| 401 | uint *val) | ||
| 402 | { | ||
| 403 | uint mdiodata; | ||
| 404 | uint i = 0; | ||
| 405 | uint pcie_serdes_spinwait = 10; | ||
| 406 | |||
| 407 | /* enable mdio access to SERDES */ | ||
| 408 | bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), | ||
| 409 | MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL); | ||
| 410 | |||
| 411 | if (ai_get_buscorerev(pi->sih) >= 10) { | ||
| 412 | /* new serdes is slower in rw, | ||
| 413 | * using two layers of reg address mapping | ||
| 414 | */ | ||
| 415 | if (!pcie_mdiosetblock(pi, physmedia)) | ||
| 416 | return 1; | ||
| 417 | mdiodata = ((MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) | | ||
| 418 | (regaddr << MDIODATA_REGADDR_SHF)); | ||
| 419 | pcie_serdes_spinwait *= 20; | ||
| 420 | } else { | ||
| 421 | mdiodata = ((physmedia << MDIODATA_DEVADDR_SHF_OLD) | | ||
| 422 | (regaddr << MDIODATA_REGADDR_SHF_OLD)); | ||
| 423 | } | ||
| 424 | |||
| 425 | if (!write) | ||
| 426 | mdiodata |= (MDIODATA_START | MDIODATA_READ | MDIODATA_TA); | ||
| 427 | else | ||
| 428 | mdiodata |= (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA | | ||
| 429 | *val); | ||
| 430 | |||
| 431 | bcma_write32(pi->core, PCIEREGOFFS(mdiodata), mdiodata); | ||
| 432 | |||
| 433 | pr28829_delay(); | ||
| 434 | |||
| 435 | /* retry till the transaction is complete */ | ||
| 436 | while (i < pcie_serdes_spinwait) { | ||
| 437 | if (bcma_read32(pi->core, PCIEREGOFFS(mdiocontrol)) & | ||
| 438 | MDIOCTL_ACCESS_DONE) { | ||
| 439 | if (!write) { | ||
| 440 | pr28829_delay(); | ||
| 441 | *val = (bcma_read32(pi->core, | ||
| 442 | PCIEREGOFFS(mdiodata)) & | ||
| 443 | MDIODATA_MASK); | ||
| 444 | } | ||
| 445 | /* Disable mdio access to SERDES */ | ||
| 446 | bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), 0); | ||
| 447 | return 0; | ||
| 448 | } | ||
| 449 | udelay(1000); | ||
| 450 | i++; | ||
| 451 | } | ||
| 452 | |||
| 453 | /* Timed out. Disable mdio access to SERDES. */ | ||
| 454 | bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), 0); | ||
| 455 | return 1; | ||
| 456 | } | ||
| 457 | |||
| 458 | /* use the mdio interface to read from mdio slaves */ | ||
| 459 | static int | ||
| 460 | pcie_mdioread(struct pcicore_info *pi, uint physmedia, uint regaddr, | ||
| 461 | uint *regval) | ||
| 462 | { | ||
| 463 | return pcie_mdioop(pi, physmedia, regaddr, false, regval); | ||
| 464 | } | ||
| 465 | |||
| 466 | /* use the mdio interface to write to mdio slaves */ | ||
| 467 | static int | ||
| 468 | pcie_mdiowrite(struct pcicore_info *pi, uint physmedia, uint regaddr, uint val) | ||
| 469 | { | ||
| 470 | return pcie_mdioop(pi, physmedia, regaddr, true, &val); | ||
| 471 | } | ||
| 472 | |||
| 473 | /* ***** Support functions ***** */ | ||
| 474 | static u8 pcie_clkreq(struct pcicore_info *pi, u32 mask, u32 val) | ||
| 475 | { | ||
| 476 | u32 reg_val; | ||
| 477 | u8 offset; | ||
| 478 | |||
| 479 | offset = pi->pciecap_lcreg_offset; | ||
| 480 | if (!offset) | ||
| 481 | return 0; | ||
| 482 | |||
| 483 | pci_read_config_dword(pi->dev, offset, ®_val); | ||
| 484 | /* set operation */ | ||
| 485 | if (mask) { | ||
| 486 | if (val) | ||
| 487 | reg_val |= PCIE_CLKREQ_ENAB; | ||
| 488 | else | ||
| 489 | reg_val &= ~PCIE_CLKREQ_ENAB; | ||
| 490 | pci_write_config_dword(pi->dev, offset, reg_val); | ||
| 491 | pci_read_config_dword(pi->dev, offset, ®_val); | ||
| 492 | } | ||
| 493 | if (reg_val & PCIE_CLKREQ_ENAB) | ||
| 494 | return 1; | ||
| 495 | else | ||
| 496 | return 0; | ||
| 497 | } | ||
| 498 | |||
| 499 | static void pcie_extendL1timer(struct pcicore_info *pi, bool extend) | ||
| 500 | { | ||
| 501 | u32 w; | ||
| 502 | struct si_pub *sih = pi->sih; | ||
| 503 | |||
| 504 | if (ai_get_buscoretype(sih) != PCIE_CORE_ID || | ||
| 505 | ai_get_buscorerev(sih) < 7) | ||
| 506 | return; | ||
| 507 | |||
| 508 | w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); | ||
| 509 | if (extend) | ||
| 510 | w |= PCIE_ASPMTIMER_EXTEND; | ||
| 511 | else | ||
| 512 | w &= ~PCIE_ASPMTIMER_EXTEND; | ||
| 513 | pcie_writereg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w); | ||
| 514 | w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); | ||
| 515 | } | ||
| 516 | |||
| 517 | /* centralized clkreq control policy */ | ||
| 518 | static void pcie_clkreq_upd(struct pcicore_info *pi, uint state) | ||
| 519 | { | ||
| 520 | struct si_pub *sih = pi->sih; | ||
| 521 | |||
| 522 | switch (state) { | ||
| 523 | case SI_DOATTACH: | ||
| 524 | if (PCIE_ASPM(sih)) | ||
| 525 | pcie_clkreq(pi, 1, 0); | ||
| 526 | break; | ||
| 527 | case SI_PCIDOWN: | ||
| 528 | /* turn on serdes PLL down */ | ||
| 529 | if (ai_get_buscorerev(sih) == 6) { | ||
| 530 | ai_cc_reg(sih, | ||
| 531 | offsetof(struct chipcregs, chipcontrol_addr), | ||
| 532 | ~0, 0); | ||
| 533 | ai_cc_reg(sih, | ||
| 534 | offsetof(struct chipcregs, chipcontrol_data), | ||
| 535 | ~0x40, 0); | ||
| 536 | } else if (pi->pcie_pr42767) { | ||
| 537 | pcie_clkreq(pi, 1, 1); | ||
| 538 | } | ||
| 539 | break; | ||
| 540 | case SI_PCIUP: | ||
| 541 | /* turn off serdes PLL down */ | ||
| 542 | if (ai_get_buscorerev(sih) == 6) { | ||
| 543 | ai_cc_reg(sih, | ||
| 544 | offsetof(struct chipcregs, chipcontrol_addr), | ||
| 545 | ~0, 0); | ||
| 546 | ai_cc_reg(sih, | ||
| 547 | offsetof(struct chipcregs, chipcontrol_data), | ||
| 548 | ~0x40, 0x40); | ||
| 549 | } else if (PCIE_ASPM(sih)) { /* disable clkreq */ | ||
| 550 | pcie_clkreq(pi, 1, 0); | ||
| 551 | } | ||
| 552 | break; | ||
| 553 | } | ||
| 554 | } | ||
| 555 | |||
| 556 | /* ***** PCI core WARs ***** */ | ||
| 557 | /* Done only once at attach time */ | ||
| 558 | static void pcie_war_polarity(struct pcicore_info *pi) | ||
| 559 | { | ||
| 560 | u32 w; | ||
| 561 | |||
| 562 | if (pi->pcie_polarity != 0) | ||
| 563 | return; | ||
| 564 | |||
| 565 | w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_PLP_STATUSREG); | ||
| 566 | |||
| 567 | /* Detect the current polarity at attach and force that polarity and | ||
| 568 | * disable changing the polarity | ||
| 569 | */ | ||
| 570 | if ((w & PCIE_PLP_POLARITYINV_STAT) == 0) | ||
| 571 | pi->pcie_polarity = SERDES_RX_CTRL_FORCE; | ||
| 572 | else | ||
| 573 | pi->pcie_polarity = (SERDES_RX_CTRL_FORCE | | ||
| 574 | SERDES_RX_CTRL_POLARITY); | ||
| 575 | } | ||
| 576 | |||
| 577 | /* enable ASPM and CLKREQ if srom doesn't have it */ | ||
| 578 | /* Needs to happen when update to shadow SROM is needed | ||
| 579 | * : Coming out of 'standby'/'hibernate' | ||
| 580 | * : If pcie_war_aspm_ovr state changed | ||
| 581 | */ | ||
| 582 | static void pcie_war_aspm_clkreq(struct pcicore_info *pi) | ||
| 583 | { | ||
| 584 | struct si_pub *sih = pi->sih; | ||
| 585 | u16 val16; | ||
| 586 | u32 w; | ||
| 587 | |||
| 588 | if (!PCIE_ASPM(sih)) | ||
| 589 | return; | ||
| 590 | |||
| 591 | /* bypass this on QT or VSIM */ | ||
| 592 | val16 = bcma_read16(pi->core, PCIEREGOFFS(sprom[SRSH_ASPM_OFFSET])); | ||
| 593 | |||
| 594 | val16 &= ~SRSH_ASPM_ENB; | ||
| 595 | if (pi->pcie_war_aspm_ovr == PCIE_ASPM_ENAB) | ||
| 596 | val16 |= SRSH_ASPM_ENB; | ||
| 597 | else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L1_ENAB) | ||
| 598 | val16 |= SRSH_ASPM_L1_ENB; | ||
| 599 | else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L0s_ENAB) | ||
| 600 | val16 |= SRSH_ASPM_L0s_ENB; | ||
| 601 | |||
| 602 | bcma_write16(pi->core, PCIEREGOFFS(sprom[SRSH_ASPM_OFFSET]), val16); | ||
| 603 | |||
| 604 | pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w); | ||
| 605 | w &= ~PCIE_ASPM_ENAB; | ||
| 606 | w |= pi->pcie_war_aspm_ovr; | ||
| 607 | pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w); | ||
| 608 | |||
| 609 | val16 = bcma_read16(pi->core, | ||
| 610 | PCIEREGOFFS(sprom[SRSH_CLKREQ_OFFSET_REV5])); | ||
| 611 | |||
| 612 | if (pi->pcie_war_aspm_ovr != PCIE_ASPM_DISAB) { | ||
| 613 | val16 |= SRSH_CLKREQ_ENB; | ||
| 614 | pi->pcie_pr42767 = true; | ||
| 615 | } else | ||
| 616 | val16 &= ~SRSH_CLKREQ_ENB; | ||
| 617 | |||
| 618 | bcma_write16(pi->core, PCIEREGOFFS(sprom[SRSH_CLKREQ_OFFSET_REV5]), | ||
| 619 | val16); | ||
| 620 | } | ||
| 621 | |||
| 622 | /* Apply the polarity determined at the start */ | ||
| 623 | /* Needs to happen when coming out of 'standby'/'hibernate' */ | ||
| 624 | static void pcie_war_serdes(struct pcicore_info *pi) | ||
| 625 | { | ||
| 626 | u32 w = 0; | ||
| 627 | |||
| 628 | if (pi->pcie_polarity != 0) | ||
| 629 | pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CTRL, | ||
| 630 | pi->pcie_polarity); | ||
| 631 | |||
| 632 | pcie_mdioread(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, &w); | ||
| 633 | if (w & PLL_CTRL_FREQDET_EN) { | ||
| 634 | w &= ~PLL_CTRL_FREQDET_EN; | ||
| 635 | pcie_mdiowrite(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, w); | ||
| 636 | } | ||
| 637 | } | ||
| 638 | |||
| 639 | /* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */ | ||
| 640 | /* Needs to happen when coming out of 'standby'/'hibernate' */ | ||
| 641 | static void pcie_misc_config_fixup(struct pcicore_info *pi) | ||
| 642 | { | ||
| 643 | u16 val16; | ||
| 644 | |||
| 645 | val16 = bcma_read16(pi->core, | ||
| 646 | PCIEREGOFFS(sprom[SRSH_PCIE_MISC_CONFIG])); | ||
| 647 | |||
| 648 | if ((val16 & SRSH_L23READY_EXIT_NOPERST) == 0) { | ||
| 649 | val16 |= SRSH_L23READY_EXIT_NOPERST; | ||
| 650 | bcma_write16(pi->core, | ||
| 651 | PCIEREGOFFS(sprom[SRSH_PCIE_MISC_CONFIG]), val16); | ||
| 652 | } | ||
| 653 | } | ||
| 654 | |||
| 655 | /* quick hack for testing */ | ||
| 656 | /* Needs to happen when coming out of 'standby'/'hibernate' */ | ||
| 657 | static void pcie_war_noplldown(struct pcicore_info *pi) | ||
| 658 | { | ||
| 659 | /* turn off serdes PLL down */ | ||
| 660 | ai_cc_reg(pi->sih, offsetof(struct chipcregs, chipcontrol), | ||
| 661 | CHIPCTRL_4321_PLL_DOWN, CHIPCTRL_4321_PLL_DOWN); | ||
| 662 | |||
| 663 | /* clear srom shadow backdoor */ | ||
| 664 | bcma_write16(pi->core, PCIEREGOFFS(sprom[SRSH_BD_OFFSET]), 0); | ||
| 665 | } | ||
| 666 | |||
| 667 | /* Needs to happen when coming out of 'standby'/'hibernate' */ | ||
| 668 | static void pcie_war_pci_setup(struct pcicore_info *pi) | ||
| 669 | { | ||
| 670 | struct si_pub *sih = pi->sih; | ||
| 671 | u32 w; | ||
| 672 | |||
| 673 | if (ai_get_buscorerev(sih) == 0 || ai_get_buscorerev(sih) == 1) { | ||
| 674 | w = pcie_readreg(pi->core, PCIE_PCIEREGS, | ||
| 675 | PCIE_TLP_WORKAROUNDSREG); | ||
| 676 | w |= 0x8; | ||
| 677 | pcie_writereg(pi->core, PCIE_PCIEREGS, | ||
| 678 | PCIE_TLP_WORKAROUNDSREG, w); | ||
| 679 | } | ||
| 680 | |||
| 681 | if (ai_get_buscorerev(sih) == 1) { | ||
| 682 | w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_LCREG); | ||
| 683 | w |= 0x40; | ||
| 684 | pcie_writereg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_LCREG, w); | ||
| 685 | } | ||
| 686 | |||
| 687 | if (ai_get_buscorerev(sih) == 0) { | ||
| 688 | pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_TIMER1, 0x8128); | ||
| 689 | pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDR, 0x0100); | ||
| 690 | pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDRBW, 0x1466); | ||
| 691 | } else if (PCIE_ASPM(sih)) { | ||
| 692 | /* Change the L1 threshold for better performance */ | ||
| 693 | w = pcie_readreg(pi->core, PCIE_PCIEREGS, | ||
| 694 | PCIE_DLLP_PMTHRESHREG); | ||
| 695 | w &= ~PCIE_L1THRESHOLDTIME_MASK; | ||
| 696 | w |= PCIE_L1THRESHOLD_WARVAL << PCIE_L1THRESHOLDTIME_SHIFT; | ||
| 697 | pcie_writereg(pi->core, PCIE_PCIEREGS, | ||
| 698 | PCIE_DLLP_PMTHRESHREG, w); | ||
| 699 | |||
| 700 | pcie_war_serdes(pi); | ||
| 701 | |||
| 702 | pcie_war_aspm_clkreq(pi); | ||
| 703 | } else if (ai_get_buscorerev(pi->sih) == 7) | ||
| 704 | pcie_war_noplldown(pi); | ||
| 705 | |||
| 706 | /* Note that the fix is actually in the SROM, | ||
| 707 | * that's why this is open-ended | ||
| 708 | */ | ||
| 709 | if (ai_get_buscorerev(pi->sih) >= 6) | ||
| 710 | pcie_misc_config_fixup(pi); | ||
| 711 | } | ||
| 712 | |||
| 713 | /* ***** Functions called during driver state changes ***** */ | ||
| 714 | void pcicore_attach(struct pcicore_info *pi, int state) | ||
| 715 | { | ||
| 716 | struct si_pub *sih = pi->sih; | ||
| 717 | u32 bfl2 = (u32)getintvar(sih, BRCMS_SROM_BOARDFLAGS2); | ||
| 718 | |||
| 719 | /* Determine if this board needs override */ | ||
| 720 | if (PCIE_ASPM(sih)) { | ||
| 721 | if (bfl2 & BFL2_PCIEWAR_OVR) | ||
| 722 | pi->pcie_war_aspm_ovr = PCIE_ASPM_DISAB; | ||
| 723 | else | ||
| 724 | pi->pcie_war_aspm_ovr = PCIE_ASPM_ENAB; | ||
| 725 | } | ||
| 726 | |||
| 727 | /* These need to happen in this order only */ | ||
| 728 | pcie_war_polarity(pi); | ||
| 729 | |||
| 730 | pcie_war_serdes(pi); | ||
| 731 | |||
| 732 | pcie_war_aspm_clkreq(pi); | ||
| 733 | |||
| 734 | pcie_clkreq_upd(pi, state); | ||
| 735 | |||
| 736 | } | ||
| 737 | |||
| 738 | void pcicore_hwup(struct pcicore_info *pi) | ||
| 739 | { | ||
| 740 | if (!pi || ai_get_buscoretype(pi->sih) != PCIE_CORE_ID) | ||
| 741 | return; | ||
| 742 | |||
| 743 | pcie_war_pci_setup(pi); | ||
| 744 | } | ||
| 745 | |||
| 746 | void pcicore_up(struct pcicore_info *pi, int state) | ||
| 747 | { | ||
| 748 | if (!pi || ai_get_buscoretype(pi->sih) != PCIE_CORE_ID) | ||
| 749 | return; | ||
| 750 | |||
| 751 | /* Restore L1 timer for better performance */ | ||
| 752 | pcie_extendL1timer(pi, true); | ||
| 753 | |||
| 754 | pcie_clkreq_upd(pi, state); | ||
| 755 | } | ||
| 756 | |||
| 757 | /* When the device is going to enter D3 state | ||
| 758 | * (or the system is going to enter S3/S4 states) | ||
| 759 | */ | ||
| 760 | void pcicore_sleep(struct pcicore_info *pi) | ||
| 761 | { | ||
| 762 | u32 w; | ||
| 763 | |||
| 764 | if (!pi || !PCIE_ASPM(pi->sih)) | ||
| 765 | return; | ||
| 766 | |||
| 767 | pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w); | ||
| 768 | w &= ~PCIE_CAP_LCREG_ASPML1; | ||
| 769 | pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w); | ||
| 770 | |||
| 771 | pi->pcie_pr42767 = false; | ||
| 772 | } | ||
| 773 | |||
| 774 | void pcicore_down(struct pcicore_info *pi, int state) | ||
| 775 | { | ||
| 776 | if (!pi || ai_get_buscoretype(pi->sih) != PCIE_CORE_ID) | ||
| 777 | return; | ||
| 778 | |||
| 779 | pcie_clkreq_upd(pi, state); | ||
| 780 | |||
| 781 | /* Reduce L1 timer for better power savings */ | ||
| 782 | pcie_extendL1timer(pi, false); | ||
| 783 | } | ||
| 784 | |||
| 785 | void pcicore_fixcfg(struct pcicore_info *pi) | ||
| 786 | { | ||
| 787 | struct bcma_device *core = pi->core; | ||
| 788 | u16 val16; | ||
| 789 | uint regoff; | ||
| 790 | |||
| 791 | switch (pi->core->id.id) { | ||
| 792 | case BCMA_CORE_PCI: | ||
| 793 | regoff = PCIREGOFFS(sprom[SRSH_PI_OFFSET]); | ||
| 794 | break; | ||
| 795 | |||
| 796 | case BCMA_CORE_PCIE: | ||
| 797 | regoff = PCIEREGOFFS(sprom[SRSH_PI_OFFSET]); | ||
| 798 | break; | ||
| 799 | |||
| 800 | default: | ||
| 801 | return; | ||
| 802 | } | ||
| 803 | |||
| 804 | val16 = bcma_read16(pi->core, regoff); | ||
| 805 | if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != | ||
| 806 | (u16)core->core_index) { | ||
| 807 | val16 = ((u16)core->core_index << SRSH_PI_SHIFT) | | ||
| 808 | (val16 & ~SRSH_PI_MASK); | ||
| 809 | bcma_write16(pi->core, regoff, val16); | ||
| 810 | } | ||
| 811 | } | ||
| 812 | |||
| 813 | /* precondition: current core is pci core */ | ||
| 814 | void | ||
| 815 | pcicore_pci_setup(struct pcicore_info *pi) | ||
| 816 | { | ||
| 817 | bcma_set32(pi->core, PCIREGOFFS(sbtopci2), | ||
| 818 | SBTOPCI_PREF | SBTOPCI_BURST); | ||
| 819 | |||
| 820 | if (pi->core->id.rev >= 11) { | ||
| 821 | bcma_set32(pi->core, PCIREGOFFS(sbtopci2), | ||
| 822 | SBTOPCI_RC_READMULTI); | ||
| 823 | bcma_set32(pi->core, PCIREGOFFS(clkrun), PCI_CLKRUN_DSBL); | ||
| 824 | (void)bcma_read32(pi->core, PCIREGOFFS(clkrun)); | ||
| 825 | } | ||
| 826 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/nicpci.h b/drivers/net/wireless/brcm80211/brcmsmac/nicpci.h deleted file mode 100644 index 9fc3ead540a..00000000000 --- a/drivers/net/wireless/brcm80211/brcmsmac/nicpci.h +++ /dev/null | |||
| @@ -1,77 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2010 Broadcom Corporation | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef _BRCM_NICPCI_H_ | ||
| 18 | #define _BRCM_NICPCI_H_ | ||
| 19 | |||
| 20 | #include "types.h" | ||
| 21 | |||
| 22 | /* PCI configuration address space size */ | ||
| 23 | #define PCI_SZPCR 256 | ||
| 24 | |||
| 25 | /* Brcm PCI configuration registers */ | ||
| 26 | /* backplane address space accessed by BAR0 */ | ||
| 27 | #define PCI_BAR0_WIN 0x80 | ||
| 28 | /* sprom property control */ | ||
| 29 | #define PCI_SPROM_CONTROL 0x88 | ||
| 30 | /* mask of PCI and other cores interrupts */ | ||
| 31 | #define PCI_INT_MASK 0x94 | ||
| 32 | /* backplane core interrupt mask bits offset */ | ||
| 33 | #define PCI_SBIM_SHIFT 8 | ||
| 34 | /* backplane address space accessed by second 4KB of BAR0 */ | ||
| 35 | #define PCI_BAR0_WIN2 0xac | ||
| 36 | /* pci config space gpio input (>=rev3) */ | ||
| 37 | #define PCI_GPIO_IN 0xb0 | ||
| 38 | /* pci config space gpio output (>=rev3) */ | ||
| 39 | #define PCI_GPIO_OUT 0xb4 | ||
| 40 | /* pci config space gpio output enable (>=rev3) */ | ||
| 41 | #define PCI_GPIO_OUTEN 0xb8 | ||
| 42 | |||
| 43 | /* bar0 + 4K accesses external sprom */ | ||
| 44 | #define PCI_BAR0_SPROM_OFFSET (4 * 1024) | ||
| 45 | /* bar0 + 6K accesses pci core registers */ | ||
| 46 | #define PCI_BAR0_PCIREGS_OFFSET (6 * 1024) | ||
| 47 | /* | ||
| 48 | * pci core SB registers are at the end of the | ||
| 49 | * 8KB window, so their address is the "regular" | ||
| 50 | * address plus 4K | ||
| 51 | */ | ||
| 52 | #define PCI_BAR0_PCISBR_OFFSET (4 * 1024) | ||
| 53 | /* bar0 window size Match with corerev 13 */ | ||
| 54 | #define PCI_BAR0_WINSZ (16 * 1024) | ||
| 55 | /* On pci corerev >= 13 and all pcie, the bar0 is now 16KB and it maps: */ | ||
| 56 | /* bar0 + 8K accesses pci/pcie core registers */ | ||
| 57 | #define PCI_16KB0_PCIREGS_OFFSET (8 * 1024) | ||
| 58 | /* bar0 + 12K accesses chipc core registers */ | ||
| 59 | #define PCI_16KB0_CCREGS_OFFSET (12 * 1024) | ||
| 60 | |||
| 61 | struct sbpciregs; | ||
| 62 | struct sbpcieregs; | ||
| 63 | |||
| 64 | extern struct pcicore_info *pcicore_init(struct si_pub *sih, | ||
| 65 | struct bcma_device *core); | ||
| 66 | extern void pcicore_deinit(struct pcicore_info *pch); | ||
| 67 | extern void pcicore_attach(struct pcicore_info *pch, int state); | ||
| 68 | extern void pcicore_hwup(struct pcicore_info *pch); | ||
| 69 | extern void pcicore_up(struct pcicore_info *pch, int state); | ||
| 70 | extern void pcicore_sleep(struct pcicore_info *pch); | ||
| 71 | extern void pcicore_down(struct pcicore_info *pch, int state); | ||
| 72 | extern u8 pcicore_find_pci_capability(struct pci_dev *dev, u8 req_cap_id, | ||
| 73 | unsigned char *buf, u32 *buflen); | ||
| 74 | extern void pcicore_fixcfg(struct pcicore_info *pch); | ||
| 75 | extern void pcicore_pci_setup(struct pcicore_info *pch); | ||
| 76 | |||
| 77 | #endif /* _BRCM_NICPCI_H_ */ | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/otp.c b/drivers/net/wireless/brcm80211/brcmsmac/otp.c deleted file mode 100644 index f1ca1262586..00000000000 --- a/drivers/net/wireless/brcm80211/brcmsmac/otp.c +++ /dev/null | |||
| @@ -1,410 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2010 Broadcom Corporation | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/io.h> | ||
| 18 | #include <linux/errno.h> | ||
| 19 | #include <linux/string.h> | ||
| 20 | |||
| 21 | #include <brcm_hw_ids.h> | ||
| 22 | #include <chipcommon.h> | ||
| 23 | #include "aiutils.h" | ||
| 24 | #include "otp.h" | ||
| 25 | |||
| 26 | #define OTPS_GUP_MASK 0x00000f00 | ||
| 27 | #define OTPS_GUP_SHIFT 8 | ||
| 28 | /* h/w subregion is programmed */ | ||
| 29 | #define OTPS_GUP_HW 0x00000100 | ||
| 30 | /* s/w subregion is programmed */ | ||
| 31 | #define OTPS_GUP_SW 0x00000200 | ||
| 32 | /* chipid/pkgopt subregion is programmed */ | ||
| 33 | #define OTPS_GUP_CI 0x00000400 | ||
| 34 | /* fuse subregion is programmed */ | ||
| 35 | #define OTPS_GUP_FUSE 0x00000800 | ||
| 36 | |||
| 37 | /* Fields in otpprog in rev >= 21 */ | ||
| 38 | #define OTPP_COL_MASK 0x000000ff | ||
| 39 | #define OTPP_COL_SHIFT 0 | ||
| 40 | #define OTPP_ROW_MASK 0x0000ff00 | ||
| 41 | #define OTPP_ROW_SHIFT 8 | ||
| 42 | #define OTPP_OC_MASK 0x0f000000 | ||
| 43 | #define OTPP_OC_SHIFT 24 | ||
| 44 | #define OTPP_READERR 0x10000000 | ||
| 45 | #define OTPP_VALUE_MASK 0x20000000 | ||
| 46 | #define OTPP_VALUE_SHIFT 29 | ||
| 47 | #define OTPP_START_BUSY 0x80000000 | ||
| 48 | #define OTPP_READ 0x40000000 | ||
| 49 | |||
| 50 | /* Opcodes for OTPP_OC field */ | ||
| 51 | #define OTPPOC_READ 0 | ||
| 52 | #define OTPPOC_BIT_PROG 1 | ||
| 53 | #define OTPPOC_VERIFY 3 | ||
| 54 | #define OTPPOC_INIT 4 | ||
| 55 | #define OTPPOC_SET 5 | ||
| 56 | #define OTPPOC_RESET 6 | ||
| 57 | #define OTPPOC_OCST 7 | ||
| 58 | #define OTPPOC_ROW_LOCK 8 | ||
| 59 | #define OTPPOC_PRESCN_TEST 9 | ||
| 60 | |||
| 61 | #define OTPTYPE_IPX(ccrev) ((ccrev) == 21 || (ccrev) >= 23) | ||
| 62 | |||
| 63 | #define OTPP_TRIES 10000000 /* # of tries for OTPP */ | ||
| 64 | |||
| 65 | #define MAXNUMRDES 9 /* Maximum OTP redundancy entries */ | ||
| 66 | |||
| 67 | /* Fixed size subregions sizes in words */ | ||
| 68 | #define OTPGU_CI_SZ 2 | ||
| 69 | |||
| 70 | struct otpinfo; | ||
| 71 | |||
| 72 | /* OTP function struct */ | ||
| 73 | struct otp_fn_s { | ||
| 74 | int (*init)(struct si_pub *sih, struct otpinfo *oi); | ||
| 75 | int (*read_region)(struct otpinfo *oi, int region, u16 *data, | ||
| 76 | uint *wlen); | ||
| 77 | }; | ||
| 78 | |||
| 79 | struct otpinfo { | ||
| 80 | struct bcma_device *core; /* chipc core */ | ||
| 81 | const struct otp_fn_s *fn; /* OTP functions */ | ||
| 82 | struct si_pub *sih; /* Saved sb handle */ | ||
| 83 | |||
| 84 | /* IPX OTP section */ | ||
| 85 | u16 wsize; /* Size of otp in words */ | ||
| 86 | u16 rows; /* Geometry */ | ||
| 87 | u16 cols; /* Geometry */ | ||
| 88 | u32 status; /* Flag bits (lock/prog/rv). | ||
| 89 | * (Reflected only when OTP is power cycled) | ||
| 90 | */ | ||
| 91 | u16 hwbase; /* hardware subregion offset */ | ||
| 92 | u16 hwlim; /* hardware subregion boundary */ | ||
| 93 | u16 swbase; /* software subregion offset */ | ||
| 94 | u16 swlim; /* software subregion boundary */ | ||
| 95 | u16 fbase; /* fuse subregion offset */ | ||
| 96 | u16 flim; /* fuse subregion boundary */ | ||
| 97 | int otpgu_base; /* offset to General Use Region */ | ||
| 98 | }; | ||
| 99 | |||
| 100 | /* OTP layout */ | ||
| 101 | /* CC revs 21, 24 and 27 OTP General Use Region word offset */ | ||
| 102 | #define REVA4_OTPGU_BASE 12 | ||
| 103 | |||
| 104 | /* CC revs 23, 25, 26, 28 and above OTP General Use Region word offset */ | ||
| 105 | #define REVB8_OTPGU_BASE 20 | ||
| 106 | |||
| 107 | /* CC rev 36 OTP General Use Region word offset */ | ||
| 108 | #define REV36_OTPGU_BASE 12 | ||
| 109 | |||
| 110 | /* Subregion word offsets in General Use region */ | ||
| 111 | #define OTPGU_HSB_OFF 0 | ||
| 112 | #define OTPGU_SFB_OFF 1 | ||
| 113 | #define OTPGU_CI_OFF 2 | ||
| 114 | #define OTPGU_P_OFF 3 | ||
| 115 | #define OTPGU_SROM_OFF 4 | ||
| 116 | |||
| 117 | /* Flag bit offsets in General Use region */ | ||
| 118 | #define OTPGU_HWP_OFF 60 | ||
| 119 | #define OTPGU_SWP_OFF 61 | ||
| 120 | #define OTPGU_CIP_OFF 62 | ||
| 121 | #define OTPGU_FUSEP_OFF 63 | ||
| 122 | #define OTPGU_CIP_MSK 0x4000 | ||
| 123 | #define OTPGU_P_MSK 0xf000 | ||
| 124 | #define OTPGU_P_SHIFT (OTPGU_HWP_OFF % 16) | ||
| 125 | |||
| 126 | /* OTP Size */ | ||
| 127 | #define OTP_SZ_FU_324 ((roundup(324, 8))/8) /* 324 bits */ | ||
| 128 | #define OTP_SZ_FU_288 (288/8) /* 288 bits */ | ||
| 129 | #define OTP_SZ_FU_216 (216/8) /* 216 bits */ | ||
| 130 | #define OTP_SZ_FU_72 (72/8) /* 72 bits */ | ||
| 131 | #define OTP_SZ_CHECKSUM (16/8) /* 16 bits */ | ||
| 132 | #define OTP4315_SWREG_SZ 178 /* 178 bytes */ | ||
| 133 | #define OTP_SZ_FU_144 (144/8) /* 144 bits */ | ||
| 134 | |||
| 135 | static u16 | ||
| 136 | ipxotp_otpr(struct otpinfo *oi, uint wn) | ||
| 137 | { | ||
| 138 | return bcma_read16(oi->core, | ||
| 139 | CHIPCREGOFFS(sromotp[wn])); | ||
| 140 | } | ||
| 141 | |||
| 142 | /* | ||
| 143 | * Calculate max HW/SW region byte size by subtracting fuse region | ||
| 144 | * and checksum size, osizew is oi->wsize (OTP size - GU size) in words | ||
| 145 | */ | ||
| 146 | static int ipxotp_max_rgnsz(struct si_pub *sih, int osizew) | ||
| 147 | { | ||
| 148 | int ret = 0; | ||
| 149 | |||
| 150 | switch (ai_get_chip_id(sih)) { | ||
| 151 | case BCM43224_CHIP_ID: | ||
| 152 | case BCM43225_CHIP_ID: | ||
| 153 | ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM; | ||
| 154 | break; | ||
| 155 | case BCM4313_CHIP_ID: | ||
| 156 | ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM; | ||
| 157 | break; | ||
| 158 | default: | ||
| 159 | break; /* Don't know about this chip */ | ||
| 160 | } | ||
| 161 | |||
| 162 | return ret; | ||
| 163 | } | ||
| 164 | |||
| 165 | static void _ipxotp_init(struct otpinfo *oi) | ||
| 166 | { | ||
| 167 | uint k; | ||
| 168 | u32 otpp, st; | ||
| 169 | int ccrev = ai_get_ccrev(oi->sih); | ||
| 170 | |||
| 171 | |||
| 172 | /* | ||
| 173 | * record word offset of General Use Region | ||
| 174 | * for various chipcommon revs | ||
| 175 | */ | ||
| 176 | if (ccrev == 21 || ccrev == 24 | ||
| 177 | || ccrev == 27) { | ||
| 178 | oi->otpgu_base = REVA4_OTPGU_BASE; | ||
| 179 | } else if (ccrev == 36) { | ||
| 180 | /* | ||
| 181 | * OTP size greater than equal to 2KB (128 words), | ||
| 182 | * otpgu_base is similar to rev23 | ||
| 183 | */ | ||
| 184 | if (oi->wsize >= 128) | ||
| 185 | oi->otpgu_base = REVB8_OTPGU_BASE; | ||
| 186 | else | ||
| 187 | oi->otpgu_base = REV36_OTPGU_BASE; | ||
| 188 | } else if (ccrev == 23 || ccrev >= 25) { | ||
| 189 | oi->otpgu_base = REVB8_OTPGU_BASE; | ||
| 190 | } | ||
| 191 | |||
| 192 | /* First issue an init command so the status is up to date */ | ||
| 193 | otpp = | ||
| 194 | OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK); | ||
| 195 | |||
| 196 | bcma_write32(oi->core, CHIPCREGOFFS(otpprog), otpp); | ||
| 197 | st = bcma_read32(oi->core, CHIPCREGOFFS(otpprog)); | ||
| 198 | for (k = 0; (st & OTPP_START_BUSY) && (k < OTPP_TRIES); k++) | ||
| 199 | st = bcma_read32(oi->core, CHIPCREGOFFS(otpprog)); | ||
| 200 | if (k >= OTPP_TRIES) | ||
| 201 | return; | ||
| 202 | |||
| 203 | /* Read OTP lock bits and subregion programmed indication bits */ | ||
| 204 | oi->status = bcma_read32(oi->core, CHIPCREGOFFS(otpstatus)); | ||
| 205 | |||
| 206 | if ((ai_get_chip_id(oi->sih) == BCM43224_CHIP_ID) | ||
| 207 | || (ai_get_chip_id(oi->sih) == BCM43225_CHIP_ID)) { | ||
| 208 | u32 p_bits; | ||
| 209 | p_bits = (ipxotp_otpr(oi, oi->otpgu_base + OTPGU_P_OFF) & | ||
| 210 | OTPGU_P_MSK) >> OTPGU_P_SHIFT; | ||
| 211 | oi->status |= (p_bits << OTPS_GUP_SHIFT); | ||
| 212 | } | ||
| 213 | |||
| 214 | /* | ||
| 215 | * h/w region base and fuse region limit are fixed to | ||
| 216 | * the top and the bottom of the general use region. | ||
| 217 | * Everything else can be flexible. | ||
| 218 | */ | ||
| 219 | oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF; | ||
| 220 | oi->hwlim = oi->wsize; | ||
| 221 | if (oi->status & OTPS_GUP_HW) { | ||
| 222 | oi->hwlim = | ||
| 223 | ipxotp_otpr(oi, oi->otpgu_base + OTPGU_HSB_OFF) / 16; | ||
| 224 | oi->swbase = oi->hwlim; | ||
| 225 | } else | ||
| 226 | oi->swbase = oi->hwbase; | ||
| 227 | |||
| 228 | /* subtract fuse and checksum from beginning */ | ||
| 229 | oi->swlim = ipxotp_max_rgnsz(oi->sih, oi->wsize) / 2; | ||
| 230 | |||
| 231 | if (oi->status & OTPS_GUP_SW) { | ||
| 232 | oi->swlim = | ||
| 233 | ipxotp_otpr(oi, oi->otpgu_base + OTPGU_SFB_OFF) / 16; | ||
| 234 | oi->fbase = oi->swlim; | ||
| 235 | } else | ||
| 236 | oi->fbase = oi->swbase; | ||
| 237 | |||
| 238 | oi->flim = oi->wsize; | ||
| 239 | } | ||
| 240 | |||
| 241 | static int ipxotp_init(struct si_pub *sih, struct otpinfo *oi) | ||
| 242 | { | ||
| 243 | /* Make sure we're running IPX OTP */ | ||
| 244 | if (!OTPTYPE_IPX(ai_get_ccrev(sih))) | ||
| 245 | return -EBADE; | ||
| 246 | |||
| 247 | /* Make sure OTP is not disabled */ | ||
| 248 | if (ai_is_otp_disabled(sih)) | ||
| 249 | return -EBADE; | ||
| 250 | |||
| 251 | /* Check for otp size */ | ||
| 252 | switch ((ai_get_cccaps(sih) & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) { | ||
| 253 | case 0: | ||
| 254 | /* Nothing there */ | ||
| 255 | return -EBADE; | ||
| 256 | case 1: /* 32x64 */ | ||
| 257 | oi->rows = 32; | ||
| 258 | oi->cols = 64; | ||
| 259 | oi->wsize = 128; | ||
| 260 | break; | ||
| 261 | case 2: /* 64x64 */ | ||
| 262 | oi->rows = 64; | ||
| 263 | oi->cols = 64; | ||
| 264 | oi->wsize = 256; | ||
| 265 | break; | ||
| 266 | case 5: /* 96x64 */ | ||
| 267 | oi->rows = 96; | ||
| 268 | oi->cols = 64; | ||
| 269 | oi->wsize = 384; | ||
| 270 | break; | ||
| 271 | case 7: /* 16x64 *//* 1024 bits */ | ||
| 272 | oi->rows = 16; | ||
| 273 | oi->cols = 64; | ||
| 274 | oi->wsize = 64; | ||
| 275 | break; | ||
| 276 | default: | ||
| 277 | /* Don't know the geometry */ | ||
| 278 | return -EBADE; | ||
| 279 | } | ||
| 280 | |||
| 281 | /* Retrieve OTP region info */ | ||
| 282 | _ipxotp_init(oi); | ||
| 283 | return 0; | ||
| 284 | } | ||
| 285 | |||
| 286 | static int | ||
| 287 | ipxotp_read_region(struct otpinfo *oi, int region, u16 *data, uint *wlen) | ||
| 288 | { | ||
| 289 | uint base, i, sz; | ||
| 290 | |||
| 291 | /* Validate region selection */ | ||
| 292 | switch (region) { | ||
| 293 | case OTP_HW_RGN: | ||
| 294 | sz = (uint) oi->hwlim - oi->hwbase; | ||
| 295 | if (!(oi->status & OTPS_GUP_HW)) { | ||
| 296 | *wlen = sz; | ||
| 297 | return -ENODATA; | ||
| 298 | } | ||
| 299 | if (*wlen < sz) { | ||
| 300 | *wlen = sz; | ||
| 301 | return -EOVERFLOW; | ||
| 302 | } | ||
| 303 | base = oi->hwbase; | ||
| 304 | break; | ||
| 305 | case OTP_SW_RGN: | ||
| 306 | sz = ((uint) oi->swlim - oi->swbase); | ||
| 307 | if (!(oi->status & OTPS_GUP_SW)) { | ||
| 308 | *wlen = sz; | ||
| 309 | return -ENODATA; | ||
| 310 | } | ||
| 311 | if (*wlen < sz) { | ||
| 312 | *wlen = sz; | ||
| 313 | return -EOVERFLOW; | ||
| 314 | } | ||
| 315 | base = oi->swbase; | ||
| 316 | break; | ||
| 317 | case OTP_CI_RGN: | ||
| 318 | sz = OTPGU_CI_SZ; | ||
| 319 | if (!(oi->status & OTPS_GUP_CI)) { | ||
| 320 | *wlen = sz; | ||
| 321 | return -ENODATA; | ||
| 322 | } | ||
| 323 | if (*wlen < sz) { | ||
| 324 | *wlen = sz; | ||
| 325 | return -EOVERFLOW; | ||
| 326 | } | ||
| 327 | base = oi->otpgu_base + OTPGU_CI_OFF; | ||
| 328 | break; | ||
| 329 | case OTP_FUSE_RGN: | ||
| 330 | sz = (uint) oi->flim - oi->fbase; | ||
| 331 | if (!(oi->status & OTPS_GUP_FUSE)) { | ||
| 332 | *wlen = sz; | ||
| 333 | return -ENODATA; | ||
| 334 | } | ||
| 335 | if (*wlen < sz) { | ||
| 336 | *wlen = sz; | ||
| 337 | return -EOVERFLOW; | ||
| 338 | } | ||
| 339 | base = oi->fbase; | ||
| 340 | break; | ||
| 341 | case OTP_ALL_RGN: | ||
| 342 | sz = ((uint) oi->flim - oi->hwbase); | ||
| 343 | if (!(oi->status & (OTPS_GUP_HW | OTPS_GUP_SW))) { | ||
| 344 | *wlen = sz; | ||
| 345 | return -ENODATA; | ||
| 346 | } | ||
| 347 | if (*wlen < sz) { | ||
| 348 | *wlen = sz; | ||
| 349 | return -EOVERFLOW; | ||
| 350 | } | ||
| 351 | base = oi->hwbase; | ||
| 352 | break; | ||
| 353 | default: | ||
| 354 | return -EINVAL; | ||
| 355 | } | ||
| 356 | |||
| 357 | /* Read the data */ | ||
| 358 | for (i = 0; i < sz; i++) | ||
| 359 | data[i] = ipxotp_otpr(oi, base + i); | ||
| 360 | |||
| 361 | *wlen = sz; | ||
| 362 | return 0; | ||
| 363 | } | ||
| 364 | |||
| 365 | static const struct otp_fn_s ipxotp_fn = { | ||
| 366 | (int (*)(struct si_pub *, struct otpinfo *)) ipxotp_init, | ||
| 367 | (int (*)(struct otpinfo *, int, u16 *, uint *)) ipxotp_read_region, | ||
| 368 | }; | ||
| 369 | |||
| 370 | static int otp_init(struct si_pub *sih, struct otpinfo *oi) | ||
| 371 | { | ||
| 372 | int ret; | ||
| 373 | |||
| 374 | memset(oi, 0, sizeof(struct otpinfo)); | ||
| 375 | |||
| 376 | oi->core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); | ||
| 377 | |||
| 378 | if (OTPTYPE_IPX(ai_get_ccrev(sih))) | ||
| 379 | oi->fn = &ipxotp_fn; | ||
| 380 | |||
| 381 | if (oi->fn == NULL) | ||
| 382 | return -EBADE; | ||
| 383 | |||
| 384 | oi->sih = sih; | ||
| 385 | |||
| 386 | ret = (oi->fn->init)(sih, oi); | ||
| 387 | |||
| 388 | return ret; | ||
| 389 | } | ||
| 390 | |||
| 391 | int | ||
| 392 | otp_read_region(struct si_pub *sih, int region, u16 *data, uint *wlen) { | ||
| 393 | struct otpinfo otpinfo; | ||
| 394 | struct otpinfo *oi = &otpinfo; | ||
| 395 | int err = 0; | ||
| 396 | |||
| 397 | if (ai_is_otp_disabled(sih)) { | ||
| 398 | err = -EPERM; | ||
| 399 | goto out; | ||
| 400 | } | ||
| 401 | |||
| 402 | err = otp_init(sih, oi); | ||
| 403 | if (err) | ||
| 404 | goto out; | ||
| 405 | |||
| 406 | err = ((oi)->fn->read_region)(oi, region, data, wlen); | ||
| 407 | |||
| 408 | out: | ||
| 409 | return err; | ||
| 410 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/otp.h b/drivers/net/wireless/brcm80211/brcmsmac/otp.h deleted file mode 100644 index 6b6d31cf956..00000000000 --- a/drivers/net/wireless/brcm80211/brcmsmac/otp.h +++ /dev/null | |||
| @@ -1,36 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2010 Broadcom Corporation | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef _BRCM_OTP_H_ | ||
| 18 | #define _BRCM_OTP_H_ | ||
| 19 | |||
| 20 | #include "types.h" | ||
| 21 | |||
| 22 | /* OTP regions */ | ||
| 23 | #define OTP_HW_RGN 1 | ||
| 24 | #define OTP_SW_RGN 2 | ||
| 25 | #define OTP_CI_RGN 4 | ||
| 26 | #define OTP_FUSE_RGN 8 | ||
| 27 | /* From h/w region to end of OTP including checksum */ | ||
| 28 | #define OTP_ALL_RGN 0xf | ||
| 29 | |||
| 30 | /* OTP Size */ | ||
| 31 | #define OTP_SZ_MAX (6144/8) /* maximum bytes in one CIS */ | ||
| 32 | |||
| 33 | extern int otp_read_region(struct si_pub *sih, int region, u16 *data, | ||
| 34 | uint *wlen); | ||
| 35 | |||
| 36 | #endif /* _BRCM_OTP_H_ */ | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c index 0fce56235f3..abfd78822fb 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c | |||
| @@ -4817,28 +4817,23 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi) | |||
| 4817 | s8 txpwr = 0; | 4817 | s8 txpwr = 0; |
| 4818 | int i; | 4818 | int i; |
| 4819 | struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; | 4819 | struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; |
| 4820 | struct phy_shim_info *shim = pi->sh->physhim; | 4820 | struct ssb_sprom *sprom = &pi->d11core->bus->sprom; |
| 4821 | 4821 | ||
| 4822 | if (CHSPEC_IS2G(pi->radio_chanspec)) { | 4822 | if (CHSPEC_IS2G(pi->radio_chanspec)) { |
| 4823 | u16 cckpo = 0; | 4823 | u16 cckpo = 0; |
| 4824 | u32 offset_ofdm, offset_mcs; | 4824 | u32 offset_ofdm, offset_mcs; |
| 4825 | 4825 | ||
| 4826 | pi_lcn->lcnphy_tr_isolation_mid = | 4826 | pi_lcn->lcnphy_tr_isolation_mid = sprom->fem.ghz2.tr_iso; |
| 4827 | (u8)wlapi_getintvar(shim, BRCMS_SROM_TRISO2G); | ||
| 4828 | 4827 | ||
| 4829 | pi_lcn->lcnphy_rx_power_offset = | 4828 | pi_lcn->lcnphy_rx_power_offset = sprom->rxpo2g; |
| 4830 | (u8)wlapi_getintvar(shim, BRCMS_SROM_RXPO2G); | ||
| 4831 | 4829 | ||
| 4832 | pi->txpa_2g[0] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B0); | 4830 | pi->txpa_2g[0] = sprom->pa0b0; |
| 4833 | pi->txpa_2g[1] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B1); | 4831 | pi->txpa_2g[1] = sprom->pa0b1; |
| 4834 | pi->txpa_2g[2] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B2); | 4832 | pi->txpa_2g[2] = sprom->pa0b2; |
| 4835 | 4833 | ||
| 4836 | pi_lcn->lcnphy_rssi_vf = | 4834 | pi_lcn->lcnphy_rssi_vf = sprom->rssismf2g; |
| 4837 | (u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISMF2G); | 4835 | pi_lcn->lcnphy_rssi_vc = sprom->rssismc2g; |
| 4838 | pi_lcn->lcnphy_rssi_vc = | 4836 | pi_lcn->lcnphy_rssi_gs = sprom->rssisav2g; |
| 4839 | (u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISMC2G); | ||
| 4840 | pi_lcn->lcnphy_rssi_gs = | ||
| 4841 | (u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISAV2G); | ||
| 4842 | 4837 | ||
| 4843 | pi_lcn->lcnphy_rssi_vf_lowtemp = pi_lcn->lcnphy_rssi_vf; | 4838 | pi_lcn->lcnphy_rssi_vf_lowtemp = pi_lcn->lcnphy_rssi_vf; |
| 4844 | pi_lcn->lcnphy_rssi_vc_lowtemp = pi_lcn->lcnphy_rssi_vc; | 4839 | pi_lcn->lcnphy_rssi_vc_lowtemp = pi_lcn->lcnphy_rssi_vc; |
| @@ -4848,7 +4843,7 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi) | |||
| 4848 | pi_lcn->lcnphy_rssi_vc_hightemp = pi_lcn->lcnphy_rssi_vc; | 4843 | pi_lcn->lcnphy_rssi_vc_hightemp = pi_lcn->lcnphy_rssi_vc; |
| 4849 | pi_lcn->lcnphy_rssi_gs_hightemp = pi_lcn->lcnphy_rssi_gs; | 4844 | pi_lcn->lcnphy_rssi_gs_hightemp = pi_lcn->lcnphy_rssi_gs; |
| 4850 | 4845 | ||
| 4851 | txpwr = (s8)wlapi_getintvar(shim, BRCMS_SROM_MAXP2GA0); | 4846 | txpwr = sprom->core_pwr_info[0].maxpwr_2g; |
| 4852 | pi->tx_srom_max_2g = txpwr; | 4847 | pi->tx_srom_max_2g = txpwr; |
| 4853 | 4848 | ||
| 4854 | for (i = 0; i < PWRTBL_NUM_COEFF; i++) { | 4849 | for (i = 0; i < PWRTBL_NUM_COEFF; i++) { |
| @@ -4856,8 +4851,8 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi) | |||
| 4856 | pi->txpa_2g_high_temp[i] = pi->txpa_2g[i]; | 4851 | pi->txpa_2g_high_temp[i] = pi->txpa_2g[i]; |
| 4857 | } | 4852 | } |
| 4858 | 4853 | ||
| 4859 | cckpo = (u16)wlapi_getintvar(shim, BRCMS_SROM_CCK2GPO); | 4854 | cckpo = sprom->cck2gpo; |
| 4860 | offset_ofdm = (u32)wlapi_getintvar(shim, BRCMS_SROM_OFDM2GPO); | 4855 | offset_ofdm = sprom->ofdm2gpo; |
| 4861 | if (cckpo) { | 4856 | if (cckpo) { |
| 4862 | uint max_pwr_chan = txpwr; | 4857 | uint max_pwr_chan = txpwr; |
| 4863 | 4858 | ||
| @@ -4876,7 +4871,7 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi) | |||
| 4876 | } else { | 4871 | } else { |
| 4877 | u8 opo = 0; | 4872 | u8 opo = 0; |
| 4878 | 4873 | ||
| 4879 | opo = (u8)wlapi_getintvar(shim, BRCMS_SROM_OPO); | 4874 | opo = sprom->opo; |
| 4880 | 4875 | ||
| 4881 | for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) | 4876 | for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) |
| 4882 | pi->tx_srom_max_rate_2g[i] = txpwr; | 4877 | pi->tx_srom_max_rate_2g[i] = txpwr; |
| @@ -4886,12 +4881,8 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi) | |||
| 4886 | ((offset_ofdm & 0xf) * 2); | 4881 | ((offset_ofdm & 0xf) * 2); |
| 4887 | offset_ofdm >>= 4; | 4882 | offset_ofdm >>= 4; |
| 4888 | } | 4883 | } |
| 4889 | offset_mcs = | 4884 | offset_mcs = sprom->mcs2gpo[1] << 16; |
| 4890 | wlapi_getintvar(shim, | 4885 | offset_mcs |= sprom->mcs2gpo[0]; |
| 4891 | BRCMS_SROM_MCS2GPO1) << 16; | ||
| 4892 | offset_mcs |= | ||
| 4893 | (u16) wlapi_getintvar(shim, | ||
| 4894 | BRCMS_SROM_MCS2GPO0); | ||
| 4895 | pi_lcn->lcnphy_mcs20_po = offset_mcs; | 4886 | pi_lcn->lcnphy_mcs20_po = offset_mcs; |
| 4896 | for (i = TXP_FIRST_SISO_MCS_20; | 4887 | for (i = TXP_FIRST_SISO_MCS_20; |
| 4897 | i <= TXP_LAST_SISO_MCS_20; i++) { | 4888 | i <= TXP_LAST_SISO_MCS_20; i++) { |
| @@ -4901,25 +4892,17 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi) | |||
| 4901 | } | 4892 | } |
| 4902 | } | 4893 | } |
| 4903 | 4894 | ||
| 4904 | pi_lcn->lcnphy_rawtempsense = | 4895 | pi_lcn->lcnphy_rawtempsense = sprom->rawtempsense; |
| 4905 | (u16)wlapi_getintvar(shim, BRCMS_SROM_RAWTEMPSENSE); | 4896 | pi_lcn->lcnphy_measPower = sprom->measpower; |
| 4906 | pi_lcn->lcnphy_measPower = | 4897 | pi_lcn->lcnphy_tempsense_slope = sprom->tempsense_slope; |
| 4907 | (u8)wlapi_getintvar(shim, BRCMS_SROM_MEASPOWER); | 4898 | pi_lcn->lcnphy_hw_iqcal_en = sprom->hw_iqcal_en; |
| 4908 | pi_lcn->lcnphy_tempsense_slope = | 4899 | pi_lcn->lcnphy_iqcal_swp_dis = sprom->iqcal_swp_dis; |
| 4909 | (u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPSENSE_SLOPE); | 4900 | pi_lcn->lcnphy_tempcorrx = sprom->tempcorrx; |
| 4910 | pi_lcn->lcnphy_hw_iqcal_en = | 4901 | pi_lcn->lcnphy_tempsense_option = sprom->tempsense_option; |
| 4911 | (bool)wlapi_getintvar(shim, BRCMS_SROM_HW_IQCAL_EN); | 4902 | pi_lcn->lcnphy_freqoffset_corr = sprom->freqoffset_corr; |
| 4912 | pi_lcn->lcnphy_iqcal_swp_dis = | 4903 | if (sprom->ant_available_bg > 1) |
| 4913 | (bool)wlapi_getintvar(shim, BRCMS_SROM_IQCAL_SWP_DIS); | ||
| 4914 | pi_lcn->lcnphy_tempcorrx = | ||
| 4915 | (u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPCORRX); | ||
| 4916 | pi_lcn->lcnphy_tempsense_option = | ||
| 4917 | (u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPSENSE_OPTION); | ||
| 4918 | pi_lcn->lcnphy_freqoffset_corr = | ||
| 4919 | (u8)wlapi_getintvar(shim, BRCMS_SROM_FREQOFFSET_CORR); | ||
| 4920 | if ((u8)wlapi_getintvar(shim, BRCMS_SROM_AA2G) > 1) | ||
| 4921 | wlc_phy_ant_rxdiv_set((struct brcms_phy_pub *) pi, | 4904 | wlc_phy_ant_rxdiv_set((struct brcms_phy_pub *) pi, |
| 4922 | (u8) wlapi_getintvar(shim, BRCMS_SROM_AA2G)); | 4905 | sprom->ant_available_bg); |
| 4923 | } | 4906 | } |
| 4924 | pi_lcn->lcnphy_cck_dig_filt_type = -1; | 4907 | pi_lcn->lcnphy_cck_dig_filt_type = -1; |
| 4925 | 4908 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c index 812b6e38526..13b261517cc 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c | |||
| @@ -14386,30 +14386,30 @@ static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi) | |||
| 14386 | { | 14386 | { |
| 14387 | u16 bw40po, cddpo, stbcpo, bwduppo; | 14387 | u16 bw40po, cddpo, stbcpo, bwduppo; |
| 14388 | uint band_num; | 14388 | uint band_num; |
| 14389 | struct phy_shim_info *shim = pi->sh->physhim; | 14389 | struct ssb_sprom *sprom = &pi->d11core->bus->sprom; |
| 14390 | 14390 | ||
| 14391 | if (pi->sh->sromrev >= 9) | 14391 | if (pi->sh->sromrev >= 9) |
| 14392 | return; | 14392 | return; |
| 14393 | 14393 | ||
| 14394 | bw40po = (u16) wlapi_getintvar(shim, BRCMS_SROM_BW40PO); | 14394 | bw40po = sprom->bw40po; |
| 14395 | pi->bw402gpo = bw40po & 0xf; | 14395 | pi->bw402gpo = bw40po & 0xf; |
| 14396 | pi->bw405gpo = (bw40po & 0xf0) >> 4; | 14396 | pi->bw405gpo = (bw40po & 0xf0) >> 4; |
| 14397 | pi->bw405glpo = (bw40po & 0xf00) >> 8; | 14397 | pi->bw405glpo = (bw40po & 0xf00) >> 8; |
| 14398 | pi->bw405ghpo = (bw40po & 0xf000) >> 12; | 14398 | pi->bw405ghpo = (bw40po & 0xf000) >> 12; |
| 14399 | 14399 | ||
| 14400 | cddpo = (u16) wlapi_getintvar(shim, BRCMS_SROM_CDDPO); | 14400 | cddpo = sprom->cddpo; |
| 14401 | pi->cdd2gpo = cddpo & 0xf; | 14401 | pi->cdd2gpo = cddpo & 0xf; |
| 14402 | pi->cdd5gpo = (cddpo & 0xf0) >> 4; | 14402 | pi->cdd5gpo = (cddpo & 0xf0) >> 4; |
| 14403 | pi->cdd5glpo = (cddpo & 0xf00) >> 8; | 14403 | pi->cdd5glpo = (cddpo & 0xf00) >> 8; |
| 14404 | pi->cdd5ghpo = (cddpo & 0xf000) >> 12; | 14404 | pi->cdd5ghpo = (cddpo & 0xf000) >> 12; |
| 14405 | 14405 | ||
| 14406 | stbcpo = (u16) wlapi_getintvar(shim, BRCMS_SROM_STBCPO); | 14406 | stbcpo = sprom->stbcpo; |
| 14407 | pi->stbc2gpo = stbcpo & 0xf; | 14407 | pi->stbc2gpo = stbcpo & 0xf; |
| 14408 | pi->stbc5gpo = (stbcpo & 0xf0) >> 4; | 14408 | pi->stbc5gpo = (stbcpo & 0xf0) >> 4; |
| 14409 | pi->stbc5glpo = (stbcpo & 0xf00) >> 8; | 14409 | pi->stbc5glpo = (stbcpo & 0xf00) >> 8; |
| 14410 | pi->stbc5ghpo = (stbcpo & 0xf000) >> 12; | 14410 | pi->stbc5ghpo = (stbcpo & 0xf000) >> 12; |
| 14411 | 14411 | ||
| 14412 | bwduppo = (u16) wlapi_getintvar(shim, BRCMS_SROM_BWDUPPO); | 14412 | bwduppo = sprom->bwduppo; |
| 14413 | pi->bwdup2gpo = bwduppo & 0xf; | 14413 | pi->bwdup2gpo = bwduppo & 0xf; |
| 14414 | pi->bwdup5gpo = (bwduppo & 0xf0) >> 4; | 14414 | pi->bwdup5gpo = (bwduppo & 0xf0) >> 4; |
| 14415 | pi->bwdup5glpo = (bwduppo & 0xf00) >> 8; | 14415 | pi->bwdup5glpo = (bwduppo & 0xf00) >> 8; |
| @@ -14419,242 +14419,137 @@ static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi) | |||
| 14419 | band_num++) { | 14419 | band_num++) { |
| 14420 | switch (band_num) { | 14420 | switch (band_num) { |
| 14421 | case 0: | 14421 | case 0: |
| 14422 | |||
| 14423 | pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_2g = | 14422 | pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_2g = |
| 14424 | (s8) wlapi_getintvar(shim, | 14423 | sprom->core_pwr_info[0].maxpwr_2g; |
| 14425 | BRCMS_SROM_MAXP2GA0); | ||
| 14426 | pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_2g = | 14424 | pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_2g = |
| 14427 | (s8) wlapi_getintvar(shim, | 14425 | sprom->core_pwr_info[1].maxpwr_2g; |
| 14428 | BRCMS_SROM_MAXP2GA1); | ||
| 14429 | pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_a1 = | 14426 | pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_a1 = |
| 14430 | (s16) wlapi_getintvar(shim, | 14427 | sprom->core_pwr_info[0].pa_2g[0]; |
| 14431 | BRCMS_SROM_PA2GW0A0); | ||
| 14432 | pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_a1 = | 14428 | pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_a1 = |
| 14433 | (s16) wlapi_getintvar(shim, | 14429 | sprom->core_pwr_info[1].pa_2g[0]; |
| 14434 | BRCMS_SROM_PA2GW0A1); | ||
| 14435 | pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b0 = | 14430 | pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b0 = |
| 14436 | (s16) wlapi_getintvar(shim, | 14431 | sprom->core_pwr_info[0].pa_2g[1]; |
| 14437 | BRCMS_SROM_PA2GW1A0); | ||
| 14438 | pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b0 = | 14432 | pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b0 = |
| 14439 | (s16) wlapi_getintvar(shim, | 14433 | sprom->core_pwr_info[1].pa_2g[1]; |
| 14440 | BRCMS_SROM_PA2GW1A1); | ||
| 14441 | pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b1 = | 14434 | pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b1 = |
| 14442 | (s16) wlapi_getintvar(shim, | 14435 | sprom->core_pwr_info[0].pa_2g[2]; |
| 14443 | BRCMS_SROM_PA2GW2A0); | ||
| 14444 | pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b1 = | 14436 | pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b1 = |
| 14445 | (s16) wlapi_getintvar(shim, | 14437 | sprom->core_pwr_info[1].pa_2g[2]; |
| 14446 | BRCMS_SROM_PA2GW2A1); | ||
| 14447 | pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_2g = | 14438 | pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_2g = |
| 14448 | (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT2GA0); | 14439 | sprom->core_pwr_info[0].itssi_2g; |
| 14449 | pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_2g = | 14440 | pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_2g = |
| 14450 | (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT2GA1); | 14441 | sprom->core_pwr_info[1].itssi_2g; |
| 14451 | 14442 | ||
| 14452 | pi->cck2gpo = (u16) wlapi_getintvar(shim, | 14443 | pi->cck2gpo = sprom->cck2gpo; |
| 14453 | BRCMS_SROM_CCK2GPO); | 14444 | |
| 14454 | 14445 | pi->ofdm2gpo = sprom->ofdm2gpo; | |
| 14455 | pi->ofdm2gpo = | 14446 | |
| 14456 | (u32) wlapi_getintvar(shim, | 14447 | pi->mcs2gpo[0] = sprom->mcs2gpo[0]; |
| 14457 | BRCMS_SROM_OFDM2GPO); | 14448 | pi->mcs2gpo[1] = sprom->mcs2gpo[1]; |
| 14458 | 14449 | pi->mcs2gpo[2] = sprom->mcs2gpo[2]; | |
| 14459 | pi->mcs2gpo[0] = | 14450 | pi->mcs2gpo[3] = sprom->mcs2gpo[3]; |
| 14460 | (u16) wlapi_getintvar(shim, | 14451 | pi->mcs2gpo[4] = sprom->mcs2gpo[4]; |
| 14461 | BRCMS_SROM_MCS2GPO0); | 14452 | pi->mcs2gpo[5] = sprom->mcs2gpo[5]; |
| 14462 | pi->mcs2gpo[1] = | 14453 | pi->mcs2gpo[6] = sprom->mcs2gpo[6]; |
| 14463 | (u16) wlapi_getintvar(shim, | 14454 | pi->mcs2gpo[7] = sprom->mcs2gpo[7]; |
| 14464 | BRCMS_SROM_MCS2GPO1); | ||
| 14465 | pi->mcs2gpo[2] = | ||
| 14466 | (u16) wlapi_getintvar(shim, | ||
| 14467 | BRCMS_SROM_MCS2GPO2); | ||
| 14468 | pi->mcs2gpo[3] = | ||
| 14469 | (u16) wlapi_getintvar(shim, | ||
| 14470 | BRCMS_SROM_MCS2GPO3); | ||
| 14471 | pi->mcs2gpo[4] = | ||
| 14472 | (u16) wlapi_getintvar(shim, | ||
| 14473 | BRCMS_SROM_MCS2GPO4); | ||
| 14474 | pi->mcs2gpo[5] = | ||
| 14475 | (u16) wlapi_getintvar(shim, | ||
| 14476 | BRCMS_SROM_MCS2GPO5); | ||
| 14477 | pi->mcs2gpo[6] = | ||
| 14478 | (u16) wlapi_getintvar(shim, | ||
| 14479 | BRCMS_SROM_MCS2GPO6); | ||
| 14480 | pi->mcs2gpo[7] = | ||
| 14481 | (u16) wlapi_getintvar(shim, | ||
| 14482 | BRCMS_SROM_MCS2GPO7); | ||
| 14483 | break; | 14455 | break; |
| 14484 | case 1: | 14456 | case 1: |
| 14485 | 14457 | ||
| 14486 | pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_5gm = | 14458 | pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_5gm = |
| 14487 | (s8) wlapi_getintvar(shim, BRCMS_SROM_MAXP5GA0); | 14459 | sprom->core_pwr_info[0].maxpwr_5g; |
| 14488 | pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_5gm = | 14460 | pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_5gm = |
| 14489 | (s8) wlapi_getintvar(shim, | 14461 | sprom->core_pwr_info[1].maxpwr_5g; |
| 14490 | BRCMS_SROM_MAXP5GA1); | ||
| 14491 | pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_a1 = | 14462 | pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_a1 = |
| 14492 | (s16) wlapi_getintvar(shim, | 14463 | sprom->core_pwr_info[0].pa_5g[0]; |
| 14493 | BRCMS_SROM_PA5GW0A0); | ||
| 14494 | pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_a1 = | 14464 | pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_a1 = |
| 14495 | (s16) wlapi_getintvar(shim, | 14465 | sprom->core_pwr_info[1].pa_5g[0]; |
| 14496 | BRCMS_SROM_PA5GW0A1); | ||
| 14497 | pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b0 = | 14466 | pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b0 = |
| 14498 | (s16) wlapi_getintvar(shim, | 14467 | sprom->core_pwr_info[0].pa_5g[1]; |
| 14499 | BRCMS_SROM_PA5GW1A0); | ||
| 14500 | pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b0 = | 14468 | pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b0 = |
| 14501 | (s16) wlapi_getintvar(shim, | 14469 | sprom->core_pwr_info[1].pa_5g[1]; |
| 14502 | BRCMS_SROM_PA5GW1A1); | ||
| 14503 | pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b1 = | 14470 | pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b1 = |
| 14504 | (s16) wlapi_getintvar(shim, | 14471 | sprom->core_pwr_info[0].pa_5g[2]; |
| 14505 | BRCMS_SROM_PA5GW2A0); | ||
| 14506 | pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b1 = | 14472 | pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b1 = |
| 14507 | (s16) wlapi_getintvar(shim, | 14473 | sprom->core_pwr_info[1].pa_5g[2]; |
| 14508 | BRCMS_SROM_PA5GW2A1); | ||
| 14509 | pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_5gm = | 14474 | pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_5gm = |
| 14510 | (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT5GA0); | 14475 | sprom->core_pwr_info[0].itssi_5g; |
| 14511 | pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_5gm = | 14476 | pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_5gm = |
| 14512 | (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT5GA1); | 14477 | sprom->core_pwr_info[1].itssi_5g; |
| 14513 | 14478 | ||
| 14514 | pi->ofdm5gpo = | 14479 | pi->ofdm5gpo = sprom->ofdm5gpo; |
| 14515 | (u32) wlapi_getintvar(shim, | 14480 | |
| 14516 | BRCMS_SROM_OFDM5GPO); | 14481 | pi->mcs5gpo[0] = sprom->mcs5gpo[0]; |
| 14517 | 14482 | pi->mcs5gpo[1] = sprom->mcs5gpo[1]; | |
| 14518 | pi->mcs5gpo[0] = | 14483 | pi->mcs5gpo[2] = sprom->mcs5gpo[2]; |
| 14519 | (u16) wlapi_getintvar(shim, | 14484 | pi->mcs5gpo[3] = sprom->mcs5gpo[3]; |
| 14520 | BRCMS_SROM_MCS5GPO0); | 14485 | pi->mcs5gpo[4] = sprom->mcs5gpo[4]; |
| 14521 | pi->mcs5gpo[1] = | 14486 | pi->mcs5gpo[5] = sprom->mcs5gpo[5]; |
| 14522 | (u16) wlapi_getintvar(shim, | 14487 | pi->mcs5gpo[6] = sprom->mcs5gpo[6]; |
| 14523 | BRCMS_SROM_MCS5GPO1); | 14488 | pi->mcs5gpo[7] = sprom->mcs5gpo[7]; |
| 14524 | pi->mcs5gpo[2] = | ||
| 14525 | (u16) wlapi_getintvar(shim, | ||
| 14526 | BRCMS_SROM_MCS5GPO2); | ||
| 14527 | pi->mcs5gpo[3] = | ||
| 14528 | (u16) wlapi_getintvar(shim, | ||
| 14529 | BRCMS_SROM_MCS5GPO3); | ||
| 14530 | pi->mcs5gpo[4] = | ||
| 14531 | (u16) wlapi_getintvar(shim, | ||
| 14532 | BRCMS_SROM_MCS5GPO4); | ||
| 14533 | pi->mcs5gpo[5] = | ||
| 14534 | (u16) wlapi_getintvar(shim, | ||
| 14535 | BRCMS_SROM_MCS5GPO5); | ||
| 14536 | pi->mcs5gpo[6] = | ||
| 14537 | (u16) wlapi_getintvar(shim, | ||
| 14538 | BRCMS_SROM_MCS5GPO6); | ||
| 14539 | pi->mcs5gpo[7] = | ||
| 14540 | (u16) wlapi_getintvar(shim, | ||
| 14541 | BRCMS_SROM_MCS5GPO7); | ||
| 14542 | break; | 14489 | break; |
| 14543 | case 2: | 14490 | case 2: |
| 14544 | 14491 | ||
| 14545 | pi->nphy_pwrctrl_info[0].max_pwr_5gl = | 14492 | pi->nphy_pwrctrl_info[0].max_pwr_5gl = |
| 14546 | (s8) wlapi_getintvar(shim, | 14493 | sprom->core_pwr_info[0].maxpwr_5gl; |
| 14547 | BRCMS_SROM_MAXP5GLA0); | ||
| 14548 | pi->nphy_pwrctrl_info[1].max_pwr_5gl = | 14494 | pi->nphy_pwrctrl_info[1].max_pwr_5gl = |
| 14549 | (s8) wlapi_getintvar(shim, | 14495 | sprom->core_pwr_info[1].maxpwr_5gl; |
| 14550 | BRCMS_SROM_MAXP5GLA1); | ||
| 14551 | pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1 = | 14496 | pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1 = |
| 14552 | (s16) wlapi_getintvar(shim, | 14497 | sprom->core_pwr_info[0].pa_5gl[0]; |
| 14553 | BRCMS_SROM_PA5GLW0A0); | ||
| 14554 | pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1 = | 14498 | pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1 = |
| 14555 | (s16) wlapi_getintvar(shim, | 14499 | sprom->core_pwr_info[1].pa_5gl[0]; |
| 14556 | BRCMS_SROM_PA5GLW0A1); | ||
| 14557 | pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0 = | 14500 | pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0 = |
| 14558 | (s16) wlapi_getintvar(shim, | 14501 | sprom->core_pwr_info[0].pa_5gl[1]; |
| 14559 | BRCMS_SROM_PA5GLW1A0); | ||
| 14560 | pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0 = | 14502 | pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0 = |
| 14561 | (s16) wlapi_getintvar(shim, | 14503 | sprom->core_pwr_info[1].pa_5gl[1]; |
| 14562 | BRCMS_SROM_PA5GLW1A1); | ||
| 14563 | pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1 = | 14504 | pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1 = |
| 14564 | (s16) wlapi_getintvar(shim, | 14505 | sprom->core_pwr_info[0].pa_5gl[2]; |
| 14565 | BRCMS_SROM_PA5GLW2A0); | ||
| 14566 | pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1 = | 14506 | pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1 = |
| 14567 | (s16) wlapi_getintvar(shim, | 14507 | sprom->core_pwr_info[1].pa_5gl[2]; |
| 14568 | BRCMS_SROM_PA5GLW2A1); | ||
| 14569 | pi->nphy_pwrctrl_info[0].idle_targ_5gl = 0; | 14508 | pi->nphy_pwrctrl_info[0].idle_targ_5gl = 0; |
| 14570 | pi->nphy_pwrctrl_info[1].idle_targ_5gl = 0; | 14509 | pi->nphy_pwrctrl_info[1].idle_targ_5gl = 0; |
| 14571 | 14510 | ||
| 14572 | pi->ofdm5glpo = | 14511 | pi->ofdm5glpo = sprom->ofdm5glpo; |
| 14573 | (u32) wlapi_getintvar(shim, | 14512 | |
| 14574 | BRCMS_SROM_OFDM5GLPO); | 14513 | pi->mcs5glpo[0] = sprom->mcs5glpo[0]; |
| 14575 | 14514 | pi->mcs5glpo[1] = sprom->mcs5glpo[1]; | |
| 14576 | pi->mcs5glpo[0] = | 14515 | pi->mcs5glpo[2] = sprom->mcs5glpo[2]; |
| 14577 | (u16) wlapi_getintvar(shim, | 14516 | pi->mcs5glpo[3] = sprom->mcs5glpo[3]; |
| 14578 | BRCMS_SROM_MCS5GLPO0); | 14517 | pi->mcs5glpo[4] = sprom->mcs5glpo[4]; |
| 14579 | pi->mcs5glpo[1] = | 14518 | pi->mcs5glpo[5] = sprom->mcs5glpo[5]; |
| 14580 | (u16) wlapi_getintvar(shim, | 14519 | pi->mcs5glpo[6] = sprom->mcs5glpo[6]; |
| 14581 | BRCMS_SROM_MCS5GLPO1); | 14520 | pi->mcs5glpo[7] = sprom->mcs5glpo[7]; |
| 14582 | pi->mcs5glpo[2] = | ||
| 14583 | (u16) wlapi_getintvar(shim, | ||
| 14584 | BRCMS_SROM_MCS5GLPO2); | ||
| 14585 | pi->mcs5glpo[3] = | ||
| 14586 | (u16) wlapi_getintvar(shim, | ||
| 14587 | BRCMS_SROM_MCS5GLPO3); | ||
| 14588 | pi->mcs5glpo[4] = | ||
| 14589 | (u16) wlapi_getintvar(shim, | ||
| 14590 | BRCMS_SROM_MCS5GLPO4); | ||
| 14591 | pi->mcs5glpo[5] = | ||
| 14592 | (u16) wlapi_getintvar(shim, | ||
| 14593 | BRCMS_SROM_MCS5GLPO5); | ||
| 14594 | pi->mcs5glpo[6] = | ||
| 14595 | (u16) wlapi_getintvar(shim, | ||
| 14596 | BRCMS_SROM_MCS5GLPO6); | ||
| 14597 | pi->mcs5glpo[7] = | ||
| 14598 | (u16) wlapi_getintvar(shim, | ||
| 14599 | BRCMS_SROM_MCS5GLPO7); | ||
| 14600 | break; | 14521 | break; |
| 14601 | case 3: | 14522 | case 3: |
| 14602 | 14523 | ||
| 14603 | pi->nphy_pwrctrl_info[0].max_pwr_5gh = | 14524 | pi->nphy_pwrctrl_info[0].max_pwr_5gh = |
| 14604 | (s8) wlapi_getintvar(shim, | 14525 | sprom->core_pwr_info[0].maxpwr_5gh; |
| 14605 | BRCMS_SROM_MAXP5GHA0); | ||
| 14606 | pi->nphy_pwrctrl_info[1].max_pwr_5gh = | 14526 | pi->nphy_pwrctrl_info[1].max_pwr_5gh = |
| 14607 | (s8) wlapi_getintvar(shim, | 14527 | sprom->core_pwr_info[1].maxpwr_5gh; |
| 14608 | BRCMS_SROM_MAXP5GHA1); | ||
| 14609 | pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1 = | 14528 | pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1 = |
| 14610 | (s16) wlapi_getintvar(shim, | 14529 | sprom->core_pwr_info[0].pa_5gh[0]; |
| 14611 | BRCMS_SROM_PA5GHW0A0); | ||
| 14612 | pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1 = | 14530 | pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1 = |
| 14613 | (s16) wlapi_getintvar(shim, | 14531 | sprom->core_pwr_info[1].pa_5gh[0]; |
| 14614 | BRCMS_SROM_PA5GHW0A1); | ||
| 14615 | pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0 = | 14532 | pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0 = |
| 14616 | (s16) wlapi_getintvar(shim, | 14533 | sprom->core_pwr_info[0].pa_5gh[1]; |
| 14617 | BRCMS_SROM_PA5GHW1A0); | ||
| 14618 | pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0 = | 14534 | pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0 = |
| 14619 | (s16) wlapi_getintvar(shim, | 14535 | sprom->core_pwr_info[1].pa_5gh[1]; |
| 14620 | BRCMS_SROM_PA5GHW1A1); | ||
| 14621 | pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1 = | 14536 | pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1 = |
| 14622 | (s16) wlapi_getintvar(shim, | 14537 | sprom->core_pwr_info[0].pa_5gh[2]; |
| 14623 | BRCMS_SROM_PA5GHW2A0); | ||
| 14624 | pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1 = | 14538 | pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1 = |
| 14625 | (s16) wlapi_getintvar(shim, | 14539 | sprom->core_pwr_info[1].pa_5gh[2]; |
| 14626 | BRCMS_SROM_PA5GHW2A1); | ||
| 14627 | pi->nphy_pwrctrl_info[0].idle_targ_5gh = 0; | 14540 | pi->nphy_pwrctrl_info[0].idle_targ_5gh = 0; |
| 14628 | pi->nphy_pwrctrl_info[1].idle_targ_5gh = 0; | 14541 | pi->nphy_pwrctrl_info[1].idle_targ_5gh = 0; |
| 14629 | 14542 | ||
| 14630 | pi->ofdm5ghpo = | 14543 | pi->ofdm5ghpo = sprom->ofdm5ghpo; |
| 14631 | (u32) wlapi_getintvar(shim, | 14544 | |
| 14632 | BRCMS_SROM_OFDM5GHPO); | 14545 | pi->mcs5ghpo[0] = sprom->mcs5ghpo[0]; |
| 14633 | 14546 | pi->mcs5ghpo[1] = sprom->mcs5ghpo[1]; | |
| 14634 | pi->mcs5ghpo[0] = | 14547 | pi->mcs5ghpo[2] = sprom->mcs5ghpo[2]; |
| 14635 | (u16) wlapi_getintvar(shim, | 14548 | pi->mcs5ghpo[3] = sprom->mcs5ghpo[3]; |
| 14636 | BRCMS_SROM_MCS5GHPO0); | 14549 | pi->mcs5ghpo[4] = sprom->mcs5ghpo[4]; |
| 14637 | pi->mcs5ghpo[1] = | 14550 | pi->mcs5ghpo[5] = sprom->mcs5ghpo[5]; |
| 14638 | (u16) wlapi_getintvar(shim, | 14551 | pi->mcs5ghpo[6] = sprom->mcs5ghpo[6]; |
| 14639 | BRCMS_SROM_MCS5GHPO1); | 14552 | pi->mcs5ghpo[7] = sprom->mcs5ghpo[7]; |
| 14640 | pi->mcs5ghpo[2] = | ||
| 14641 | (u16) wlapi_getintvar(shim, | ||
| 14642 | BRCMS_SROM_MCS5GHPO2); | ||
| 14643 | pi->mcs5ghpo[3] = | ||
| 14644 | (u16) wlapi_getintvar(shim, | ||
| 14645 | BRCMS_SROM_MCS5GHPO3); | ||
| 14646 | pi->mcs5ghpo[4] = | ||
| 14647 | (u16) wlapi_getintvar(shim, | ||
| 14648 | BRCMS_SROM_MCS5GHPO4); | ||
| 14649 | pi->mcs5ghpo[5] = | ||
| 14650 | (u16) wlapi_getintvar(shim, | ||
| 14651 | BRCMS_SROM_MCS5GHPO5); | ||
| 14652 | pi->mcs5ghpo[6] = | ||
| 14653 | (u16) wlapi_getintvar(shim, | ||
| 14654 | BRCMS_SROM_MCS5GHPO6); | ||
| 14655 | pi->mcs5ghpo[7] = | ||
| 14656 | (u16) wlapi_getintvar(shim, | ||
| 14657 | BRCMS_SROM_MCS5GHPO7); | ||
| 14658 | break; | 14553 | break; |
| 14659 | } | 14554 | } |
| 14660 | } | 14555 | } |
| @@ -14664,45 +14559,34 @@ static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi) | |||
| 14664 | 14559 | ||
| 14665 | static bool wlc_phy_txpwr_srom_read_nphy(struct brcms_phy *pi) | 14560 | static bool wlc_phy_txpwr_srom_read_nphy(struct brcms_phy *pi) |
| 14666 | { | 14561 | { |
| 14667 | struct phy_shim_info *shim = pi->sh->physhim; | 14562 | struct ssb_sprom *sprom = &pi->d11core->bus->sprom; |
| 14668 | 14563 | ||
| 14669 | pi->antswitch = (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWITCH); | 14564 | pi->antswitch = sprom->antswitch; |
| 14670 | pi->aa2g = (u8) wlapi_getintvar(shim, BRCMS_SROM_AA2G); | 14565 | pi->aa2g = sprom->ant_available_bg; |
| 14671 | pi->aa5g = (u8) wlapi_getintvar(shim, BRCMS_SROM_AA5G); | 14566 | pi->aa5g = sprom->ant_available_a; |
| 14672 | 14567 | ||
| 14673 | pi->srom_fem2g.tssipos = (u8) wlapi_getintvar(shim, | 14568 | pi->srom_fem2g.tssipos = sprom->fem.ghz2.tssipos; |
| 14674 | BRCMS_SROM_TSSIPOS2G); | 14569 | pi->srom_fem2g.extpagain = sprom->fem.ghz2.extpa_gain; |
| 14675 | pi->srom_fem2g.extpagain = (u8) wlapi_getintvar(shim, | 14570 | pi->srom_fem2g.pdetrange = sprom->fem.ghz2.pdet_range; |
| 14676 | BRCMS_SROM_EXTPAGAIN2G); | 14571 | pi->srom_fem2g.triso = sprom->fem.ghz2.tr_iso; |
| 14677 | pi->srom_fem2g.pdetrange = (u8) wlapi_getintvar(shim, | 14572 | pi->srom_fem2g.antswctrllut = sprom->fem.ghz2.antswlut; |
| 14678 | BRCMS_SROM_PDETRANGE2G); | 14573 | |
| 14679 | pi->srom_fem2g.triso = (u8) wlapi_getintvar(shim, BRCMS_SROM_TRISO2G); | 14574 | pi->srom_fem5g.tssipos = sprom->fem.ghz5.tssipos; |
| 14680 | pi->srom_fem2g.antswctrllut = | 14575 | pi->srom_fem5g.extpagain = sprom->fem.ghz5.extpa_gain; |
| 14681 | (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWCTL2G); | 14576 | pi->srom_fem5g.pdetrange = sprom->fem.ghz5.pdet_range; |
| 14682 | 14577 | pi->srom_fem5g.triso = sprom->fem.ghz5.tr_iso; | |
| 14683 | pi->srom_fem5g.tssipos = (u8) wlapi_getintvar(shim, | 14578 | if (sprom->fem.ghz5.antswlut) |
| 14684 | BRCMS_SROM_TSSIPOS5G); | 14579 | pi->srom_fem5g.antswctrllut = sprom->fem.ghz5.antswlut; |
| 14685 | pi->srom_fem5g.extpagain = (u8) wlapi_getintvar(shim, | ||
| 14686 | BRCMS_SROM_EXTPAGAIN5G); | ||
| 14687 | pi->srom_fem5g.pdetrange = (u8) wlapi_getintvar(shim, | ||
| 14688 | BRCMS_SROM_PDETRANGE5G); | ||
| 14689 | pi->srom_fem5g.triso = (u8) wlapi_getintvar(shim, BRCMS_SROM_TRISO5G); | ||
| 14690 | if (wlapi_getvar(shim, BRCMS_SROM_ANTSWCTL5G)) | ||
| 14691 | pi->srom_fem5g.antswctrllut = | ||
| 14692 | (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWCTL5G); | ||
| 14693 | else | 14580 | else |
| 14694 | pi->srom_fem5g.antswctrllut = | 14581 | pi->srom_fem5g.antswctrllut = sprom->fem.ghz2.antswlut; |
| 14695 | (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWCTL2G); | ||
| 14696 | 14582 | ||
| 14697 | wlc_phy_txpower_ipa_upd(pi); | 14583 | wlc_phy_txpower_ipa_upd(pi); |
| 14698 | 14584 | ||
| 14699 | pi->phy_txcore_disable_temp = | 14585 | pi->phy_txcore_disable_temp = sprom->tempthresh; |
| 14700 | (s16) wlapi_getintvar(shim, BRCMS_SROM_TEMPTHRESH); | ||
| 14701 | if (pi->phy_txcore_disable_temp == 0) | 14586 | if (pi->phy_txcore_disable_temp == 0) |
| 14702 | pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP; | 14587 | pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP; |
| 14703 | 14588 | ||
| 14704 | pi->phy_tempsense_offset = (s8) wlapi_getintvar(shim, | 14589 | pi->phy_tempsense_offset = sprom->tempoffset; |
| 14705 | BRCMS_SROM_TEMPOFFSET); | ||
| 14706 | if (pi->phy_tempsense_offset != 0) { | 14590 | if (pi->phy_tempsense_offset != 0) { |
| 14707 | if (pi->phy_tempsense_offset > | 14591 | if (pi->phy_tempsense_offset > |
| 14708 | (NPHY_SROM_TEMPSHIFT + NPHY_SROM_MAXTEMPOFFSET)) | 14592 | (NPHY_SROM_TEMPSHIFT + NPHY_SROM_MAXTEMPOFFSET)) |
| @@ -14717,8 +14601,7 @@ static bool wlc_phy_txpwr_srom_read_nphy(struct brcms_phy *pi) | |||
| 14717 | pi->phy_txcore_enable_temp = | 14601 | pi->phy_txcore_enable_temp = |
| 14718 | pi->phy_txcore_disable_temp - PHY_HYSTERESIS_DELTATEMP; | 14602 | pi->phy_txcore_disable_temp - PHY_HYSTERESIS_DELTATEMP; |
| 14719 | 14603 | ||
| 14720 | pi->phycal_tempdelta = | 14604 | pi->phycal_tempdelta = sprom->phycal_tempdelta; |
| 14721 | (u8) wlapi_getintvar(shim, BRCMS_SROM_PHYCAL_TEMPDELTA); | ||
| 14722 | if (pi->phycal_tempdelta > NPHY_CAL_MAXTEMPDELTA) | 14605 | if (pi->phycal_tempdelta > NPHY_CAL_MAXTEMPDELTA) |
| 14723 | pi->phycal_tempdelta = 0; | 14606 | pi->phycal_tempdelta = 0; |
| 14724 | 14607 | ||
| @@ -21460,7 +21343,7 @@ void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init) | |||
| 21460 | write_phy_reg(pi, 0xc8, 0x0); | 21343 | write_phy_reg(pi, 0xc8, 0x0); |
| 21461 | write_phy_reg(pi, 0xc9, 0x0); | 21344 | write_phy_reg(pi, 0xc9, 0x0); |
| 21462 | 21345 | ||
| 21463 | ai_gpiocontrol(pi->sh->sih, mask, mask, GPIO_DRV_PRIORITY); | 21346 | bcma_chipco_gpio_control(&pi->d11core->bus->drv_cc, mask, mask); |
| 21464 | 21347 | ||
| 21465 | mc = bcma_read32(pi->d11core, D11REGOFFS(maccontrol)); | 21348 | mc = bcma_read32(pi->d11core, D11REGOFFS(maccontrol)); |
| 21466 | mc &= ~MCTL_GPOUT_SEL_MASK; | 21349 | mc &= ~MCTL_GPOUT_SEL_MASK; |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.c b/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.c index 5926854f62e..a0de5db0cd6 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.c | |||
| @@ -214,12 +214,3 @@ wlapi_copyto_objmem(struct phy_shim_info *physhim, uint offset, const void *buf, | |||
| 214 | { | 214 | { |
| 215 | brcms_b_copyto_objmem(physhim->wlc_hw, offset, buf, l, sel); | 215 | brcms_b_copyto_objmem(physhim->wlc_hw, offset, buf, l, sel); |
| 216 | } | 216 | } |
| 217 | |||
| 218 | char *wlapi_getvar(struct phy_shim_info *physhim, enum brcms_srom_id id) | ||
| 219 | { | ||
| 220 | return getvar(physhim->wlc_hw->sih, id); | ||
| 221 | } | ||
| 222 | int wlapi_getintvar(struct phy_shim_info *physhim, enum brcms_srom_id id) | ||
| 223 | { | ||
| 224 | return getintvar(physhim->wlc_hw->sih, id); | ||
| 225 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h b/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h index 9168c459b18..2c5b66b7597 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h | |||
| @@ -175,8 +175,5 @@ extern void wlapi_copyto_objmem(struct phy_shim_info *physhim, uint, | |||
| 175 | extern void wlapi_high_update_phy_mode(struct phy_shim_info *physhim, | 175 | extern void wlapi_high_update_phy_mode(struct phy_shim_info *physhim, |
| 176 | u32 phy_mode); | 176 | u32 phy_mode); |
| 177 | extern u16 wlapi_bmac_get_txant(struct phy_shim_info *physhim); | 177 | extern u16 wlapi_bmac_get_txant(struct phy_shim_info *physhim); |
| 178 | extern char *wlapi_getvar(struct phy_shim_info *physhim, enum brcms_srom_id id); | ||
| 179 | extern int wlapi_getintvar(struct phy_shim_info *physhim, | ||
| 180 | enum brcms_srom_id id); | ||
| 181 | 178 | ||
| 182 | #endif /* _BRCM_PHY_SHIM_H_ */ | 179 | #endif /* _BRCM_PHY_SHIM_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h index f0038ad7d7b..aa5d67f8d87 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h | |||
| @@ -22,232 +22,6 @@ | |||
| 22 | #include "types.h" | 22 | #include "types.h" |
| 23 | #include "defs.h" | 23 | #include "defs.h" |
| 24 | 24 | ||
| 25 | enum brcms_srom_id { | ||
| 26 | BRCMS_SROM_NULL, | ||
| 27 | BRCMS_SROM_CONT, | ||
| 28 | BRCMS_SROM_AA2G, | ||
| 29 | BRCMS_SROM_AA5G, | ||
| 30 | BRCMS_SROM_AG0, | ||
| 31 | BRCMS_SROM_AG1, | ||
| 32 | BRCMS_SROM_AG2, | ||
| 33 | BRCMS_SROM_AG3, | ||
| 34 | BRCMS_SROM_ANTSWCTL2G, | ||
| 35 | BRCMS_SROM_ANTSWCTL5G, | ||
| 36 | BRCMS_SROM_ANTSWITCH, | ||
| 37 | BRCMS_SROM_BOARDFLAGS2, | ||
| 38 | BRCMS_SROM_BOARDFLAGS, | ||
| 39 | BRCMS_SROM_BOARDNUM, | ||
| 40 | BRCMS_SROM_BOARDREV, | ||
| 41 | BRCMS_SROM_BOARDTYPE, | ||
| 42 | BRCMS_SROM_BW40PO, | ||
| 43 | BRCMS_SROM_BWDUPPO, | ||
| 44 | BRCMS_SROM_BXA2G, | ||
| 45 | BRCMS_SROM_BXA5G, | ||
| 46 | BRCMS_SROM_CC, | ||
| 47 | BRCMS_SROM_CCK2GPO, | ||
| 48 | BRCMS_SROM_CCKBW202GPO, | ||
| 49 | BRCMS_SROM_CCKBW20UL2GPO, | ||
| 50 | BRCMS_SROM_CCODE, | ||
| 51 | BRCMS_SROM_CDDPO, | ||
| 52 | BRCMS_SROM_DEVID, | ||
| 53 | BRCMS_SROM_ET1MACADDR, | ||
| 54 | BRCMS_SROM_EXTPAGAIN2G, | ||
| 55 | BRCMS_SROM_EXTPAGAIN5G, | ||
| 56 | BRCMS_SROM_FREQOFFSET_CORR, | ||
| 57 | BRCMS_SROM_HW_IQCAL_EN, | ||
| 58 | BRCMS_SROM_IL0MACADDR, | ||
| 59 | BRCMS_SROM_IQCAL_SWP_DIS, | ||
| 60 | BRCMS_SROM_LEDBH0, | ||
| 61 | BRCMS_SROM_LEDBH1, | ||
| 62 | BRCMS_SROM_LEDBH2, | ||
| 63 | BRCMS_SROM_LEDBH3, | ||
| 64 | BRCMS_SROM_LEDDC, | ||
| 65 | BRCMS_SROM_LEGOFDM40DUPPO, | ||
| 66 | BRCMS_SROM_LEGOFDMBW202GPO, | ||
| 67 | BRCMS_SROM_LEGOFDMBW205GHPO, | ||
| 68 | BRCMS_SROM_LEGOFDMBW205GLPO, | ||
| 69 | BRCMS_SROM_LEGOFDMBW205GMPO, | ||
| 70 | BRCMS_SROM_LEGOFDMBW20UL2GPO, | ||
| 71 | BRCMS_SROM_LEGOFDMBW20UL5GHPO, | ||
| 72 | BRCMS_SROM_LEGOFDMBW20UL5GLPO, | ||
| 73 | BRCMS_SROM_LEGOFDMBW20UL5GMPO, | ||
| 74 | BRCMS_SROM_MACADDR, | ||
| 75 | BRCMS_SROM_MCS2GPO0, | ||
| 76 | BRCMS_SROM_MCS2GPO1, | ||
| 77 | BRCMS_SROM_MCS2GPO2, | ||
| 78 | BRCMS_SROM_MCS2GPO3, | ||
| 79 | BRCMS_SROM_MCS2GPO4, | ||
| 80 | BRCMS_SROM_MCS2GPO5, | ||
| 81 | BRCMS_SROM_MCS2GPO6, | ||
| 82 | BRCMS_SROM_MCS2GPO7, | ||
| 83 | BRCMS_SROM_MCS32PO, | ||
| 84 | BRCMS_SROM_MCS5GHPO0, | ||
| 85 | BRCMS_SROM_MCS5GHPO1, | ||
| 86 | BRCMS_SROM_MCS5GHPO2, | ||
| 87 | BRCMS_SROM_MCS5GHPO3, | ||
| 88 | BRCMS_SROM_MCS5GHPO4, | ||
| 89 | BRCMS_SROM_MCS5GHPO5, | ||
| 90 | BRCMS_SROM_MCS5GHPO6, | ||
| 91 | BRCMS_SROM_MCS5GHPO7, | ||
| 92 | BRCMS_SROM_MCS5GLPO0, | ||
| 93 | BRCMS_SROM_MCS5GLPO1, | ||
| 94 | BRCMS_SROM_MCS5GLPO2, | ||
| 95 | BRCMS_SROM_MCS5GLPO3, | ||
| 96 | BRCMS_SROM_MCS5GLPO4, | ||
| 97 | BRCMS_SROM_MCS5GLPO5, | ||
| 98 | BRCMS_SROM_MCS5GLPO6, | ||
| 99 | BRCMS_SROM_MCS5GLPO7, | ||
| 100 | BRCMS_SROM_MCS5GPO0, | ||
| 101 | BRCMS_SROM_MCS5GPO1, | ||
| 102 | BRCMS_SROM_MCS5GPO2, | ||
| 103 | BRCMS_SROM_MCS5GPO3, | ||
| 104 | BRCMS_SROM_MCS5GPO4, | ||
| 105 | BRCMS_SROM_MCS5GPO5, | ||
| 106 | BRCMS_SROM_MCS5GPO6, | ||
| 107 | BRCMS_SROM_MCS5GPO7, | ||
| 108 | BRCMS_SROM_MCSBW202GPO, | ||
| 109 | BRCMS_SROM_MCSBW205GHPO, | ||
| 110 | BRCMS_SROM_MCSBW205GLPO, | ||
| 111 | BRCMS_SROM_MCSBW205GMPO, | ||
| 112 | BRCMS_SROM_MCSBW20UL2GPO, | ||
| 113 | BRCMS_SROM_MCSBW20UL5GHPO, | ||
| 114 | BRCMS_SROM_MCSBW20UL5GLPO, | ||
| 115 | BRCMS_SROM_MCSBW20UL5GMPO, | ||
| 116 | BRCMS_SROM_MCSBW402GPO, | ||
| 117 | BRCMS_SROM_MCSBW405GHPO, | ||
| 118 | BRCMS_SROM_MCSBW405GLPO, | ||
| 119 | BRCMS_SROM_MCSBW405GMPO, | ||
| 120 | BRCMS_SROM_MEASPOWER, | ||
| 121 | BRCMS_SROM_OFDM2GPO, | ||
| 122 | BRCMS_SROM_OFDM5GHPO, | ||
| 123 | BRCMS_SROM_OFDM5GLPO, | ||
| 124 | BRCMS_SROM_OFDM5GPO, | ||
| 125 | BRCMS_SROM_OPO, | ||
| 126 | BRCMS_SROM_PA0B0, | ||
| 127 | BRCMS_SROM_PA0B1, | ||
| 128 | BRCMS_SROM_PA0B2, | ||
| 129 | BRCMS_SROM_PA0ITSSIT, | ||
| 130 | BRCMS_SROM_PA0MAXPWR, | ||
| 131 | BRCMS_SROM_PA1B0, | ||
| 132 | BRCMS_SROM_PA1B1, | ||
| 133 | BRCMS_SROM_PA1B2, | ||
| 134 | BRCMS_SROM_PA1HIB0, | ||
| 135 | BRCMS_SROM_PA1HIB1, | ||
| 136 | BRCMS_SROM_PA1HIB2, | ||
| 137 | BRCMS_SROM_PA1HIMAXPWR, | ||
| 138 | BRCMS_SROM_PA1ITSSIT, | ||
| 139 | BRCMS_SROM_PA1LOB0, | ||
| 140 | BRCMS_SROM_PA1LOB1, | ||
| 141 | BRCMS_SROM_PA1LOB2, | ||
| 142 | BRCMS_SROM_PA1LOMAXPWR, | ||
| 143 | BRCMS_SROM_PA1MAXPWR, | ||
| 144 | BRCMS_SROM_PDETRANGE2G, | ||
| 145 | BRCMS_SROM_PDETRANGE5G, | ||
| 146 | BRCMS_SROM_PHYCAL_TEMPDELTA, | ||
| 147 | BRCMS_SROM_RAWTEMPSENSE, | ||
| 148 | BRCMS_SROM_REGREV, | ||
| 149 | BRCMS_SROM_REV, | ||
| 150 | BRCMS_SROM_RSSISAV2G, | ||
| 151 | BRCMS_SROM_RSSISAV5G, | ||
| 152 | BRCMS_SROM_RSSISMC2G, | ||
| 153 | BRCMS_SROM_RSSISMC5G, | ||
| 154 | BRCMS_SROM_RSSISMF2G, | ||
| 155 | BRCMS_SROM_RSSISMF5G, | ||
| 156 | BRCMS_SROM_RXCHAIN, | ||
| 157 | BRCMS_SROM_RXPO2G, | ||
| 158 | BRCMS_SROM_RXPO5G, | ||
| 159 | BRCMS_SROM_STBCPO, | ||
| 160 | BRCMS_SROM_TEMPCORRX, | ||
| 161 | BRCMS_SROM_TEMPOFFSET, | ||
| 162 | BRCMS_SROM_TEMPSENSE_OPTION, | ||
| 163 | BRCMS_SROM_TEMPSENSE_SLOPE, | ||
| 164 | BRCMS_SROM_TEMPTHRESH, | ||
| 165 | BRCMS_SROM_TRI2G, | ||
| 166 | BRCMS_SROM_TRI5GH, | ||
| 167 | BRCMS_SROM_TRI5GL, | ||
| 168 | BRCMS_SROM_TRI5G, | ||
| 169 | BRCMS_SROM_TRISO2G, | ||
| 170 | BRCMS_SROM_TRISO5G, | ||
| 171 | BRCMS_SROM_TSSIPOS2G, | ||
| 172 | BRCMS_SROM_TSSIPOS5G, | ||
| 173 | BRCMS_SROM_TXCHAIN, | ||
| 174 | /* | ||
| 175 | * per-path identifiers (see srom.c) | ||
| 176 | */ | ||
| 177 | BRCMS_SROM_ITT2GA0, | ||
| 178 | BRCMS_SROM_ITT2GA1, | ||
| 179 | BRCMS_SROM_ITT2GA2, | ||
| 180 | BRCMS_SROM_ITT2GA3, | ||
| 181 | BRCMS_SROM_ITT5GA0, | ||
| 182 | BRCMS_SROM_ITT5GA1, | ||
| 183 | BRCMS_SROM_ITT5GA2, | ||
| 184 | BRCMS_SROM_ITT5GA3, | ||
| 185 | BRCMS_SROM_MAXP2GA0, | ||
| 186 | BRCMS_SROM_MAXP2GA1, | ||
| 187 | BRCMS_SROM_MAXP2GA2, | ||
| 188 | BRCMS_SROM_MAXP2GA3, | ||
| 189 | BRCMS_SROM_MAXP5GA0, | ||
| 190 | BRCMS_SROM_MAXP5GA1, | ||
| 191 | BRCMS_SROM_MAXP5GA2, | ||
| 192 | BRCMS_SROM_MAXP5GA3, | ||
| 193 | BRCMS_SROM_MAXP5GHA0, | ||
| 194 | BRCMS_SROM_MAXP5GHA1, | ||
| 195 | BRCMS_SROM_MAXP5GHA2, | ||
| 196 | BRCMS_SROM_MAXP5GHA3, | ||
| 197 | BRCMS_SROM_MAXP5GLA0, | ||
| 198 | BRCMS_SROM_MAXP5GLA1, | ||
| 199 | BRCMS_SROM_MAXP5GLA2, | ||
| 200 | BRCMS_SROM_MAXP5GLA3, | ||
| 201 | BRCMS_SROM_PA2GW0A0, | ||
| 202 | BRCMS_SROM_PA2GW0A1, | ||
| 203 | BRCMS_SROM_PA2GW0A2, | ||
| 204 | BRCMS_SROM_PA2GW0A3, | ||
| 205 | BRCMS_SROM_PA2GW1A0, | ||
| 206 | BRCMS_SROM_PA2GW1A1, | ||
| 207 | BRCMS_SROM_PA2GW1A2, | ||
| 208 | BRCMS_SROM_PA2GW1A3, | ||
| 209 | BRCMS_SROM_PA2GW2A0, | ||
| 210 | BRCMS_SROM_PA2GW2A1, | ||
| 211 | BRCMS_SROM_PA2GW2A2, | ||
| 212 | BRCMS_SROM_PA2GW2A3, | ||
| 213 | BRCMS_SROM_PA5GHW0A0, | ||
| 214 | BRCMS_SROM_PA5GHW0A1, | ||
| 215 | BRCMS_SROM_PA5GHW0A2, | ||
| 216 | BRCMS_SROM_PA5GHW0A3, | ||
| 217 | BRCMS_SROM_PA5GHW1A0, | ||
| 218 | BRCMS_SROM_PA5GHW1A1, | ||
| 219 | BRCMS_SROM_PA5GHW1A2, | ||
| 220 | BRCMS_SROM_PA5GHW1A3, | ||
| 221 | BRCMS_SROM_PA5GHW2A0, | ||
| 222 | BRCMS_SROM_PA5GHW2A1, | ||
| 223 | BRCMS_SROM_PA5GHW2A2, | ||
| 224 | BRCMS_SROM_PA5GHW2A3, | ||
| 225 | BRCMS_SROM_PA5GLW0A0, | ||
| 226 | BRCMS_SROM_PA5GLW0A1, | ||
| 227 | BRCMS_SROM_PA5GLW0A2, | ||
| 228 | BRCMS_SROM_PA5GLW0A3, | ||
| 229 | BRCMS_SROM_PA5GLW1A0, | ||
| 230 | BRCMS_SROM_PA5GLW1A1, | ||
| 231 | BRCMS_SROM_PA5GLW1A2, | ||
| 232 | BRCMS_SROM_PA5GLW1A3, | ||
| 233 | BRCMS_SROM_PA5GLW2A0, | ||
| 234 | BRCMS_SROM_PA5GLW2A1, | ||
| 235 | BRCMS_SROM_PA5GLW2A2, | ||
| 236 | BRCMS_SROM_PA5GLW2A3, | ||
| 237 | BRCMS_SROM_PA5GW0A0, | ||
| 238 | BRCMS_SROM_PA5GW0A1, | ||
| 239 | BRCMS_SROM_PA5GW0A2, | ||
| 240 | BRCMS_SROM_PA5GW0A3, | ||
| 241 | BRCMS_SROM_PA5GW1A0, | ||
| 242 | BRCMS_SROM_PA5GW1A1, | ||
| 243 | BRCMS_SROM_PA5GW1A2, | ||
| 244 | BRCMS_SROM_PA5GW1A3, | ||
| 245 | BRCMS_SROM_PA5GW2A0, | ||
| 246 | BRCMS_SROM_PA5GW2A1, | ||
| 247 | BRCMS_SROM_PA5GW2A2, | ||
| 248 | BRCMS_SROM_PA5GW2A3, | ||
| 249 | }; | ||
| 250 | |||
| 251 | #define BRCMS_NUMRATES 16 /* max # of rates in a rateset */ | 25 | #define BRCMS_NUMRATES 16 /* max # of rates in a rateset */ |
| 252 | 26 | ||
| 253 | /* phy types */ | 27 | /* phy types */ |
| @@ -565,8 +339,6 @@ extern void brcms_c_ampdu_flush(struct brcms_c_info *wlc, | |||
| 565 | struct ieee80211_sta *sta, u16 tid); | 339 | struct ieee80211_sta *sta, u16 tid); |
| 566 | extern void brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid, | 340 | extern void brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid, |
| 567 | u8 ba_wsize, uint max_rx_ampdu_bytes); | 341 | u8 ba_wsize, uint max_rx_ampdu_bytes); |
| 568 | extern char *getvar(struct si_pub *sih, enum brcms_srom_id id); | ||
| 569 | extern int getintvar(struct si_pub *sih, enum brcms_srom_id id); | ||
| 570 | extern int brcms_c_module_register(struct brcms_pub *pub, | 342 | extern int brcms_c_module_register(struct brcms_pub *pub, |
| 571 | const char *name, struct brcms_info *hdl, | 343 | const char *name, struct brcms_info *hdl, |
| 572 | int (*down_fn)(void *handle)); | 344 | int (*down_fn)(void *handle)); |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/srom.c b/drivers/net/wireless/brcm80211/brcmsmac/srom.c deleted file mode 100644 index b96f4b9d74b..00000000000 --- a/drivers/net/wireless/brcm80211/brcmsmac/srom.c +++ /dev/null | |||
| @@ -1,980 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2010 Broadcom Corporation | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/string.h> | ||
| 19 | #include <linux/io.h> | ||
| 20 | #include <linux/etherdevice.h> | ||
| 21 | #include <linux/crc8.h> | ||
| 22 | #include <stdarg.h> | ||
| 23 | |||
| 24 | #include <chipcommon.h> | ||
| 25 | #include <brcmu_utils.h> | ||
| 26 | #include "pub.h" | ||
| 27 | #include "nicpci.h" | ||
| 28 | #include "aiutils.h" | ||
| 29 | #include "otp.h" | ||
| 30 | #include "srom.h" | ||
| 31 | #include "soc.h" | ||
| 32 | |||
| 33 | /* | ||
| 34 | * SROM CRC8 polynomial value: | ||
| 35 | * | ||
| 36 | * x^8 + x^7 +x^6 + x^4 + x^2 + 1 | ||
| 37 | */ | ||
| 38 | #define SROM_CRC8_POLY 0xAB | ||
| 39 | |||
| 40 | /* Maximum srom: 6 Kilobits == 768 bytes */ | ||
| 41 | #define SROM_MAX 768 | ||
| 42 | |||
| 43 | /* PCI fields */ | ||
| 44 | #define PCI_F0DEVID 48 | ||
| 45 | |||
| 46 | #define SROM_WORDS 64 | ||
| 47 | |||
| 48 | #define SROM_SSID 2 | ||
| 49 | |||
| 50 | #define SROM_WL1LHMAXP 29 | ||
| 51 | |||
| 52 | #define SROM_WL1LPAB0 30 | ||
| 53 | #define SROM_WL1LPAB1 31 | ||
| 54 | #define SROM_WL1LPAB2 32 | ||
| 55 | |||
| 56 | #define SROM_WL1HPAB0 33 | ||
| 57 | #define SROM_WL1HPAB1 34 | ||
| 58 | #define SROM_WL1HPAB2 35 | ||
| 59 | |||
| 60 | #define SROM_MACHI_IL0 36 | ||
| 61 | #define SROM_MACMID_IL0 37 | ||
| 62 | #define SROM_MACLO_IL0 38 | ||
| 63 | #define SROM_MACHI_ET1 42 | ||
| 64 | #define SROM_MACMID_ET1 43 | ||
| 65 | #define SROM_MACLO_ET1 44 | ||
| 66 | |||
| 67 | #define SROM_BXARSSI2G 40 | ||
| 68 | #define SROM_BXARSSI5G 41 | ||
| 69 | |||
| 70 | #define SROM_TRI52G 42 | ||
| 71 | #define SROM_TRI5GHL 43 | ||
| 72 | |||
| 73 | #define SROM_RXPO52G 45 | ||
| 74 | |||
| 75 | #define SROM_AABREV 46 | ||
| 76 | /* Fields in AABREV */ | ||
| 77 | #define SROM_BR_MASK 0x00ff | ||
| 78 | #define SROM_CC_MASK 0x0f00 | ||
| 79 | #define SROM_CC_SHIFT 8 | ||
| 80 | #define SROM_AA0_MASK 0x3000 | ||
| 81 | #define SROM_AA0_SHIFT 12 | ||
| 82 | #define SROM_AA1_MASK 0xc000 | ||
| 83 | #define SROM_AA1_SHIFT 14 | ||
| 84 | |||
| 85 | #define SROM_WL0PAB0 47 | ||
| 86 | #define SROM_WL0PAB1 48 | ||
| 87 | #define SROM_WL0PAB2 49 | ||
| 88 | |||
| 89 | #define SROM_LEDBH10 50 | ||
| 90 | #define SROM_LEDBH32 51 | ||
| 91 | |||
| 92 | #define SROM_WL10MAXP 52 | ||
| 93 | |||
| 94 | #define SROM_WL1PAB0 53 | ||
| 95 | #define SROM_WL1PAB1 54 | ||
| 96 | #define SROM_WL1PAB2 55 | ||
| 97 | |||
| 98 | #define SROM_ITT 56 | ||
| 99 | |||
| 100 | #define SROM_BFL 57 | ||
| 101 | #define SROM_BFL2 28 | ||
| 102 | |||
| 103 | #define SROM_AG10 58 | ||
| 104 | |||
| 105 | #define SROM_CCODE 59 | ||
| 106 | |||
| 107 | #define SROM_OPO 60 | ||
| 108 | |||
| 109 | #define SROM_CRCREV 63 | ||
| 110 | |||
| 111 | #define SROM4_WORDS 220 | ||
| 112 | |||
| 113 | #define SROM4_TXCHAIN_MASK 0x000f | ||
| 114 | #define SROM4_RXCHAIN_MASK 0x00f0 | ||
| 115 | #define SROM4_SWITCH_MASK 0xff00 | ||
| 116 | |||
| 117 | /* Per-path fields */ | ||
| 118 | #define MAX_PATH_SROM 4 | ||
| 119 | |||
| 120 | #define SROM4_CRCREV 219 | ||
| 121 | |||
| 122 | /* SROM Rev 8: Make space for a 48word hardware header for PCIe rev >= 6. | ||
| 123 | * This is acombined srom for both MIMO and SISO boards, usable in | ||
| 124 | * the .130 4Kilobit OTP with hardware redundancy. | ||
| 125 | */ | ||
| 126 | #define SROM8_BREV 65 | ||
| 127 | |||
| 128 | #define SROM8_BFL0 66 | ||
| 129 | #define SROM8_BFL1 67 | ||
| 130 | #define SROM8_BFL2 68 | ||
| 131 | #define SROM8_BFL3 69 | ||
| 132 | |||
| 133 | #define SROM8_MACHI 70 | ||
| 134 | #define SROM8_MACMID 71 | ||
| 135 | #define SROM8_MACLO 72 | ||
| 136 | |||
| 137 | #define SROM8_CCODE 73 | ||
| 138 | #define SROM8_REGREV 74 | ||
| 139 | |||
| 140 | #define SROM8_LEDBH10 75 | ||
| 141 | #define SROM8_LEDBH32 76 | ||
| 142 | |||
| 143 | #define SROM8_LEDDC 77 | ||
| 144 | |||
| 145 | #define SROM8_AA 78 | ||
| 146 | |||
| 147 | #define SROM8_AG10 79 | ||
| 148 | #define SROM8_AG32 80 | ||
| 149 | |||
| 150 | #define SROM8_TXRXC 81 | ||
| 151 | |||
| 152 | #define SROM8_BXARSSI2G 82 | ||
| 153 | #define SROM8_BXARSSI5G 83 | ||
| 154 | #define SROM8_TRI52G 84 | ||
| 155 | #define SROM8_TRI5GHL 85 | ||
| 156 | #define SROM8_RXPO52G 86 | ||
| 157 | |||
| 158 | #define SROM8_FEM2G 87 | ||
| 159 | #define SROM8_FEM5G 88 | ||
| 160 | #define SROM8_FEM_ANTSWLUT_MASK 0xf800 | ||
| 161 | #define SROM8_FEM_ANTSWLUT_SHIFT 11 | ||
| 162 | #define SROM8_FEM_TR_ISO_MASK 0x0700 | ||
| 163 | #define SROM8_FEM_TR_ISO_SHIFT 8 | ||
| 164 | #define SROM8_FEM_PDET_RANGE_MASK 0x00f8 | ||
| 165 | #define SROM8_FEM_PDET_RANGE_SHIFT 3 | ||
| 166 | #define SROM8_FEM_EXTPA_GAIN_MASK 0x0006 | ||
| 167 | #define SROM8_FEM_EXTPA_GAIN_SHIFT 1 | ||
| 168 | #define SROM8_FEM_TSSIPOS_MASK 0x0001 | ||
| 169 | #define SROM8_FEM_TSSIPOS_SHIFT 0 | ||
| 170 | |||
| 171 | #define SROM8_THERMAL 89 | ||
| 172 | |||
| 173 | /* Temp sense related entries */ | ||
| 174 | #define SROM8_MPWR_RAWTS 90 | ||
| 175 | #define SROM8_TS_SLP_OPT_CORRX 91 | ||
| 176 | /* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, | ||
| 177 | * IQSWP: IQ CAL swap disable */ | ||
| 178 | #define SROM8_FOC_HWIQ_IQSWP 92 | ||
| 179 | |||
| 180 | /* Temperature delta for PHY calibration */ | ||
| 181 | #define SROM8_PHYCAL_TEMPDELTA 93 | ||
| 182 | |||
| 183 | /* Per-path offsets & fields */ | ||
| 184 | #define SROM8_PATH0 96 | ||
| 185 | #define SROM8_PATH1 112 | ||
| 186 | #define SROM8_PATH2 128 | ||
| 187 | #define SROM8_PATH3 144 | ||
| 188 | |||
| 189 | #define SROM8_2G_ITT_MAXP 0 | ||
| 190 | #define SROM8_2G_PA 1 | ||
| 191 | #define SROM8_5G_ITT_MAXP 4 | ||
| 192 | #define SROM8_5GLH_MAXP 5 | ||
| 193 | #define SROM8_5G_PA 6 | ||
| 194 | #define SROM8_5GL_PA 9 | ||
| 195 | #define SROM8_5GH_PA 12 | ||
| 196 | |||
| 197 | /* All the miriad power offsets */ | ||
| 198 | #define SROM8_2G_CCKPO 160 | ||
| 199 | |||
| 200 | #define SROM8_2G_OFDMPO 161 | ||
| 201 | #define SROM8_5G_OFDMPO 163 | ||
| 202 | #define SROM8_5GL_OFDMPO 165 | ||
| 203 | #define SROM8_5GH_OFDMPO 167 | ||
| 204 | |||
| 205 | #define SROM8_2G_MCSPO 169 | ||
| 206 | #define SROM8_5G_MCSPO 177 | ||
| 207 | #define SROM8_5GL_MCSPO 185 | ||
| 208 | #define SROM8_5GH_MCSPO 193 | ||
| 209 | |||
| 210 | #define SROM8_CDDPO 201 | ||
| 211 | #define SROM8_STBCPO 202 | ||
| 212 | #define SROM8_BW40PO 203 | ||
| 213 | #define SROM8_BWDUPPO 204 | ||
| 214 | |||
| 215 | /* SISO PA parameters are in the path0 spaces */ | ||
| 216 | #define SROM8_SISO 96 | ||
| 217 | |||
| 218 | /* Legacy names for SISO PA paramters */ | ||
| 219 | #define SROM8_W0_ITTMAXP (SROM8_SISO + SROM8_2G_ITT_MAXP) | ||
| 220 | #define SROM8_W0_PAB0 (SROM8_SISO + SROM8_2G_PA) | ||
| 221 | #define SROM8_W0_PAB1 (SROM8_SISO + SROM8_2G_PA + 1) | ||
| 222 | #define SROM8_W0_PAB2 (SROM8_SISO + SROM8_2G_PA + 2) | ||
| 223 | #define SROM8_W1_ITTMAXP (SROM8_SISO + SROM8_5G_ITT_MAXP) | ||
| 224 | #define SROM8_W1_MAXP_LCHC (SROM8_SISO + SROM8_5GLH_MAXP) | ||
| 225 | #define SROM8_W1_PAB0 (SROM8_SISO + SROM8_5G_PA) | ||
| 226 | #define SROM8_W1_PAB1 (SROM8_SISO + SROM8_5G_PA + 1) | ||
| 227 | #define SROM8_W1_PAB2 (SROM8_SISO + SROM8_5G_PA + 2) | ||
| 228 | #define SROM8_W1_PAB0_LC (SROM8_SISO + SROM8_5GL_PA) | ||
| 229 | #define SROM8_W1_PAB1_LC (SROM8_SISO + SROM8_5GL_PA + 1) | ||
| 230 | #define SROM8_W1_PAB2_LC (SROM8_SISO + SROM8_5GL_PA + 2) | ||
| 231 | #define SROM8_W1_PAB0_HC (SROM8_SISO + SROM8_5GH_PA) | ||
| 232 | #define SROM8_W1_PAB1_HC (SROM8_SISO + SROM8_5GH_PA + 1) | ||
| 233 | #define SROM8_W1_PAB2_HC (SROM8_SISO + SROM8_5GH_PA + 2) | ||
| 234 | |||
| 235 | /* SROM REV 9 */ | ||
| 236 | #define SROM9_2GPO_CCKBW20 160 | ||
| 237 | #define SROM9_2GPO_CCKBW20UL 161 | ||
| 238 | #define SROM9_2GPO_LOFDMBW20 162 | ||
| 239 | #define SROM9_2GPO_LOFDMBW20UL 164 | ||
| 240 | |||
| 241 | #define SROM9_5GLPO_LOFDMBW20 166 | ||
| 242 | #define SROM9_5GLPO_LOFDMBW20UL 168 | ||
| 243 | #define SROM9_5GMPO_LOFDMBW20 170 | ||
| 244 | #define SROM9_5GMPO_LOFDMBW20UL 172 | ||
| 245 | #define SROM9_5GHPO_LOFDMBW20 174 | ||
| 246 | #define SROM9_5GHPO_LOFDMBW20UL 176 | ||
| 247 | |||
| 248 | #define SROM9_2GPO_MCSBW20 178 | ||
| 249 | #define SROM9_2GPO_MCSBW20UL 180 | ||
| 250 | #define SROM9_2GPO_MCSBW40 182 | ||
| 251 | |||
| 252 | #define SROM9_5GLPO_MCSBW20 184 | ||
| 253 | #define SROM9_5GLPO_MCSBW20UL 186 | ||
| 254 | #define SROM9_5GLPO_MCSBW40 188 | ||
| 255 | #define SROM9_5GMPO_MCSBW20 190 | ||
| 256 | #define SROM9_5GMPO_MCSBW20UL 192 | ||
| 257 | #define SROM9_5GMPO_MCSBW40 194 | ||
| 258 | #define SROM9_5GHPO_MCSBW20 196 | ||
| 259 | #define SROM9_5GHPO_MCSBW20UL 198 | ||
| 260 | #define SROM9_5GHPO_MCSBW40 200 | ||
| 261 | |||
| 262 | #define SROM9_PO_MCS32 202 | ||
| 263 | #define SROM9_PO_LOFDM40DUP 203 | ||
| 264 | |||
| 265 | /* SROM flags (see sromvar_t) */ | ||
| 266 | |||
| 267 | /* value continues as described by the next entry */ | ||
| 268 | #define SRFL_MORE 1 | ||
| 269 | #define SRFL_NOFFS 2 /* value bits can't be all one's */ | ||
| 270 | #define SRFL_PRHEX 4 /* value is in hexdecimal format */ | ||
| 271 | #define SRFL_PRSIGN 8 /* value is in signed decimal format */ | ||
| 272 | #define SRFL_CCODE 0x10 /* value is in country code format */ | ||
| 273 | #define SRFL_ETHADDR 0x20 /* value is an Ethernet address */ | ||
| 274 | #define SRFL_LEDDC 0x40 /* value is an LED duty cycle */ | ||
| 275 | /* do not generate a nvram param, entry is for mfgc */ | ||
| 276 | #define SRFL_NOVAR 0x80 | ||
| 277 | |||
| 278 | /* Max. nvram variable table size */ | ||
| 279 | #define MAXSZ_NVRAM_VARS 4096 | ||
| 280 | |||
| 281 | /* | ||
| 282 | * indicates type of value. | ||
| 283 | */ | ||
| 284 | enum brcms_srom_var_type { | ||
| 285 | BRCMS_SROM_STRING, | ||
| 286 | BRCMS_SROM_SNUMBER, | ||
| 287 | BRCMS_SROM_UNUMBER | ||
| 288 | }; | ||
| 289 | |||
| 290 | /* | ||
| 291 | * storage type for srom variable. | ||
| 292 | * | ||
| 293 | * var_list: for linked list operations. | ||
| 294 | * varid: identifier of the variable. | ||
| 295 | * var_type: type of variable. | ||
| 296 | * buf: variable value when var_type == BRCMS_SROM_STRING. | ||
| 297 | * uval: unsigned variable value when var_type == BRCMS_SROM_UNUMBER. | ||
| 298 | * sval: signed variable value when var_type == BRCMS_SROM_SNUMBER. | ||
| 299 | */ | ||
| 300 | struct brcms_srom_list_head { | ||
| 301 | struct list_head var_list; | ||
| 302 | enum brcms_srom_id varid; | ||
| 303 | enum brcms_srom_var_type var_type; | ||
| 304 | union { | ||
| 305 | char buf[0]; | ||
| 306 | u32 uval; | ||
| 307 | s32 sval; | ||
| 308 | }; | ||
| 309 | }; | ||
| 310 | |||
| 311 | struct brcms_sromvar { | ||
| 312 | enum brcms_srom_id varid; | ||
| 313 | u32 revmask; | ||
| 314 | u32 flags; | ||
| 315 | u16 off; | ||
| 316 | u16 mask; | ||
| 317 | }; | ||
| 318 | |||
| 319 | struct brcms_varbuf { | ||
| 320 | char *base; /* pointer to buffer base */ | ||
| 321 | char *buf; /* pointer to current position */ | ||
| 322 | unsigned int size; /* current (residual) size in bytes */ | ||
| 323 | }; | ||
| 324 | |||
| 325 | /* | ||
| 326 | * Assumptions: | ||
| 327 | * - Ethernet address spans across 3 consecutive words | ||
| 328 | * | ||
| 329 | * Table rules: | ||
| 330 | * - Add multiple entries next to each other if a value spans across multiple | ||
| 331 | * words (even multiple fields in the same word) with each entry except the | ||
| 332 | * last having it's SRFL_MORE bit set. | ||
| 333 | * - Ethernet address entry does not follow above rule and must not have | ||
| 334 | * SRFL_MORE bit set. Its SRFL_ETHADDR bit implies it takes multiple words. | ||
| 335 | * - The last entry's name field must be NULL to indicate the end of the table. | ||
| 336 | * Other entries must have non-NULL name. | ||
| 337 | */ | ||
| 338 | static const struct brcms_sromvar pci_sromvars[] = { | ||
| 339 | {BRCMS_SROM_DEVID, 0xffffff00, SRFL_PRHEX | SRFL_NOVAR, PCI_F0DEVID, | ||
| 340 | 0xffff}, | ||
| 341 | {BRCMS_SROM_BOARDREV, 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff}, | ||
| 342 | {BRCMS_SROM_BOARDFLAGS, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL0, | ||
| 343 | 0xffff}, | ||
| 344 | {BRCMS_SROM_CONT, 0, 0, SROM8_BFL1, 0xffff}, | ||
| 345 | {BRCMS_SROM_BOARDFLAGS2, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL2, | ||
| 346 | 0xffff}, | ||
| 347 | {BRCMS_SROM_CONT, 0, 0, SROM8_BFL3, 0xffff}, | ||
| 348 | {BRCMS_SROM_BOARDTYPE, 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff}, | ||
| 349 | {BRCMS_SROM_BOARDNUM, 0xffffff00, 0, SROM8_MACLO, 0xffff}, | ||
| 350 | {BRCMS_SROM_REGREV, 0xffffff00, 0, SROM8_REGREV, 0x00ff}, | ||
| 351 | {BRCMS_SROM_LEDBH0, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff}, | ||
| 352 | {BRCMS_SROM_LEDBH1, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff00}, | ||
| 353 | {BRCMS_SROM_LEDBH2, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff}, | ||
| 354 | {BRCMS_SROM_LEDBH3, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff00}, | ||
| 355 | {BRCMS_SROM_PA0B0, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff}, | ||
| 356 | {BRCMS_SROM_PA0B1, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff}, | ||
| 357 | {BRCMS_SROM_PA0B2, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff}, | ||
| 358 | {BRCMS_SROM_PA0ITSSIT, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff00}, | ||
| 359 | {BRCMS_SROM_PA0MAXPWR, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0x00ff}, | ||
| 360 | {BRCMS_SROM_OPO, 0xffffff00, 0, SROM8_2G_OFDMPO, 0x00ff}, | ||
| 361 | {BRCMS_SROM_AA2G, 0xffffff00, 0, SROM8_AA, 0x00ff}, | ||
| 362 | {BRCMS_SROM_AA5G, 0xffffff00, 0, SROM8_AA, 0xff00}, | ||
| 363 | {BRCMS_SROM_AG0, 0xffffff00, 0, SROM8_AG10, 0x00ff}, | ||
| 364 | {BRCMS_SROM_AG1, 0xffffff00, 0, SROM8_AG10, 0xff00}, | ||
| 365 | {BRCMS_SROM_AG2, 0xffffff00, 0, SROM8_AG32, 0x00ff}, | ||
| 366 | {BRCMS_SROM_AG3, 0xffffff00, 0, SROM8_AG32, 0xff00}, | ||
| 367 | {BRCMS_SROM_PA1B0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff}, | ||
| 368 | {BRCMS_SROM_PA1B1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff}, | ||
| 369 | {BRCMS_SROM_PA1B2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff}, | ||
| 370 | {BRCMS_SROM_PA1LOB0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_LC, 0xffff}, | ||
| 371 | {BRCMS_SROM_PA1LOB1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_LC, 0xffff}, | ||
| 372 | {BRCMS_SROM_PA1LOB2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_LC, 0xffff}, | ||
| 373 | {BRCMS_SROM_PA1HIB0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_HC, 0xffff}, | ||
| 374 | {BRCMS_SROM_PA1HIB1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_HC, 0xffff}, | ||
| 375 | {BRCMS_SROM_PA1HIB2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_HC, 0xffff}, | ||
| 376 | {BRCMS_SROM_PA1ITSSIT, 0xffffff00, 0, SROM8_W1_ITTMAXP, 0xff00}, | ||
| 377 | {BRCMS_SROM_PA1MAXPWR, 0xffffff00, 0, SROM8_W1_ITTMAXP, 0x00ff}, | ||
| 378 | {BRCMS_SROM_PA1LOMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff00}, | ||
| 379 | {BRCMS_SROM_PA1HIMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0x00ff}, | ||
| 380 | {BRCMS_SROM_BXA2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x1800}, | ||
| 381 | {BRCMS_SROM_RSSISAV2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x0700}, | ||
| 382 | {BRCMS_SROM_RSSISMC2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x00f0}, | ||
| 383 | {BRCMS_SROM_RSSISMF2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x000f}, | ||
| 384 | {BRCMS_SROM_BXA5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x1800}, | ||
| 385 | {BRCMS_SROM_RSSISAV5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x0700}, | ||
| 386 | {BRCMS_SROM_RSSISMC5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x00f0}, | ||
| 387 | {BRCMS_SROM_RSSISMF5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x000f}, | ||
| 388 | {BRCMS_SROM_TRI2G, 0xffffff00, 0, SROM8_TRI52G, 0x00ff}, | ||
| 389 | {BRCMS_SROM_TRI5G, 0xffffff00, 0, SROM8_TRI52G, 0xff00}, | ||
| 390 | {BRCMS_SROM_TRI5GL, 0xffffff00, 0, SROM8_TRI5GHL, 0x00ff}, | ||
| 391 | {BRCMS_SROM_TRI5GH, 0xffffff00, 0, SROM8_TRI5GHL, 0xff00}, | ||
| 392 | {BRCMS_SROM_RXPO2G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff}, | ||
| 393 | {BRCMS_SROM_RXPO5G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00}, | ||
| 394 | {BRCMS_SROM_TXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, | ||
| 395 | SROM4_TXCHAIN_MASK}, | ||
| 396 | {BRCMS_SROM_RXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, | ||
| 397 | SROM4_RXCHAIN_MASK}, | ||
| 398 | {BRCMS_SROM_ANTSWITCH, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, | ||
| 399 | SROM4_SWITCH_MASK}, | ||
| 400 | {BRCMS_SROM_TSSIPOS2G, 0xffffff00, 0, SROM8_FEM2G, | ||
| 401 | SROM8_FEM_TSSIPOS_MASK}, | ||
| 402 | {BRCMS_SROM_EXTPAGAIN2G, 0xffffff00, 0, SROM8_FEM2G, | ||
| 403 | SROM8_FEM_EXTPA_GAIN_MASK}, | ||
| 404 | {BRCMS_SROM_PDETRANGE2G, 0xffffff00, 0, SROM8_FEM2G, | ||
| 405 | SROM8_FEM_PDET_RANGE_MASK}, | ||
| 406 | {BRCMS_SROM_TRISO2G, 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TR_ISO_MASK}, | ||
| 407 | {BRCMS_SROM_ANTSWCTL2G, 0xffffff00, 0, SROM8_FEM2G, | ||
| 408 | SROM8_FEM_ANTSWLUT_MASK}, | ||
| 409 | {BRCMS_SROM_TSSIPOS5G, 0xffffff00, 0, SROM8_FEM5G, | ||
| 410 | SROM8_FEM_TSSIPOS_MASK}, | ||
| 411 | {BRCMS_SROM_EXTPAGAIN5G, 0xffffff00, 0, SROM8_FEM5G, | ||
| 412 | SROM8_FEM_EXTPA_GAIN_MASK}, | ||
| 413 | {BRCMS_SROM_PDETRANGE5G, 0xffffff00, 0, SROM8_FEM5G, | ||
| 414 | SROM8_FEM_PDET_RANGE_MASK}, | ||
| 415 | {BRCMS_SROM_TRISO5G, 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TR_ISO_MASK}, | ||
| 416 | {BRCMS_SROM_ANTSWCTL5G, 0xffffff00, 0, SROM8_FEM5G, | ||
| 417 | SROM8_FEM_ANTSWLUT_MASK}, | ||
| 418 | {BRCMS_SROM_TEMPTHRESH, 0xffffff00, 0, SROM8_THERMAL, 0xff00}, | ||
| 419 | {BRCMS_SROM_TEMPOFFSET, 0xffffff00, 0, SROM8_THERMAL, 0x00ff}, | ||
| 420 | |||
| 421 | {BRCMS_SROM_CCODE, 0xffffff00, SRFL_CCODE, SROM8_CCODE, 0xffff}, | ||
| 422 | {BRCMS_SROM_MACADDR, 0xffffff00, SRFL_ETHADDR, SROM8_MACHI, 0xffff}, | ||
| 423 | {BRCMS_SROM_LEDDC, 0xffffff00, SRFL_NOFFS | SRFL_LEDDC, SROM8_LEDDC, | ||
| 424 | 0xffff}, | ||
| 425 | {BRCMS_SROM_RAWTEMPSENSE, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, | ||
| 426 | 0x01ff}, | ||
| 427 | {BRCMS_SROM_MEASPOWER, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, | ||
| 428 | 0xfe00}, | ||
| 429 | {BRCMS_SROM_TEMPSENSE_SLOPE, 0xffffff00, SRFL_PRHEX, | ||
| 430 | SROM8_TS_SLP_OPT_CORRX, 0x00ff}, | ||
| 431 | {BRCMS_SROM_TEMPCORRX, 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, | ||
| 432 | 0xfc00}, | ||
| 433 | {BRCMS_SROM_TEMPSENSE_OPTION, 0xffffff00, SRFL_PRHEX, | ||
| 434 | SROM8_TS_SLP_OPT_CORRX, 0x0300}, | ||
| 435 | {BRCMS_SROM_FREQOFFSET_CORR, 0xffffff00, SRFL_PRHEX, | ||
| 436 | SROM8_FOC_HWIQ_IQSWP, 0x000f}, | ||
| 437 | {BRCMS_SROM_IQCAL_SWP_DIS, 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, | ||
| 438 | 0x0010}, | ||
| 439 | {BRCMS_SROM_HW_IQCAL_EN, 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, | ||
| 440 | 0x0020}, | ||
| 441 | {BRCMS_SROM_PHYCAL_TEMPDELTA, 0xffffff00, 0, SROM8_PHYCAL_TEMPDELTA, | ||
| 442 | 0x00ff}, | ||
| 443 | |||
| 444 | {BRCMS_SROM_CCK2GPO, 0x00000100, 0, SROM8_2G_CCKPO, 0xffff}, | ||
| 445 | {BRCMS_SROM_OFDM2GPO, 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff}, | ||
| 446 | {BRCMS_SROM_CONT, 0, 0, SROM8_2G_OFDMPO + 1, 0xffff}, | ||
| 447 | {BRCMS_SROM_OFDM5GPO, 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff}, | ||
| 448 | {BRCMS_SROM_CONT, 0, 0, SROM8_5G_OFDMPO + 1, 0xffff}, | ||
| 449 | {BRCMS_SROM_OFDM5GLPO, 0x00000100, SRFL_MORE, SROM8_5GL_OFDMPO, 0xffff}, | ||
| 450 | {BRCMS_SROM_CONT, 0, 0, SROM8_5GL_OFDMPO + 1, 0xffff}, | ||
| 451 | {BRCMS_SROM_OFDM5GHPO, 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff}, | ||
| 452 | {BRCMS_SROM_CONT, 0, 0, SROM8_5GH_OFDMPO + 1, 0xffff}, | ||
| 453 | {BRCMS_SROM_MCS2GPO0, 0x00000100, 0, SROM8_2G_MCSPO, 0xffff}, | ||
| 454 | {BRCMS_SROM_MCS2GPO1, 0x00000100, 0, SROM8_2G_MCSPO + 1, 0xffff}, | ||
| 455 | {BRCMS_SROM_MCS2GPO2, 0x00000100, 0, SROM8_2G_MCSPO + 2, 0xffff}, | ||
| 456 | {BRCMS_SROM_MCS2GPO3, 0x00000100, 0, SROM8_2G_MCSPO + 3, 0xffff}, | ||
| 457 | {BRCMS_SROM_MCS2GPO4, 0x00000100, 0, SROM8_2G_MCSPO + 4, 0xffff}, | ||
| 458 | {BRCMS_SROM_MCS2GPO5, 0x00000100, 0, SROM8_2G_MCSPO + 5, 0xffff}, | ||
| 459 | {BRCMS_SROM_MCS2GPO6, 0x00000100, 0, SROM8_2G_MCSPO + 6, 0xffff}, | ||
| 460 | {BRCMS_SROM_MCS2GPO7, 0x00000100, 0, SROM8_2G_MCSPO + 7, 0xffff}, | ||
| 461 | {BRCMS_SROM_MCS5GPO0, 0x00000100, 0, SROM8_5G_MCSPO, 0xffff}, | ||
| 462 | {BRCMS_SROM_MCS5GPO1, 0x00000100, 0, SROM8_5G_MCSPO + 1, 0xffff}, | ||
| 463 | {BRCMS_SROM_MCS5GPO2, 0x00000100, 0, SROM8_5G_MCSPO + 2, 0xffff}, | ||
| 464 | {BRCMS_SROM_MCS5GPO3, 0x00000100, 0, SROM8_5G_MCSPO + 3, 0xffff}, | ||
| 465 | {BRCMS_SROM_MCS5GPO4, 0x00000100, 0, SROM8_5G_MCSPO + 4, 0xffff}, | ||
| 466 | {BRCMS_SROM_MCS5GPO5, 0x00000100, 0, SROM8_5G_MCSPO + 5, 0xffff}, | ||
| 467 | {BRCMS_SROM_MCS5GPO6, 0x00000100, 0, SROM8_5G_MCSPO + 6, 0xffff}, | ||
| 468 | {BRCMS_SROM_MCS5GPO7, 0x00000100, 0, SROM8_5G_MCSPO + 7, 0xffff}, | ||
| 469 | {BRCMS_SROM_MCS5GLPO0, 0x00000100, 0, SROM8_5GL_MCSPO, 0xffff}, | ||
| 470 | {BRCMS_SROM_MCS5GLPO1, 0x00000100, 0, SROM8_5GL_MCSPO + 1, 0xffff}, | ||
| 471 | {BRCMS_SROM_MCS5GLPO2, 0x00000100, 0, SROM8_5GL_MCSPO + 2, 0xffff}, | ||
| 472 | {BRCMS_SROM_MCS5GLPO3, 0x00000100, 0, SROM8_5GL_MCSPO + 3, 0xffff}, | ||
| 473 | {BRCMS_SROM_MCS5GLPO4, 0x00000100, 0, SROM8_5GL_MCSPO + 4, 0xffff}, | ||
| 474 | {BRCMS_SROM_MCS5GLPO5, 0x00000100, 0, SROM8_5GL_MCSPO + 5, 0xffff}, | ||
| 475 | {BRCMS_SROM_MCS5GLPO6, 0x00000100, 0, SROM8_5GL_MCSPO + 6, 0xffff}, | ||
| 476 | {BRCMS_SROM_MCS5GLPO7, 0x00000100, 0, SROM8_5GL_MCSPO + 7, 0xffff}, | ||
| 477 | {BRCMS_SROM_MCS5GHPO0, 0x00000100, 0, SROM8_5GH_MCSPO, 0xffff}, | ||
| 478 | {BRCMS_SROM_MCS5GHPO1, 0x00000100, 0, SROM8_5GH_MCSPO + 1, 0xffff}, | ||
| 479 | {BRCMS_SROM_MCS5GHPO2, 0x00000100, 0, SROM8_5GH_MCSPO + 2, 0xffff}, | ||
| 480 | {BRCMS_SROM_MCS5GHPO3, 0x00000100, 0, SROM8_5GH_MCSPO + 3, 0xffff}, | ||
| 481 | {BRCMS_SROM_MCS5GHPO4, 0x00000100, 0, SROM8_5GH_MCSPO + 4, 0xffff}, | ||
| 482 | {BRCMS_SROM_MCS5GHPO5, 0x00000100, 0, SROM8_5GH_MCSPO + 5, 0xffff}, | ||
| 483 | {BRCMS_SROM_MCS5GHPO6, 0x00000100, 0, SROM8_5GH_MCSPO + 6, 0xffff}, | ||
| 484 | {BRCMS_SROM_MCS5GHPO7, 0x00000100, 0, SROM8_5GH_MCSPO + 7, 0xffff}, | ||
| 485 | {BRCMS_SROM_CDDPO, 0x00000100, 0, SROM8_CDDPO, 0xffff}, | ||
| 486 | {BRCMS_SROM_STBCPO, 0x00000100, 0, SROM8_STBCPO, 0xffff}, | ||
| 487 | {BRCMS_SROM_BW40PO, 0x00000100, 0, SROM8_BW40PO, 0xffff}, | ||
| 488 | {BRCMS_SROM_BWDUPPO, 0x00000100, 0, SROM8_BWDUPPO, 0xffff}, | ||
| 489 | |||
| 490 | /* power per rate from sromrev 9 */ | ||
| 491 | {BRCMS_SROM_CCKBW202GPO, 0xfffffe00, 0, SROM9_2GPO_CCKBW20, 0xffff}, | ||
| 492 | {BRCMS_SROM_CCKBW20UL2GPO, 0xfffffe00, 0, SROM9_2GPO_CCKBW20UL, 0xffff}, | ||
| 493 | {BRCMS_SROM_LEGOFDMBW202GPO, 0xfffffe00, SRFL_MORE, | ||
| 494 | SROM9_2GPO_LOFDMBW20, 0xffff}, | ||
| 495 | {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_LOFDMBW20 + 1, 0xffff}, | ||
| 496 | {BRCMS_SROM_LEGOFDMBW20UL2GPO, 0xfffffe00, SRFL_MORE, | ||
| 497 | SROM9_2GPO_LOFDMBW20UL, 0xffff}, | ||
| 498 | {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_LOFDMBW20UL + 1, 0xffff}, | ||
| 499 | {BRCMS_SROM_LEGOFDMBW205GLPO, 0xfffffe00, SRFL_MORE, | ||
| 500 | SROM9_5GLPO_LOFDMBW20, 0xffff}, | ||
| 501 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_LOFDMBW20 + 1, 0xffff}, | ||
| 502 | {BRCMS_SROM_LEGOFDMBW20UL5GLPO, 0xfffffe00, SRFL_MORE, | ||
| 503 | SROM9_5GLPO_LOFDMBW20UL, 0xffff}, | ||
| 504 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_LOFDMBW20UL + 1, 0xffff}, | ||
| 505 | {BRCMS_SROM_LEGOFDMBW205GMPO, 0xfffffe00, SRFL_MORE, | ||
| 506 | SROM9_5GMPO_LOFDMBW20, 0xffff}, | ||
| 507 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_LOFDMBW20 + 1, 0xffff}, | ||
| 508 | {BRCMS_SROM_LEGOFDMBW20UL5GMPO, 0xfffffe00, SRFL_MORE, | ||
| 509 | SROM9_5GMPO_LOFDMBW20UL, 0xffff}, | ||
| 510 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_LOFDMBW20UL + 1, 0xffff}, | ||
| 511 | {BRCMS_SROM_LEGOFDMBW205GHPO, 0xfffffe00, SRFL_MORE, | ||
| 512 | SROM9_5GHPO_LOFDMBW20, 0xffff}, | ||
| 513 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_LOFDMBW20 + 1, 0xffff}, | ||
| 514 | {BRCMS_SROM_LEGOFDMBW20UL5GHPO, 0xfffffe00, SRFL_MORE, | ||
| 515 | SROM9_5GHPO_LOFDMBW20UL, 0xffff}, | ||
| 516 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_LOFDMBW20UL + 1, 0xffff}, | ||
| 517 | {BRCMS_SROM_MCSBW202GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20, | ||
| 518 | 0xffff}, | ||
| 519 | {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW20 + 1, 0xffff}, | ||
| 520 | {BRCMS_SROM_MCSBW20UL2GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20UL, | ||
| 521 | 0xffff}, | ||
| 522 | {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW20UL + 1, 0xffff}, | ||
| 523 | {BRCMS_SROM_MCSBW402GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW40, | ||
| 524 | 0xffff}, | ||
| 525 | {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW40 + 1, 0xffff}, | ||
| 526 | {BRCMS_SROM_MCSBW205GLPO, 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20, | ||
| 527 | 0xffff}, | ||
| 528 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW20 + 1, 0xffff}, | ||
| 529 | {BRCMS_SROM_MCSBW20UL5GLPO, 0xfffffe00, SRFL_MORE, | ||
| 530 | SROM9_5GLPO_MCSBW20UL, 0xffff}, | ||
| 531 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW20UL + 1, 0xffff}, | ||
| 532 | {BRCMS_SROM_MCSBW405GLPO, 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW40, | ||
| 533 | 0xffff}, | ||
| 534 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW40 + 1, 0xffff}, | ||
| 535 | {BRCMS_SROM_MCSBW205GMPO, 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20, | ||
| 536 | 0xffff}, | ||
| 537 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW20 + 1, 0xffff}, | ||
| 538 | {BRCMS_SROM_MCSBW20UL5GMPO, 0xfffffe00, SRFL_MORE, | ||
| 539 | SROM9_5GMPO_MCSBW20UL, 0xffff}, | ||
| 540 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW20UL + 1, 0xffff}, | ||
| 541 | {BRCMS_SROM_MCSBW405GMPO, 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW40, | ||
| 542 | 0xffff}, | ||
| 543 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW40 + 1, 0xffff}, | ||
| 544 | {BRCMS_SROM_MCSBW205GHPO, 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20, | ||
| 545 | 0xffff}, | ||
| 546 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW20 + 1, 0xffff}, | ||
| 547 | {BRCMS_SROM_MCSBW20UL5GHPO, 0xfffffe00, SRFL_MORE, | ||
| 548 | SROM9_5GHPO_MCSBW20UL, 0xffff}, | ||
| 549 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW20UL + 1, 0xffff}, | ||
| 550 | {BRCMS_SROM_MCSBW405GHPO, 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW40, | ||
| 551 | 0xffff}, | ||
| 552 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW40 + 1, 0xffff}, | ||
| 553 | {BRCMS_SROM_MCS32PO, 0xfffffe00, 0, SROM9_PO_MCS32, 0xffff}, | ||
| 554 | {BRCMS_SROM_LEGOFDM40DUPPO, 0xfffffe00, 0, SROM9_PO_LOFDM40DUP, 0xffff}, | ||
| 555 | |||
| 556 | {BRCMS_SROM_NULL, 0, 0, 0, 0} | ||
| 557 | }; | ||
| 558 | |||
| 559 | static const struct brcms_sromvar perpath_pci_sromvars[] = { | ||
| 560 | {BRCMS_SROM_MAXP2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0x00ff}, | ||
| 561 | {BRCMS_SROM_ITT2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff00}, | ||
| 562 | {BRCMS_SROM_ITT5GA0, 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff00}, | ||
| 563 | {BRCMS_SROM_PA2GW0A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA, 0xffff}, | ||
| 564 | {BRCMS_SROM_PA2GW1A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 1, 0xffff}, | ||
| 565 | {BRCMS_SROM_PA2GW2A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 2, 0xffff}, | ||
| 566 | {BRCMS_SROM_MAXP5GA0, 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0x00ff}, | ||
| 567 | {BRCMS_SROM_MAXP5GHA0, 0xffffff00, 0, SROM8_5GLH_MAXP, 0x00ff}, | ||
| 568 | {BRCMS_SROM_MAXP5GLA0, 0xffffff00, 0, SROM8_5GLH_MAXP, 0xff00}, | ||
| 569 | {BRCMS_SROM_PA5GW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA, 0xffff}, | ||
| 570 | {BRCMS_SROM_PA5GW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 1, 0xffff}, | ||
| 571 | {BRCMS_SROM_PA5GW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 2, 0xffff}, | ||
| 572 | {BRCMS_SROM_PA5GLW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA, 0xffff}, | ||
| 573 | {BRCMS_SROM_PA5GLW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 1, | ||
| 574 | 0xffff}, | ||
| 575 | {BRCMS_SROM_PA5GLW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 2, | ||
| 576 | 0xffff}, | ||
| 577 | {BRCMS_SROM_PA5GHW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA, 0xffff}, | ||
| 578 | {BRCMS_SROM_PA5GHW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 1, | ||
| 579 | 0xffff}, | ||
| 580 | {BRCMS_SROM_PA5GHW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 2, | ||
| 581 | 0xffff}, | ||
| 582 | {BRCMS_SROM_NULL, 0, 0, 0, 0} | ||
| 583 | }; | ||
| 584 | |||
| 585 | /* crc table has the same contents for every device instance, so it can be | ||
| 586 | * shared between devices. */ | ||
| 587 | static u8 brcms_srom_crc8_table[CRC8_TABLE_SIZE]; | ||
| 588 | |||
| 589 | static uint mask_shift(u16 mask) | ||
| 590 | { | ||
| 591 | uint i; | ||
| 592 | for (i = 0; i < (sizeof(mask) << 3); i++) { | ||
| 593 | if (mask & (1 << i)) | ||
| 594 | return i; | ||
| 595 | } | ||
| 596 | return 0; | ||
| 597 | } | ||
| 598 | |||
| 599 | static uint mask_width(u16 mask) | ||
| 600 | { | ||
| 601 | int i; | ||
| 602 | for (i = (sizeof(mask) << 3) - 1; i >= 0; i--) { | ||
| 603 | if (mask & (1 << i)) | ||
| 604 | return (uint) (i - mask_shift(mask) + 1); | ||
| 605 | } | ||
| 606 | return 0; | ||
| 607 | } | ||
| 608 | |||
| 609 | static inline void le16_to_cpu_buf(u16 *buf, uint nwords) | ||
| 610 | { | ||
| 611 | while (nwords--) | ||
| 612 | *(buf + nwords) = le16_to_cpu(*(__le16 *)(buf + nwords)); | ||
| 613 | } | ||
| 614 | |||
| 615 | static inline void cpu_to_le16_buf(u16 *buf, uint nwords) | ||
| 616 | { | ||
| 617 | while (nwords--) | ||
| 618 | *(__le16 *)(buf + nwords) = cpu_to_le16(*(buf + nwords)); | ||
| 619 | } | ||
| 620 | |||
| 621 | /* | ||
| 622 | * convert binary srom data into linked list of srom variable items. | ||
| 623 | */ | ||
| 624 | static int | ||
| 625 | _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list) | ||
| 626 | { | ||
| 627 | struct brcms_srom_list_head *entry; | ||
| 628 | enum brcms_srom_id id; | ||
| 629 | u16 w; | ||
| 630 | u32 val = 0; | ||
| 631 | const struct brcms_sromvar *srv; | ||
| 632 | uint width; | ||
| 633 | uint flags; | ||
| 634 | u32 sr = (1 << sromrev); | ||
| 635 | uint p; | ||
| 636 | uint pb = SROM8_PATH0; | ||
| 637 | const uint psz = SROM8_PATH1 - SROM8_PATH0; | ||
| 638 | |||
| 639 | /* first store the srom revision */ | ||
| 640 | entry = kzalloc(sizeof(struct brcms_srom_list_head), GFP_KERNEL); | ||
| 641 | if (!entry) | ||
| 642 | return -ENOMEM; | ||
| 643 | |||
| 644 | entry->varid = BRCMS_SROM_REV; | ||
| 645 | entry->var_type = BRCMS_SROM_UNUMBER; | ||
| 646 | entry->uval = sromrev; | ||
| 647 | list_add(&entry->var_list, var_list); | ||
| 648 | |||
| 649 | for (srv = pci_sromvars; srv->varid != BRCMS_SROM_NULL; srv++) { | ||
| 650 | enum brcms_srom_var_type type; | ||
| 651 | u8 ea[ETH_ALEN]; | ||
| 652 | u8 extra_space = 0; | ||
| 653 | |||
| 654 | if ((srv->revmask & sr) == 0) | ||
| 655 | continue; | ||
| 656 | |||
| 657 | flags = srv->flags; | ||
| 658 | id = srv->varid; | ||
| 659 | |||
| 660 | /* This entry is for mfgc only. Don't generate param for it, */ | ||
| 661 | if (flags & SRFL_NOVAR) | ||
| 662 | continue; | ||
| 663 | |||
| 664 | if (flags & SRFL_ETHADDR) { | ||
| 665 | /* | ||
| 666 | * stored in string format XX:XX:XX:XX:XX:XX (17 chars) | ||
| 667 | */ | ||
| 668 | ea[0] = (srom[srv->off] >> 8) & 0xff; | ||
| 669 | ea[1] = srom[srv->off] & 0xff; | ||
| 670 | ea[2] = (srom[srv->off + 1] >> 8) & 0xff; | ||
| 671 | ea[3] = srom[srv->off + 1] & 0xff; | ||
| 672 | ea[4] = (srom[srv->off + 2] >> 8) & 0xff; | ||
| 673 | ea[5] = srom[srv->off + 2] & 0xff; | ||
| 674 | /* 17 characters + string terminator - union size */ | ||
| 675 | extra_space = 18 - sizeof(s32); | ||
| 676 | type = BRCMS_SROM_STRING; | ||
| 677 | } else { | ||
| 678 | w = srom[srv->off]; | ||
| 679 | val = (w & srv->mask) >> mask_shift(srv->mask); | ||
| 680 | width = mask_width(srv->mask); | ||
| 681 | |||
| 682 | while (srv->flags & SRFL_MORE) { | ||
| 683 | srv++; | ||
| 684 | if (srv->off == 0) | ||
| 685 | continue; | ||
| 686 | |||
| 687 | w = srom[srv->off]; | ||
| 688 | val += | ||
| 689 | ((w & srv->mask) >> mask_shift(srv-> | ||
| 690 | mask)) << | ||
| 691 | width; | ||
| 692 | width += mask_width(srv->mask); | ||
| 693 | } | ||
| 694 | |||
| 695 | if ((flags & SRFL_NOFFS) | ||
| 696 | && ((int)val == (1 << width) - 1)) | ||
| 697 | continue; | ||
| 698 | |||
| 699 | if (flags & SRFL_CCODE) { | ||
| 700 | type = BRCMS_SROM_STRING; | ||
| 701 | } else if (flags & SRFL_LEDDC) { | ||
| 702 | /* LED Powersave duty cycle has to be scaled: | ||
| 703 | *(oncount >> 24) (offcount >> 8) | ||
| 704 | */ | ||
| 705 | u32 w32 = /* oncount */ | ||
| 706 | (((val >> 8) & 0xff) << 24) | | ||
| 707 | /* offcount */ | ||
| 708 | (((val & 0xff)) << 8); | ||
| 709 | type = BRCMS_SROM_UNUMBER; | ||
| 710 | val = w32; | ||
| 711 | } else if ((flags & SRFL_PRSIGN) | ||
| 712 | && (val & (1 << (width - 1)))) { | ||
| 713 | type = BRCMS_SROM_SNUMBER; | ||
| 714 | val |= ~0 << width; | ||
| 715 | } else | ||
| 716 | type = BRCMS_SROM_UNUMBER; | ||
| 717 | } | ||
| 718 | |||
| 719 | entry = kzalloc(sizeof(struct brcms_srom_list_head) + | ||
| 720 | extra_space, GFP_KERNEL); | ||
| 721 | if (!entry) | ||
| 722 | return -ENOMEM; | ||
| 723 | entry->varid = id; | ||
| 724 | entry->var_type = type; | ||
| 725 | if (flags & SRFL_ETHADDR) { | ||
| 726 | snprintf(entry->buf, 18, "%pM", ea); | ||
| 727 | } else if (flags & SRFL_CCODE) { | ||
| 728 | if (val == 0) | ||
| 729 | entry->buf[0] = '\0'; | ||
| 730 | else | ||
| 731 | snprintf(entry->buf, 3, "%c%c", | ||
| 732 | (val >> 8), (val & 0xff)); | ||
| 733 | } else { | ||
| 734 | entry->uval = val; | ||
| 735 | } | ||
| 736 | |||
| 737 | list_add(&entry->var_list, var_list); | ||
| 738 | } | ||
| 739 | |||
| 740 | for (p = 0; p < MAX_PATH_SROM; p++) { | ||
| 741 | for (srv = perpath_pci_sromvars; | ||
| 742 | srv->varid != BRCMS_SROM_NULL; srv++) { | ||
| 743 | if ((srv->revmask & sr) == 0) | ||
| 744 | continue; | ||
| 745 | |||
| 746 | if (srv->flags & SRFL_NOVAR) | ||
| 747 | continue; | ||
| 748 | |||
| 749 | w = srom[pb + srv->off]; | ||
| 750 | val = (w & srv->mask) >> mask_shift(srv->mask); | ||
| 751 | width = mask_width(srv->mask); | ||
| 752 | |||
| 753 | /* Cheating: no per-path var is more than | ||
| 754 | * 1 word */ | ||
| 755 | if ((srv->flags & SRFL_NOFFS) | ||
| 756 | && ((int)val == (1 << width) - 1)) | ||
| 757 | continue; | ||
| 758 | |||
| 759 | entry = | ||
| 760 | kzalloc(sizeof(struct brcms_srom_list_head), | ||
| 761 | GFP_KERNEL); | ||
| 762 | if (!entry) | ||
| 763 | return -ENOMEM; | ||
| 764 | entry->varid = srv->varid+p; | ||
| 765 | entry->var_type = BRCMS_SROM_UNUMBER; | ||
| 766 | entry->uval = val; | ||
| 767 | list_add(&entry->var_list, var_list); | ||
| 768 | } | ||
| 769 | pb += psz; | ||
| 770 | } | ||
| 771 | return 0; | ||
| 772 | } | ||
| 773 | |||
| 774 | /* | ||
| 775 | * The crc check is done on a little-endian array, we need | ||
| 776 | * to switch the bytes around before checking crc (and | ||
| 777 | * then switch it back). | ||
| 778 | */ | ||
| 779 | static int do_crc_check(u16 *buf, unsigned nwords) | ||
| 780 | { | ||
| 781 | u8 crc; | ||
| 782 | |||
| 783 | cpu_to_le16_buf(buf, nwords); | ||
| 784 | crc = crc8(brcms_srom_crc8_table, (void *)buf, nwords << 1, CRC8_INIT_VALUE); | ||
| 785 | le16_to_cpu_buf(buf, nwords); | ||
| 786 | |||
| 787 | return crc == CRC8_GOOD_VALUE(brcms_srom_crc8_table); | ||
| 788 | } | ||
| 789 | |||
| 790 | /* | ||
| 791 | * Read in and validate sprom. | ||
| 792 | * Return 0 on success, nonzero on error. | ||
| 793 | */ | ||
| 794 | static int | ||
| 795 | sprom_read_pci(struct si_pub *sih, u16 *buf, uint nwords, bool check_crc) | ||
| 796 | { | ||
| 797 | int err = 0; | ||
| 798 | uint i; | ||
| 799 | struct bcma_device *core; | ||
| 800 | uint sprom_offset; | ||
| 801 | |||
| 802 | /* determine core to read */ | ||
| 803 | if (ai_get_ccrev(sih) < 32) { | ||
| 804 | core = ai_findcore(sih, BCMA_CORE_80211, 0); | ||
| 805 | sprom_offset = PCI_BAR0_SPROM_OFFSET; | ||
| 806 | } else { | ||
| 807 | core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); | ||
| 808 | sprom_offset = CHIPCREGOFFS(sromotp); | ||
| 809 | } | ||
| 810 | |||
| 811 | /* read the sprom */ | ||
| 812 | for (i = 0; i < nwords; i++) | ||
| 813 | buf[i] = bcma_read16(core, sprom_offset+i*2); | ||
| 814 | |||
| 815 | if (buf[0] == 0xffff) | ||
| 816 | /* | ||
| 817 | * The hardware thinks that an srom that starts with | ||
| 818 | * 0xffff is blank, regardless of the rest of the | ||
| 819 | * content, so declare it bad. | ||
| 820 | */ | ||
| 821 | return -ENODATA; | ||
| 822 | |||
| 823 | if (check_crc && !do_crc_check(buf, nwords)) | ||
| 824 | err = -EIO; | ||
| 825 | |||
| 826 | return err; | ||
| 827 | } | ||
| 828 | |||
| 829 | static int otp_read_pci(struct si_pub *sih, u16 *buf, uint nwords) | ||
| 830 | { | ||
| 831 | u8 *otp; | ||
| 832 | uint sz = OTP_SZ_MAX / 2; /* size in words */ | ||
| 833 | int err = 0; | ||
| 834 | |||
| 835 | otp = kzalloc(OTP_SZ_MAX, GFP_ATOMIC); | ||
| 836 | if (otp == NULL) | ||
| 837 | return -ENOMEM; | ||
| 838 | |||
| 839 | err = otp_read_region(sih, OTP_HW_RGN, (u16 *) otp, &sz); | ||
| 840 | |||
| 841 | sz = min_t(uint, sz, nwords); | ||
| 842 | memcpy(buf, otp, sz * 2); | ||
| 843 | |||
| 844 | kfree(otp); | ||
| 845 | |||
| 846 | /* Check CRC */ | ||
| 847 | if (buf[0] == 0xffff) | ||
| 848 | /* The hardware thinks that an srom that starts with 0xffff | ||
| 849 | * is blank, regardless of the rest of the content, so declare | ||
| 850 | * it bad. | ||
| 851 | */ | ||
| 852 | return -ENODATA; | ||
| 853 | |||
| 854 | /* fixup the endianness so crc8 will pass */ | ||
| 855 | cpu_to_le16_buf(buf, sz); | ||
| 856 | if (crc8(brcms_srom_crc8_table, (u8 *) buf, sz * 2, | ||
| 857 | CRC8_INIT_VALUE) != CRC8_GOOD_VALUE(brcms_srom_crc8_table)) | ||
| 858 | err = -EIO; | ||
| 859 | else | ||
| 860 | /* now correct the endianness of the byte array */ | ||
| 861 | le16_to_cpu_buf(buf, sz); | ||
| 862 | |||
| 863 | return err; | ||
| 864 | } | ||
| 865 | |||
| 866 | /* | ||
| 867 | * Initialize nonvolatile variable table from sprom. | ||
| 868 | * Return 0 on success, nonzero on error. | ||
| 869 | */ | ||
| 870 | int srom_var_init(struct si_pub *sih) | ||
| 871 | { | ||
| 872 | u16 *srom; | ||
| 873 | u8 sromrev = 0; | ||
| 874 | u32 sr; | ||
| 875 | int err = 0; | ||
| 876 | |||
| 877 | /* | ||
| 878 | * Apply CRC over SROM content regardless SROM is present or not. | ||
| 879 | */ | ||
| 880 | srom = kmalloc(SROM_MAX, GFP_ATOMIC); | ||
| 881 | if (!srom) | ||
| 882 | return -ENOMEM; | ||
| 883 | |||
| 884 | crc8_populate_lsb(brcms_srom_crc8_table, SROM_CRC8_POLY); | ||
| 885 | if (ai_is_sprom_available(sih)) { | ||
| 886 | err = sprom_read_pci(sih, srom, SROM4_WORDS, true); | ||
| 887 | |||
| 888 | if (err == 0) | ||
| 889 | /* srom read and passed crc */ | ||
| 890 | /* top word of sprom contains version and crc8 */ | ||
| 891 | sromrev = srom[SROM4_CRCREV] & 0xff; | ||
| 892 | } else { | ||
| 893 | /* Use OTP if SPROM not available */ | ||
| 894 | err = otp_read_pci(sih, srom, SROM4_WORDS); | ||
| 895 | if (err == 0) | ||
| 896 | /* OTP only contain SROM rev8/rev9 for now */ | ||
| 897 | sromrev = srom[SROM4_CRCREV] & 0xff; | ||
| 898 | } | ||
| 899 | |||
| 900 | if (!err) { | ||
| 901 | struct si_info *sii = (struct si_info *)sih; | ||
| 902 | |||
| 903 | /* Bitmask for the sromrev */ | ||
| 904 | sr = 1 << sromrev; | ||
| 905 | |||
| 906 | /* | ||
| 907 | * srom version check: Current valid versions: 8, 9 | ||
| 908 | */ | ||
| 909 | if ((sr & 0x300) == 0) { | ||
| 910 | err = -EINVAL; | ||
| 911 | goto errout; | ||
| 912 | } | ||
| 913 | |||
| 914 | INIT_LIST_HEAD(&sii->var_list); | ||
| 915 | |||
| 916 | /* parse SROM into name=value pairs. */ | ||
| 917 | err = _initvars_srom_pci(sromrev, srom, &sii->var_list); | ||
| 918 | if (err) | ||
| 919 | srom_free_vars(sih); | ||
| 920 | } | ||
| 921 | |||
| 922 | errout: | ||
| 923 | kfree(srom); | ||
| 924 | return err; | ||
| 925 | } | ||
| 926 | |||
| 927 | void srom_free_vars(struct si_pub *sih) | ||
| 928 | { | ||
| 929 | struct si_info *sii; | ||
| 930 | struct brcms_srom_list_head *entry, *next; | ||
| 931 | |||
| 932 | sii = (struct si_info *)sih; | ||
| 933 | list_for_each_entry_safe(entry, next, &sii->var_list, var_list) { | ||
| 934 | list_del(&entry->var_list); | ||
| 935 | kfree(entry); | ||
| 936 | } | ||
| 937 | } | ||
| 938 | |||
| 939 | /* | ||
| 940 | * Search the name=value vars for a specific one and return its value. | ||
| 941 | * Returns NULL if not found. | ||
| 942 | */ | ||
| 943 | char *getvar(struct si_pub *sih, enum brcms_srom_id id) | ||
| 944 | { | ||
| 945 | struct si_info *sii; | ||
| 946 | struct brcms_srom_list_head *entry; | ||
| 947 | |||
| 948 | sii = (struct si_info *)sih; | ||
| 949 | |||
| 950 | list_for_each_entry(entry, &sii->var_list, var_list) | ||
| 951 | if (entry->varid == id) | ||
| 952 | return &entry->buf[0]; | ||
| 953 | |||
| 954 | /* nothing found */ | ||
| 955 | return NULL; | ||
| 956 | } | ||
| 957 | |||
| 958 | /* | ||
| 959 | * Search the vars for a specific one and return its value as | ||
| 960 | * an integer. Returns 0 if not found.- | ||
| 961 | */ | ||
| 962 | int getintvar(struct si_pub *sih, enum brcms_srom_id id) | ||
| 963 | { | ||
| 964 | struct si_info *sii; | ||
| 965 | struct brcms_srom_list_head *entry; | ||
| 966 | unsigned long res; | ||
| 967 | |||
| 968 | sii = (struct si_info *)sih; | ||
| 969 | |||
| 970 | list_for_each_entry(entry, &sii->var_list, var_list) | ||
| 971 | if (entry->varid == id) { | ||
| 972 | if (entry->var_type == BRCMS_SROM_SNUMBER || | ||
| 973 | entry->var_type == BRCMS_SROM_UNUMBER) | ||
| 974 | return (int)entry->sval; | ||
| 975 | else if (!kstrtoul(&entry->buf[0], 0, &res)) | ||
| 976 | return (int)res; | ||
| 977 | } | ||
| 978 | |||
| 979 | return 0; | ||
| 980 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/srom.h b/drivers/net/wireless/brcm80211/brcmsmac/srom.h deleted file mode 100644 index f2a58f262c9..00000000000 --- a/drivers/net/wireless/brcm80211/brcmsmac/srom.h +++ /dev/null | |||
| @@ -1,29 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2010 Broadcom Corporation | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef _BRCM_SROM_H_ | ||
| 18 | #define _BRCM_SROM_H_ | ||
| 19 | |||
| 20 | #include "types.h" | ||
| 21 | |||
| 22 | /* Prototypes */ | ||
| 23 | extern int srom_var_init(struct si_pub *sih); | ||
| 24 | extern void srom_free_vars(struct si_pub *sih); | ||
| 25 | |||
| 26 | extern int srom_read(struct si_pub *sih, uint bus, void *curmap, | ||
| 27 | uint byteoff, uint nbytes, u16 *buf, bool check_crc); | ||
| 28 | |||
| 29 | #endif /* _BRCM_SROM_H_ */ | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/stf.c b/drivers/net/wireless/brcm80211/brcmsmac/stf.c index d8f528eb180..ed1d1aa71d2 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/stf.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/stf.c | |||
| @@ -370,9 +370,11 @@ void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc) | |||
| 370 | 370 | ||
| 371 | void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc) | 371 | void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc) |
| 372 | { | 372 | { |
| 373 | struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom; | ||
| 374 | |||
| 373 | /* get available rx/tx chains */ | 375 | /* get available rx/tx chains */ |
| 374 | wlc->stf->hw_txchain = (u8) getintvar(wlc->hw->sih, BRCMS_SROM_TXCHAIN); | 376 | wlc->stf->hw_txchain = sprom->txchain; |
| 375 | wlc->stf->hw_rxchain = (u8) getintvar(wlc->hw->sih, BRCMS_SROM_RXCHAIN); | 377 | wlc->stf->hw_rxchain = sprom->rxchain; |
| 376 | 378 | ||
| 377 | /* these parameter are intended to be used for all PHY types */ | 379 | /* these parameter are intended to be used for all PHY types */ |
| 378 | if (wlc->stf->hw_txchain == 0 || wlc->stf->hw_txchain == 0xf) { | 380 | if (wlc->stf->hw_txchain == 0 || wlc->stf->hw_txchain == 0xf) { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 01dc4426731..e55ec6c8a92 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
| 32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
| 33 | #include <linux/sched.h> | 33 | #include <linux/sched.h> |
| 34 | #include <net/mac80211.h> | ||
| 34 | 35 | ||
| 35 | #include "iwl-dev.h" | 36 | #include "iwl-dev.h" |
| 36 | #include "iwl-io.h" | 37 | #include "iwl-io.h" |
| @@ -273,9 +274,20 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv) | |||
| 273 | return; | 274 | return; |
| 274 | } | 275 | } |
| 275 | 276 | ||
| 277 | /* | ||
| 278 | * Possible situations when BT needs to take over for receive, | ||
| 279 | * at the same time where STA needs to response to AP's frame(s), | ||
| 280 | * reduce the tx power of the required response frames, by that, | ||
| 281 | * allow the concurrent BT receive & WiFi transmit | ||
| 282 | * (BT - ANT A, WiFi -ANT B), without interference to one another | ||
| 283 | * | ||
| 284 | * Reduced tx power apply to control frames only (ACK/Back/CTS) | ||
| 285 | * when indicated by the BT config command | ||
| 286 | */ | ||
| 276 | basic.kill_ack_mask = priv->kill_ack_mask; | 287 | basic.kill_ack_mask = priv->kill_ack_mask; |
| 277 | basic.kill_cts_mask = priv->kill_cts_mask; | 288 | basic.kill_cts_mask = priv->kill_cts_mask; |
| 278 | basic.reduce_txpower = priv->reduced_txpower; | 289 | if (priv->reduced_txpower) |
| 290 | basic.reduce_txpower = IWLAGN_BT_REDUCED_TX_PWR; | ||
| 279 | basic.valid = priv->bt_valid; | 291 | basic.valid = priv->bt_valid; |
| 280 | 292 | ||
| 281 | /* | 293 | /* |
| @@ -589,13 +601,31 @@ static bool iwlagn_set_kill_msk(struct iwl_priv *priv, | |||
| 589 | return need_update; | 601 | return need_update; |
| 590 | } | 602 | } |
| 591 | 603 | ||
| 604 | /* | ||
| 605 | * Upon RSSI changes, sends a bt config command with following changes | ||
| 606 | * 1. enable/disable "reduced control frames tx power | ||
| 607 | * 2. update the "kill)ack_mask" and "kill_cts_mask" | ||
| 608 | * | ||
| 609 | * If "reduced tx power" is enabled, uCode shall | ||
| 610 | * 1. ACK/Back/CTS rate shall reduced to 6Mbps | ||
| 611 | * 2. not use duplciate 20/40MHz mode | ||
| 612 | */ | ||
| 592 | static bool iwlagn_fill_txpower_mode(struct iwl_priv *priv, | 613 | static bool iwlagn_fill_txpower_mode(struct iwl_priv *priv, |
| 593 | struct iwl_bt_uart_msg *uart_msg) | 614 | struct iwl_bt_uart_msg *uart_msg) |
| 594 | { | 615 | { |
| 595 | bool need_update = false; | 616 | bool need_update = false; |
| 617 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
| 618 | int ave_rssi; | ||
| 596 | 619 | ||
| 620 | ave_rssi = ieee80211_ave_rssi(ctx->vif); | ||
| 621 | if (!ave_rssi) { | ||
| 622 | /* no rssi data, no changes to reduce tx power */ | ||
| 623 | IWL_DEBUG_COEX(priv, "no rssi data available\n"); | ||
| 624 | return need_update; | ||
| 625 | } | ||
| 597 | if (!priv->reduced_txpower && | 626 | if (!priv->reduced_txpower && |
| 598 | !iwl_is_associated(priv, IWL_RXON_CTX_PAN) && | 627 | !iwl_is_associated(priv, IWL_RXON_CTX_PAN) && |
| 628 | (ave_rssi > BT_ENABLE_REDUCED_TXPOWER_THRESHOLD) && | ||
| 599 | (uart_msg->frame3 & (BT_UART_MSG_FRAME3ACL_MSK | | 629 | (uart_msg->frame3 & (BT_UART_MSG_FRAME3ACL_MSK | |
| 600 | BT_UART_MSG_FRAME3OBEX_MSK)) && | 630 | BT_UART_MSG_FRAME3OBEX_MSK)) && |
| 601 | !(uart_msg->frame3 & (BT_UART_MSG_FRAME3SCOESCO_MSK | | 631 | !(uart_msg->frame3 & (BT_UART_MSG_FRAME3SCOESCO_MSK | |
| @@ -606,13 +636,14 @@ static bool iwlagn_fill_txpower_mode(struct iwl_priv *priv, | |||
| 606 | need_update = true; | 636 | need_update = true; |
| 607 | } else if (priv->reduced_txpower && | 637 | } else if (priv->reduced_txpower && |
| 608 | (iwl_is_associated(priv, IWL_RXON_CTX_PAN) || | 638 | (iwl_is_associated(priv, IWL_RXON_CTX_PAN) || |
| 639 | (ave_rssi < BT_DISABLE_REDUCED_TXPOWER_THRESHOLD) || | ||
| 609 | (uart_msg->frame3 & (BT_UART_MSG_FRAME3SCOESCO_MSK | | 640 | (uart_msg->frame3 & (BT_UART_MSG_FRAME3SCOESCO_MSK | |
| 610 | BT_UART_MSG_FRAME3SNIFF_MSK | BT_UART_MSG_FRAME3A2DP_MSK)) || | 641 | BT_UART_MSG_FRAME3SNIFF_MSK | BT_UART_MSG_FRAME3A2DP_MSK)) || |
| 611 | !(uart_msg->frame3 & (BT_UART_MSG_FRAME3ACL_MSK | | 642 | !(uart_msg->frame3 & (BT_UART_MSG_FRAME3ACL_MSK | |
| 612 | BT_UART_MSG_FRAME3OBEX_MSK)))) { | 643 | BT_UART_MSG_FRAME3OBEX_MSK)))) { |
| 613 | /* disable reduced tx power */ | 644 | /* disable reduced tx power */ |
| 614 | priv->reduced_txpower = false; | 645 | priv->reduced_txpower = false; |
| 615 | priv->bt_valid &= ~IWLAGN_BT_VALID_REDUCED_TX_PWR; | 646 | priv->bt_valid |= IWLAGN_BT_VALID_REDUCED_TX_PWR; |
| 616 | need_update = true; | 647 | need_update = true; |
| 617 | } | 648 | } |
| 618 | 649 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 74fbee62730..0a3aa7c8300 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | |||
| @@ -61,6 +61,10 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, | |||
| 61 | RXON_FILTER_ACCEPT_GRP_MSK; | 61 | RXON_FILTER_ACCEPT_GRP_MSK; |
| 62 | break; | 62 | break; |
| 63 | 63 | ||
| 64 | case NL80211_IFTYPE_MONITOR: | ||
| 65 | ctx->staging.dev_type = RXON_DEV_TYPE_SNIFFER; | ||
| 66 | break; | ||
| 67 | |||
| 64 | default: | 68 | default: |
| 65 | IWL_ERR(priv, "Unsupported interface type %d\n", | 69 | IWL_ERR(priv, "Unsupported interface type %d\n", |
| 66 | ctx->vif->type); | 70 | ctx->vif->type); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index f2e9f298a94..3366e2e2f00 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
| @@ -590,11 +590,17 @@ turn_off: | |||
| 590 | spin_unlock_bh(&priv->sta_lock); | 590 | spin_unlock_bh(&priv->sta_lock); |
| 591 | 591 | ||
| 592 | if (test_bit(txq_id, priv->agg_q_alloc)) { | 592 | if (test_bit(txq_id, priv->agg_q_alloc)) { |
| 593 | /* If the transport didn't know that we wanted to start | 593 | /* |
| 594 | * agreggation, don't tell it that we want to stop them | 594 | * If the transport didn't know that we wanted to start |
| 595 | * agreggation, don't tell it that we want to stop them. | ||
| 596 | * This can happen when we don't get the addBA response on | ||
| 597 | * time, or we hadn't time to drain the AC queues. | ||
| 595 | */ | 598 | */ |
| 596 | if (agg_state != IWL_AGG_STARTING) | 599 | if (agg_state == IWL_AGG_ON) |
| 597 | iwl_trans_tx_agg_disable(priv->trans, txq_id); | 600 | iwl_trans_tx_agg_disable(priv->trans, txq_id); |
| 601 | else | ||
| 602 | IWL_DEBUG_TX_QUEUES(priv, "Don't disable tx agg: %d\n", | ||
| 603 | agg_state); | ||
| 598 | iwlagn_dealloc_agg_txq(priv, txq_id); | 604 | iwlagn_dealloc_agg_txq(priv, txq_id); |
| 599 | } | 605 | } |
| 600 | 606 | ||
| @@ -1300,10 +1306,11 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
| 1300 | (u8 *) &ba_resp->sta_addr_lo32, | 1306 | (u8 *) &ba_resp->sta_addr_lo32, |
| 1301 | ba_resp->sta_id); | 1307 | ba_resp->sta_id); |
| 1302 | IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, " | 1308 | IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, " |
| 1303 | "scd_flow = %d, scd_ssn = %d\n", | 1309 | "scd_flow = %d, scd_ssn = %d sent:%d, acked:%d\n", |
| 1304 | ba_resp->tid, le16_to_cpu(ba_resp->seq_ctl), | 1310 | ba_resp->tid, le16_to_cpu(ba_resp->seq_ctl), |
| 1305 | (unsigned long long)le64_to_cpu(ba_resp->bitmap), | 1311 | (unsigned long long)le64_to_cpu(ba_resp->bitmap), |
| 1306 | scd_flow, ba_resp_scd_ssn); | 1312 | scd_flow, ba_resp_scd_ssn, ba_resp->txed, |
| 1313 | ba_resp->txed_2_done); | ||
| 1307 | 1314 | ||
| 1308 | /* Mark that the expected block-ack response arrived */ | 1315 | /* Mark that the expected block-ack response arrived */ |
| 1309 | agg->wait_for_ba = false; | 1316 | agg->wait_for_ba = false; |
| @@ -1319,8 +1326,6 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
| 1319 | */ | 1326 | */ |
| 1320 | ba_resp->txed = ba_resp->txed_2_done; | 1327 | ba_resp->txed = ba_resp->txed_2_done; |
| 1321 | } | 1328 | } |
| 1322 | IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n", | ||
| 1323 | ba_resp->txed, ba_resp->txed_2_done); | ||
| 1324 | 1329 | ||
| 1325 | priv->tid_data[sta_id][tid].next_reclaimed = ba_resp_scd_ssn; | 1330 | priv->tid_data[sta_id][tid].next_reclaimed = ba_resp_scd_ssn; |
| 1326 | 1331 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8d7637083fc..ec36e2b020b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
| @@ -603,7 +603,7 @@ void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) | |||
| 603 | priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY; | 603 | priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY; |
| 604 | priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; | 604 | priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; |
| 605 | priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes = | 605 | priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes = |
| 606 | BIT(NL80211_IFTYPE_ADHOC); | 606 | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_MONITOR); |
| 607 | priv->contexts[IWL_RXON_CTX_BSS].interface_modes = | 607 | priv->contexts[IWL_RXON_CTX_BSS].interface_modes = |
| 608 | BIT(NL80211_IFTYPE_STATION); | 608 | BIT(NL80211_IFTYPE_STATION); |
| 609 | priv->contexts[IWL_RXON_CTX_BSS].ap_devtype = RXON_DEV_TYPE_AP; | 609 | priv->contexts[IWL_RXON_CTX_BSS].ap_devtype = RXON_DEV_TYPE_AP; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 83a6930f365..9af6a239b38 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
| @@ -1910,6 +1910,8 @@ enum iwl_bt_kill_idx { | |||
| 1910 | IWLAGN_BT_VALID_REDUCED_TX_PWR | \ | 1910 | IWLAGN_BT_VALID_REDUCED_TX_PWR | \ |
| 1911 | IWLAGN_BT_VALID_3W_LUT) | 1911 | IWLAGN_BT_VALID_3W_LUT) |
| 1912 | 1912 | ||
| 1913 | #define IWLAGN_BT_REDUCED_TX_PWR BIT(0) | ||
| 1914 | |||
| 1913 | #define IWLAGN_BT_DECISION_LUT_SIZE 12 | 1915 | #define IWLAGN_BT_DECISION_LUT_SIZE 12 |
| 1914 | 1916 | ||
| 1915 | struct iwl_basic_bt_cmd { | 1917 | struct iwl_basic_bt_cmd { |
| @@ -1923,6 +1925,10 @@ struct iwl_basic_bt_cmd { | |||
| 1923 | u8 bt3_timer_t2_value; | 1925 | u8 bt3_timer_t2_value; |
| 1924 | __le16 bt4_reaction_time; /* unused */ | 1926 | __le16 bt4_reaction_time; /* unused */ |
| 1925 | __le32 bt3_lookup_table[IWLAGN_BT_DECISION_LUT_SIZE]; | 1927 | __le32 bt3_lookup_table[IWLAGN_BT_DECISION_LUT_SIZE]; |
| 1928 | /* | ||
| 1929 | * bit 0: use reduced tx power for control frame | ||
| 1930 | * bit 1 - 7: reserved | ||
| 1931 | */ | ||
| 1926 | u8 reduce_txpower; | 1932 | u8 reduce_txpower; |
| 1927 | u8 reserved; | 1933 | u8 reserved; |
| 1928 | __le16 valid; | 1934 | __le16 valid; |
| @@ -2272,7 +2278,6 @@ struct iwl_ssid_ie { | |||
| 2272 | #define IWL_GOOD_CRC_TH_DISABLED 0 | 2278 | #define IWL_GOOD_CRC_TH_DISABLED 0 |
| 2273 | #define IWL_GOOD_CRC_TH_DEFAULT cpu_to_le16(1) | 2279 | #define IWL_GOOD_CRC_TH_DEFAULT cpu_to_le16(1) |
| 2274 | #define IWL_GOOD_CRC_TH_NEVER cpu_to_le16(0xffff) | 2280 | #define IWL_GOOD_CRC_TH_NEVER cpu_to_le16(0xffff) |
| 2275 | #define IWL_MAX_SCAN_SIZE 1024 | ||
| 2276 | #define IWL_MAX_CMD_SIZE 4096 | 2281 | #define IWL_MAX_CMD_SIZE 4096 |
| 2277 | 2282 | ||
| 2278 | /* | 2283 | /* |
diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index d33cc9cc7d3..ab2f4d7500a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c | |||
| @@ -150,6 +150,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, | |||
| 150 | IEEE80211_HW_QUEUE_CONTROL | | 150 | IEEE80211_HW_QUEUE_CONTROL | |
| 151 | IEEE80211_HW_SUPPORTS_PS | | 151 | IEEE80211_HW_SUPPORTS_PS | |
| 152 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | | 152 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | |
| 153 | IEEE80211_HW_WANT_MONITOR_VIF | | ||
| 153 | IEEE80211_HW_SCAN_WHILE_IDLE; | 154 | IEEE80211_HW_SCAN_WHILE_IDLE; |
| 154 | 155 | ||
| 155 | hw->offchannel_tx_hw_queue = IWL_AUX_QUEUE; | 156 | hw->offchannel_tx_hw_queue = IWL_AUX_QUEUE; |
| @@ -223,8 +224,8 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, | |||
| 223 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | 224 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
| 224 | 225 | ||
| 225 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; | 226 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; |
| 226 | /* we create the 802.11 header and a zero-length SSID element */ | 227 | /* we create the 802.11 header and a max-length SSID element */ |
| 227 | hw->wiphy->max_scan_ie_len = capa->max_probe_length - 24 - 2; | 228 | hw->wiphy->max_scan_ie_len = capa->max_probe_length - 24 - 34; |
| 228 | 229 | ||
| 229 | /* | 230 | /* |
| 230 | * We don't use all queues: 4 and 9 are unused and any | 231 | * We don't use all queues: 4 and 9 are unused and any |
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 8352265dbc4..544ddf17f5b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c | |||
| @@ -253,6 +253,8 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, | |||
| 253 | 253 | ||
| 254 | IWL_DEBUG_POWER(priv, "numSkipDtim = %u, dtimPeriod = %d\n", | 254 | IWL_DEBUG_POWER(priv, "numSkipDtim = %u, dtimPeriod = %d\n", |
| 255 | skip, period); | 255 | skip, period); |
| 256 | /* The power level here is 0-4 (used as array index), but user expects | ||
| 257 | to see 1-5 (according to spec). */ | ||
| 256 | IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1); | 258 | IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1); |
| 257 | } | 259 | } |
| 258 | 260 | ||
| @@ -308,10 +310,12 @@ static void iwl_power_build_cmd(struct iwl_priv *priv, | |||
| 308 | priv->power_data.debug_sleep_level_override, | 310 | priv->power_data.debug_sleep_level_override, |
| 309 | dtimper); | 311 | dtimper); |
| 310 | else { | 312 | else { |
| 313 | /* Note that the user parameter is 1-5 (according to spec), | ||
| 314 | but we pass 0-4 because it acts as an array index. */ | ||
| 311 | if (iwlwifi_mod_params.power_level > IWL_POWER_INDEX_1 && | 315 | if (iwlwifi_mod_params.power_level > IWL_POWER_INDEX_1 && |
| 312 | iwlwifi_mod_params.power_level <= IWL_POWER_INDEX_5) | 316 | iwlwifi_mod_params.power_level <= IWL_POWER_NUM) |
| 313 | iwl_static_sleep_cmd(priv, cmd, | 317 | iwl_static_sleep_cmd(priv, cmd, |
| 314 | iwlwifi_mod_params.power_level, dtimper); | 318 | iwlwifi_mod_params.power_level - 1, dtimper); |
| 315 | else | 319 | else |
| 316 | iwl_static_sleep_cmd(priv, cmd, | 320 | iwl_static_sleep_cmd(priv, cmd, |
| 317 | IWL_POWER_INDEX_1, dtimper); | 321 | IWL_POWER_INDEX_1, dtimper); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index a8437a6bc18..031d8e21f82 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
| @@ -52,6 +52,7 @@ | |||
| 52 | #define IWL_PASSIVE_DWELL_TIME_52 (10) | 52 | #define IWL_PASSIVE_DWELL_TIME_52 (10) |
| 53 | #define IWL_PASSIVE_DWELL_BASE (100) | 53 | #define IWL_PASSIVE_DWELL_BASE (100) |
| 54 | #define IWL_CHANNEL_TUNE_TIME 5 | 54 | #define IWL_CHANNEL_TUNE_TIME 5 |
| 55 | #define MAX_SCAN_CHANNEL 50 | ||
| 55 | 56 | ||
| 56 | static int iwl_send_scan_abort(struct iwl_priv *priv) | 57 | static int iwl_send_scan_abort(struct iwl_priv *priv) |
| 57 | { | 58 | { |
| @@ -616,7 +617,8 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, | |||
| 616 | */ | 617 | */ |
| 617 | 618 | ||
| 618 | static u16 iwl_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta, | 619 | static u16 iwl_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta, |
| 619 | const u8 *ies, int ie_len, int left) | 620 | const u8 *ies, int ie_len, const u8 *ssid, |
| 621 | u8 ssid_len, int left) | ||
| 620 | { | 622 | { |
| 621 | int len = 0; | 623 | int len = 0; |
| 622 | u8 *pos = NULL; | 624 | u8 *pos = NULL; |
| @@ -638,14 +640,18 @@ static u16 iwl_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta, | |||
| 638 | /* ...next IE... */ | 640 | /* ...next IE... */ |
| 639 | pos = &frame->u.probe_req.variable[0]; | 641 | pos = &frame->u.probe_req.variable[0]; |
| 640 | 642 | ||
| 641 | /* fill in our indirect SSID IE */ | 643 | /* fill in our SSID IE */ |
| 642 | left -= 2; | 644 | left -= ssid_len + 2; |
| 643 | if (left < 0) | 645 | if (left < 0) |
| 644 | return 0; | 646 | return 0; |
| 645 | *pos++ = WLAN_EID_SSID; | 647 | *pos++ = WLAN_EID_SSID; |
| 646 | *pos++ = 0; | 648 | *pos++ = ssid_len; |
| 649 | if (ssid && ssid_len) { | ||
| 650 | memcpy(pos, ssid, ssid_len); | ||
| 651 | pos += ssid_len; | ||
| 652 | } | ||
| 647 | 653 | ||
| 648 | len += 2; | 654 | len += ssid_len + 2; |
| 649 | 655 | ||
| 650 | if (WARN_ON(left < ie_len)) | 656 | if (WARN_ON(left < ie_len)) |
| 651 | return len; | 657 | return len; |
| @@ -679,6 +685,15 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
| 679 | u8 active_chains; | 685 | u8 active_chains; |
| 680 | u8 scan_tx_antennas = priv->hw_params.valid_tx_ant; | 686 | u8 scan_tx_antennas = priv->hw_params.valid_tx_ant; |
| 681 | int ret; | 687 | int ret; |
| 688 | int scan_cmd_size = sizeof(struct iwl_scan_cmd) + | ||
| 689 | MAX_SCAN_CHANNEL * sizeof(struct iwl_scan_channel) + | ||
| 690 | priv->fw->ucode_capa.max_probe_length; | ||
| 691 | const u8 *ssid = NULL; | ||
| 692 | u8 ssid_len = 0; | ||
| 693 | |||
| 694 | if (WARN_ON_ONCE(priv->scan_request && | ||
| 695 | priv->scan_request->n_channels > MAX_SCAN_CHANNEL)) | ||
| 696 | return -EINVAL; | ||
| 682 | 697 | ||
| 683 | lockdep_assert_held(&priv->mutex); | 698 | lockdep_assert_held(&priv->mutex); |
| 684 | 699 | ||
| @@ -686,8 +701,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
| 686 | ctx = iwl_rxon_ctx_from_vif(vif); | 701 | ctx = iwl_rxon_ctx_from_vif(vif); |
| 687 | 702 | ||
| 688 | if (!priv->scan_cmd) { | 703 | if (!priv->scan_cmd) { |
| 689 | priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) + | 704 | priv->scan_cmd = kmalloc(scan_cmd_size, GFP_KERNEL); |
| 690 | IWL_MAX_SCAN_SIZE, GFP_KERNEL); | ||
| 691 | if (!priv->scan_cmd) { | 705 | if (!priv->scan_cmd) { |
| 692 | IWL_DEBUG_SCAN(priv, | 706 | IWL_DEBUG_SCAN(priv, |
| 693 | "fail to allocate memory for scan\n"); | 707 | "fail to allocate memory for scan\n"); |
| @@ -695,7 +709,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
| 695 | } | 709 | } |
| 696 | } | 710 | } |
| 697 | scan = priv->scan_cmd; | 711 | scan = priv->scan_cmd; |
| 698 | memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE); | 712 | memset(scan, 0, scan_cmd_size); |
| 699 | 713 | ||
| 700 | scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; | 714 | scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; |
| 701 | scan->quiet_time = IWL_ACTIVE_QUIET_TIME; | 715 | scan->quiet_time = IWL_ACTIVE_QUIET_TIME; |
| @@ -746,10 +760,18 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
| 746 | if (priv->scan_request->n_ssids) { | 760 | if (priv->scan_request->n_ssids) { |
| 747 | int i, p = 0; | 761 | int i, p = 0; |
| 748 | IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); | 762 | IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); |
| 749 | for (i = 0; i < priv->scan_request->n_ssids; i++) { | 763 | /* |
| 750 | /* always does wildcard anyway */ | 764 | * The highest priority SSID is inserted to the |
| 751 | if (!priv->scan_request->ssids[i].ssid_len) | 765 | * probe request template. |
| 752 | continue; | 766 | */ |
| 767 | ssid_len = priv->scan_request->ssids[0].ssid_len; | ||
| 768 | ssid = priv->scan_request->ssids[0].ssid; | ||
| 769 | |||
| 770 | /* | ||
| 771 | * Invert the order of ssids, the firmware will invert | ||
| 772 | * it back. | ||
| 773 | */ | ||
| 774 | for (i = priv->scan_request->n_ssids - 1; i >= 1; i--) { | ||
| 753 | scan->direct_scan[p].id = WLAN_EID_SSID; | 775 | scan->direct_scan[p].id = WLAN_EID_SSID; |
| 754 | scan->direct_scan[p].len = | 776 | scan->direct_scan[p].len = |
| 755 | priv->scan_request->ssids[i].ssid_len; | 777 | priv->scan_request->ssids[i].ssid_len; |
| @@ -883,7 +905,8 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
| 883 | vif->addr, | 905 | vif->addr, |
| 884 | priv->scan_request->ie, | 906 | priv->scan_request->ie, |
| 885 | priv->scan_request->ie_len, | 907 | priv->scan_request->ie_len, |
| 886 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | 908 | ssid, ssid_len, |
| 909 | scan_cmd_size - sizeof(*scan)); | ||
| 887 | break; | 910 | break; |
| 888 | case IWL_SCAN_RADIO_RESET: | 911 | case IWL_SCAN_RADIO_RESET: |
| 889 | case IWL_SCAN_ROC: | 912 | case IWL_SCAN_ROC: |
| @@ -891,7 +914,8 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
| 891 | cmd_len = iwl_fill_probe_req( | 914 | cmd_len = iwl_fill_probe_req( |
| 892 | (struct ieee80211_mgmt *)scan->data, | 915 | (struct ieee80211_mgmt *)scan->data, |
| 893 | iwl_bcast_addr, NULL, 0, | 916 | iwl_bcast_addr, NULL, 0, |
| 894 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | 917 | NULL, 0, |
| 918 | scan_cmd_size - sizeof(*scan)); | ||
| 895 | break; | 919 | break; |
| 896 | default: | 920 | default: |
| 897 | BUG(); | 921 | BUG(); |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 03c0c6b1372..fb787df0166 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
| @@ -746,6 +746,11 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
| 746 | hwsim_check_sta_magic(txi->control.sta); | 746 | hwsim_check_sta_magic(txi->control.sta); |
| 747 | 747 | ||
| 748 | ieee80211_tx_info_clear_status(txi); | 748 | ieee80211_tx_info_clear_status(txi); |
| 749 | |||
| 750 | /* frame was transmitted at most favorable rate at first attempt */ | ||
| 751 | txi->control.rates[0].count = 1; | ||
| 752 | txi->control.rates[1].idx = -1; | ||
| 753 | |||
| 749 | if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) && ack) | 754 | if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) && ack) |
| 750 | txi->flags |= IEEE80211_TX_STAT_ACK; | 755 | txi->flags |= IEEE80211_TX_STAT_ACK; |
| 751 | ieee80211_tx_status_irqsafe(hw, skb); | 756 | ieee80211_tx_status_irqsafe(hw, skb); |
diff --git a/drivers/net/wireless/mwifiex/Makefile b/drivers/net/wireless/mwifiex/Makefile index 5c1a46bf1e1..3f66ebb0a63 100644 --- a/drivers/net/wireless/mwifiex/Makefile +++ b/drivers/net/wireless/mwifiex/Makefile | |||
| @@ -29,6 +29,8 @@ mwifiex-y += scan.o | |||
| 29 | mwifiex-y += join.o | 29 | mwifiex-y += join.o |
| 30 | mwifiex-y += sta_ioctl.o | 30 | mwifiex-y += sta_ioctl.o |
| 31 | mwifiex-y += sta_cmd.o | 31 | mwifiex-y += sta_cmd.o |
| 32 | mwifiex-y += uap_cmd.o | ||
| 33 | mwifiex-y += ie.o | ||
| 32 | mwifiex-y += sta_cmdresp.o | 34 | mwifiex-y += sta_cmdresp.o |
| 33 | mwifiex-y += sta_event.o | 35 | mwifiex-y += sta_event.o |
| 34 | mwifiex-y += sta_tx.o | 36 | mwifiex-y += sta_tx.o |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index c78ea873a63..87671446e24 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
| @@ -20,6 +20,23 @@ | |||
| 20 | #include "cfg80211.h" | 20 | #include "cfg80211.h" |
| 21 | #include "main.h" | 21 | #include "main.h" |
| 22 | 22 | ||
| 23 | static const struct ieee80211_iface_limit mwifiex_ap_sta_limits[] = { | ||
| 24 | { | ||
| 25 | .max = 1, .types = BIT(NL80211_IFTYPE_STATION), | ||
| 26 | }, | ||
| 27 | { | ||
| 28 | .max = 1, .types = BIT(NL80211_IFTYPE_AP), | ||
| 29 | }, | ||
| 30 | }; | ||
| 31 | |||
| 32 | static const struct ieee80211_iface_combination mwifiex_iface_comb_ap_sta = { | ||
| 33 | .limits = mwifiex_ap_sta_limits, | ||
| 34 | .num_different_channels = 1, | ||
| 35 | .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits), | ||
| 36 | .max_interfaces = MWIFIEX_MAX_BSS_NUM, | ||
| 37 | .beacon_int_infra_match = true, | ||
| 38 | }; | ||
| 39 | |||
| 23 | /* | 40 | /* |
| 24 | * This function maps the nl802.11 channel type into driver channel type. | 41 | * This function maps the nl802.11 channel type into driver channel type. |
| 25 | * | 42 | * |
| @@ -67,7 +84,7 @@ mwifiex_is_alg_wep(u32 cipher) | |||
| 67 | /* | 84 | /* |
| 68 | * This function retrieves the private structure from kernel wiphy structure. | 85 | * This function retrieves the private structure from kernel wiphy structure. |
| 69 | */ | 86 | */ |
| 70 | static void *mwifiex_cfg80211_get_priv(struct wiphy *wiphy) | 87 | static void *mwifiex_cfg80211_get_adapter(struct wiphy *wiphy) |
| 71 | { | 88 | { |
| 72 | return (void *) (*(unsigned long *) wiphy_priv(wiphy)); | 89 | return (void *) (*(unsigned long *) wiphy_priv(wiphy)); |
| 73 | } | 90 | } |
| @@ -80,8 +97,10 @@ mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev, | |||
| 80 | u8 key_index, bool pairwise, const u8 *mac_addr) | 97 | u8 key_index, bool pairwise, const u8 *mac_addr) |
| 81 | { | 98 | { |
| 82 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev); | 99 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev); |
| 100 | const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | ||
| 101 | const u8 *peer_mac = pairwise ? mac_addr : bc_mac; | ||
| 83 | 102 | ||
| 84 | if (mwifiex_set_encode(priv, NULL, 0, key_index, 1)) { | 103 | if (mwifiex_set_encode(priv, NULL, 0, key_index, peer_mac, 1)) { |
| 85 | wiphy_err(wiphy, "deleting the crypto keys\n"); | 104 | wiphy_err(wiphy, "deleting the crypto keys\n"); |
| 86 | return -EFAULT; | 105 | return -EFAULT; |
| 87 | } | 106 | } |
| @@ -98,7 +117,8 @@ mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy, | |||
| 98 | enum nl80211_tx_power_setting type, | 117 | enum nl80211_tx_power_setting type, |
| 99 | int mbm) | 118 | int mbm) |
| 100 | { | 119 | { |
| 101 | struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); | 120 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); |
| 121 | struct mwifiex_private *priv; | ||
| 102 | struct mwifiex_power_cfg power_cfg; | 122 | struct mwifiex_power_cfg power_cfg; |
| 103 | int dbm = MBM_TO_DBM(mbm); | 123 | int dbm = MBM_TO_DBM(mbm); |
| 104 | 124 | ||
| @@ -109,6 +129,8 @@ mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy, | |||
| 109 | power_cfg.is_power_auto = 1; | 129 | power_cfg.is_power_auto = 1; |
| 110 | } | 130 | } |
| 111 | 131 | ||
| 132 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); | ||
| 133 | |||
| 112 | return mwifiex_set_tx_power(priv, &power_cfg); | 134 | return mwifiex_set_tx_power(priv, &power_cfg); |
| 113 | } | 135 | } |
| 114 | 136 | ||
| @@ -148,7 +170,7 @@ mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev, | |||
| 148 | if (!priv->sec_info.wep_enabled) | 170 | if (!priv->sec_info.wep_enabled) |
| 149 | return 0; | 171 | return 0; |
| 150 | 172 | ||
| 151 | if (mwifiex_set_encode(priv, NULL, 0, key_index, 0)) { | 173 | if (mwifiex_set_encode(priv, NULL, 0, key_index, NULL, 0)) { |
| 152 | wiphy_err(wiphy, "set default Tx key index\n"); | 174 | wiphy_err(wiphy, "set default Tx key index\n"); |
| 153 | return -EFAULT; | 175 | return -EFAULT; |
| 154 | } | 176 | } |
| @@ -165,9 +187,11 @@ mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, | |||
| 165 | struct key_params *params) | 187 | struct key_params *params) |
| 166 | { | 188 | { |
| 167 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev); | 189 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev); |
| 190 | const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | ||
| 191 | const u8 *peer_mac = pairwise ? mac_addr : bc_mac; | ||
| 168 | 192 | ||
| 169 | if (mwifiex_set_encode(priv, params->key, params->key_len, | 193 | if (mwifiex_set_encode(priv, params->key, params->key_len, |
| 170 | key_index, 0)) { | 194 | key_index, peer_mac, 0)) { |
| 171 | wiphy_err(wiphy, "crypto keys added\n"); | 195 | wiphy_err(wiphy, "crypto keys added\n"); |
| 172 | return -EFAULT; | 196 | return -EFAULT; |
| 173 | } | 197 | } |
| @@ -192,13 +216,13 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) | |||
| 192 | enum ieee80211_band band; | 216 | enum ieee80211_band band; |
| 193 | struct ieee80211_supported_band *sband; | 217 | struct ieee80211_supported_band *sband; |
| 194 | struct ieee80211_channel *ch; | 218 | struct ieee80211_channel *ch; |
| 195 | struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); | 219 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); |
| 196 | struct mwifiex_adapter *adapter = priv->adapter; | 220 | struct mwifiex_private *priv; |
| 197 | struct mwifiex_802_11d_domain_reg *domain_info = &adapter->domain_reg; | 221 | struct mwifiex_802_11d_domain_reg *domain_info = &adapter->domain_reg; |
| 198 | 222 | ||
| 199 | /* Set country code */ | 223 | /* Set country code */ |
| 200 | domain_info->country_code[0] = priv->country_code[0]; | 224 | domain_info->country_code[0] = adapter->country_code[0]; |
| 201 | domain_info->country_code[1] = priv->country_code[1]; | 225 | domain_info->country_code[1] = adapter->country_code[1]; |
| 202 | domain_info->country_code[2] = ' '; | 226 | domain_info->country_code[2] = ' '; |
| 203 | 227 | ||
| 204 | band = mwifiex_band_to_radio_type(adapter->config_bands); | 228 | band = mwifiex_band_to_radio_type(adapter->config_bands); |
| @@ -250,6 +274,8 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) | |||
| 250 | 274 | ||
| 251 | domain_info->no_of_triplet = no_of_triplet; | 275 | domain_info->no_of_triplet = no_of_triplet; |
| 252 | 276 | ||
| 277 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); | ||
| 278 | |||
| 253 | if (mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, | 279 | if (mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, |
| 254 | HostCmd_ACT_GEN_SET, 0, NULL)) { | 280 | HostCmd_ACT_GEN_SET, 0, NULL)) { |
| 255 | wiphy_err(wiphy, "11D: setting domain info in FW\n"); | 281 | wiphy_err(wiphy, "11D: setting domain info in FW\n"); |
| @@ -272,12 +298,12 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) | |||
| 272 | static int mwifiex_reg_notifier(struct wiphy *wiphy, | 298 | static int mwifiex_reg_notifier(struct wiphy *wiphy, |
| 273 | struct regulatory_request *request) | 299 | struct regulatory_request *request) |
| 274 | { | 300 | { |
| 275 | struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); | 301 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); |
| 276 | 302 | ||
| 277 | wiphy_dbg(wiphy, "info: cfg80211 regulatory domain callback for domain" | 303 | wiphy_dbg(wiphy, "info: cfg80211 regulatory domain callback for %c%c\n", |
| 278 | " %c%c\n", request->alpha2[0], request->alpha2[1]); | 304 | request->alpha2[0], request->alpha2[1]); |
| 279 | 305 | ||
| 280 | memcpy(priv->country_code, request->alpha2, sizeof(request->alpha2)); | 306 | memcpy(adapter->country_code, request->alpha2, sizeof(request->alpha2)); |
| 281 | 307 | ||
| 282 | switch (request->initiator) { | 308 | switch (request->initiator) { |
| 283 | case NL80211_REGDOM_SET_BY_DRIVER: | 309 | case NL80211_REGDOM_SET_BY_DRIVER: |
| @@ -361,33 +387,10 @@ mwifiex_set_rf_channel(struct mwifiex_private *priv, | |||
| 361 | if (mwifiex_bss_set_channel(priv, &cfp)) | 387 | if (mwifiex_bss_set_channel(priv, &cfp)) |
| 362 | return -EFAULT; | 388 | return -EFAULT; |
| 363 | 389 | ||
| 364 | return mwifiex_drv_change_adhoc_chan(priv, cfp.channel); | 390 | if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) |
| 365 | } | 391 | return mwifiex_drv_change_adhoc_chan(priv, cfp.channel); |
| 366 | |||
| 367 | /* | ||
| 368 | * CFG802.11 operation handler to set channel. | ||
| 369 | * | ||
| 370 | * This function can only be used when station is not connected. | ||
| 371 | */ | ||
| 372 | static int | ||
| 373 | mwifiex_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, | ||
| 374 | struct ieee80211_channel *chan, | ||
| 375 | enum nl80211_channel_type channel_type) | ||
| 376 | { | ||
| 377 | struct mwifiex_private *priv; | ||
| 378 | |||
| 379 | if (dev) | ||
| 380 | priv = mwifiex_netdev_get_priv(dev); | ||
| 381 | else | 392 | else |
| 382 | priv = mwifiex_cfg80211_get_priv(wiphy); | 393 | return mwifiex_uap_set_channel(priv, cfp.channel); |
| 383 | |||
| 384 | if (priv->media_connected) { | ||
| 385 | wiphy_err(wiphy, "This setting is valid only when station " | ||
| 386 | "is not connected\n"); | ||
| 387 | return -EINVAL; | ||
| 388 | } | ||
| 389 | |||
| 390 | return mwifiex_set_rf_channel(priv, chan, channel_type); | ||
| 391 | } | 394 | } |
| 392 | 395 | ||
| 393 | /* | 396 | /* |
| @@ -399,18 +402,13 @@ mwifiex_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, | |||
| 399 | static int | 402 | static int |
| 400 | mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr) | 403 | mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr) |
| 401 | { | 404 | { |
| 402 | int ret; | ||
| 403 | |||
| 404 | if (frag_thr < MWIFIEX_FRAG_MIN_VALUE || | 405 | if (frag_thr < MWIFIEX_FRAG_MIN_VALUE || |
| 405 | frag_thr > MWIFIEX_FRAG_MAX_VALUE) | 406 | frag_thr > MWIFIEX_FRAG_MAX_VALUE) |
| 406 | return -EINVAL; | 407 | frag_thr = MWIFIEX_FRAG_MAX_VALUE; |
| 407 | |||
| 408 | /* Send request to firmware */ | ||
| 409 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, | ||
| 410 | HostCmd_ACT_GEN_SET, FRAG_THRESH_I, | ||
| 411 | &frag_thr); | ||
| 412 | 408 | ||
| 413 | return ret; | 409 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, |
| 410 | HostCmd_ACT_GEN_SET, FRAG_THRESH_I, | ||
| 411 | &frag_thr); | ||
| 414 | } | 412 | } |
| 415 | 413 | ||
| 416 | /* | 414 | /* |
| @@ -439,19 +437,85 @@ mwifiex_set_rts(struct mwifiex_private *priv, u32 rts_thr) | |||
| 439 | static int | 437 | static int |
| 440 | mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) | 438 | mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) |
| 441 | { | 439 | { |
| 442 | struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); | 440 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); |
| 443 | int ret = 0; | 441 | struct mwifiex_private *priv; |
| 442 | struct mwifiex_uap_bss_param *bss_cfg; | ||
| 443 | int ret, bss_started, i; | ||
| 444 | |||
| 445 | for (i = 0; i < adapter->priv_num; i++) { | ||
| 446 | priv = adapter->priv[i]; | ||
| 447 | |||
| 448 | switch (priv->bss_role) { | ||
| 449 | case MWIFIEX_BSS_ROLE_UAP: | ||
| 450 | bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), | ||
| 451 | GFP_KERNEL); | ||
| 452 | if (!bss_cfg) | ||
| 453 | return -ENOMEM; | ||
| 454 | |||
| 455 | mwifiex_set_sys_config_invalid_data(bss_cfg); | ||
| 456 | |||
| 457 | if (changed & WIPHY_PARAM_RTS_THRESHOLD) | ||
| 458 | bss_cfg->rts_threshold = wiphy->rts_threshold; | ||
| 459 | if (changed & WIPHY_PARAM_FRAG_THRESHOLD) | ||
| 460 | bss_cfg->frag_threshold = wiphy->frag_threshold; | ||
| 461 | if (changed & WIPHY_PARAM_RETRY_LONG) | ||
| 462 | bss_cfg->retry_limit = wiphy->retry_long; | ||
| 463 | |||
| 464 | bss_started = priv->bss_started; | ||
| 465 | |||
| 466 | ret = mwifiex_send_cmd_sync(priv, | ||
| 467 | HostCmd_CMD_UAP_BSS_STOP, | ||
| 468 | HostCmd_ACT_GEN_SET, 0, | ||
| 469 | NULL); | ||
| 470 | if (ret) { | ||
| 471 | wiphy_err(wiphy, "Failed to stop the BSS\n"); | ||
| 472 | kfree(bss_cfg); | ||
| 473 | return ret; | ||
| 474 | } | ||
| 444 | 475 | ||
| 445 | if (changed & WIPHY_PARAM_RTS_THRESHOLD) { | 476 | ret = mwifiex_send_cmd_async(priv, |
| 446 | ret = mwifiex_set_rts(priv, wiphy->rts_threshold); | 477 | HostCmd_CMD_UAP_SYS_CONFIG, |
| 447 | if (ret) | 478 | HostCmd_ACT_GEN_SET, |
| 448 | return ret; | 479 | UAP_BSS_PARAMS_I, bss_cfg); |
| 449 | } | ||
| 450 | 480 | ||
| 451 | if (changed & WIPHY_PARAM_FRAG_THRESHOLD) | 481 | kfree(bss_cfg); |
| 452 | ret = mwifiex_set_frag(priv, wiphy->frag_threshold); | ||
| 453 | 482 | ||
| 454 | return ret; | 483 | if (ret) { |
| 484 | wiphy_err(wiphy, "Failed to set bss config\n"); | ||
| 485 | return ret; | ||
| 486 | } | ||
| 487 | |||
| 488 | if (!bss_started) | ||
| 489 | break; | ||
| 490 | |||
| 491 | ret = mwifiex_send_cmd_async(priv, | ||
| 492 | HostCmd_CMD_UAP_BSS_START, | ||
| 493 | HostCmd_ACT_GEN_SET, 0, | ||
| 494 | NULL); | ||
| 495 | if (ret) { | ||
| 496 | wiphy_err(wiphy, "Failed to start BSS\n"); | ||
| 497 | return ret; | ||
| 498 | } | ||
| 499 | |||
| 500 | break; | ||
| 501 | case MWIFIEX_BSS_ROLE_STA: | ||
| 502 | if (changed & WIPHY_PARAM_RTS_THRESHOLD) { | ||
| 503 | ret = mwifiex_set_rts(priv, | ||
| 504 | wiphy->rts_threshold); | ||
| 505 | if (ret) | ||
| 506 | return ret; | ||
| 507 | } | ||
| 508 | if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { | ||
| 509 | ret = mwifiex_set_frag(priv, | ||
| 510 | wiphy->frag_threshold); | ||
| 511 | if (ret) | ||
| 512 | return ret; | ||
| 513 | } | ||
| 514 | break; | ||
| 515 | } | ||
| 516 | } | ||
| 517 | |||
| 518 | return 0; | ||
| 455 | } | 519 | } |
| 456 | 520 | ||
| 457 | /* | 521 | /* |
| @@ -466,31 +530,59 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, | |||
| 466 | int ret; | 530 | int ret; |
| 467 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 531 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
| 468 | 532 | ||
| 469 | if (priv->bss_mode == type) { | 533 | switch (dev->ieee80211_ptr->iftype) { |
| 470 | wiphy_warn(wiphy, "already set to required type\n"); | ||
| 471 | return 0; | ||
| 472 | } | ||
| 473 | |||
| 474 | priv->bss_mode = type; | ||
| 475 | |||
| 476 | switch (type) { | ||
| 477 | case NL80211_IFTYPE_ADHOC: | 534 | case NL80211_IFTYPE_ADHOC: |
| 478 | dev->ieee80211_ptr->iftype = NL80211_IFTYPE_ADHOC; | 535 | switch (type) { |
| 479 | wiphy_dbg(wiphy, "info: setting interface type to adhoc\n"); | 536 | case NL80211_IFTYPE_STATION: |
| 537 | break; | ||
| 538 | case NL80211_IFTYPE_UNSPECIFIED: | ||
| 539 | wiphy_warn(wiphy, "%s: kept type as IBSS\n", dev->name); | ||
| 540 | case NL80211_IFTYPE_ADHOC: /* This shouldn't happen */ | ||
| 541 | return 0; | ||
| 542 | case NL80211_IFTYPE_AP: | ||
| 543 | default: | ||
| 544 | wiphy_err(wiphy, "%s: changing to %d not supported\n", | ||
| 545 | dev->name, type); | ||
| 546 | return -EOPNOTSUPP; | ||
| 547 | } | ||
| 480 | break; | 548 | break; |
| 481 | case NL80211_IFTYPE_STATION: | 549 | case NL80211_IFTYPE_STATION: |
| 482 | dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; | 550 | switch (type) { |
| 483 | wiphy_dbg(wiphy, "info: setting interface type to managed\n"); | 551 | case NL80211_IFTYPE_ADHOC: |
| 552 | break; | ||
| 553 | case NL80211_IFTYPE_UNSPECIFIED: | ||
| 554 | wiphy_warn(wiphy, "%s: kept type as STA\n", dev->name); | ||
| 555 | case NL80211_IFTYPE_STATION: /* This shouldn't happen */ | ||
| 556 | return 0; | ||
| 557 | case NL80211_IFTYPE_AP: | ||
| 558 | default: | ||
| 559 | wiphy_err(wiphy, "%s: changing to %d not supported\n", | ||
| 560 | dev->name, type); | ||
| 561 | return -EOPNOTSUPP; | ||
| 562 | } | ||
| 563 | break; | ||
| 564 | case NL80211_IFTYPE_AP: | ||
| 565 | switch (type) { | ||
| 566 | case NL80211_IFTYPE_UNSPECIFIED: | ||
| 567 | wiphy_warn(wiphy, "%s: kept type as AP\n", dev->name); | ||
| 568 | case NL80211_IFTYPE_AP: /* This shouldn't happen */ | ||
| 569 | return 0; | ||
| 570 | case NL80211_IFTYPE_ADHOC: | ||
| 571 | case NL80211_IFTYPE_STATION: | ||
| 572 | default: | ||
| 573 | wiphy_err(wiphy, "%s: changing to %d not supported\n", | ||
| 574 | dev->name, type); | ||
| 575 | return -EOPNOTSUPP; | ||
| 576 | } | ||
| 484 | break; | 577 | break; |
| 485 | case NL80211_IFTYPE_UNSPECIFIED: | ||
| 486 | dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; | ||
| 487 | wiphy_dbg(wiphy, "info: setting interface type to auto\n"); | ||
| 488 | return 0; | ||
| 489 | default: | 578 | default: |
| 490 | wiphy_err(wiphy, "unknown interface type: %d\n", type); | 579 | wiphy_err(wiphy, "%s: unknown iftype: %d\n", |
| 491 | return -EINVAL; | 580 | dev->name, dev->ieee80211_ptr->iftype); |
| 581 | return -EOPNOTSUPP; | ||
| 492 | } | 582 | } |
| 493 | 583 | ||
| 584 | dev->ieee80211_ptr->iftype = type; | ||
| 585 | priv->bss_mode = type; | ||
| 494 | mwifiex_deauthenticate(priv, NULL); | 586 | mwifiex_deauthenticate(priv, NULL); |
| 495 | 587 | ||
| 496 | priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; | 588 | priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; |
| @@ -804,6 +896,90 @@ static int mwifiex_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy, | |||
| 804 | return 0; | 896 | return 0; |
| 805 | } | 897 | } |
| 806 | 898 | ||
| 899 | /* cfg80211 operation handler for stop ap. | ||
| 900 | * Function stops BSS running at uAP interface. | ||
| 901 | */ | ||
| 902 | static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | ||
| 903 | { | ||
| 904 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | ||
| 905 | |||
| 906 | if (mwifiex_del_mgmt_ies(priv)) | ||
| 907 | wiphy_err(wiphy, "Failed to delete mgmt IEs!\n"); | ||
| 908 | |||
| 909 | if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP, | ||
| 910 | HostCmd_ACT_GEN_SET, 0, NULL)) { | ||
| 911 | wiphy_err(wiphy, "Failed to stop the BSS\n"); | ||
| 912 | return -1; | ||
| 913 | } | ||
| 914 | |||
| 915 | return 0; | ||
| 916 | } | ||
| 917 | |||
| 918 | /* cfg80211 operation handler for start_ap. | ||
| 919 | * Function sets beacon period, DTIM period, SSID and security into | ||
| 920 | * AP config structure. | ||
| 921 | * AP is configured with these settings and BSS is started. | ||
| 922 | */ | ||
| 923 | static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | ||
| 924 | struct net_device *dev, | ||
| 925 | struct cfg80211_ap_settings *params) | ||
| 926 | { | ||
| 927 | struct mwifiex_uap_bss_param *bss_cfg; | ||
| 928 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | ||
| 929 | |||
| 930 | if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) | ||
| 931 | return -1; | ||
| 932 | if (mwifiex_set_mgmt_ies(priv, params)) | ||
| 933 | return -1; | ||
| 934 | |||
| 935 | bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL); | ||
| 936 | if (!bss_cfg) | ||
| 937 | return -ENOMEM; | ||
| 938 | |||
| 939 | mwifiex_set_sys_config_invalid_data(bss_cfg); | ||
| 940 | |||
| 941 | if (params->beacon_interval) | ||
| 942 | bss_cfg->beacon_period = params->beacon_interval; | ||
| 943 | if (params->dtim_period) | ||
| 944 | bss_cfg->dtim_period = params->dtim_period; | ||
| 945 | |||
| 946 | if (params->ssid && params->ssid_len) { | ||
| 947 | memcpy(bss_cfg->ssid.ssid, params->ssid, params->ssid_len); | ||
| 948 | bss_cfg->ssid.ssid_len = params->ssid_len; | ||
| 949 | } | ||
| 950 | |||
| 951 | if (mwifiex_set_secure_params(priv, bss_cfg, params)) { | ||
| 952 | kfree(bss_cfg); | ||
| 953 | wiphy_err(wiphy, "Failed to parse secuirty parameters!\n"); | ||
| 954 | return -1; | ||
| 955 | } | ||
| 956 | |||
| 957 | if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP, | ||
| 958 | HostCmd_ACT_GEN_SET, 0, NULL)) { | ||
| 959 | wiphy_err(wiphy, "Failed to stop the BSS\n"); | ||
| 960 | kfree(bss_cfg); | ||
| 961 | return -1; | ||
| 962 | } | ||
| 963 | |||
| 964 | if (mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_SYS_CONFIG, | ||
| 965 | HostCmd_ACT_GEN_SET, | ||
| 966 | UAP_BSS_PARAMS_I, bss_cfg)) { | ||
| 967 | wiphy_err(wiphy, "Failed to set the SSID\n"); | ||
| 968 | kfree(bss_cfg); | ||
| 969 | return -1; | ||
| 970 | } | ||
| 971 | |||
| 972 | kfree(bss_cfg); | ||
| 973 | |||
| 974 | if (mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_BSS_START, | ||
| 975 | HostCmd_ACT_GEN_SET, 0, NULL)) { | ||
| 976 | wiphy_err(wiphy, "Failed to start the BSS\n"); | ||
| 977 | return -1; | ||
| 978 | } | ||
| 979 | |||
| 980 | return 0; | ||
| 981 | } | ||
| 982 | |||
| 807 | /* | 983 | /* |
| 808 | * CFG802.11 operation handler for disconnection request. | 984 | * CFG802.11 operation handler for disconnection request. |
| 809 | * | 985 | * |
| @@ -923,7 +1099,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, | |||
| 923 | priv->wep_key_curr_index = 0; | 1099 | priv->wep_key_curr_index = 0; |
| 924 | priv->sec_info.encryption_mode = 0; | 1100 | priv->sec_info.encryption_mode = 0; |
| 925 | priv->sec_info.is_authtype_auto = 0; | 1101 | priv->sec_info.is_authtype_auto = 0; |
| 926 | ret = mwifiex_set_encode(priv, NULL, 0, 0, 1); | 1102 | ret = mwifiex_set_encode(priv, NULL, 0, 0, NULL, 1); |
| 927 | 1103 | ||
| 928 | if (mode == NL80211_IFTYPE_ADHOC) { | 1104 | if (mode == NL80211_IFTYPE_ADHOC) { |
| 929 | /* "privacy" is set only for ad-hoc mode */ | 1105 | /* "privacy" is set only for ad-hoc mode */ |
| @@ -971,7 +1147,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, | |||
| 971 | " with key len %d\n", sme->key_len); | 1147 | " with key len %d\n", sme->key_len); |
| 972 | priv->wep_key_curr_index = sme->key_idx; | 1148 | priv->wep_key_curr_index = sme->key_idx; |
| 973 | ret = mwifiex_set_encode(priv, sme->key, sme->key_len, | 1149 | ret = mwifiex_set_encode(priv, sme->key, sme->key_len, |
| 974 | sme->key_idx, 0); | 1150 | sme->key_idx, NULL, 0); |
| 975 | } | 1151 | } |
| 976 | } | 1152 | } |
| 977 | done: | 1153 | done: |
| @@ -1050,6 +1226,11 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
| 1050 | goto done; | 1226 | goto done; |
| 1051 | } | 1227 | } |
| 1052 | 1228 | ||
| 1229 | if (priv->bss_mode == NL80211_IFTYPE_AP) { | ||
| 1230 | wiphy_err(wiphy, "skip association request for AP interface\n"); | ||
| 1231 | goto done; | ||
| 1232 | } | ||
| 1233 | |||
| 1053 | wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n", | 1234 | wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n", |
| 1054 | (char *) sme->ssid, sme->bssid); | 1235 | (char *) sme->ssid, sme->bssid); |
| 1055 | 1236 | ||
| @@ -1283,15 +1464,12 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
| 1283 | u32 *flags, | 1464 | u32 *flags, |
| 1284 | struct vif_params *params) | 1465 | struct vif_params *params) |
| 1285 | { | 1466 | { |
| 1286 | struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); | 1467 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); |
| 1287 | struct mwifiex_adapter *adapter; | 1468 | struct mwifiex_private *priv; |
| 1288 | struct net_device *dev; | 1469 | struct net_device *dev; |
| 1289 | void *mdev_priv; | 1470 | void *mdev_priv; |
| 1471 | struct wireless_dev *wdev; | ||
| 1290 | 1472 | ||
| 1291 | if (!priv) | ||
| 1292 | return NULL; | ||
| 1293 | |||
| 1294 | adapter = priv->adapter; | ||
| 1295 | if (!adapter) | 1473 | if (!adapter) |
| 1296 | return NULL; | 1474 | return NULL; |
| 1297 | 1475 | ||
| @@ -1299,12 +1477,21 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
| 1299 | case NL80211_IFTYPE_UNSPECIFIED: | 1477 | case NL80211_IFTYPE_UNSPECIFIED: |
| 1300 | case NL80211_IFTYPE_STATION: | 1478 | case NL80211_IFTYPE_STATION: |
| 1301 | case NL80211_IFTYPE_ADHOC: | 1479 | case NL80211_IFTYPE_ADHOC: |
| 1480 | priv = adapter->priv[MWIFIEX_BSS_TYPE_STA]; | ||
| 1302 | if (priv->bss_mode) { | 1481 | if (priv->bss_mode) { |
| 1303 | wiphy_err(wiphy, "cannot create multiple" | 1482 | wiphy_err(wiphy, |
| 1304 | " station/adhoc interfaces\n"); | 1483 | "cannot create multiple sta/adhoc ifaces\n"); |
| 1305 | return NULL; | 1484 | return NULL; |
| 1306 | } | 1485 | } |
| 1307 | 1486 | ||
| 1487 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); | ||
| 1488 | if (!wdev) | ||
| 1489 | return NULL; | ||
| 1490 | |||
| 1491 | wdev->wiphy = wiphy; | ||
| 1492 | priv->wdev = wdev; | ||
| 1493 | wdev->iftype = NL80211_IFTYPE_STATION; | ||
| 1494 | |||
| 1308 | if (type == NL80211_IFTYPE_UNSPECIFIED) | 1495 | if (type == NL80211_IFTYPE_UNSPECIFIED) |
| 1309 | priv->bss_mode = NL80211_IFTYPE_STATION; | 1496 | priv->bss_mode = NL80211_IFTYPE_STATION; |
| 1310 | else | 1497 | else |
| @@ -1312,11 +1499,36 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
| 1312 | 1499 | ||
| 1313 | priv->bss_type = MWIFIEX_BSS_TYPE_STA; | 1500 | priv->bss_type = MWIFIEX_BSS_TYPE_STA; |
| 1314 | priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; | 1501 | priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; |
| 1315 | priv->bss_priority = 0; | 1502 | priv->bss_priority = MWIFIEX_BSS_ROLE_STA; |
| 1316 | priv->bss_role = MWIFIEX_BSS_ROLE_STA; | 1503 | priv->bss_role = MWIFIEX_BSS_ROLE_STA; |
| 1317 | priv->bss_num = 0; | 1504 | priv->bss_num = 0; |
| 1318 | 1505 | ||
| 1319 | break; | 1506 | break; |
| 1507 | case NL80211_IFTYPE_AP: | ||
| 1508 | priv = adapter->priv[MWIFIEX_BSS_TYPE_UAP]; | ||
| 1509 | |||
| 1510 | if (priv->bss_mode) { | ||
| 1511 | wiphy_err(wiphy, "Can't create multiple AP interfaces"); | ||
| 1512 | return NULL; | ||
| 1513 | } | ||
| 1514 | |||
| 1515 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); | ||
| 1516 | if (!wdev) | ||
| 1517 | return NULL; | ||
| 1518 | |||
| 1519 | priv->wdev = wdev; | ||
| 1520 | wdev->wiphy = wiphy; | ||
| 1521 | wdev->iftype = NL80211_IFTYPE_AP; | ||
| 1522 | |||
| 1523 | priv->bss_type = MWIFIEX_BSS_TYPE_UAP; | ||
| 1524 | priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; | ||
| 1525 | priv->bss_priority = MWIFIEX_BSS_ROLE_UAP; | ||
| 1526 | priv->bss_role = MWIFIEX_BSS_ROLE_UAP; | ||
| 1527 | priv->bss_started = 0; | ||
| 1528 | priv->bss_num = 0; | ||
| 1529 | priv->bss_mode = type; | ||
| 1530 | |||
| 1531 | break; | ||
| 1320 | default: | 1532 | default: |
| 1321 | wiphy_err(wiphy, "type not supported\n"); | 1533 | wiphy_err(wiphy, "type not supported\n"); |
| 1322 | return NULL; | 1534 | return NULL; |
| @@ -1329,6 +1541,15 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
| 1329 | goto error; | 1541 | goto error; |
| 1330 | } | 1542 | } |
| 1331 | 1543 | ||
| 1544 | mwifiex_init_priv_params(priv, dev); | ||
| 1545 | priv->netdev = dev; | ||
| 1546 | |||
| 1547 | mwifiex_setup_ht_caps(&wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, priv); | ||
| 1548 | |||
| 1549 | if (adapter->config_bands & BAND_A) | ||
| 1550 | mwifiex_setup_ht_caps( | ||
| 1551 | &wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, priv); | ||
| 1552 | |||
| 1332 | dev_net_set(dev, wiphy_net(wiphy)); | 1553 | dev_net_set(dev, wiphy_net(wiphy)); |
| 1333 | dev->ieee80211_ptr = priv->wdev; | 1554 | dev->ieee80211_ptr = priv->wdev; |
| 1334 | dev->ieee80211_ptr->iftype = priv->bss_mode; | 1555 | dev->ieee80211_ptr->iftype = priv->bss_mode; |
| @@ -1343,9 +1564,6 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
| 1343 | mdev_priv = netdev_priv(dev); | 1564 | mdev_priv = netdev_priv(dev); |
| 1344 | *((unsigned long *) mdev_priv) = (unsigned long) priv; | 1565 | *((unsigned long *) mdev_priv) = (unsigned long) priv; |
| 1345 | 1566 | ||
| 1346 | priv->netdev = dev; | ||
| 1347 | mwifiex_init_priv_params(priv, dev); | ||
| 1348 | |||
| 1349 | SET_NETDEV_DEV(dev, adapter->dev); | 1567 | SET_NETDEV_DEV(dev, adapter->dev); |
| 1350 | 1568 | ||
| 1351 | /* Register network device */ | 1569 | /* Register network device */ |
| @@ -1417,7 +1635,6 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { | |||
| 1417 | .get_station = mwifiex_cfg80211_get_station, | 1635 | .get_station = mwifiex_cfg80211_get_station, |
| 1418 | .dump_station = mwifiex_cfg80211_dump_station, | 1636 | .dump_station = mwifiex_cfg80211_dump_station, |
| 1419 | .set_wiphy_params = mwifiex_cfg80211_set_wiphy_params, | 1637 | .set_wiphy_params = mwifiex_cfg80211_set_wiphy_params, |
| 1420 | .set_channel = mwifiex_cfg80211_set_channel, | ||
| 1421 | .join_ibss = mwifiex_cfg80211_join_ibss, | 1638 | .join_ibss = mwifiex_cfg80211_join_ibss, |
| 1422 | .leave_ibss = mwifiex_cfg80211_leave_ibss, | 1639 | .leave_ibss = mwifiex_cfg80211_leave_ibss, |
| 1423 | .add_key = mwifiex_cfg80211_add_key, | 1640 | .add_key = mwifiex_cfg80211_add_key, |
| @@ -1426,6 +1643,8 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { | |||
| 1426 | .set_power_mgmt = mwifiex_cfg80211_set_power_mgmt, | 1643 | .set_power_mgmt = mwifiex_cfg80211_set_power_mgmt, |
| 1427 | .set_tx_power = mwifiex_cfg80211_set_tx_power, | 1644 | .set_tx_power = mwifiex_cfg80211_set_tx_power, |
| 1428 | .set_bitrate_mask = mwifiex_cfg80211_set_bitrate_mask, | 1645 | .set_bitrate_mask = mwifiex_cfg80211_set_bitrate_mask, |
| 1646 | .start_ap = mwifiex_cfg80211_start_ap, | ||
| 1647 | .stop_ap = mwifiex_cfg80211_stop_ap, | ||
| 1429 | .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config, | 1648 | .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config, |
| 1430 | }; | 1649 | }; |
| 1431 | 1650 | ||
| @@ -1436,82 +1655,67 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { | |||
| 1436 | * default parameters and handler function pointers, and finally | 1655 | * default parameters and handler function pointers, and finally |
| 1437 | * registers the device. | 1656 | * registers the device. |
| 1438 | */ | 1657 | */ |
| 1439 | int mwifiex_register_cfg80211(struct mwifiex_private *priv) | 1658 | |
| 1659 | int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) | ||
| 1440 | { | 1660 | { |
| 1441 | int ret; | 1661 | int ret; |
| 1442 | void *wdev_priv; | 1662 | void *wdev_priv; |
| 1443 | struct wireless_dev *wdev; | 1663 | struct wiphy *wiphy; |
| 1444 | struct ieee80211_sta_ht_cap *ht_info; | 1664 | struct mwifiex_private *priv = adapter->priv[MWIFIEX_BSS_TYPE_STA]; |
| 1445 | u8 *country_code; | 1665 | u8 *country_code; |
| 1446 | 1666 | ||
| 1447 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); | 1667 | /* create a new wiphy for use with cfg80211 */ |
| 1448 | if (!wdev) { | 1668 | wiphy = wiphy_new(&mwifiex_cfg80211_ops, |
| 1449 | dev_err(priv->adapter->dev, "%s: allocating wireless device\n", | 1669 | sizeof(struct mwifiex_adapter *)); |
| 1450 | __func__); | 1670 | if (!wiphy) { |
| 1451 | return -ENOMEM; | 1671 | dev_err(adapter->dev, "%s: creating new wiphy\n", __func__); |
| 1452 | } | ||
| 1453 | wdev->wiphy = | ||
| 1454 | wiphy_new(&mwifiex_cfg80211_ops, | ||
| 1455 | sizeof(struct mwifiex_private *)); | ||
| 1456 | if (!wdev->wiphy) { | ||
| 1457 | kfree(wdev); | ||
| 1458 | return -ENOMEM; | 1672 | return -ENOMEM; |
| 1459 | } | 1673 | } |
| 1460 | wdev->iftype = NL80211_IFTYPE_STATION; | 1674 | wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH; |
| 1461 | wdev->wiphy->max_scan_ssids = 10; | 1675 | wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN; |
| 1462 | wdev->wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN; | 1676 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
| 1463 | wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 1677 | BIT(NL80211_IFTYPE_ADHOC) | |
| 1464 | BIT(NL80211_IFTYPE_ADHOC); | 1678 | BIT(NL80211_IFTYPE_AP); |
| 1465 | 1679 | ||
| 1466 | wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz; | 1680 | wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz; |
| 1467 | ht_info = &wdev->wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap; | 1681 | if (adapter->config_bands & BAND_A) |
| 1468 | mwifiex_setup_ht_caps(ht_info, priv); | 1682 | wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz; |
| 1469 | 1683 | else | |
| 1470 | if (priv->adapter->config_bands & BAND_A) { | 1684 | wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; |
| 1471 | wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz; | 1685 | |
| 1472 | ht_info = &wdev->wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap; | 1686 | wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta; |
| 1473 | mwifiex_setup_ht_caps(ht_info, priv); | 1687 | wiphy->n_iface_combinations = 1; |
| 1474 | } else { | ||
| 1475 | wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; | ||
| 1476 | } | ||
| 1477 | 1688 | ||
| 1478 | /* Initialize cipher suits */ | 1689 | /* Initialize cipher suits */ |
| 1479 | wdev->wiphy->cipher_suites = mwifiex_cipher_suites; | 1690 | wiphy->cipher_suites = mwifiex_cipher_suites; |
| 1480 | wdev->wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites); | 1691 | wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites); |
| 1481 | 1692 | ||
| 1482 | memcpy(wdev->wiphy->perm_addr, priv->curr_addr, ETH_ALEN); | 1693 | memcpy(wiphy->perm_addr, priv->curr_addr, ETH_ALEN); |
| 1483 | wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 1694 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
| 1695 | wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_CUSTOM_REGULATORY; | ||
| 1484 | 1696 | ||
| 1485 | /* Reserve space for mwifiex specific private data for BSS */ | 1697 | /* Reserve space for mwifiex specific private data for BSS */ |
| 1486 | wdev->wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv); | 1698 | wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv); |
| 1487 | |||
| 1488 | wdev->wiphy->reg_notifier = mwifiex_reg_notifier; | ||
| 1489 | 1699 | ||
| 1490 | /* Set struct mwifiex_private pointer in wiphy_priv */ | 1700 | wiphy->reg_notifier = mwifiex_reg_notifier; |
| 1491 | wdev_priv = wiphy_priv(wdev->wiphy); | ||
| 1492 | 1701 | ||
| 1493 | *(unsigned long *) wdev_priv = (unsigned long) priv; | 1702 | /* Set struct mwifiex_adapter pointer in wiphy_priv */ |
| 1703 | wdev_priv = wiphy_priv(wiphy); | ||
| 1704 | *(unsigned long *)wdev_priv = (unsigned long)adapter; | ||
| 1494 | 1705 | ||
| 1495 | set_wiphy_dev(wdev->wiphy, (struct device *) priv->adapter->dev); | 1706 | set_wiphy_dev(wiphy, (struct device *)priv->adapter->dev); |
| 1496 | 1707 | ||
| 1497 | ret = wiphy_register(wdev->wiphy); | 1708 | ret = wiphy_register(wiphy); |
| 1498 | if (ret < 0) { | 1709 | if (ret < 0) { |
| 1499 | dev_err(priv->adapter->dev, "%s: registering cfg80211 device\n", | 1710 | dev_err(adapter->dev, |
| 1500 | __func__); | 1711 | "%s: wiphy_register failed: %d\n", __func__, ret); |
| 1501 | wiphy_free(wdev->wiphy); | 1712 | wiphy_free(wiphy); |
| 1502 | kfree(wdev); | ||
| 1503 | return ret; | 1713 | return ret; |
| 1504 | } else { | ||
| 1505 | dev_dbg(priv->adapter->dev, | ||
| 1506 | "info: successfully registered wiphy device\n"); | ||
| 1507 | } | 1714 | } |
| 1508 | |||
| 1509 | country_code = mwifiex_11d_code_2_region(priv->adapter->region_code); | 1715 | country_code = mwifiex_11d_code_2_region(priv->adapter->region_code); |
| 1510 | if (country_code && regulatory_hint(wdev->wiphy, country_code)) | 1716 | if (country_code && regulatory_hint(wiphy, country_code)) |
| 1511 | dev_err(priv->adapter->dev, | 1717 | dev_err(adapter->dev, "regulatory_hint() failed\n"); |
| 1512 | "%s: regulatory_hint failed\n", __func__); | ||
| 1513 | |||
| 1514 | priv->wdev = wdev; | ||
| 1515 | 1718 | ||
| 1719 | adapter->wiphy = wiphy; | ||
| 1516 | return ret; | 1720 | return ret; |
| 1517 | } | 1721 | } |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.h b/drivers/net/wireless/mwifiex/cfg80211.h index 76c76c60438..c5848934f11 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.h +++ b/drivers/net/wireless/mwifiex/cfg80211.h | |||
| @@ -24,6 +24,6 @@ | |||
| 24 | 24 | ||
| 25 | #include "main.h" | 25 | #include "main.h" |
| 26 | 26 | ||
| 27 | int mwifiex_register_cfg80211(struct mwifiex_private *); | 27 | int mwifiex_register_cfg80211(struct mwifiex_adapter *); |
| 28 | 28 | ||
| 29 | #endif | 29 | #endif |
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 1710beffb93..51e023ec1de 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c | |||
| @@ -440,6 +440,11 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter) | |||
| 440 | do_gettimeofday(&tstamp); | 440 | do_gettimeofday(&tstamp); |
| 441 | dev_dbg(adapter->dev, "event: %lu.%lu: cause: %#x\n", | 441 | dev_dbg(adapter->dev, "event: %lu.%lu: cause: %#x\n", |
| 442 | tstamp.tv_sec, tstamp.tv_usec, eventcause); | 442 | tstamp.tv_sec, tstamp.tv_usec, eventcause); |
| 443 | } else { | ||
| 444 | /* Handle PS_SLEEP/AWAKE events on STA */ | ||
| 445 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); | ||
| 446 | if (!priv) | ||
| 447 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); | ||
| 443 | } | 448 | } |
| 444 | 449 | ||
| 445 | ret = mwifiex_process_sta_event(priv); | 450 | ret = mwifiex_process_sta_event(priv); |
| @@ -540,8 +545,20 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, | |||
| 540 | 545 | ||
| 541 | /* Prepare command */ | 546 | /* Prepare command */ |
| 542 | if (cmd_no) { | 547 | if (cmd_no) { |
| 543 | ret = mwifiex_sta_prepare_cmd(priv, cmd_no, cmd_action, | 548 | switch (cmd_no) { |
| 544 | cmd_oid, data_buf, cmd_ptr); | 549 | case HostCmd_CMD_UAP_SYS_CONFIG: |
| 550 | case HostCmd_CMD_UAP_BSS_START: | ||
| 551 | case HostCmd_CMD_UAP_BSS_STOP: | ||
| 552 | ret = mwifiex_uap_prepare_cmd(priv, cmd_no, cmd_action, | ||
| 553 | cmd_oid, data_buf, | ||
| 554 | cmd_ptr); | ||
| 555 | break; | ||
| 556 | default: | ||
| 557 | ret = mwifiex_sta_prepare_cmd(priv, cmd_no, cmd_action, | ||
| 558 | cmd_oid, data_buf, | ||
| 559 | cmd_ptr); | ||
| 560 | break; | ||
| 561 | } | ||
| 545 | } else { | 562 | } else { |
| 546 | ret = mwifiex_cmd_host_cmd(priv, cmd_ptr, data_buf); | 563 | ret = mwifiex_cmd_host_cmd(priv, cmd_ptr, data_buf); |
| 547 | cmd_node->cmd_flag |= CMD_F_HOSTCMD; | 564 | cmd_node->cmd_flag |= CMD_F_HOSTCMD; |
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index d04aba4131d..f918f66e5e2 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h | |||
| @@ -28,7 +28,7 @@ | |||
| 28 | #include <linux/ieee80211.h> | 28 | #include <linux/ieee80211.h> |
| 29 | 29 | ||
| 30 | 30 | ||
| 31 | #define MWIFIEX_MAX_BSS_NUM (1) | 31 | #define MWIFIEX_MAX_BSS_NUM (2) |
| 32 | 32 | ||
| 33 | #define MWIFIEX_MIN_DATA_HEADER_LEN 36 /* sizeof(mwifiex_txpd) | 33 | #define MWIFIEX_MIN_DATA_HEADER_LEN 36 /* sizeof(mwifiex_txpd) |
| 34 | * + 4 byte alignment | 34 | * + 4 byte alignment |
| @@ -55,11 +55,17 @@ | |||
| 55 | #define MWIFIEX_RX_DATA_BUF_SIZE (4 * 1024) | 55 | #define MWIFIEX_RX_DATA_BUF_SIZE (4 * 1024) |
| 56 | #define MWIFIEX_RX_CMD_BUF_SIZE (2 * 1024) | 56 | #define MWIFIEX_RX_CMD_BUF_SIZE (2 * 1024) |
| 57 | 57 | ||
| 58 | #define MAX_BEACON_PERIOD (4000) | ||
| 59 | #define MIN_BEACON_PERIOD (50) | ||
| 60 | #define MAX_DTIM_PERIOD (100) | ||
| 61 | #define MIN_DTIM_PERIOD (1) | ||
| 62 | |||
| 58 | #define MWIFIEX_RTS_MIN_VALUE (0) | 63 | #define MWIFIEX_RTS_MIN_VALUE (0) |
| 59 | #define MWIFIEX_RTS_MAX_VALUE (2347) | 64 | #define MWIFIEX_RTS_MAX_VALUE (2347) |
| 60 | #define MWIFIEX_FRAG_MIN_VALUE (256) | 65 | #define MWIFIEX_FRAG_MIN_VALUE (256) |
| 61 | #define MWIFIEX_FRAG_MAX_VALUE (2346) | 66 | #define MWIFIEX_FRAG_MAX_VALUE (2346) |
| 62 | 67 | ||
| 68 | #define MWIFIEX_RETRY_LIMIT 14 | ||
| 63 | #define MWIFIEX_SDIO_BLOCK_SIZE 256 | 69 | #define MWIFIEX_SDIO_BLOCK_SIZE 256 |
| 64 | 70 | ||
| 65 | #define MWIFIEX_BUF_FLAG_REQUEUED_PKT BIT(0) | 71 | #define MWIFIEX_BUF_FLAG_REQUEUED_PKT BIT(0) |
| @@ -92,6 +98,11 @@ struct mwifiex_fw_image { | |||
| 92 | u32 fw_len; | 98 | u32 fw_len; |
| 93 | }; | 99 | }; |
| 94 | 100 | ||
| 101 | struct mwifiex_802_11_ssid { | ||
| 102 | u32 ssid_len; | ||
| 103 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | ||
| 104 | }; | ||
| 105 | |||
| 95 | struct mwifiex_wait_queue { | 106 | struct mwifiex_wait_queue { |
| 96 | wait_queue_head_t wait; | 107 | wait_queue_head_t wait; |
| 97 | int status; | 108 | int status; |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 5f6adeb9b95..9f674bbebe6 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
| @@ -93,6 +93,20 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
| 93 | 93 | ||
| 94 | #define CAL_SNR(RSSI, NF) ((s16)((s16)(RSSI)-(s16)(NF))) | 94 | #define CAL_SNR(RSSI, NF) ((s16)((s16)(RSSI)-(s16)(NF))) |
| 95 | 95 | ||
| 96 | #define UAP_BSS_PARAMS_I 0 | ||
| 97 | #define UAP_CUSTOM_IE_I 1 | ||
| 98 | #define MWIFIEX_AUTO_IDX_MASK 0xffff | ||
| 99 | #define MWIFIEX_DELETE_MASK 0x0000 | ||
| 100 | #define MGMT_MASK_ASSOC_REQ 0x01 | ||
| 101 | #define MGMT_MASK_REASSOC_REQ 0x04 | ||
| 102 | #define MGMT_MASK_ASSOC_RESP 0x02 | ||
| 103 | #define MGMT_MASK_REASSOC_RESP 0x08 | ||
| 104 | #define MGMT_MASK_PROBE_REQ 0x10 | ||
| 105 | #define MGMT_MASK_PROBE_RESP 0x20 | ||
| 106 | #define MGMT_MASK_BEACON 0x100 | ||
| 107 | |||
| 108 | #define TLV_TYPE_UAP_SSID 0x0000 | ||
| 109 | |||
| 96 | #define PROPRIETARY_TLV_BASE_ID 0x0100 | 110 | #define PROPRIETARY_TLV_BASE_ID 0x0100 |
| 97 | #define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0) | 111 | #define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0) |
| 98 | #define TLV_TYPE_CHANLIST (PROPRIETARY_TLV_BASE_ID + 1) | 112 | #define TLV_TYPE_CHANLIST (PROPRIETARY_TLV_BASE_ID + 1) |
| @@ -104,14 +118,26 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
| 104 | #define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19) | 118 | #define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19) |
| 105 | #define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22) | 119 | #define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22) |
| 106 | #define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31) | 120 | #define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31) |
| 121 | #define TLV_TYPE_STA_MAC_ADDR (PROPRIETARY_TLV_BASE_ID + 32) | ||
| 107 | #define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 42) | 122 | #define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 42) |
| 123 | #define TLV_TYPE_UAP_BEACON_PERIOD (PROPRIETARY_TLV_BASE_ID + 44) | ||
| 124 | #define TLV_TYPE_UAP_DTIM_PERIOD (PROPRIETARY_TLV_BASE_ID + 45) | ||
| 125 | #define TLV_TYPE_UAP_RTS_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 51) | ||
| 126 | #define TLV_TYPE_UAP_WPA_PASSPHRASE (PROPRIETARY_TLV_BASE_ID + 60) | ||
| 127 | #define TLV_TYPE_UAP_ENCRY_PROTOCOL (PROPRIETARY_TLV_BASE_ID + 64) | ||
| 128 | #define TLV_TYPE_UAP_AKMP (PROPRIETARY_TLV_BASE_ID + 65) | ||
| 129 | #define TLV_TYPE_UAP_FRAG_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 70) | ||
| 108 | #define TLV_TYPE_RATE_DROP_CONTROL (PROPRIETARY_TLV_BASE_ID + 82) | 130 | #define TLV_TYPE_RATE_DROP_CONTROL (PROPRIETARY_TLV_BASE_ID + 82) |
| 109 | #define TLV_TYPE_RATE_SCOPE (PROPRIETARY_TLV_BASE_ID + 83) | 131 | #define TLV_TYPE_RATE_SCOPE (PROPRIETARY_TLV_BASE_ID + 83) |
| 110 | #define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 84) | 132 | #define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 84) |
| 133 | #define TLV_TYPE_UAP_RETRY_LIMIT (PROPRIETARY_TLV_BASE_ID + 93) | ||
| 111 | #define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94) | 134 | #define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94) |
| 135 | #define TLV_TYPE_UAP_MGMT_FRAME (PROPRIETARY_TLV_BASE_ID + 104) | ||
| 112 | #define TLV_TYPE_MGMT_IE (PROPRIETARY_TLV_BASE_ID + 105) | 136 | #define TLV_TYPE_MGMT_IE (PROPRIETARY_TLV_BASE_ID + 105) |
| 113 | #define TLV_TYPE_AUTO_DS_PARAM (PROPRIETARY_TLV_BASE_ID + 113) | 137 | #define TLV_TYPE_AUTO_DS_PARAM (PROPRIETARY_TLV_BASE_ID + 113) |
| 114 | #define TLV_TYPE_PS_PARAM (PROPRIETARY_TLV_BASE_ID + 114) | 138 | #define TLV_TYPE_PS_PARAM (PROPRIETARY_TLV_BASE_ID + 114) |
| 139 | #define TLV_TYPE_PWK_CIPHER (PROPRIETARY_TLV_BASE_ID + 145) | ||
| 140 | #define TLV_TYPE_GWK_CIPHER (PROPRIETARY_TLV_BASE_ID + 146) | ||
| 115 | 141 | ||
| 116 | #define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048 | 142 | #define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048 |
| 117 | 143 | ||
| @@ -209,6 +235,9 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
| 209 | #define HostCmd_CMD_RSSI_INFO 0x00a4 | 235 | #define HostCmd_CMD_RSSI_INFO 0x00a4 |
| 210 | #define HostCmd_CMD_FUNC_INIT 0x00a9 | 236 | #define HostCmd_CMD_FUNC_INIT 0x00a9 |
| 211 | #define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa | 237 | #define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa |
| 238 | #define HostCmd_CMD_UAP_SYS_CONFIG 0x00b0 | ||
| 239 | #define HostCmd_CMD_UAP_BSS_START 0x00b1 | ||
| 240 | #define HostCmd_CMD_UAP_BSS_STOP 0x00b2 | ||
| 212 | #define HostCmd_CMD_11N_CFG 0x00cd | 241 | #define HostCmd_CMD_11N_CFG 0x00cd |
| 213 | #define HostCmd_CMD_11N_ADDBA_REQ 0x00ce | 242 | #define HostCmd_CMD_11N_ADDBA_REQ 0x00ce |
| 214 | #define HostCmd_CMD_11N_ADDBA_RSP 0x00cf | 243 | #define HostCmd_CMD_11N_ADDBA_RSP 0x00cf |
| @@ -223,6 +252,19 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
| 223 | #define HostCmd_CMD_SET_BSS_MODE 0x00f7 | 252 | #define HostCmd_CMD_SET_BSS_MODE 0x00f7 |
| 224 | #define HostCmd_CMD_PCIE_DESC_DETAILS 0x00fa | 253 | #define HostCmd_CMD_PCIE_DESC_DETAILS 0x00fa |
| 225 | 254 | ||
| 255 | #define PROTOCOL_NO_SECURITY 0x01 | ||
| 256 | #define PROTOCOL_STATIC_WEP 0x02 | ||
| 257 | #define PROTOCOL_WPA 0x08 | ||
| 258 | #define PROTOCOL_WPA2 0x20 | ||
| 259 | #define PROTOCOL_WPA2_MIXED 0x28 | ||
| 260 | #define PROTOCOL_EAP 0x40 | ||
| 261 | #define KEY_MGMT_NONE 0x04 | ||
| 262 | #define KEY_MGMT_PSK 0x02 | ||
| 263 | #define KEY_MGMT_EAP 0x01 | ||
| 264 | #define CIPHER_TKIP 0x04 | ||
| 265 | #define CIPHER_AES_CCMP 0x08 | ||
| 266 | #define VALID_CIPHER_BITMAP 0x0c | ||
| 267 | |||
| 226 | enum ENH_PS_MODES { | 268 | enum ENH_PS_MODES { |
| 227 | EN_PS = 1, | 269 | EN_PS = 1, |
| 228 | DIS_PS = 2, | 270 | DIS_PS = 2, |
| @@ -313,15 +355,20 @@ enum ENH_PS_MODES { | |||
| 313 | #define EVENT_DATA_SNR_HIGH 0x00000027 | 355 | #define EVENT_DATA_SNR_HIGH 0x00000027 |
| 314 | #define EVENT_LINK_QUALITY 0x00000028 | 356 | #define EVENT_LINK_QUALITY 0x00000028 |
| 315 | #define EVENT_PORT_RELEASE 0x0000002b | 357 | #define EVENT_PORT_RELEASE 0x0000002b |
| 358 | #define EVENT_UAP_STA_DEAUTH 0x0000002c | ||
| 359 | #define EVENT_UAP_STA_ASSOC 0x0000002d | ||
| 360 | #define EVENT_UAP_BSS_START 0x0000002e | ||
| 316 | #define EVENT_PRE_BEACON_LOST 0x00000031 | 361 | #define EVENT_PRE_BEACON_LOST 0x00000031 |
| 317 | #define EVENT_ADDBA 0x00000033 | 362 | #define EVENT_ADDBA 0x00000033 |
| 318 | #define EVENT_DELBA 0x00000034 | 363 | #define EVENT_DELBA 0x00000034 |
| 319 | #define EVENT_BA_STREAM_TIEMOUT 0x00000037 | 364 | #define EVENT_BA_STREAM_TIEMOUT 0x00000037 |
| 320 | #define EVENT_AMSDU_AGGR_CTRL 0x00000042 | 365 | #define EVENT_AMSDU_AGGR_CTRL 0x00000042 |
| 366 | #define EVENT_UAP_BSS_IDLE 0x00000043 | ||
| 367 | #define EVENT_UAP_BSS_ACTIVE 0x00000044 | ||
| 321 | #define EVENT_WEP_ICV_ERR 0x00000046 | 368 | #define EVENT_WEP_ICV_ERR 0x00000046 |
| 322 | #define EVENT_HS_ACT_REQ 0x00000047 | 369 | #define EVENT_HS_ACT_REQ 0x00000047 |
| 323 | #define EVENT_BW_CHANGE 0x00000048 | 370 | #define EVENT_BW_CHANGE 0x00000048 |
| 324 | 371 | #define EVENT_UAP_MIC_COUNTERMEASURES 0x0000004c | |
| 325 | #define EVENT_HOSTWAKE_STAIE 0x0000004d | 372 | #define EVENT_HOSTWAKE_STAIE 0x0000004d |
| 326 | 373 | ||
| 327 | #define EVENT_ID_MASK 0xffff | 374 | #define EVENT_ID_MASK 0xffff |
| @@ -1103,6 +1150,101 @@ struct host_cmd_ds_802_11_eeprom_access { | |||
| 1103 | u8 value; | 1150 | u8 value; |
| 1104 | } __packed; | 1151 | } __packed; |
| 1105 | 1152 | ||
| 1153 | struct host_cmd_tlv { | ||
| 1154 | __le16 type; | ||
| 1155 | __le16 len; | ||
| 1156 | } __packed; | ||
| 1157 | |||
| 1158 | struct mwifiex_assoc_event { | ||
| 1159 | u8 sta_addr[ETH_ALEN]; | ||
| 1160 | __le16 type; | ||
| 1161 | __le16 len; | ||
| 1162 | __le16 frame_control; | ||
| 1163 | __le16 cap_info; | ||
| 1164 | __le16 listen_interval; | ||
| 1165 | u8 data[0]; | ||
| 1166 | } __packed; | ||
| 1167 | |||
| 1168 | struct host_cmd_ds_sys_config { | ||
| 1169 | __le16 action; | ||
| 1170 | u8 tlv[0]; | ||
| 1171 | }; | ||
| 1172 | |||
| 1173 | struct host_cmd_tlv_akmp { | ||
| 1174 | struct host_cmd_tlv tlv; | ||
| 1175 | __le16 key_mgmt; | ||
| 1176 | __le16 key_mgmt_operation; | ||
| 1177 | } __packed; | ||
| 1178 | |||
| 1179 | struct host_cmd_tlv_pwk_cipher { | ||
| 1180 | struct host_cmd_tlv tlv; | ||
| 1181 | __le16 proto; | ||
| 1182 | u8 cipher; | ||
| 1183 | u8 reserved; | ||
| 1184 | } __packed; | ||
| 1185 | |||
| 1186 | struct host_cmd_tlv_gwk_cipher { | ||
| 1187 | struct host_cmd_tlv tlv; | ||
| 1188 | u8 cipher; | ||
| 1189 | u8 reserved; | ||
| 1190 | } __packed; | ||
| 1191 | |||
| 1192 | struct host_cmd_tlv_passphrase { | ||
| 1193 | struct host_cmd_tlv tlv; | ||
| 1194 | u8 passphrase[0]; | ||
| 1195 | } __packed; | ||
| 1196 | |||
| 1197 | struct host_cmd_tlv_auth_type { | ||
| 1198 | struct host_cmd_tlv tlv; | ||
| 1199 | u8 auth_type; | ||
| 1200 | } __packed; | ||
| 1201 | |||
| 1202 | struct host_cmd_tlv_encrypt_protocol { | ||
| 1203 | struct host_cmd_tlv tlv; | ||
| 1204 | __le16 proto; | ||
| 1205 | } __packed; | ||
| 1206 | |||
| 1207 | struct host_cmd_tlv_ssid { | ||
| 1208 | struct host_cmd_tlv tlv; | ||
| 1209 | u8 ssid[0]; | ||
| 1210 | } __packed; | ||
| 1211 | |||
| 1212 | struct host_cmd_tlv_beacon_period { | ||
| 1213 | struct host_cmd_tlv tlv; | ||
| 1214 | __le16 period; | ||
| 1215 | } __packed; | ||
| 1216 | |||
| 1217 | struct host_cmd_tlv_dtim_period { | ||
| 1218 | struct host_cmd_tlv tlv; | ||
| 1219 | u8 period; | ||
| 1220 | } __packed; | ||
| 1221 | |||
| 1222 | struct host_cmd_tlv_frag_threshold { | ||
| 1223 | struct host_cmd_tlv tlv; | ||
| 1224 | __le16 frag_thr; | ||
| 1225 | } __packed; | ||
| 1226 | |||
| 1227 | struct host_cmd_tlv_rts_threshold { | ||
| 1228 | struct host_cmd_tlv tlv; | ||
| 1229 | __le16 rts_thr; | ||
| 1230 | } __packed; | ||
| 1231 | |||
| 1232 | struct host_cmd_tlv_retry_limit { | ||
| 1233 | struct host_cmd_tlv tlv; | ||
| 1234 | u8 limit; | ||
| 1235 | } __packed; | ||
| 1236 | |||
| 1237 | struct host_cmd_tlv_mac_addr { | ||
| 1238 | struct host_cmd_tlv tlv; | ||
| 1239 | u8 mac_addr[ETH_ALEN]; | ||
| 1240 | } __packed; | ||
| 1241 | |||
| 1242 | struct host_cmd_tlv_channel_band { | ||
| 1243 | struct host_cmd_tlv tlv; | ||
| 1244 | u8 band_config; | ||
| 1245 | u8 channel; | ||
| 1246 | } __packed; | ||
| 1247 | |||
| 1106 | struct host_cmd_ds_802_11_rf_channel { | 1248 | struct host_cmd_ds_802_11_rf_channel { |
| 1107 | __le16 action; | 1249 | __le16 action; |
| 1108 | __le16 current_channel; | 1250 | __le16 current_channel; |
| @@ -1167,6 +1309,20 @@ struct host_cmd_ds_802_11_subsc_evt { | |||
| 1167 | __le16 events; | 1309 | __le16 events; |
| 1168 | } __packed; | 1310 | } __packed; |
| 1169 | 1311 | ||
| 1312 | struct mwifiex_ie { | ||
| 1313 | __le16 ie_index; | ||
| 1314 | __le16 mgmt_subtype_mask; | ||
| 1315 | __le16 ie_length; | ||
| 1316 | u8 ie_buffer[IEEE_MAX_IE_SIZE]; | ||
| 1317 | } __packed; | ||
| 1318 | |||
| 1319 | #define MAX_MGMT_IE_INDEX 16 | ||
| 1320 | struct mwifiex_ie_list { | ||
| 1321 | __le16 type; | ||
| 1322 | __le16 len; | ||
| 1323 | struct mwifiex_ie ie_list[MAX_MGMT_IE_INDEX]; | ||
| 1324 | } __packed; | ||
| 1325 | |||
| 1170 | struct host_cmd_ds_command { | 1326 | struct host_cmd_ds_command { |
| 1171 | __le16 command; | 1327 | __le16 command; |
| 1172 | __le16 size; | 1328 | __le16 size; |
| @@ -1217,6 +1373,7 @@ struct host_cmd_ds_command { | |||
| 1217 | struct host_cmd_ds_pcie_details pcie_host_spec; | 1373 | struct host_cmd_ds_pcie_details pcie_host_spec; |
| 1218 | struct host_cmd_ds_802_11_eeprom_access eeprom; | 1374 | struct host_cmd_ds_802_11_eeprom_access eeprom; |
| 1219 | struct host_cmd_ds_802_11_subsc_evt subsc_evt; | 1375 | struct host_cmd_ds_802_11_subsc_evt subsc_evt; |
| 1376 | struct host_cmd_ds_sys_config uap_sys_config; | ||
| 1220 | } params; | 1377 | } params; |
| 1221 | } __packed; | 1378 | } __packed; |
| 1222 | 1379 | ||
diff --git a/drivers/net/wireless/mwifiex/ie.c b/drivers/net/wireless/mwifiex/ie.c new file mode 100644 index 00000000000..ceb82cd749c --- /dev/null +++ b/drivers/net/wireless/mwifiex/ie.c | |||
| @@ -0,0 +1,396 @@ | |||
| 1 | /* | ||
| 2 | * Marvell Wireless LAN device driver: management IE handling- setting and | ||
| 3 | * deleting IE. | ||
| 4 | * | ||
| 5 | * Copyright (C) 2012, Marvell International Ltd. | ||
| 6 | * | ||
| 7 | * This software file (the "File") is distributed by Marvell International | ||
| 8 | * Ltd. under the terms of the GNU General Public License Version 2, June 1991 | ||
| 9 | * (the "License"). You may use, redistribute and/or modify this File in | ||
| 10 | * accordance with the terms and conditions of the License, a copy of which | ||
| 11 | * is available by writing to the Free Software Foundation, Inc., | ||
| 12 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the | ||
| 13 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. | ||
| 14 | * | ||
| 15 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE | ||
| 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE | ||
| 17 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about | ||
| 18 | * this warranty disclaimer. | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include "main.h" | ||
| 22 | |||
| 23 | /* This function checks if current IE index is used by any on other interface. | ||
| 24 | * Return: -1: yes, current IE index is used by someone else. | ||
| 25 | * 0: no, current IE index is NOT used by other interface. | ||
| 26 | */ | ||
| 27 | static int | ||
| 28 | mwifiex_ie_index_used_by_other_intf(struct mwifiex_private *priv, u16 idx) | ||
| 29 | { | ||
| 30 | int i; | ||
| 31 | struct mwifiex_adapter *adapter = priv->adapter; | ||
| 32 | struct mwifiex_ie *ie; | ||
| 33 | |||
| 34 | for (i = 0; i < adapter->priv_num; i++) { | ||
| 35 | if (adapter->priv[i] != priv) { | ||
| 36 | ie = &adapter->priv[i]->mgmt_ie[idx]; | ||
| 37 | if (ie->mgmt_subtype_mask && ie->ie_length) | ||
| 38 | return -1; | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | return 0; | ||
| 43 | } | ||
| 44 | |||
| 45 | /* Get unused IE index. This index will be used for setting new IE */ | ||
| 46 | static int | ||
| 47 | mwifiex_ie_get_autoidx(struct mwifiex_private *priv, u16 subtype_mask, | ||
| 48 | struct mwifiex_ie *ie, u16 *index) | ||
| 49 | { | ||
| 50 | u16 mask, len, i; | ||
| 51 | |||
| 52 | for (i = 0; i < priv->adapter->max_mgmt_ie_index; i++) { | ||
| 53 | mask = le16_to_cpu(priv->mgmt_ie[i].mgmt_subtype_mask); | ||
| 54 | len = le16_to_cpu(priv->mgmt_ie[i].ie_length) + | ||
| 55 | le16_to_cpu(ie->ie_length); | ||
| 56 | |||
| 57 | if (mask == MWIFIEX_AUTO_IDX_MASK) | ||
| 58 | continue; | ||
| 59 | |||
| 60 | if (mask == subtype_mask) { | ||
| 61 | if (len > IEEE_MAX_IE_SIZE) | ||
| 62 | continue; | ||
| 63 | |||
| 64 | *index = i; | ||
| 65 | return 0; | ||
| 66 | } | ||
| 67 | |||
| 68 | if (!priv->mgmt_ie[i].ie_length) { | ||
| 69 | if (mwifiex_ie_index_used_by_other_intf(priv, i)) | ||
| 70 | continue; | ||
| 71 | |||
| 72 | *index = i; | ||
| 73 | return 0; | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | return -1; | ||
| 78 | } | ||
| 79 | |||
| 80 | /* This function prepares IE data buffer for command to be sent to FW */ | ||
| 81 | static int | ||
| 82 | mwifiex_update_autoindex_ies(struct mwifiex_private *priv, | ||
| 83 | struct mwifiex_ie_list *ie_list) | ||
| 84 | { | ||
| 85 | u16 travel_len, index, mask; | ||
| 86 | s16 input_len; | ||
| 87 | struct mwifiex_ie *ie; | ||
| 88 | u8 *tmp; | ||
| 89 | |||
| 90 | input_len = le16_to_cpu(ie_list->len); | ||
| 91 | travel_len = sizeof(struct host_cmd_tlv); | ||
| 92 | |||
| 93 | ie_list->len = 0; | ||
| 94 | |||
| 95 | while (input_len > 0) { | ||
| 96 | ie = (struct mwifiex_ie *)(((u8 *)ie_list) + travel_len); | ||
| 97 | input_len -= le16_to_cpu(ie->ie_length) + MWIFIEX_IE_HDR_SIZE; | ||
| 98 | travel_len += le16_to_cpu(ie->ie_length) + MWIFIEX_IE_HDR_SIZE; | ||
| 99 | |||
| 100 | index = le16_to_cpu(ie->ie_index); | ||
| 101 | mask = le16_to_cpu(ie->mgmt_subtype_mask); | ||
| 102 | |||
| 103 | if (index == MWIFIEX_AUTO_IDX_MASK) { | ||
| 104 | /* automatic addition */ | ||
| 105 | if (mwifiex_ie_get_autoidx(priv, mask, ie, &index)) | ||
| 106 | return -1; | ||
| 107 | if (index == MWIFIEX_AUTO_IDX_MASK) | ||
| 108 | return -1; | ||
| 109 | |||
| 110 | tmp = (u8 *)&priv->mgmt_ie[index].ie_buffer; | ||
| 111 | tmp += le16_to_cpu(priv->mgmt_ie[index].ie_length); | ||
| 112 | memcpy(tmp, &ie->ie_buffer, le16_to_cpu(ie->ie_length)); | ||
| 113 | le16_add_cpu(&priv->mgmt_ie[index].ie_length, | ||
| 114 | le16_to_cpu(ie->ie_length)); | ||
| 115 | priv->mgmt_ie[index].ie_index = cpu_to_le16(index); | ||
| 116 | priv->mgmt_ie[index].mgmt_subtype_mask = | ||
| 117 | cpu_to_le16(mask); | ||
| 118 | |||
| 119 | ie->ie_index = cpu_to_le16(index); | ||
| 120 | ie->ie_length = priv->mgmt_ie[index].ie_length; | ||
| 121 | memcpy(&ie->ie_buffer, &priv->mgmt_ie[index].ie_buffer, | ||
| 122 | le16_to_cpu(priv->mgmt_ie[index].ie_length)); | ||
| 123 | } else { | ||
| 124 | if (mask != MWIFIEX_DELETE_MASK) | ||
| 125 | return -1; | ||
| 126 | /* | ||
| 127 | * Check if this index is being used on any | ||
| 128 | * other interface. | ||
| 129 | */ | ||
| 130 | if (mwifiex_ie_index_used_by_other_intf(priv, index)) | ||
| 131 | return -1; | ||
| 132 | |||
| 133 | ie->ie_length = 0; | ||
| 134 | memcpy(&priv->mgmt_ie[index], ie, | ||
| 135 | sizeof(struct mwifiex_ie)); | ||
| 136 | } | ||
| 137 | |||
| 138 | le16_add_cpu(&ie_list->len, | ||
| 139 | le16_to_cpu(priv->mgmt_ie[index].ie_length) + | ||
| 140 | MWIFIEX_IE_HDR_SIZE); | ||
| 141 | } | ||
| 142 | |||
| 143 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) | ||
| 144 | return mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_SYS_CONFIG, | ||
| 145 | HostCmd_ACT_GEN_SET, | ||
| 146 | UAP_CUSTOM_IE_I, ie_list); | ||
| 147 | |||
| 148 | return 0; | ||
| 149 | } | ||
| 150 | |||
| 151 | /* Copy individual custom IEs for beacon, probe response and assoc response | ||
| 152 | * and prepare single structure for IE setting. | ||
| 153 | * This function also updates allocated IE indices from driver. | ||
| 154 | */ | ||
| 155 | static int | ||
| 156 | mwifiex_update_uap_custom_ie(struct mwifiex_private *priv, | ||
| 157 | struct mwifiex_ie *beacon_ie, u16 *beacon_idx, | ||
| 158 | struct mwifiex_ie *pr_ie, u16 *probe_idx, | ||
| 159 | struct mwifiex_ie *ar_ie, u16 *assoc_idx) | ||
| 160 | { | ||
| 161 | struct mwifiex_ie_list *ap_custom_ie; | ||
| 162 | u8 *pos; | ||
| 163 | u16 len; | ||
| 164 | int ret; | ||
| 165 | |||
| 166 | ap_custom_ie = kzalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | ||
| 167 | if (!ap_custom_ie) | ||
| 168 | return -ENOMEM; | ||
| 169 | |||
| 170 | ap_custom_ie->type = cpu_to_le16(TLV_TYPE_MGMT_IE); | ||
| 171 | pos = (u8 *)ap_custom_ie->ie_list; | ||
| 172 | |||
| 173 | if (beacon_ie) { | ||
| 174 | len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE + | ||
| 175 | le16_to_cpu(beacon_ie->ie_length); | ||
| 176 | memcpy(pos, beacon_ie, len); | ||
| 177 | pos += len; | ||
| 178 | le16_add_cpu(&ap_custom_ie->len, len); | ||
| 179 | } | ||
| 180 | if (pr_ie) { | ||
| 181 | len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE + | ||
| 182 | le16_to_cpu(pr_ie->ie_length); | ||
| 183 | memcpy(pos, pr_ie, len); | ||
| 184 | pos += len; | ||
| 185 | le16_add_cpu(&ap_custom_ie->len, len); | ||
| 186 | } | ||
| 187 | if (ar_ie) { | ||
| 188 | len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE + | ||
| 189 | le16_to_cpu(ar_ie->ie_length); | ||
| 190 | memcpy(pos, ar_ie, len); | ||
| 191 | pos += len; | ||
| 192 | le16_add_cpu(&ap_custom_ie->len, len); | ||
| 193 | } | ||
| 194 | |||
| 195 | ret = mwifiex_update_autoindex_ies(priv, ap_custom_ie); | ||
| 196 | |||
| 197 | pos = (u8 *)(&ap_custom_ie->ie_list[0].ie_index); | ||
| 198 | if (beacon_ie && *beacon_idx == MWIFIEX_AUTO_IDX_MASK) { | ||
| 199 | /* save beacon ie index after auto-indexing */ | ||
| 200 | *beacon_idx = le16_to_cpu(ap_custom_ie->ie_list[0].ie_index); | ||
| 201 | len = sizeof(*beacon_ie) - IEEE_MAX_IE_SIZE + | ||
| 202 | le16_to_cpu(beacon_ie->ie_length); | ||
| 203 | pos += len; | ||
| 204 | } | ||
| 205 | if (pr_ie && le16_to_cpu(pr_ie->ie_index) == MWIFIEX_AUTO_IDX_MASK) { | ||
| 206 | /* save probe resp ie index after auto-indexing */ | ||
| 207 | *probe_idx = *((u16 *)pos); | ||
| 208 | len = sizeof(*pr_ie) - IEEE_MAX_IE_SIZE + | ||
| 209 | le16_to_cpu(pr_ie->ie_length); | ||
| 210 | pos += len; | ||
| 211 | } | ||
| 212 | if (ar_ie && le16_to_cpu(ar_ie->ie_index) == MWIFIEX_AUTO_IDX_MASK) | ||
| 213 | /* save assoc resp ie index after auto-indexing */ | ||
| 214 | *assoc_idx = *((u16 *)pos); | ||
| 215 | |||
| 216 | return ret; | ||
| 217 | } | ||
| 218 | |||
| 219 | /* This function parses different IEs- Tail IEs, beacon IEs, probe response IEs, | ||
| 220 | * association response IEs from cfg80211_ap_settings function and sets these IE | ||
| 221 | * to FW. | ||
| 222 | */ | ||
| 223 | int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, | ||
| 224 | struct cfg80211_ap_settings *params) | ||
| 225 | { | ||
| 226 | struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL; | ||
| 227 | struct mwifiex_ie *ar_ie = NULL, *rsn_ie = NULL; | ||
| 228 | struct ieee_types_header *ie = NULL; | ||
| 229 | u16 beacon_idx = MWIFIEX_AUTO_IDX_MASK, pr_idx = MWIFIEX_AUTO_IDX_MASK; | ||
| 230 | u16 ar_idx = MWIFIEX_AUTO_IDX_MASK, rsn_idx = MWIFIEX_AUTO_IDX_MASK; | ||
| 231 | u16 mask; | ||
| 232 | int ret = 0; | ||
| 233 | |||
| 234 | if (params->beacon.tail && params->beacon.tail_len) { | ||
| 235 | ie = (void *)cfg80211_find_ie(WLAN_EID_RSN, params->beacon.tail, | ||
| 236 | params->beacon.tail_len); | ||
| 237 | if (ie) { | ||
| 238 | rsn_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | ||
| 239 | if (!rsn_ie) | ||
| 240 | return -ENOMEM; | ||
| 241 | |||
| 242 | rsn_ie->ie_index = cpu_to_le16(rsn_idx); | ||
| 243 | mask = MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP | | ||
| 244 | MGMT_MASK_ASSOC_RESP; | ||
| 245 | rsn_ie->mgmt_subtype_mask = cpu_to_le16(mask); | ||
| 246 | rsn_ie->ie_length = cpu_to_le16(ie->len + 2); | ||
| 247 | memcpy(rsn_ie->ie_buffer, ie, ie->len + 2); | ||
| 248 | |||
| 249 | if (mwifiex_update_uap_custom_ie(priv, rsn_ie, &rsn_idx, | ||
| 250 | NULL, NULL, | ||
| 251 | NULL, NULL)) { | ||
| 252 | ret = -1; | ||
| 253 | goto done; | ||
| 254 | } | ||
| 255 | |||
| 256 | priv->rsn_idx = rsn_idx; | ||
| 257 | } | ||
| 258 | } | ||
| 259 | |||
| 260 | if (params->beacon.beacon_ies && params->beacon.beacon_ies_len) { | ||
| 261 | beacon_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | ||
| 262 | if (!beacon_ie) { | ||
| 263 | ret = -ENOMEM; | ||
| 264 | goto done; | ||
| 265 | } | ||
| 266 | |||
| 267 | beacon_ie->ie_index = cpu_to_le16(beacon_idx); | ||
| 268 | beacon_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON); | ||
| 269 | beacon_ie->ie_length = | ||
| 270 | cpu_to_le16(params->beacon.beacon_ies_len); | ||
| 271 | memcpy(beacon_ie->ie_buffer, params->beacon.beacon_ies, | ||
| 272 | params->beacon.beacon_ies_len); | ||
| 273 | } | ||
| 274 | |||
| 275 | if (params->beacon.proberesp_ies && params->beacon.proberesp_ies_len) { | ||
| 276 | pr_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | ||
| 277 | if (!pr_ie) { | ||
| 278 | ret = -ENOMEM; | ||
| 279 | goto done; | ||
| 280 | } | ||
| 281 | |||
| 282 | pr_ie->ie_index = cpu_to_le16(pr_idx); | ||
| 283 | pr_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_PROBE_RESP); | ||
| 284 | pr_ie->ie_length = | ||
| 285 | cpu_to_le16(params->beacon.proberesp_ies_len); | ||
| 286 | memcpy(pr_ie->ie_buffer, params->beacon.proberesp_ies, | ||
| 287 | params->beacon.proberesp_ies_len); | ||
| 288 | } | ||
| 289 | |||
| 290 | if (params->beacon.assocresp_ies && params->beacon.assocresp_ies_len) { | ||
| 291 | ar_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | ||
| 292 | if (!ar_ie) { | ||
| 293 | ret = -ENOMEM; | ||
| 294 | goto done; | ||
| 295 | } | ||
| 296 | |||
| 297 | ar_ie->ie_index = cpu_to_le16(ar_idx); | ||
| 298 | mask = MGMT_MASK_ASSOC_RESP | MGMT_MASK_REASSOC_RESP; | ||
| 299 | ar_ie->mgmt_subtype_mask = cpu_to_le16(mask); | ||
| 300 | ar_ie->ie_length = | ||
| 301 | cpu_to_le16(params->beacon.assocresp_ies_len); | ||
| 302 | memcpy(ar_ie->ie_buffer, params->beacon.assocresp_ies, | ||
| 303 | params->beacon.assocresp_ies_len); | ||
| 304 | } | ||
| 305 | |||
| 306 | if (beacon_ie || pr_ie || ar_ie) { | ||
| 307 | ret = mwifiex_update_uap_custom_ie(priv, beacon_ie, | ||
| 308 | &beacon_idx, pr_ie, | ||
| 309 | &pr_idx, ar_ie, &ar_idx); | ||
| 310 | if (ret) | ||
| 311 | goto done; | ||
| 312 | } | ||
| 313 | |||
| 314 | priv->beacon_idx = beacon_idx; | ||
| 315 | priv->proberesp_idx = pr_idx; | ||
| 316 | priv->assocresp_idx = ar_idx; | ||
| 317 | |||
| 318 | done: | ||
| 319 | kfree(beacon_ie); | ||
| 320 | kfree(pr_ie); | ||
| 321 | kfree(ar_ie); | ||
| 322 | kfree(rsn_ie); | ||
| 323 | |||
| 324 | return ret; | ||
| 325 | } | ||
| 326 | |||
| 327 | /* This function removes management IE set */ | ||
| 328 | int mwifiex_del_mgmt_ies(struct mwifiex_private *priv) | ||
| 329 | { | ||
| 330 | struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL; | ||
| 331 | struct mwifiex_ie *ar_ie = NULL, *rsn_ie = NULL; | ||
| 332 | int ret = 0; | ||
| 333 | |||
| 334 | if (priv->rsn_idx != MWIFIEX_AUTO_IDX_MASK) { | ||
| 335 | rsn_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | ||
| 336 | if (!rsn_ie) | ||
| 337 | return -ENOMEM; | ||
| 338 | |||
| 339 | rsn_ie->ie_index = cpu_to_le16(priv->rsn_idx); | ||
| 340 | rsn_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK); | ||
| 341 | rsn_ie->ie_length = 0; | ||
| 342 | if (mwifiex_update_uap_custom_ie(priv, rsn_ie, &priv->rsn_idx, | ||
| 343 | NULL, &priv->proberesp_idx, | ||
| 344 | NULL, &priv->assocresp_idx)) { | ||
| 345 | ret = -1; | ||
| 346 | goto done; | ||
| 347 | } | ||
| 348 | |||
| 349 | priv->rsn_idx = MWIFIEX_AUTO_IDX_MASK; | ||
| 350 | } | ||
| 351 | |||
| 352 | if (priv->beacon_idx != MWIFIEX_AUTO_IDX_MASK) { | ||
| 353 | beacon_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | ||
| 354 | if (!beacon_ie) { | ||
| 355 | ret = -ENOMEM; | ||
| 356 | goto done; | ||
| 357 | } | ||
| 358 | beacon_ie->ie_index = cpu_to_le16(priv->beacon_idx); | ||
| 359 | beacon_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK); | ||
| 360 | beacon_ie->ie_length = 0; | ||
| 361 | } | ||
| 362 | if (priv->proberesp_idx != MWIFIEX_AUTO_IDX_MASK) { | ||
| 363 | pr_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | ||
| 364 | if (!pr_ie) { | ||
| 365 | ret = -ENOMEM; | ||
| 366 | goto done; | ||
| 367 | } | ||
| 368 | pr_ie->ie_index = cpu_to_le16(priv->proberesp_idx); | ||
| 369 | pr_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK); | ||
| 370 | pr_ie->ie_length = 0; | ||
| 371 | } | ||
| 372 | if (priv->assocresp_idx != MWIFIEX_AUTO_IDX_MASK) { | ||
| 373 | ar_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | ||
| 374 | if (!ar_ie) { | ||
| 375 | ret = -ENOMEM; | ||
| 376 | goto done; | ||
| 377 | } | ||
| 378 | ar_ie->ie_index = cpu_to_le16(priv->assocresp_idx); | ||
| 379 | ar_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK); | ||
| 380 | ar_ie->ie_length = 0; | ||
| 381 | } | ||
| 382 | |||
| 383 | if (beacon_ie || pr_ie || ar_ie) | ||
| 384 | ret = mwifiex_update_uap_custom_ie(priv, | ||
| 385 | beacon_ie, &priv->beacon_idx, | ||
| 386 | pr_ie, &priv->proberesp_idx, | ||
| 387 | ar_ie, &priv->assocresp_idx); | ||
| 388 | |||
| 389 | done: | ||
| 390 | kfree(beacon_ie); | ||
| 391 | kfree(pr_ie); | ||
| 392 | kfree(ar_ie); | ||
| 393 | kfree(rsn_ie); | ||
| 394 | |||
| 395 | return ret; | ||
| 396 | } | ||
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index d440c3eb640..c1cb004db91 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c | |||
| @@ -279,6 +279,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) | |||
| 279 | memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter)); | 279 | memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter)); |
| 280 | adapter->arp_filter_size = 0; | 280 | adapter->arp_filter_size = 0; |
| 281 | adapter->channel_type = NL80211_CHAN_HT20; | 281 | adapter->channel_type = NL80211_CHAN_HT20; |
| 282 | adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX; | ||
| 282 | } | 283 | } |
| 283 | 284 | ||
| 284 | /* | 285 | /* |
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index f0f95524e96..e6be6ee7595 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h | |||
| @@ -62,6 +62,36 @@ enum { | |||
| 62 | BAND_AN = 16, | 62 | BAND_AN = 16, |
| 63 | }; | 63 | }; |
| 64 | 64 | ||
| 65 | #define MWIFIEX_WPA_PASSHPHRASE_LEN 64 | ||
| 66 | struct wpa_param { | ||
| 67 | u8 pairwise_cipher_wpa; | ||
| 68 | u8 pairwise_cipher_wpa2; | ||
| 69 | u8 group_cipher; | ||
| 70 | u32 length; | ||
| 71 | u8 passphrase[MWIFIEX_WPA_PASSHPHRASE_LEN]; | ||
| 72 | }; | ||
| 73 | |||
| 74 | #define KEY_MGMT_ON_HOST 0x03 | ||
| 75 | #define MWIFIEX_AUTH_MODE_AUTO 0xFF | ||
| 76 | #define BAND_CONFIG_MANUAL 0x00 | ||
| 77 | struct mwifiex_uap_bss_param { | ||
| 78 | u8 channel; | ||
| 79 | u8 band_cfg; | ||
| 80 | u16 rts_threshold; | ||
| 81 | u16 frag_threshold; | ||
| 82 | u8 retry_limit; | ||
| 83 | struct mwifiex_802_11_ssid ssid; | ||
| 84 | u8 bcast_ssid_ctl; | ||
| 85 | u8 radio_ctl; | ||
| 86 | u8 dtim_period; | ||
| 87 | u16 beacon_period; | ||
| 88 | u16 auth_mode; | ||
| 89 | u16 protocol; | ||
| 90 | u16 key_mgmt; | ||
| 91 | u16 key_mgmt_operation; | ||
| 92 | struct wpa_param wpa_cfg; | ||
| 93 | }; | ||
| 94 | |||
| 65 | enum { | 95 | enum { |
| 66 | ADHOC_IDLE, | 96 | ADHOC_IDLE, |
| 67 | ADHOC_STARTED, | 97 | ADHOC_STARTED, |
| @@ -269,6 +299,8 @@ struct mwifiex_ds_read_eeprom { | |||
| 269 | 299 | ||
| 270 | #define IEEE_MAX_IE_SIZE 256 | 300 | #define IEEE_MAX_IE_SIZE 256 |
| 271 | 301 | ||
| 302 | #define MWIFIEX_IE_HDR_SIZE (sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE) | ||
| 303 | |||
| 272 | struct mwifiex_ds_misc_gen_ie { | 304 | struct mwifiex_ds_misc_gen_ie { |
| 273 | u32 type; | 305 | u32 type; |
| 274 | u32 len; | 306 | u32 len; |
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 8a390982463..d6b4fb04011 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c | |||
| @@ -1374,22 +1374,28 @@ static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, u8 *mac) | |||
| 1374 | * | 1374 | * |
| 1375 | * In case of infra made, it sends deauthentication request, and | 1375 | * In case of infra made, it sends deauthentication request, and |
| 1376 | * in case of ad-hoc mode, a stop network request is sent to the firmware. | 1376 | * in case of ad-hoc mode, a stop network request is sent to the firmware. |
| 1377 | * In AP mode, a command to stop bss is sent to firmware. | ||
| 1377 | */ | 1378 | */ |
| 1378 | int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac) | 1379 | int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac) |
| 1379 | { | 1380 | { |
| 1380 | int ret = 0; | 1381 | if (!priv->media_connected) |
| 1382 | return 0; | ||
| 1381 | 1383 | ||
| 1382 | if (priv->media_connected) { | 1384 | switch (priv->bss_mode) { |
| 1383 | if (priv->bss_mode == NL80211_IFTYPE_STATION) { | 1385 | case NL80211_IFTYPE_STATION: |
| 1384 | ret = mwifiex_deauthenticate_infra(priv, mac); | 1386 | return mwifiex_deauthenticate_infra(priv, mac); |
| 1385 | } else if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { | 1387 | case NL80211_IFTYPE_ADHOC: |
| 1386 | ret = mwifiex_send_cmd_sync(priv, | 1388 | return mwifiex_send_cmd_sync(priv, |
| 1387 | HostCmd_CMD_802_11_AD_HOC_STOP, | 1389 | HostCmd_CMD_802_11_AD_HOC_STOP, |
| 1388 | HostCmd_ACT_GEN_SET, 0, NULL); | 1390 | HostCmd_ACT_GEN_SET, 0, NULL); |
| 1389 | } | 1391 | case NL80211_IFTYPE_AP: |
| 1392 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP, | ||
| 1393 | HostCmd_ACT_GEN_SET, 0, NULL); | ||
| 1394 | default: | ||
| 1395 | break; | ||
| 1390 | } | 1396 | } |
| 1391 | 1397 | ||
| 1392 | return ret; | 1398 | return 0; |
| 1393 | } | 1399 | } |
| 1394 | EXPORT_SYMBOL_GPL(mwifiex_deauthenticate); | 1400 | EXPORT_SYMBOL_GPL(mwifiex_deauthenticate); |
| 1395 | 1401 | ||
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index be0f0e583f7..3192855c31c 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
| @@ -64,17 +64,17 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, | |||
| 64 | 64 | ||
| 65 | adapter->priv_num = 0; | 65 | adapter->priv_num = 0; |
| 66 | 66 | ||
| 67 | /* Allocate memory for private structure */ | 67 | for (i = 0; i < MWIFIEX_MAX_BSS_NUM; i++) { |
| 68 | adapter->priv[0] = kzalloc(sizeof(struct mwifiex_private), GFP_KERNEL); | 68 | /* Allocate memory for private structure */ |
| 69 | if (!adapter->priv[0]) { | 69 | adapter->priv[i] = |
| 70 | dev_err(adapter->dev, | 70 | kzalloc(sizeof(struct mwifiex_private), GFP_KERNEL); |
| 71 | "%s: failed to alloc priv[0]\n", __func__); | 71 | if (!adapter->priv[i]) |
| 72 | goto error; | 72 | goto error; |
| 73 | } | ||
| 74 | |||
| 75 | adapter->priv_num++; | ||
| 76 | 73 | ||
| 77 | adapter->priv[0]->adapter = adapter; | 74 | adapter->priv[i]->adapter = adapter; |
| 75 | adapter->priv[i]->bss_priority = i; | ||
| 76 | adapter->priv_num++; | ||
| 77 | } | ||
| 78 | mwifiex_init_lock_list(adapter); | 78 | mwifiex_init_lock_list(adapter); |
| 79 | 79 | ||
| 80 | init_timer(&adapter->cmd_timer); | 80 | init_timer(&adapter->cmd_timer); |
| @@ -349,19 +349,26 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context) | |||
| 349 | if (adapter->hw_status != MWIFIEX_HW_STATUS_READY) | 349 | if (adapter->hw_status != MWIFIEX_HW_STATUS_READY) |
| 350 | goto done; | 350 | goto done; |
| 351 | 351 | ||
| 352 | priv = adapter->priv[0]; | 352 | priv = adapter->priv[MWIFIEX_BSS_ROLE_STA]; |
| 353 | if (mwifiex_register_cfg80211(priv) != 0) { | 353 | if (mwifiex_register_cfg80211(adapter)) { |
| 354 | dev_err(adapter->dev, "cannot register with cfg80211\n"); | 354 | dev_err(adapter->dev, "cannot register with cfg80211\n"); |
| 355 | goto err_init_fw; | 355 | goto err_init_fw; |
| 356 | } | 356 | } |
| 357 | 357 | ||
| 358 | rtnl_lock(); | 358 | rtnl_lock(); |
| 359 | /* Create station interface by default */ | 359 | /* Create station interface by default */ |
| 360 | if (!mwifiex_add_virtual_intf(priv->wdev->wiphy, "mlan%d", | 360 | if (!mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d", |
| 361 | NL80211_IFTYPE_STATION, NULL, NULL)) { | 361 | NL80211_IFTYPE_STATION, NULL, NULL)) { |
| 362 | dev_err(adapter->dev, "cannot create default STA interface\n"); | 362 | dev_err(adapter->dev, "cannot create default STA interface\n"); |
| 363 | goto err_add_intf; | 363 | goto err_add_intf; |
| 364 | } | 364 | } |
| 365 | |||
| 366 | /* Create AP interface by default */ | ||
| 367 | if (!mwifiex_add_virtual_intf(adapter->wiphy, "uap%d", | ||
| 368 | NL80211_IFTYPE_AP, NULL, NULL)) { | ||
| 369 | dev_err(adapter->dev, "cannot create default AP interface\n"); | ||
| 370 | goto err_add_intf; | ||
| 371 | } | ||
| 365 | rtnl_unlock(); | 372 | rtnl_unlock(); |
| 366 | 373 | ||
| 367 | mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1); | 374 | mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1); |
| @@ -369,7 +376,7 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context) | |||
| 369 | goto done; | 376 | goto done; |
| 370 | 377 | ||
| 371 | err_add_intf: | 378 | err_add_intf: |
| 372 | mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev); | 379 | mwifiex_del_virtual_intf(adapter->wiphy, priv->netdev); |
| 373 | rtnl_unlock(); | 380 | rtnl_unlock(); |
| 374 | err_init_fw: | 381 | err_init_fw: |
| 375 | pr_debug("info: %s: unregister device\n", __func__); | 382 | pr_debug("info: %s: unregister device\n", __func__); |
| @@ -633,6 +640,12 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv, | |||
| 633 | priv->current_key_index = 0; | 640 | priv->current_key_index = 0; |
| 634 | priv->media_connected = false; | 641 | priv->media_connected = false; |
| 635 | memset(&priv->nick_name, 0, sizeof(priv->nick_name)); | 642 | memset(&priv->nick_name, 0, sizeof(priv->nick_name)); |
| 643 | memset(priv->mgmt_ie, 0, | ||
| 644 | sizeof(struct mwifiex_ie) * MAX_MGMT_IE_INDEX); | ||
| 645 | priv->beacon_idx = MWIFIEX_AUTO_IDX_MASK; | ||
| 646 | priv->proberesp_idx = MWIFIEX_AUTO_IDX_MASK; | ||
| 647 | priv->assocresp_idx = MWIFIEX_AUTO_IDX_MASK; | ||
| 648 | priv->rsn_idx = MWIFIEX_AUTO_IDX_MASK; | ||
| 636 | priv->num_tx_timeout = 0; | 649 | priv->num_tx_timeout = 0; |
| 637 | memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN); | 650 | memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN); |
| 638 | } | 651 | } |
| @@ -830,19 +843,21 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) | |||
| 830 | 843 | ||
| 831 | rtnl_lock(); | 844 | rtnl_lock(); |
| 832 | if (priv->wdev && priv->netdev) | 845 | if (priv->wdev && priv->netdev) |
| 833 | mwifiex_del_virtual_intf(priv->wdev->wiphy, | 846 | mwifiex_del_virtual_intf(adapter->wiphy, priv->netdev); |
| 834 | priv->netdev); | ||
| 835 | rtnl_unlock(); | 847 | rtnl_unlock(); |
| 836 | } | 848 | } |
| 837 | 849 | ||
| 838 | priv = adapter->priv[0]; | 850 | priv = adapter->priv[0]; |
| 839 | if (!priv) | 851 | if (!priv || !priv->wdev) |
| 840 | goto exit_remove; | 852 | goto exit_remove; |
| 841 | 853 | ||
| 842 | if (priv->wdev) { | 854 | wiphy_unregister(priv->wdev->wiphy); |
| 843 | wiphy_unregister(priv->wdev->wiphy); | 855 | wiphy_free(priv->wdev->wiphy); |
| 844 | wiphy_free(priv->wdev->wiphy); | 856 | |
| 845 | kfree(priv->wdev); | 857 | for (i = 0; i < adapter->priv_num; i++) { |
| 858 | priv = adapter->priv[i]; | ||
| 859 | if (priv) | ||
| 860 | kfree(priv->wdev); | ||
| 846 | } | 861 | } |
| 847 | 862 | ||
| 848 | mwifiex_terminate_workqueue(adapter); | 863 | mwifiex_terminate_workqueue(adapter); |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 324ad390cac..bd3b0bf94b9 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
| @@ -116,6 +116,7 @@ enum { | |||
| 116 | #define MAX_FREQUENCY_BAND_BG 2484 | 116 | #define MAX_FREQUENCY_BAND_BG 2484 |
| 117 | 117 | ||
| 118 | #define MWIFIEX_EVENT_HEADER_LEN 4 | 118 | #define MWIFIEX_EVENT_HEADER_LEN 4 |
| 119 | #define MWIFIEX_UAP_EVENT_EXTRA_HEADER 2 | ||
| 119 | 120 | ||
| 120 | #define MWIFIEX_TYPE_LEN 4 | 121 | #define MWIFIEX_TYPE_LEN 4 |
| 121 | #define MWIFIEX_USB_TYPE_CMD 0xF00DFACE | 122 | #define MWIFIEX_USB_TYPE_CMD 0xF00DFACE |
| @@ -370,6 +371,7 @@ struct mwifiex_private { | |||
| 370 | u8 bss_role; | 371 | u8 bss_role; |
| 371 | u8 bss_priority; | 372 | u8 bss_priority; |
| 372 | u8 bss_num; | 373 | u8 bss_num; |
| 374 | u8 bss_started; | ||
| 373 | u8 frame_type; | 375 | u8 frame_type; |
| 374 | u8 curr_addr[ETH_ALEN]; | 376 | u8 curr_addr[ETH_ALEN]; |
| 375 | u8 media_connected; | 377 | u8 media_connected; |
| @@ -470,12 +472,16 @@ struct mwifiex_private { | |||
| 470 | struct cfg80211_scan_request *scan_request; | 472 | struct cfg80211_scan_request *scan_request; |
| 471 | struct mwifiex_user_scan_cfg *user_scan_cfg; | 473 | struct mwifiex_user_scan_cfg *user_scan_cfg; |
| 472 | u8 cfg_bssid[6]; | 474 | u8 cfg_bssid[6]; |
| 473 | u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; | ||
| 474 | struct wps wps; | 475 | struct wps wps; |
| 475 | u8 scan_block; | 476 | u8 scan_block; |
| 476 | s32 cqm_rssi_thold; | 477 | s32 cqm_rssi_thold; |
| 477 | u32 cqm_rssi_hyst; | 478 | u32 cqm_rssi_hyst; |
| 478 | u8 subsc_evt_rssi_state; | 479 | u8 subsc_evt_rssi_state; |
| 480 | struct mwifiex_ie mgmt_ie[MAX_MGMT_IE_INDEX]; | ||
| 481 | u16 beacon_idx; | ||
| 482 | u16 proberesp_idx; | ||
| 483 | u16 assocresp_idx; | ||
| 484 | u16 rsn_idx; | ||
| 479 | }; | 485 | }; |
| 480 | 486 | ||
| 481 | enum mwifiex_ba_status { | 487 | enum mwifiex_ba_status { |
| @@ -571,6 +577,7 @@ struct mwifiex_adapter { | |||
| 571 | char fw_name[32]; | 577 | char fw_name[32]; |
| 572 | int winner; | 578 | int winner; |
| 573 | struct device *dev; | 579 | struct device *dev; |
| 580 | struct wiphy *wiphy; | ||
| 574 | bool surprise_removed; | 581 | bool surprise_removed; |
| 575 | u32 fw_release_number; | 582 | u32 fw_release_number; |
| 576 | u16 init_wait_q_woken; | 583 | u16 init_wait_q_woken; |
| @@ -677,6 +684,8 @@ struct mwifiex_adapter { | |||
| 677 | struct cmd_ctrl_node *cmd_queued; | 684 | struct cmd_ctrl_node *cmd_queued; |
| 678 | spinlock_t queue_lock; /* lock for tx queues */ | 685 | spinlock_t queue_lock; /* lock for tx queues */ |
| 679 | struct completion fw_load; | 686 | struct completion fw_load; |
| 687 | u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; | ||
| 688 | u16 max_mgmt_ie_index; | ||
| 680 | }; | 689 | }; |
| 681 | 690 | ||
| 682 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); | 691 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); |
| @@ -760,6 +769,9 @@ int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter, | |||
| 760 | int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no, | 769 | int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no, |
| 761 | u16 cmd_action, u32 cmd_oid, | 770 | u16 cmd_action, u32 cmd_oid, |
| 762 | void *data_buf, void *cmd_buf); | 771 | void *data_buf, void *cmd_buf); |
| 772 | int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | ||
| 773 | u16 cmd_action, u32 cmd_oid, | ||
| 774 | void *data_buf, void *cmd_buf); | ||
| 763 | int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no, | 775 | int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no, |
| 764 | struct host_cmd_ds_command *resp); | 776 | struct host_cmd_ds_command *resp); |
| 765 | int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *, | 777 | int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *, |
| @@ -820,6 +832,9 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, | |||
| 820 | int is_command_pending(struct mwifiex_adapter *adapter); | 832 | int is_command_pending(struct mwifiex_adapter *adapter); |
| 821 | void mwifiex_init_priv_params(struct mwifiex_private *priv, | 833 | void mwifiex_init_priv_params(struct mwifiex_private *priv, |
| 822 | struct net_device *dev); | 834 | struct net_device *dev); |
| 835 | int mwifiex_set_secure_params(struct mwifiex_private *priv, | ||
| 836 | struct mwifiex_uap_bss_param *bss_config, | ||
| 837 | struct cfg80211_ap_settings *params); | ||
| 823 | 838 | ||
| 824 | /* | 839 | /* |
| 825 | * This function checks if the queuing is RA based or not. | 840 | * This function checks if the queuing is RA based or not. |
| @@ -933,7 +948,8 @@ int mwifiex_set_radio(struct mwifiex_private *priv, u8 option); | |||
| 933 | int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, u16 channel); | 948 | int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, u16 channel); |
| 934 | 949 | ||
| 935 | int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key, | 950 | int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key, |
| 936 | int key_len, u8 key_index, int disable); | 951 | int key_len, u8 key_index, const u8 *mac_addr, |
| 952 | int disable); | ||
| 937 | 953 | ||
| 938 | int mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len); | 954 | int mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len); |
| 939 | 955 | ||
| @@ -969,6 +985,7 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv, | |||
| 969 | 985 | ||
| 970 | int mwifiex_main_process(struct mwifiex_adapter *); | 986 | int mwifiex_main_process(struct mwifiex_adapter *); |
| 971 | 987 | ||
| 988 | int mwifiex_uap_set_channel(struct mwifiex_private *priv, int channel); | ||
| 972 | int mwifiex_bss_set_channel(struct mwifiex_private *, | 989 | int mwifiex_bss_set_channel(struct mwifiex_private *, |
| 973 | struct mwifiex_chan_freq_power *cfp); | 990 | struct mwifiex_chan_freq_power *cfp); |
| 974 | int mwifiex_get_bss_info(struct mwifiex_private *, | 991 | int mwifiex_get_bss_info(struct mwifiex_private *, |
| @@ -986,6 +1003,11 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
| 986 | u32 *flags, struct vif_params *params); | 1003 | u32 *flags, struct vif_params *params); |
| 987 | int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev); | 1004 | int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev); |
| 988 | 1005 | ||
| 1006 | void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config); | ||
| 1007 | |||
| 1008 | int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, | ||
| 1009 | struct cfg80211_ap_settings *params); | ||
| 1010 | int mwifiex_del_mgmt_ies(struct mwifiex_private *priv); | ||
| 989 | u8 *mwifiex_11d_code_2_region(u8 code); | 1011 | u8 *mwifiex_11d_code_2_region(u8 code); |
| 990 | 1012 | ||
| 991 | #ifdef CONFIG_DEBUG_FS | 1013 | #ifdef CONFIG_DEBUG_FS |
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 87ed2a1f6cd..40e025da6bc 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
| @@ -498,7 +498,8 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv, | |||
| 498 | { | 498 | { |
| 499 | struct host_cmd_ds_802_11_key_material *key_material = | 499 | struct host_cmd_ds_802_11_key_material *key_material = |
| 500 | &cmd->params.key_material; | 500 | &cmd->params.key_material; |
| 501 | u16 key_param_len = 0; | 501 | struct host_cmd_tlv_mac_addr *tlv_mac; |
| 502 | u16 key_param_len = 0, cmd_size; | ||
| 502 | int ret = 0; | 503 | int ret = 0; |
| 503 | const u8 bc_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | 504 | const u8 bc_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; |
| 504 | 505 | ||
| @@ -614,11 +615,26 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv, | |||
| 614 | cpu_to_le16((u16) enc_key->key_len + | 615 | cpu_to_le16((u16) enc_key->key_len + |
| 615 | KEYPARAMSET_FIXED_LEN); | 616 | KEYPARAMSET_FIXED_LEN); |
| 616 | 617 | ||
| 617 | key_param_len = (u16) (enc_key->key_len + KEYPARAMSET_FIXED_LEN) | 618 | key_param_len = (u16)(enc_key->key_len + KEYPARAMSET_FIXED_LEN) |
| 618 | + sizeof(struct mwifiex_ie_types_header); | 619 | + sizeof(struct mwifiex_ie_types_header); |
| 619 | 620 | ||
| 620 | cmd->size = cpu_to_le16(sizeof(key_material->action) + S_DS_GEN | 621 | cmd->size = cpu_to_le16(sizeof(key_material->action) + S_DS_GEN |
| 621 | + key_param_len); | 622 | + key_param_len); |
| 623 | |||
| 624 | if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) { | ||
| 625 | tlv_mac = (void *)((u8 *)&key_material->key_param_set + | ||
| 626 | key_param_len); | ||
| 627 | tlv_mac->tlv.type = cpu_to_le16(TLV_TYPE_STA_MAC_ADDR); | ||
| 628 | tlv_mac->tlv.len = cpu_to_le16(ETH_ALEN); | ||
| 629 | memcpy(tlv_mac->mac_addr, enc_key->mac_addr, ETH_ALEN); | ||
| 630 | cmd_size = key_param_len + S_DS_GEN + | ||
| 631 | sizeof(key_material->action) + | ||
| 632 | sizeof(struct host_cmd_tlv_mac_addr); | ||
| 633 | } else { | ||
| 634 | cmd_size = key_param_len + S_DS_GEN + | ||
| 635 | sizeof(key_material->action); | ||
| 636 | } | ||
| 637 | cmd->size = cpu_to_le16(cmd_size); | ||
| 622 | } | 638 | } |
| 623 | 639 | ||
| 624 | return ret; | 640 | return ret; |
| @@ -1248,13 +1264,15 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) | |||
| 1248 | if (ret) | 1264 | if (ret) |
| 1249 | return -1; | 1265 | return -1; |
| 1250 | 1266 | ||
| 1251 | /* Enable IEEE PS by default */ | 1267 | if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { |
| 1252 | priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; | 1268 | /* Enable IEEE PS by default */ |
| 1253 | ret = mwifiex_send_cmd_async(priv, | 1269 | priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; |
| 1254 | HostCmd_CMD_802_11_PS_MODE_ENH, | 1270 | ret = mwifiex_send_cmd_async( |
| 1255 | EN_AUTO_PS, BITMAP_STA_PS, NULL); | 1271 | priv, HostCmd_CMD_802_11_PS_MODE_ENH, |
| 1256 | if (ret) | 1272 | EN_AUTO_PS, BITMAP_STA_PS, NULL); |
| 1257 | return -1; | 1273 | if (ret) |
| 1274 | return -1; | ||
| 1275 | } | ||
| 1258 | } | 1276 | } |
| 1259 | 1277 | ||
| 1260 | /* get tx rate */ | 1278 | /* get tx rate */ |
| @@ -1270,12 +1288,14 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) | |||
| 1270 | if (ret) | 1288 | if (ret) |
| 1271 | return -1; | 1289 | return -1; |
| 1272 | 1290 | ||
| 1273 | /* set ibss coalescing_status */ | 1291 | if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) { |
| 1274 | ret = mwifiex_send_cmd_async(priv, | 1292 | /* set ibss coalescing_status */ |
| 1275 | HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, | 1293 | ret = mwifiex_send_cmd_async( |
| 1276 | HostCmd_ACT_GEN_SET, 0, &enable); | 1294 | priv, HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, |
| 1277 | if (ret) | 1295 | HostCmd_ACT_GEN_SET, 0, &enable); |
| 1278 | return -1; | 1296 | if (ret) |
| 1297 | return -1; | ||
| 1298 | } | ||
| 1279 | 1299 | ||
| 1280 | memset(&amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl)); | 1300 | memset(&amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl)); |
| 1281 | amsdu_aggr_ctrl.enable = true; | 1301 | amsdu_aggr_ctrl.enable = true; |
| @@ -1293,7 +1313,8 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) | |||
| 1293 | if (ret) | 1313 | if (ret) |
| 1294 | return -1; | 1314 | return -1; |
| 1295 | 1315 | ||
| 1296 | if (first_sta && (priv->adapter->iface_type != MWIFIEX_USB)) { | 1316 | if (first_sta && priv->adapter->iface_type != MWIFIEX_USB && |
| 1317 | priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { | ||
| 1297 | /* Enable auto deep sleep */ | 1318 | /* Enable auto deep sleep */ |
| 1298 | auto_ds.auto_ds = DEEP_SLEEP_ON; | 1319 | auto_ds.auto_ds = DEEP_SLEEP_ON; |
| 1299 | auto_ds.idle_time = DEEP_SLEEP_IDLE_TIME; | 1320 | auto_ds.idle_time = DEEP_SLEEP_IDLE_TIME; |
| @@ -1305,12 +1326,16 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) | |||
| 1305 | return -1; | 1326 | return -1; |
| 1306 | } | 1327 | } |
| 1307 | 1328 | ||
| 1308 | /* Send cmd to FW to enable/disable 11D function */ | 1329 | if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { |
| 1309 | state_11d = ENABLE_11D; | 1330 | /* Send cmd to FW to enable/disable 11D function */ |
| 1310 | ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SNMP_MIB, | 1331 | state_11d = ENABLE_11D; |
| 1311 | HostCmd_ACT_GEN_SET, DOT11D_I, &state_11d); | 1332 | ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SNMP_MIB, |
| 1312 | if (ret) | 1333 | HostCmd_ACT_GEN_SET, DOT11D_I, |
| 1313 | dev_err(priv->adapter->dev, "11D: failed to enable 11D\n"); | 1334 | &state_11d); |
| 1335 | if (ret) | ||
| 1336 | dev_err(priv->adapter->dev, | ||
| 1337 | "11D: failed to enable 11D\n"); | ||
| 1338 | } | ||
| 1314 | 1339 | ||
| 1315 | /* Send cmd to FW to configure 11n specific configuration | 1340 | /* Send cmd to FW to configure 11n specific configuration |
| 1316 | * (Short GI, Channel BW, Green field support etc.) for transmit | 1341 | * (Short GI, Channel BW, Green field support etc.) for transmit |
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 3aa54243dea..a79ed9bd969 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c | |||
| @@ -944,6 +944,14 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, | |||
| 944 | case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: | 944 | case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: |
| 945 | ret = mwifiex_ret_subsc_evt(priv, resp, data_buf); | 945 | ret = mwifiex_ret_subsc_evt(priv, resp, data_buf); |
| 946 | break; | 946 | break; |
| 947 | case HostCmd_CMD_UAP_SYS_CONFIG: | ||
| 948 | break; | ||
| 949 | case HostCmd_CMD_UAP_BSS_START: | ||
| 950 | priv->bss_started = 1; | ||
| 951 | break; | ||
| 952 | case HostCmd_CMD_UAP_BSS_STOP: | ||
| 953 | priv->bss_started = 0; | ||
| 954 | break; | ||
| 947 | default: | 955 | default: |
| 948 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", | 956 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", |
| 949 | resp->command); | 957 | resp->command); |
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index f6bbb9307f8..4ace5a3dcd2 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c | |||
| @@ -184,8 +184,10 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv) | |||
| 184 | int mwifiex_process_sta_event(struct mwifiex_private *priv) | 184 | int mwifiex_process_sta_event(struct mwifiex_private *priv) |
| 185 | { | 185 | { |
| 186 | struct mwifiex_adapter *adapter = priv->adapter; | 186 | struct mwifiex_adapter *adapter = priv->adapter; |
| 187 | int ret = 0; | 187 | int len, ret = 0; |
| 188 | u32 eventcause = adapter->event_cause; | 188 | u32 eventcause = adapter->event_cause; |
| 189 | struct station_info sinfo; | ||
| 190 | struct mwifiex_assoc_event *event; | ||
| 189 | 191 | ||
| 190 | switch (eventcause) { | 192 | switch (eventcause) { |
| 191 | case EVENT_DUMMY_HOST_WAKEUP_SIGNAL: | 193 | case EVENT_DUMMY_HOST_WAKEUP_SIGNAL: |
| @@ -402,6 +404,53 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) | |||
| 402 | case EVENT_HOSTWAKE_STAIE: | 404 | case EVENT_HOSTWAKE_STAIE: |
| 403 | dev_dbg(adapter->dev, "event: HOSTWAKE_STAIE %d\n", eventcause); | 405 | dev_dbg(adapter->dev, "event: HOSTWAKE_STAIE %d\n", eventcause); |
| 404 | break; | 406 | break; |
| 407 | |||
| 408 | case EVENT_UAP_STA_ASSOC: | ||
| 409 | skb_pull(adapter->event_skb, MWIFIEX_UAP_EVENT_EXTRA_HEADER); | ||
| 410 | memset(&sinfo, 0, sizeof(sinfo)); | ||
| 411 | event = (struct mwifiex_assoc_event *)adapter->event_skb->data; | ||
| 412 | if (le16_to_cpu(event->type) == TLV_TYPE_UAP_MGMT_FRAME) { | ||
| 413 | len = -1; | ||
| 414 | |||
| 415 | if (ieee80211_is_assoc_req(event->frame_control)) | ||
| 416 | len = 0; | ||
| 417 | else if (ieee80211_is_reassoc_req(event->frame_control)) | ||
| 418 | /* There will be ETH_ALEN bytes of | ||
| 419 | * current_ap_addr before the re-assoc ies. | ||
| 420 | */ | ||
| 421 | len = ETH_ALEN; | ||
| 422 | |||
| 423 | if (len != -1) { | ||
| 424 | sinfo.filled = STATION_INFO_ASSOC_REQ_IES; | ||
| 425 | sinfo.assoc_req_ies = (u8 *)&event->data[len]; | ||
| 426 | len = (u8 *)sinfo.assoc_req_ies - | ||
| 427 | (u8 *)&event->frame_control; | ||
| 428 | sinfo.assoc_req_ies_len = | ||
| 429 | le16_to_cpu(event->len) - (u16)len; | ||
| 430 | } | ||
| 431 | } | ||
| 432 | cfg80211_new_sta(priv->netdev, event->sta_addr, &sinfo, | ||
| 433 | GFP_KERNEL); | ||
| 434 | break; | ||
| 435 | case EVENT_UAP_STA_DEAUTH: | ||
| 436 | skb_pull(adapter->event_skb, MWIFIEX_UAP_EVENT_EXTRA_HEADER); | ||
| 437 | cfg80211_del_sta(priv->netdev, adapter->event_skb->data, | ||
| 438 | GFP_KERNEL); | ||
| 439 | break; | ||
| 440 | case EVENT_UAP_BSS_IDLE: | ||
| 441 | priv->media_connected = false; | ||
| 442 | break; | ||
| 443 | case EVENT_UAP_BSS_ACTIVE: | ||
| 444 | priv->media_connected = true; | ||
| 445 | break; | ||
| 446 | case EVENT_UAP_BSS_START: | ||
| 447 | dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause); | ||
| 448 | memcpy(priv->netdev->dev_addr, adapter->event_body+2, ETH_ALEN); | ||
| 449 | break; | ||
| 450 | case EVENT_UAP_MIC_COUNTERMEASURES: | ||
| 451 | /* For future development */ | ||
| 452 | dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause); | ||
| 453 | break; | ||
| 405 | default: | 454 | default: |
| 406 | dev_dbg(adapter->dev, "event: unknown event id: %#x\n", | 455 | dev_dbg(adapter->dev, "event: unknown event id: %#x\n", |
| 407 | eventcause); | 456 | eventcause); |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 58970e0f7d1..106c449477b 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
| @@ -462,7 +462,7 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv, | |||
| 462 | 462 | ||
| 463 | info->bss_chan = bss_desc->channel; | 463 | info->bss_chan = bss_desc->channel; |
| 464 | 464 | ||
| 465 | memcpy(info->country_code, priv->country_code, | 465 | memcpy(info->country_code, adapter->country_code, |
| 466 | IEEE80211_COUNTRY_STRING_LEN); | 466 | IEEE80211_COUNTRY_STRING_LEN); |
| 467 | 467 | ||
| 468 | info->media_connected = priv->media_connected; | 468 | info->media_connected = priv->media_connected; |
| @@ -1219,7 +1219,8 @@ mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, char *version, | |||
| 1219 | * with requisite parameters and calls the IOCTL handler. | 1219 | * with requisite parameters and calls the IOCTL handler. |
| 1220 | */ | 1220 | */ |
| 1221 | int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key, | 1221 | int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key, |
| 1222 | int key_len, u8 key_index, int disable) | 1222 | int key_len, u8 key_index, |
| 1223 | const u8 *mac_addr, int disable) | ||
| 1223 | { | 1224 | { |
| 1224 | struct mwifiex_ds_encrypt_key encrypt_key; | 1225 | struct mwifiex_ds_encrypt_key encrypt_key; |
| 1225 | 1226 | ||
| @@ -1229,8 +1230,12 @@ int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key, | |||
| 1229 | encrypt_key.key_index = key_index; | 1230 | encrypt_key.key_index = key_index; |
| 1230 | if (key_len) | 1231 | if (key_len) |
| 1231 | memcpy(encrypt_key.key_material, key, key_len); | 1232 | memcpy(encrypt_key.key_material, key, key_len); |
| 1233 | if (mac_addr) | ||
| 1234 | memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN); | ||
| 1232 | } else { | 1235 | } else { |
| 1233 | encrypt_key.key_disable = true; | 1236 | encrypt_key.key_disable = true; |
| 1237 | if (mac_addr) | ||
| 1238 | memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN); | ||
| 1234 | } | 1239 | } |
| 1235 | 1240 | ||
| 1236 | return mwifiex_sec_ioctl_encrypt_key(priv, &encrypt_key); | 1241 | return mwifiex_sec_ioctl_encrypt_key(priv, &encrypt_key); |
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c new file mode 100644 index 00000000000..76dfbc42a73 --- /dev/null +++ b/drivers/net/wireless/mwifiex/uap_cmd.c | |||
| @@ -0,0 +1,432 @@ | |||
| 1 | /* | ||
| 2 | * Marvell Wireless LAN device driver: AP specific command handling | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012, Marvell International Ltd. | ||
| 5 | * | ||
| 6 | * This software file (the "File") is distributed by Marvell International | ||
| 7 | * Ltd. under the terms of the GNU General Public License Version 2, June 1991 | ||
| 8 | * (the "License"). You may use, redistribute and/or modify this File in | ||
| 9 | * accordance with the terms and conditions of the License, a copy of which | ||
| 10 | * is available by writing to the Free Software Foundation, Inc., | ||
| 11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the | ||
| 12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. | ||
| 13 | * | ||
| 14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE | ||
| 15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE | ||
| 16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about | ||
| 17 | * this warranty disclaimer. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include "main.h" | ||
| 21 | |||
| 22 | /* This function parses security related parameters from cfg80211_ap_settings | ||
| 23 | * and sets into FW understandable bss_config structure. | ||
| 24 | */ | ||
| 25 | int mwifiex_set_secure_params(struct mwifiex_private *priv, | ||
| 26 | struct mwifiex_uap_bss_param *bss_config, | ||
| 27 | struct cfg80211_ap_settings *params) { | ||
| 28 | int i; | ||
| 29 | |||
| 30 | switch (params->auth_type) { | ||
| 31 | case NL80211_AUTHTYPE_OPEN_SYSTEM: | ||
| 32 | bss_config->auth_mode = WLAN_AUTH_OPEN; | ||
| 33 | break; | ||
| 34 | case NL80211_AUTHTYPE_SHARED_KEY: | ||
| 35 | bss_config->auth_mode = WLAN_AUTH_SHARED_KEY; | ||
| 36 | break; | ||
| 37 | case NL80211_AUTHTYPE_NETWORK_EAP: | ||
| 38 | bss_config->auth_mode = WLAN_AUTH_LEAP; | ||
| 39 | break; | ||
| 40 | default: | ||
| 41 | bss_config->auth_mode = MWIFIEX_AUTH_MODE_AUTO; | ||
| 42 | break; | ||
| 43 | } | ||
| 44 | |||
| 45 | bss_config->key_mgmt_operation |= KEY_MGMT_ON_HOST; | ||
| 46 | |||
| 47 | for (i = 0; i < params->crypto.n_akm_suites; i++) { | ||
| 48 | switch (params->crypto.akm_suites[i]) { | ||
| 49 | case WLAN_AKM_SUITE_8021X: | ||
| 50 | if (params->crypto.wpa_versions & | ||
| 51 | NL80211_WPA_VERSION_1) { | ||
| 52 | bss_config->protocol = PROTOCOL_WPA; | ||
| 53 | bss_config->key_mgmt = KEY_MGMT_EAP; | ||
| 54 | } | ||
| 55 | if (params->crypto.wpa_versions & | ||
| 56 | NL80211_WPA_VERSION_2) { | ||
| 57 | bss_config->protocol = PROTOCOL_WPA2; | ||
| 58 | bss_config->key_mgmt = KEY_MGMT_EAP; | ||
| 59 | } | ||
| 60 | break; | ||
| 61 | case WLAN_AKM_SUITE_PSK: | ||
| 62 | if (params->crypto.wpa_versions & | ||
| 63 | NL80211_WPA_VERSION_1) { | ||
| 64 | bss_config->protocol = PROTOCOL_WPA; | ||
| 65 | bss_config->key_mgmt = KEY_MGMT_PSK; | ||
| 66 | } | ||
| 67 | if (params->crypto.wpa_versions & | ||
| 68 | NL80211_WPA_VERSION_2) { | ||
| 69 | bss_config->protocol = PROTOCOL_WPA2; | ||
| 70 | bss_config->key_mgmt = KEY_MGMT_PSK; | ||
| 71 | } | ||
| 72 | break; | ||
| 73 | default: | ||
| 74 | break; | ||
| 75 | } | ||
| 76 | } | ||
| 77 | for (i = 0; i < params->crypto.n_ciphers_pairwise; i++) { | ||
| 78 | switch (params->crypto.ciphers_pairwise[i]) { | ||
| 79 | case WLAN_CIPHER_SUITE_WEP40: | ||
| 80 | case WLAN_CIPHER_SUITE_WEP104: | ||
| 81 | break; | ||
| 82 | case WLAN_CIPHER_SUITE_TKIP: | ||
| 83 | bss_config->wpa_cfg.pairwise_cipher_wpa = CIPHER_TKIP; | ||
| 84 | break; | ||
| 85 | case WLAN_CIPHER_SUITE_CCMP: | ||
| 86 | bss_config->wpa_cfg.pairwise_cipher_wpa2 = | ||
| 87 | CIPHER_AES_CCMP; | ||
| 88 | default: | ||
| 89 | break; | ||
| 90 | } | ||
| 91 | } | ||
| 92 | |||
| 93 | switch (params->crypto.cipher_group) { | ||
| 94 | case WLAN_CIPHER_SUITE_WEP40: | ||
| 95 | case WLAN_CIPHER_SUITE_WEP104: | ||
| 96 | break; | ||
| 97 | case WLAN_CIPHER_SUITE_TKIP: | ||
| 98 | bss_config->wpa_cfg.group_cipher = CIPHER_TKIP; | ||
| 99 | break; | ||
| 100 | case WLAN_CIPHER_SUITE_CCMP: | ||
| 101 | bss_config->wpa_cfg.group_cipher = CIPHER_AES_CCMP; | ||
| 102 | break; | ||
| 103 | default: | ||
| 104 | break; | ||
| 105 | } | ||
| 106 | |||
| 107 | return 0; | ||
| 108 | } | ||
| 109 | |||
| 110 | /* This function initializes some of mwifiex_uap_bss_param variables. | ||
| 111 | * This helps FW in ignoring invalid values. These values may or may not | ||
| 112 | * be get updated to valid ones at later stage. | ||
| 113 | */ | ||
| 114 | void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config) | ||
| 115 | { | ||
| 116 | config->bcast_ssid_ctl = 0x7F; | ||
| 117 | config->radio_ctl = 0x7F; | ||
| 118 | config->dtim_period = 0x7F; | ||
| 119 | config->beacon_period = 0x7FFF; | ||
| 120 | config->auth_mode = 0x7F; | ||
| 121 | config->rts_threshold = 0x7FFF; | ||
| 122 | config->frag_threshold = 0x7FFF; | ||
| 123 | config->retry_limit = 0x7F; | ||
| 124 | } | ||
| 125 | |||
| 126 | /* This function parses BSS related parameters from structure | ||
| 127 | * and prepares TLVs. These TLVs are appended to command buffer. | ||
| 128 | */ | ||
| 129 | static int | ||
| 130 | mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size) | ||
| 131 | { | ||
| 132 | struct host_cmd_tlv_dtim_period *dtim_period; | ||
| 133 | struct host_cmd_tlv_beacon_period *beacon_period; | ||
| 134 | struct host_cmd_tlv_ssid *ssid; | ||
| 135 | struct host_cmd_tlv_channel_band *chan_band; | ||
| 136 | struct host_cmd_tlv_frag_threshold *frag_threshold; | ||
| 137 | struct host_cmd_tlv_rts_threshold *rts_threshold; | ||
| 138 | struct host_cmd_tlv_retry_limit *retry_limit; | ||
| 139 | struct host_cmd_tlv_pwk_cipher *pwk_cipher; | ||
| 140 | struct host_cmd_tlv_gwk_cipher *gwk_cipher; | ||
| 141 | struct host_cmd_tlv_encrypt_protocol *encrypt_protocol; | ||
| 142 | struct host_cmd_tlv_auth_type *auth_type; | ||
| 143 | struct host_cmd_tlv_passphrase *passphrase; | ||
| 144 | struct host_cmd_tlv_akmp *tlv_akmp; | ||
| 145 | struct mwifiex_uap_bss_param *bss_cfg = cmd_buf; | ||
| 146 | u16 cmd_size = *param_size; | ||
| 147 | |||
| 148 | if (bss_cfg->ssid.ssid_len) { | ||
| 149 | ssid = (struct host_cmd_tlv_ssid *)tlv; | ||
| 150 | ssid->tlv.type = cpu_to_le16(TLV_TYPE_UAP_SSID); | ||
| 151 | ssid->tlv.len = cpu_to_le16((u16)bss_cfg->ssid.ssid_len); | ||
| 152 | memcpy(ssid->ssid, bss_cfg->ssid.ssid, bss_cfg->ssid.ssid_len); | ||
| 153 | cmd_size += sizeof(struct host_cmd_tlv) + | ||
| 154 | bss_cfg->ssid.ssid_len; | ||
| 155 | tlv += sizeof(struct host_cmd_tlv) + bss_cfg->ssid.ssid_len; | ||
| 156 | } | ||
| 157 | if (bss_cfg->channel && bss_cfg->channel <= MAX_CHANNEL_BAND_BG) { | ||
| 158 | chan_band = (struct host_cmd_tlv_channel_band *)tlv; | ||
| 159 | chan_band->tlv.type = cpu_to_le16(TLV_TYPE_CHANNELBANDLIST); | ||
| 160 | chan_band->tlv.len = | ||
| 161 | cpu_to_le16(sizeof(struct host_cmd_tlv_channel_band) - | ||
| 162 | sizeof(struct host_cmd_tlv)); | ||
| 163 | chan_band->band_config = bss_cfg->band_cfg; | ||
| 164 | chan_band->channel = bss_cfg->channel; | ||
| 165 | cmd_size += sizeof(struct host_cmd_tlv_channel_band); | ||
| 166 | tlv += sizeof(struct host_cmd_tlv_channel_band); | ||
| 167 | } | ||
| 168 | if (bss_cfg->beacon_period >= MIN_BEACON_PERIOD && | ||
| 169 | bss_cfg->beacon_period <= MAX_BEACON_PERIOD) { | ||
| 170 | beacon_period = (struct host_cmd_tlv_beacon_period *)tlv; | ||
| 171 | beacon_period->tlv.type = | ||
| 172 | cpu_to_le16(TLV_TYPE_UAP_BEACON_PERIOD); | ||
| 173 | beacon_period->tlv.len = | ||
| 174 | cpu_to_le16(sizeof(struct host_cmd_tlv_beacon_period) - | ||
| 175 | sizeof(struct host_cmd_tlv)); | ||
| 176 | beacon_period->period = cpu_to_le16(bss_cfg->beacon_period); | ||
| 177 | cmd_size += sizeof(struct host_cmd_tlv_beacon_period); | ||
| 178 | tlv += sizeof(struct host_cmd_tlv_beacon_period); | ||
| 179 | } | ||
| 180 | if (bss_cfg->dtim_period >= MIN_DTIM_PERIOD && | ||
| 181 | bss_cfg->dtim_period <= MAX_DTIM_PERIOD) { | ||
| 182 | dtim_period = (struct host_cmd_tlv_dtim_period *)tlv; | ||
| 183 | dtim_period->tlv.type = cpu_to_le16(TLV_TYPE_UAP_DTIM_PERIOD); | ||
| 184 | dtim_period->tlv.len = | ||
| 185 | cpu_to_le16(sizeof(struct host_cmd_tlv_dtim_period) - | ||
| 186 | sizeof(struct host_cmd_tlv)); | ||
| 187 | dtim_period->period = bss_cfg->dtim_period; | ||
| 188 | cmd_size += sizeof(struct host_cmd_tlv_dtim_period); | ||
| 189 | tlv += sizeof(struct host_cmd_tlv_dtim_period); | ||
| 190 | } | ||
| 191 | if (bss_cfg->rts_threshold <= MWIFIEX_RTS_MAX_VALUE) { | ||
| 192 | rts_threshold = (struct host_cmd_tlv_rts_threshold *)tlv; | ||
| 193 | rts_threshold->tlv.type = | ||
| 194 | cpu_to_le16(TLV_TYPE_UAP_RTS_THRESHOLD); | ||
| 195 | rts_threshold->tlv.len = | ||
| 196 | cpu_to_le16(sizeof(struct host_cmd_tlv_rts_threshold) - | ||
| 197 | sizeof(struct host_cmd_tlv)); | ||
| 198 | rts_threshold->rts_thr = cpu_to_le16(bss_cfg->rts_threshold); | ||
| 199 | cmd_size += sizeof(struct host_cmd_tlv_frag_threshold); | ||
| 200 | tlv += sizeof(struct host_cmd_tlv_frag_threshold); | ||
| 201 | } | ||
| 202 | if ((bss_cfg->frag_threshold >= MWIFIEX_FRAG_MIN_VALUE) && | ||
| 203 | (bss_cfg->frag_threshold <= MWIFIEX_FRAG_MAX_VALUE)) { | ||
| 204 | frag_threshold = (struct host_cmd_tlv_frag_threshold *)tlv; | ||
| 205 | frag_threshold->tlv.type = | ||
| 206 | cpu_to_le16(TLV_TYPE_UAP_FRAG_THRESHOLD); | ||
| 207 | frag_threshold->tlv.len = | ||
| 208 | cpu_to_le16(sizeof(struct host_cmd_tlv_frag_threshold) - | ||
| 209 | sizeof(struct host_cmd_tlv)); | ||
| 210 | frag_threshold->frag_thr = cpu_to_le16(bss_cfg->frag_threshold); | ||
| 211 | cmd_size += sizeof(struct host_cmd_tlv_frag_threshold); | ||
| 212 | tlv += sizeof(struct host_cmd_tlv_frag_threshold); | ||
| 213 | } | ||
| 214 | if (bss_cfg->retry_limit <= MWIFIEX_RETRY_LIMIT) { | ||
| 215 | retry_limit = (struct host_cmd_tlv_retry_limit *)tlv; | ||
| 216 | retry_limit->tlv.type = cpu_to_le16(TLV_TYPE_UAP_RETRY_LIMIT); | ||
| 217 | retry_limit->tlv.len = | ||
| 218 | cpu_to_le16(sizeof(struct host_cmd_tlv_retry_limit) - | ||
| 219 | sizeof(struct host_cmd_tlv)); | ||
| 220 | retry_limit->limit = (u8)bss_cfg->retry_limit; | ||
| 221 | cmd_size += sizeof(struct host_cmd_tlv_retry_limit); | ||
| 222 | tlv += sizeof(struct host_cmd_tlv_retry_limit); | ||
| 223 | } | ||
| 224 | if ((bss_cfg->protocol & PROTOCOL_WPA) || | ||
| 225 | (bss_cfg->protocol & PROTOCOL_WPA2) || | ||
| 226 | (bss_cfg->protocol & PROTOCOL_EAP)) { | ||
| 227 | tlv_akmp = (struct host_cmd_tlv_akmp *)tlv; | ||
| 228 | tlv_akmp->tlv.type = cpu_to_le16(TLV_TYPE_UAP_AKMP); | ||
| 229 | tlv_akmp->tlv.len = | ||
| 230 | cpu_to_le16(sizeof(struct host_cmd_tlv_akmp) - | ||
| 231 | sizeof(struct host_cmd_tlv)); | ||
| 232 | tlv_akmp->key_mgmt_operation = | ||
| 233 | cpu_to_le16(bss_cfg->key_mgmt_operation); | ||
| 234 | tlv_akmp->key_mgmt = cpu_to_le16(bss_cfg->key_mgmt); | ||
| 235 | cmd_size += sizeof(struct host_cmd_tlv_akmp); | ||
| 236 | tlv += sizeof(struct host_cmd_tlv_akmp); | ||
| 237 | |||
| 238 | if (bss_cfg->wpa_cfg.pairwise_cipher_wpa & | ||
| 239 | VALID_CIPHER_BITMAP) { | ||
| 240 | pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv; | ||
| 241 | pwk_cipher->tlv.type = | ||
| 242 | cpu_to_le16(TLV_TYPE_PWK_CIPHER); | ||
| 243 | pwk_cipher->tlv.len = cpu_to_le16( | ||
| 244 | sizeof(struct host_cmd_tlv_pwk_cipher) - | ||
| 245 | sizeof(struct host_cmd_tlv)); | ||
| 246 | pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA); | ||
| 247 | pwk_cipher->cipher = | ||
| 248 | bss_cfg->wpa_cfg.pairwise_cipher_wpa; | ||
| 249 | cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher); | ||
| 250 | tlv += sizeof(struct host_cmd_tlv_pwk_cipher); | ||
| 251 | } | ||
| 252 | if (bss_cfg->wpa_cfg.pairwise_cipher_wpa2 & | ||
| 253 | VALID_CIPHER_BITMAP) { | ||
| 254 | pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv; | ||
| 255 | pwk_cipher->tlv.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER); | ||
| 256 | pwk_cipher->tlv.len = cpu_to_le16( | ||
| 257 | sizeof(struct host_cmd_tlv_pwk_cipher) - | ||
| 258 | sizeof(struct host_cmd_tlv)); | ||
| 259 | pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA2); | ||
| 260 | pwk_cipher->cipher = | ||
| 261 | bss_cfg->wpa_cfg.pairwise_cipher_wpa2; | ||
| 262 | cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher); | ||
| 263 | tlv += sizeof(struct host_cmd_tlv_pwk_cipher); | ||
| 264 | } | ||
| 265 | if (bss_cfg->wpa_cfg.group_cipher & VALID_CIPHER_BITMAP) { | ||
| 266 | gwk_cipher = (struct host_cmd_tlv_gwk_cipher *)tlv; | ||
| 267 | gwk_cipher->tlv.type = cpu_to_le16(TLV_TYPE_GWK_CIPHER); | ||
| 268 | gwk_cipher->tlv.len = cpu_to_le16( | ||
| 269 | sizeof(struct host_cmd_tlv_gwk_cipher) - | ||
| 270 | sizeof(struct host_cmd_tlv)); | ||
| 271 | gwk_cipher->cipher = bss_cfg->wpa_cfg.group_cipher; | ||
| 272 | cmd_size += sizeof(struct host_cmd_tlv_gwk_cipher); | ||
| 273 | tlv += sizeof(struct host_cmd_tlv_gwk_cipher); | ||
| 274 | } | ||
| 275 | if (bss_cfg->wpa_cfg.length) { | ||
| 276 | passphrase = (struct host_cmd_tlv_passphrase *)tlv; | ||
| 277 | passphrase->tlv.type = | ||
| 278 | cpu_to_le16(TLV_TYPE_UAP_WPA_PASSPHRASE); | ||
| 279 | passphrase->tlv.len = | ||
| 280 | cpu_to_le16(bss_cfg->wpa_cfg.length); | ||
| 281 | memcpy(passphrase->passphrase, | ||
| 282 | bss_cfg->wpa_cfg.passphrase, | ||
| 283 | bss_cfg->wpa_cfg.length); | ||
| 284 | cmd_size += sizeof(struct host_cmd_tlv) + | ||
| 285 | bss_cfg->wpa_cfg.length; | ||
| 286 | tlv += sizeof(struct host_cmd_tlv) + | ||
| 287 | bss_cfg->wpa_cfg.length; | ||
| 288 | } | ||
| 289 | } | ||
| 290 | if ((bss_cfg->auth_mode <= WLAN_AUTH_SHARED_KEY) || | ||
| 291 | (bss_cfg->auth_mode == MWIFIEX_AUTH_MODE_AUTO)) { | ||
| 292 | auth_type = (struct host_cmd_tlv_auth_type *)tlv; | ||
| 293 | auth_type->tlv.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE); | ||
| 294 | auth_type->tlv.len = | ||
| 295 | cpu_to_le16(sizeof(struct host_cmd_tlv_auth_type) - | ||
| 296 | sizeof(struct host_cmd_tlv)); | ||
| 297 | auth_type->auth_type = (u8)bss_cfg->auth_mode; | ||
| 298 | cmd_size += sizeof(struct host_cmd_tlv_auth_type); | ||
| 299 | tlv += sizeof(struct host_cmd_tlv_auth_type); | ||
| 300 | } | ||
| 301 | if (bss_cfg->protocol) { | ||
| 302 | encrypt_protocol = (struct host_cmd_tlv_encrypt_protocol *)tlv; | ||
| 303 | encrypt_protocol->tlv.type = | ||
| 304 | cpu_to_le16(TLV_TYPE_UAP_ENCRY_PROTOCOL); | ||
| 305 | encrypt_protocol->tlv.len = | ||
| 306 | cpu_to_le16(sizeof(struct host_cmd_tlv_encrypt_protocol) | ||
| 307 | - sizeof(struct host_cmd_tlv)); | ||
| 308 | encrypt_protocol->proto = cpu_to_le16(bss_cfg->protocol); | ||
| 309 | cmd_size += sizeof(struct host_cmd_tlv_encrypt_protocol); | ||
| 310 | tlv += sizeof(struct host_cmd_tlv_encrypt_protocol); | ||
| 311 | } | ||
| 312 | |||
| 313 | *param_size = cmd_size; | ||
| 314 | |||
| 315 | return 0; | ||
| 316 | } | ||
| 317 | |||
| 318 | /* This function parses custom IEs from IE list and prepares command buffer */ | ||
| 319 | static int mwifiex_uap_custom_ie_prepare(u8 *tlv, void *cmd_buf, u16 *ie_size) | ||
| 320 | { | ||
| 321 | struct mwifiex_ie_list *ap_ie = cmd_buf; | ||
| 322 | struct host_cmd_tlv *tlv_ie = (struct host_cmd_tlv *)tlv; | ||
| 323 | |||
| 324 | if (!ap_ie || !ap_ie->len || !ap_ie->ie_list) | ||
| 325 | return -1; | ||
| 326 | |||
| 327 | *ie_size += le16_to_cpu(ap_ie->len) + sizeof(struct host_cmd_tlv); | ||
| 328 | |||
| 329 | tlv_ie->type = cpu_to_le16(TLV_TYPE_MGMT_IE); | ||
| 330 | tlv_ie->len = ap_ie->len; | ||
| 331 | tlv += sizeof(struct host_cmd_tlv); | ||
| 332 | |||
| 333 | memcpy(tlv, ap_ie->ie_list, le16_to_cpu(ap_ie->len)); | ||
| 334 | |||
| 335 | return 0; | ||
| 336 | } | ||
| 337 | |||
| 338 | /* Parse AP config structure and prepare TLV based command structure | ||
| 339 | * to be sent to FW for uAP configuration | ||
| 340 | */ | ||
| 341 | static int | ||
| 342 | mwifiex_cmd_uap_sys_config(struct host_cmd_ds_command *cmd, u16 cmd_action, | ||
| 343 | u32 type, void *cmd_buf) | ||
| 344 | { | ||
| 345 | u8 *tlv; | ||
| 346 | u16 cmd_size, param_size, ie_size; | ||
| 347 | struct host_cmd_ds_sys_config *sys_cfg; | ||
| 348 | |||
| 349 | cmd->command = cpu_to_le16(HostCmd_CMD_UAP_SYS_CONFIG); | ||
| 350 | cmd_size = (u16)(sizeof(struct host_cmd_ds_sys_config) + S_DS_GEN); | ||
| 351 | sys_cfg = (struct host_cmd_ds_sys_config *)&cmd->params.uap_sys_config; | ||
| 352 | sys_cfg->action = cpu_to_le16(cmd_action); | ||
| 353 | tlv = sys_cfg->tlv; | ||
| 354 | |||
| 355 | switch (type) { | ||
| 356 | case UAP_BSS_PARAMS_I: | ||
| 357 | param_size = cmd_size; | ||
| 358 | if (mwifiex_uap_bss_param_prepare(tlv, cmd_buf, ¶m_size)) | ||
| 359 | return -1; | ||
| 360 | cmd->size = cpu_to_le16(param_size); | ||
| 361 | break; | ||
| 362 | case UAP_CUSTOM_IE_I: | ||
| 363 | ie_size = cmd_size; | ||
| 364 | if (mwifiex_uap_custom_ie_prepare(tlv, cmd_buf, &ie_size)) | ||
| 365 | return -1; | ||
| 366 | cmd->size = cpu_to_le16(ie_size); | ||
| 367 | break; | ||
| 368 | default: | ||
| 369 | return -1; | ||
| 370 | } | ||
| 371 | |||
| 372 | return 0; | ||
| 373 | } | ||
| 374 | |||
| 375 | /* This function prepares the AP specific commands before sending them | ||
| 376 | * to the firmware. | ||
| 377 | * This is a generic function which calls specific command preparation | ||
| 378 | * routines based upon the command number. | ||
| 379 | */ | ||
| 380 | int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no, | ||
| 381 | u16 cmd_action, u32 type, | ||
| 382 | void *data_buf, void *cmd_buf) | ||
| 383 | { | ||
| 384 | struct host_cmd_ds_command *cmd = cmd_buf; | ||
| 385 | |||
| 386 | switch (cmd_no) { | ||
| 387 | case HostCmd_CMD_UAP_SYS_CONFIG: | ||
| 388 | if (mwifiex_cmd_uap_sys_config(cmd, cmd_action, type, data_buf)) | ||
| 389 | return -1; | ||
| 390 | break; | ||
| 391 | case HostCmd_CMD_UAP_BSS_START: | ||
| 392 | case HostCmd_CMD_UAP_BSS_STOP: | ||
| 393 | cmd->command = cpu_to_le16(cmd_no); | ||
| 394 | cmd->size = cpu_to_le16(S_DS_GEN); | ||
| 395 | break; | ||
| 396 | default: | ||
| 397 | dev_err(priv->adapter->dev, | ||
| 398 | "PREP_CMD: unknown cmd %#x\n", cmd_no); | ||
| 399 | return -1; | ||
| 400 | } | ||
| 401 | |||
| 402 | return 0; | ||
| 403 | } | ||
| 404 | |||
| 405 | /* This function sets the RF channel for AP. | ||
| 406 | * | ||
| 407 | * This function populates channel information in AP config structure | ||
| 408 | * and sends command to configure channel information in AP. | ||
| 409 | */ | ||
| 410 | int mwifiex_uap_set_channel(struct mwifiex_private *priv, int channel) | ||
| 411 | { | ||
| 412 | struct mwifiex_uap_bss_param *bss_cfg; | ||
| 413 | struct wiphy *wiphy = priv->wdev->wiphy; | ||
| 414 | |||
| 415 | bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL); | ||
| 416 | if (!bss_cfg) | ||
| 417 | return -ENOMEM; | ||
| 418 | |||
| 419 | bss_cfg->band_cfg = BAND_CONFIG_MANUAL; | ||
| 420 | bss_cfg->channel = channel; | ||
| 421 | |||
| 422 | if (mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_SYS_CONFIG, | ||
| 423 | HostCmd_ACT_GEN_SET, | ||
| 424 | UAP_BSS_PARAMS_I, bss_cfg)) { | ||
| 425 | wiphy_err(wiphy, "Failed to set the uAP channel\n"); | ||
| 426 | kfree(bss_cfg); | ||
| 427 | return -1; | ||
| 428 | } | ||
| 429 | |||
| 430 | kfree(bss_cfg); | ||
| 431 | return 0; | ||
| 432 | } | ||
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 429a1dee2d2..f3fc6551585 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c | |||
| @@ -885,6 +885,10 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, | |||
| 885 | tid_ptr = &(priv_tmp)->wmm. | 885 | tid_ptr = &(priv_tmp)->wmm. |
| 886 | tid_tbl_ptr[tos_to_tid[i]]; | 886 | tid_tbl_ptr[tos_to_tid[i]]; |
| 887 | 887 | ||
| 888 | /* For non-STA ra_list_curr may be NULL */ | ||
| 889 | if (!tid_ptr->ra_list_curr) | ||
| 890 | continue; | ||
| 891 | |||
| 888 | spin_lock_irqsave(&tid_ptr->tid_tbl_lock, | 892 | spin_lock_irqsave(&tid_ptr->tid_tbl_lock, |
| 889 | flags); | 893 | flags); |
| 890 | is_list_empty = | 894 | is_list_empty = |
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index b91d1bb30b4..f11953b2602 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
| @@ -505,9 +505,6 @@ static int rndis_join_ibss(struct wiphy *wiphy, struct net_device *dev, | |||
| 505 | 505 | ||
| 506 | static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev); | 506 | static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev); |
| 507 | 507 | ||
| 508 | static int rndis_set_channel(struct wiphy *wiphy, struct net_device *dev, | ||
| 509 | struct ieee80211_channel *chan, enum nl80211_channel_type channel_type); | ||
| 510 | |||
| 511 | static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev, | 508 | static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev, |
| 512 | u8 key_index, bool pairwise, const u8 *mac_addr, | 509 | u8 key_index, bool pairwise, const u8 *mac_addr, |
| 513 | struct key_params *params); | 510 | struct key_params *params); |
| @@ -549,7 +546,6 @@ static const struct cfg80211_ops rndis_config_ops = { | |||
| 549 | .disconnect = rndis_disconnect, | 546 | .disconnect = rndis_disconnect, |
| 550 | .join_ibss = rndis_join_ibss, | 547 | .join_ibss = rndis_join_ibss, |
| 551 | .leave_ibss = rndis_leave_ibss, | 548 | .leave_ibss = rndis_leave_ibss, |
| 552 | .set_channel = rndis_set_channel, | ||
| 553 | .add_key = rndis_add_key, | 549 | .add_key = rndis_add_key, |
| 554 | .del_key = rndis_del_key, | 550 | .del_key = rndis_del_key, |
| 555 | .set_default_key = rndis_set_default_key, | 551 | .set_default_key = rndis_set_default_key, |
| @@ -2398,16 +2394,6 @@ static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev) | |||
| 2398 | return deauthenticate(usbdev); | 2394 | return deauthenticate(usbdev); |
| 2399 | } | 2395 | } |
| 2400 | 2396 | ||
| 2401 | static int rndis_set_channel(struct wiphy *wiphy, struct net_device *netdev, | ||
| 2402 | struct ieee80211_channel *chan, enum nl80211_channel_type channel_type) | ||
| 2403 | { | ||
| 2404 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); | ||
| 2405 | struct usbnet *usbdev = priv->usbdev; | ||
| 2406 | |||
| 2407 | return set_channel(usbdev, | ||
| 2408 | ieee80211_frequency_to_channel(chan->center_freq)); | ||
| 2409 | } | ||
| 2410 | |||
| 2411 | static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev, | 2397 | static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev, |
| 2412 | u8 key_index, bool pairwise, const u8 *mac_addr, | 2398 | u8 key_index, bool pairwise, const u8 *mac_addr, |
| 2413 | struct key_params *params) | 2399 | struct key_params *params) |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 931331d9521..cad25bfebd7 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
| @@ -1192,6 +1192,7 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { | |||
| 1192 | { PCI_DEVICE(0x1814, 0x5390) }, | 1192 | { PCI_DEVICE(0x1814, 0x5390) }, |
| 1193 | { PCI_DEVICE(0x1814, 0x5392) }, | 1193 | { PCI_DEVICE(0x1814, 0x5392) }, |
| 1194 | { PCI_DEVICE(0x1814, 0x539a) }, | 1194 | { PCI_DEVICE(0x1814, 0x539a) }, |
| 1195 | { PCI_DEVICE(0x1814, 0x539b) }, | ||
| 1195 | { PCI_DEVICE(0x1814, 0x539f) }, | 1196 | { PCI_DEVICE(0x1814, 0x539f) }, |
| 1196 | #endif | 1197 | #endif |
| 1197 | { 0, } | 1198 | { 0, } |
diff --git a/drivers/net/wireless/ti/wl12xx/Kconfig b/drivers/net/wireless/ti/wl12xx/Kconfig index 5b92329122c..c2183594655 100644 --- a/drivers/net/wireless/ti/wl12xx/Kconfig +++ b/drivers/net/wireless/ti/wl12xx/Kconfig | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | config WL12XX | 1 | config WL12XX |
| 2 | tristate "TI wl12xx support" | 2 | tristate "TI wl12xx support" |
| 3 | depends on MAC80211 | ||
| 3 | select WLCORE | 4 | select WLCORE |
| 4 | ---help--- | 5 | ---help--- |
| 5 | This module adds support for wireless adapters based on TI wl1271, | 6 | This module adds support for wireless adapters based on TI wl1271, |
diff --git a/drivers/net/wireless/ti/wlcore/Kconfig b/drivers/net/wireless/ti/wlcore/Kconfig index 9d04c38938b..54156b0b5c2 100644 --- a/drivers/net/wireless/ti/wlcore/Kconfig +++ b/drivers/net/wireless/ti/wlcore/Kconfig | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | config WLCORE | 1 | config WLCORE |
| 2 | tristate "TI wlcore support" | 2 | tristate "TI wlcore support" |
| 3 | depends on WL_TI && GENERIC_HARDIRQS | 3 | depends on WL_TI && GENERIC_HARDIRQS && MAC80211 |
| 4 | depends on INET | 4 | depends on INET |
| 5 | select FW_LOADER | 5 | select FW_LOADER |
| 6 | ---help--- | 6 | ---help--- |
diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c index 5912541a925..509aa881d79 100644 --- a/drivers/net/wireless/ti/wlcore/acx.c +++ b/drivers/net/wireless/ti/wlcore/acx.c | |||
| @@ -1714,3 +1714,83 @@ out: | |||
| 1714 | return ret; | 1714 | return ret; |
| 1715 | 1715 | ||
| 1716 | } | 1716 | } |
| 1717 | |||
| 1718 | /* Set the global behaviour of RX filters - On/Off + default action */ | ||
| 1719 | int wl1271_acx_default_rx_filter_enable(struct wl1271 *wl, bool enable, | ||
| 1720 | enum rx_filter_action action) | ||
| 1721 | { | ||
| 1722 | struct acx_default_rx_filter *acx; | ||
| 1723 | int ret; | ||
| 1724 | |||
| 1725 | wl1271_debug(DEBUG_ACX, "acx default rx filter en: %d act: %d", | ||
| 1726 | enable, action); | ||
| 1727 | |||
| 1728 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
| 1729 | if (!acx) | ||
| 1730 | return -ENOMEM; | ||
| 1731 | |||
| 1732 | acx->enable = enable; | ||
| 1733 | acx->default_action = action; | ||
| 1734 | |||
| 1735 | ret = wl1271_cmd_configure(wl, ACX_ENABLE_RX_DATA_FILTER, acx, | ||
| 1736 | sizeof(*acx)); | ||
| 1737 | if (ret < 0) { | ||
| 1738 | wl1271_warning("acx default rx filter enable failed: %d", ret); | ||
| 1739 | goto out; | ||
| 1740 | } | ||
| 1741 | |||
| 1742 | out: | ||
| 1743 | kfree(acx); | ||
| 1744 | return ret; | ||
| 1745 | } | ||
| 1746 | |||
| 1747 | /* Configure or disable a specific RX filter pattern */ | ||
| 1748 | int wl1271_acx_set_rx_filter(struct wl1271 *wl, u8 index, bool enable, | ||
| 1749 | struct wl12xx_rx_filter *filter) | ||
| 1750 | { | ||
| 1751 | struct acx_rx_filter_cfg *acx; | ||
| 1752 | int fields_size = 0; | ||
| 1753 | int acx_size; | ||
| 1754 | int ret; | ||
| 1755 | |||
| 1756 | WARN_ON(enable && !filter); | ||
| 1757 | WARN_ON(index >= WL1271_MAX_RX_FILTERS); | ||
| 1758 | |||
| 1759 | wl1271_debug(DEBUG_ACX, | ||
| 1760 | "acx set rx filter idx: %d enable: %d filter: %p", | ||
| 1761 | index, enable, filter); | ||
| 1762 | |||
| 1763 | if (enable) { | ||
| 1764 | fields_size = wl1271_rx_filter_get_fields_size(filter); | ||
| 1765 | |||
| 1766 | wl1271_debug(DEBUG_ACX, "act: %d num_fields: %d field_size: %d", | ||
| 1767 | filter->action, filter->num_fields, fields_size); | ||
| 1768 | } | ||
| 1769 | |||
| 1770 | acx_size = ALIGN(sizeof(*acx) + fields_size, 4); | ||
| 1771 | acx = kzalloc(acx_size, GFP_KERNEL); | ||
| 1772 | |||
| 1773 | if (!acx) | ||
| 1774 | return -ENOMEM; | ||
| 1775 | |||
| 1776 | acx->enable = enable; | ||
| 1777 | acx->index = index; | ||
| 1778 | |||
| 1779 | if (enable) { | ||
| 1780 | acx->num_fields = filter->num_fields; | ||
| 1781 | acx->action = filter->action; | ||
| 1782 | wl1271_rx_filter_flatten_fields(filter, acx->fields); | ||
| 1783 | } | ||
| 1784 | |||
| 1785 | wl1271_dump(DEBUG_ACX, "RX_FILTER: ", acx, acx_size); | ||
| 1786 | |||
| 1787 | ret = wl1271_cmd_configure(wl, ACX_SET_RX_DATA_FILTER, acx, acx_size); | ||
| 1788 | if (ret < 0) { | ||
| 1789 | wl1271_warning("setting rx filter failed: %d", ret); | ||
| 1790 | goto out; | ||
| 1791 | } | ||
| 1792 | |||
| 1793 | out: | ||
| 1794 | kfree(acx); | ||
| 1795 | return ret; | ||
| 1796 | } | ||
diff --git a/drivers/net/wireless/ti/wlcore/acx.h b/drivers/net/wireless/ti/wlcore/acx.h index b2f88831b7a..8106b2ebfe6 100644 --- a/drivers/net/wireless/ti/wlcore/acx.h +++ b/drivers/net/wireless/ti/wlcore/acx.h | |||
| @@ -1147,6 +1147,32 @@ struct wl12xx_acx_config_hangover { | |||
| 1147 | u8 padding[2]; | 1147 | u8 padding[2]; |
| 1148 | } __packed; | 1148 | } __packed; |
| 1149 | 1149 | ||
| 1150 | |||
| 1151 | struct acx_default_rx_filter { | ||
| 1152 | struct acx_header header; | ||
| 1153 | u8 enable; | ||
| 1154 | |||
| 1155 | /* action of type FILTER_XXX */ | ||
| 1156 | u8 default_action; | ||
| 1157 | |||
| 1158 | u8 pad[2]; | ||
| 1159 | } __packed; | ||
| 1160 | |||
| 1161 | |||
| 1162 | struct acx_rx_filter_cfg { | ||
| 1163 | struct acx_header header; | ||
| 1164 | |||
| 1165 | u8 enable; | ||
| 1166 | |||
| 1167 | /* 0 - WL1271_MAX_RX_FILTERS-1 */ | ||
| 1168 | u8 index; | ||
| 1169 | |||
| 1170 | u8 action; | ||
| 1171 | |||
| 1172 | u8 num_fields; | ||
| 1173 | u8 fields[0]; | ||
| 1174 | } __packed; | ||
| 1175 | |||
| 1150 | enum { | 1176 | enum { |
| 1151 | ACX_WAKE_UP_CONDITIONS = 0x0000, | 1177 | ACX_WAKE_UP_CONDITIONS = 0x0000, |
| 1152 | ACX_MEM_CFG = 0x0001, | 1178 | ACX_MEM_CFG = 0x0001, |
| @@ -1304,5 +1330,9 @@ int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); | |||
| 1304 | int wl1271_acx_fm_coex(struct wl1271 *wl); | 1330 | int wl1271_acx_fm_coex(struct wl1271 *wl); |
| 1305 | int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl); | 1331 | int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl); |
| 1306 | int wl12xx_acx_config_hangover(struct wl1271 *wl); | 1332 | int wl12xx_acx_config_hangover(struct wl1271 *wl); |
| 1333 | int wl1271_acx_default_rx_filter_enable(struct wl1271 *wl, bool enable, | ||
| 1334 | enum rx_filter_action action); | ||
| 1335 | int wl1271_acx_set_rx_filter(struct wl1271 *wl, u8 index, bool enable, | ||
| 1336 | struct wl12xx_rx_filter *filter); | ||
| 1307 | 1337 | ||
| 1308 | #endif /* __WL1271_ACX_H__ */ | 1338 | #endif /* __WL1271_ACX_H__ */ |
diff --git a/drivers/net/wireless/ti/wlcore/boot.c b/drivers/net/wireless/ti/wlcore/boot.c index 3a2207db540..9b98230f84c 100644 --- a/drivers/net/wireless/ti/wlcore/boot.c +++ b/drivers/net/wireless/ti/wlcore/boot.c | |||
| @@ -72,7 +72,7 @@ static int wlcore_boot_fw_version(struct wl1271 *wl) | |||
| 72 | struct wl1271_static_data *static_data; | 72 | struct wl1271_static_data *static_data; |
| 73 | int ret; | 73 | int ret; |
| 74 | 74 | ||
| 75 | static_data = kmalloc(sizeof(*static_data), GFP_DMA); | 75 | static_data = kmalloc(sizeof(*static_data), GFP_KERNEL | GFP_DMA); |
| 76 | if (!static_data) { | 76 | if (!static_data) { |
| 77 | wl1271_error("Couldn't allocate memory for static data!"); | 77 | wl1271_error("Couldn't allocate memory for static data!"); |
| 78 | return -ENOMEM; | 78 | return -ENOMEM; |
| @@ -413,6 +413,7 @@ int wlcore_boot_run_firmware(struct wl1271 *wl) | |||
| 413 | 413 | ||
| 414 | /* unmask required mbox events */ | 414 | /* unmask required mbox events */ |
| 415 | wl->event_mask = BSS_LOSE_EVENT_ID | | 415 | wl->event_mask = BSS_LOSE_EVENT_ID | |
| 416 | REGAINED_BSS_EVENT_ID | | ||
| 416 | SCAN_COMPLETE_EVENT_ID | | 417 | SCAN_COMPLETE_EVENT_ID | |
| 417 | ROLE_STOP_COMPLETE_EVENT_ID | | 418 | ROLE_STOP_COMPLETE_EVENT_ID | |
| 418 | RSSI_SNR_TRIGGER_0_EVENT_ID | | 419 | RSSI_SNR_TRIGGER_0_EVENT_ID | |
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 5c4716c6f04..5b128a97144 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c | |||
| @@ -123,7 +123,9 @@ static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, u32 mask) | |||
| 123 | unsigned long timeout; | 123 | unsigned long timeout; |
| 124 | int ret = 0; | 124 | int ret = 0; |
| 125 | 125 | ||
| 126 | events_vector = kmalloc(sizeof(*events_vector), GFP_DMA); | 126 | events_vector = kmalloc(sizeof(*events_vector), GFP_KERNEL | GFP_DMA); |
| 127 | if (!events_vector) | ||
| 128 | return -ENOMEM; | ||
| 127 | 129 | ||
| 128 | timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); | 130 | timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); |
| 129 | 131 | ||
| @@ -1034,7 +1036,7 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
| 1034 | skb_reserve(skb, sizeof(*hdr) + WL1271_EXTRA_SPACE_MAX); | 1036 | skb_reserve(skb, sizeof(*hdr) + WL1271_EXTRA_SPACE_MAX); |
| 1035 | 1037 | ||
| 1036 | tmpl = (struct wl12xx_arp_rsp_template *)skb_put(skb, sizeof(*tmpl)); | 1038 | tmpl = (struct wl12xx_arp_rsp_template *)skb_put(skb, sizeof(*tmpl)); |
| 1037 | memset(tmpl, 0, sizeof(tmpl)); | 1039 | memset(tmpl, 0, sizeof(*tmpl)); |
| 1038 | 1040 | ||
| 1039 | /* llc layer */ | 1041 | /* llc layer */ |
| 1040 | memcpy(tmpl->llc_hdr, rfc1042_header, sizeof(rfc1042_header)); | 1042 | memcpy(tmpl->llc_hdr, rfc1042_header, sizeof(rfc1042_header)); |
| @@ -1083,7 +1085,7 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
| 1083 | 1085 | ||
| 1084 | /* mac80211 header */ | 1086 | /* mac80211 header */ |
| 1085 | hdr = (struct ieee80211_hdr_3addr *)skb_push(skb, sizeof(*hdr)); | 1087 | hdr = (struct ieee80211_hdr_3addr *)skb_push(skb, sizeof(*hdr)); |
| 1086 | memset(hdr, 0, sizeof(hdr)); | 1088 | memset(hdr, 0, sizeof(*hdr)); |
| 1087 | fc = IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS; | 1089 | fc = IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS; |
| 1088 | if (wlvif->sta.qos) | 1090 | if (wlvif->sta.qos) |
| 1089 | fc |= IEEE80211_STYPE_QOS_DATA; | 1091 | fc |= IEEE80211_STYPE_QOS_DATA; |
diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c index 292632ddf89..28e2a633c3b 100644 --- a/drivers/net/wireless/ti/wlcore/event.c +++ b/drivers/net/wireless/ti/wlcore/event.c | |||
| @@ -103,7 +103,6 @@ static int wl1271_event_process(struct wl1271 *wl) | |||
| 103 | struct ieee80211_vif *vif; | 103 | struct ieee80211_vif *vif; |
| 104 | struct wl12xx_vif *wlvif; | 104 | struct wl12xx_vif *wlvif; |
| 105 | u32 vector; | 105 | u32 vector; |
| 106 | bool beacon_loss = false; | ||
| 107 | bool disconnect_sta = false; | 106 | bool disconnect_sta = false; |
| 108 | unsigned long sta_bitmap = 0; | 107 | unsigned long sta_bitmap = 0; |
| 109 | 108 | ||
| @@ -141,20 +140,23 @@ static int wl1271_event_process(struct wl1271 *wl) | |||
| 141 | mbox->soft_gemini_sense_info); | 140 | mbox->soft_gemini_sense_info); |
| 142 | 141 | ||
| 143 | /* | 142 | /* |
| 144 | * The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon | 143 | * We are HW_MONITOR device. On beacon loss - queue |
| 145 | * filtering) is enabled. Without PSM, the stack will receive all | 144 | * connection loss work. Cancel it on REGAINED event. |
| 146 | * beacons and can detect beacon loss by itself. | ||
| 147 | * | ||
| 148 | * As there's possibility that the driver disables PSM before receiving | ||
| 149 | * BSS_LOSE_EVENT, beacon loss has to be reported to the stack. | ||
| 150 | * | ||
| 151 | */ | 145 | */ |
| 152 | if (vector & BSS_LOSE_EVENT_ID) { | 146 | if (vector & BSS_LOSE_EVENT_ID) { |
| 153 | /* TODO: check for multi-role */ | 147 | /* TODO: check for multi-role */ |
| 148 | int delay = wl->conf.conn.synch_fail_thold * | ||
| 149 | wl->conf.conn.bss_lose_timeout; | ||
| 154 | wl1271_info("Beacon loss detected."); | 150 | wl1271_info("Beacon loss detected."); |
| 151 | cancel_delayed_work_sync(&wl->connection_loss_work); | ||
| 152 | ieee80211_queue_delayed_work(wl->hw, &wl->connection_loss_work, | ||
| 153 | msecs_to_jiffies(delay)); | ||
| 154 | } | ||
| 155 | 155 | ||
| 156 | /* indicate to the stack, that beacons have been lost */ | 156 | if (vector & REGAINED_BSS_EVENT_ID) { |
| 157 | beacon_loss = true; | 157 | /* TODO: check for multi-role */ |
| 158 | wl1271_info("Beacon regained."); | ||
| 159 | cancel_delayed_work_sync(&wl->connection_loss_work); | ||
| 158 | } | 160 | } |
| 159 | 161 | ||
| 160 | if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { | 162 | if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { |
| @@ -257,13 +259,6 @@ static int wl1271_event_process(struct wl1271 *wl) | |||
| 257 | rcu_read_unlock(); | 259 | rcu_read_unlock(); |
| 258 | } | 260 | } |
| 259 | } | 261 | } |
| 260 | |||
| 261 | if (beacon_loss) | ||
| 262 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | ||
| 263 | vif = wl12xx_wlvif_to_vif(wlvif); | ||
| 264 | ieee80211_connection_loss(vif); | ||
| 265 | } | ||
| 266 | |||
| 267 | return 0; | 262 | return 0; |
| 268 | } | 263 | } |
| 269 | 264 | ||
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 2b0f987660c..acef93390d3 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
| @@ -1120,6 +1120,7 @@ int wl1271_plt_stop(struct wl1271 *wl) | |||
| 1120 | cancel_work_sync(&wl->recovery_work); | 1120 | cancel_work_sync(&wl->recovery_work); |
| 1121 | cancel_delayed_work_sync(&wl->elp_work); | 1121 | cancel_delayed_work_sync(&wl->elp_work); |
| 1122 | cancel_delayed_work_sync(&wl->tx_watchdog_work); | 1122 | cancel_delayed_work_sync(&wl->tx_watchdog_work); |
| 1123 | cancel_delayed_work_sync(&wl->connection_loss_work); | ||
| 1123 | 1124 | ||
| 1124 | mutex_lock(&wl->mutex); | 1125 | mutex_lock(&wl->mutex); |
| 1125 | wl1271_power_off(wl); | 1126 | wl1271_power_off(wl); |
| @@ -1261,8 +1262,270 @@ static struct sk_buff *wl12xx_alloc_dummy_packet(struct wl1271 *wl) | |||
| 1261 | 1262 | ||
| 1262 | 1263 | ||
| 1263 | #ifdef CONFIG_PM | 1264 | #ifdef CONFIG_PM |
| 1265 | static int | ||
| 1266 | wl1271_validate_wowlan_pattern(struct cfg80211_wowlan_trig_pkt_pattern *p) | ||
| 1267 | { | ||
| 1268 | int num_fields = 0, in_field = 0, fields_size = 0; | ||
| 1269 | int i, pattern_len = 0; | ||
| 1270 | |||
| 1271 | if (!p->mask) { | ||
| 1272 | wl1271_warning("No mask in WoWLAN pattern"); | ||
| 1273 | return -EINVAL; | ||
| 1274 | } | ||
| 1275 | |||
| 1276 | /* | ||
| 1277 | * The pattern is broken up into segments of bytes at different offsets | ||
| 1278 | * that need to be checked by the FW filter. Each segment is called | ||
| 1279 | * a field in the FW API. We verify that the total number of fields | ||
| 1280 | * required for this pattern won't exceed FW limits (8) | ||
| 1281 | * as well as the total fields buffer won't exceed the FW limit. | ||
| 1282 | * Note that if there's a pattern which crosses Ethernet/IP header | ||
| 1283 | * boundary a new field is required. | ||
| 1284 | */ | ||
| 1285 | for (i = 0; i < p->pattern_len; i++) { | ||
| 1286 | if (test_bit(i, (unsigned long *)p->mask)) { | ||
| 1287 | if (!in_field) { | ||
| 1288 | in_field = 1; | ||
| 1289 | pattern_len = 1; | ||
| 1290 | } else { | ||
| 1291 | if (i == WL1271_RX_FILTER_ETH_HEADER_SIZE) { | ||
| 1292 | num_fields++; | ||
| 1293 | fields_size += pattern_len + | ||
| 1294 | RX_FILTER_FIELD_OVERHEAD; | ||
| 1295 | pattern_len = 1; | ||
| 1296 | } else | ||
| 1297 | pattern_len++; | ||
| 1298 | } | ||
| 1299 | } else { | ||
| 1300 | if (in_field) { | ||
| 1301 | in_field = 0; | ||
| 1302 | fields_size += pattern_len + | ||
| 1303 | RX_FILTER_FIELD_OVERHEAD; | ||
| 1304 | num_fields++; | ||
| 1305 | } | ||
| 1306 | } | ||
| 1307 | } | ||
| 1308 | |||
| 1309 | if (in_field) { | ||
| 1310 | fields_size += pattern_len + RX_FILTER_FIELD_OVERHEAD; | ||
| 1311 | num_fields++; | ||
| 1312 | } | ||
| 1313 | |||
| 1314 | if (num_fields > WL1271_RX_FILTER_MAX_FIELDS) { | ||
| 1315 | wl1271_warning("RX Filter too complex. Too many segments"); | ||
| 1316 | return -EINVAL; | ||
| 1317 | } | ||
| 1318 | |||
| 1319 | if (fields_size > WL1271_RX_FILTER_MAX_FIELDS_SIZE) { | ||
| 1320 | wl1271_warning("RX filter pattern is too big"); | ||
| 1321 | return -E2BIG; | ||
| 1322 | } | ||
| 1323 | |||
| 1324 | return 0; | ||
| 1325 | } | ||
| 1326 | |||
| 1327 | struct wl12xx_rx_filter *wl1271_rx_filter_alloc(void) | ||
| 1328 | { | ||
| 1329 | return kzalloc(sizeof(struct wl12xx_rx_filter), GFP_KERNEL); | ||
| 1330 | } | ||
| 1331 | |||
| 1332 | void wl1271_rx_filter_free(struct wl12xx_rx_filter *filter) | ||
| 1333 | { | ||
| 1334 | int i; | ||
| 1335 | |||
| 1336 | if (filter == NULL) | ||
| 1337 | return; | ||
| 1338 | |||
| 1339 | for (i = 0; i < filter->num_fields; i++) | ||
| 1340 | kfree(filter->fields[i].pattern); | ||
| 1341 | |||
| 1342 | kfree(filter); | ||
| 1343 | } | ||
| 1344 | |||
| 1345 | int wl1271_rx_filter_alloc_field(struct wl12xx_rx_filter *filter, | ||
| 1346 | u16 offset, u8 flags, | ||
| 1347 | u8 *pattern, u8 len) | ||
| 1348 | { | ||
| 1349 | struct wl12xx_rx_filter_field *field; | ||
| 1350 | |||
| 1351 | if (filter->num_fields == WL1271_RX_FILTER_MAX_FIELDS) { | ||
| 1352 | wl1271_warning("Max fields per RX filter. can't alloc another"); | ||
| 1353 | return -EINVAL; | ||
| 1354 | } | ||
| 1355 | |||
| 1356 | field = &filter->fields[filter->num_fields]; | ||
| 1357 | |||
| 1358 | field->pattern = kzalloc(len, GFP_KERNEL); | ||
| 1359 | if (!field->pattern) { | ||
| 1360 | wl1271_warning("Failed to allocate RX filter pattern"); | ||
| 1361 | return -ENOMEM; | ||
| 1362 | } | ||
| 1363 | |||
| 1364 | filter->num_fields++; | ||
| 1365 | |||
| 1366 | field->offset = cpu_to_le16(offset); | ||
| 1367 | field->flags = flags; | ||
| 1368 | field->len = len; | ||
| 1369 | memcpy(field->pattern, pattern, len); | ||
| 1370 | |||
| 1371 | return 0; | ||
| 1372 | } | ||
| 1373 | |||
| 1374 | int wl1271_rx_filter_get_fields_size(struct wl12xx_rx_filter *filter) | ||
| 1375 | { | ||
| 1376 | int i, fields_size = 0; | ||
| 1377 | |||
| 1378 | for (i = 0; i < filter->num_fields; i++) | ||
| 1379 | fields_size += filter->fields[i].len + | ||
| 1380 | sizeof(struct wl12xx_rx_filter_field) - | ||
| 1381 | sizeof(u8 *); | ||
| 1382 | |||
| 1383 | return fields_size; | ||
| 1384 | } | ||
| 1385 | |||
| 1386 | void wl1271_rx_filter_flatten_fields(struct wl12xx_rx_filter *filter, | ||
| 1387 | u8 *buf) | ||
| 1388 | { | ||
| 1389 | int i; | ||
| 1390 | struct wl12xx_rx_filter_field *field; | ||
| 1391 | |||
| 1392 | for (i = 0; i < filter->num_fields; i++) { | ||
| 1393 | field = (struct wl12xx_rx_filter_field *)buf; | ||
| 1394 | |||
| 1395 | field->offset = filter->fields[i].offset; | ||
| 1396 | field->flags = filter->fields[i].flags; | ||
| 1397 | field->len = filter->fields[i].len; | ||
| 1398 | |||
| 1399 | memcpy(&field->pattern, filter->fields[i].pattern, field->len); | ||
| 1400 | buf += sizeof(struct wl12xx_rx_filter_field) - | ||
| 1401 | sizeof(u8 *) + field->len; | ||
| 1402 | } | ||
| 1403 | } | ||
| 1404 | |||
| 1405 | /* | ||
| 1406 | * Allocates an RX filter returned through f | ||
| 1407 | * which needs to be freed using rx_filter_free() | ||
| 1408 | */ | ||
| 1409 | static int wl1271_convert_wowlan_pattern_to_rx_filter( | ||
| 1410 | struct cfg80211_wowlan_trig_pkt_pattern *p, | ||
| 1411 | struct wl12xx_rx_filter **f) | ||
| 1412 | { | ||
| 1413 | int i, j, ret = 0; | ||
| 1414 | struct wl12xx_rx_filter *filter; | ||
| 1415 | u16 offset; | ||
| 1416 | u8 flags, len; | ||
| 1417 | |||
| 1418 | filter = wl1271_rx_filter_alloc(); | ||
| 1419 | if (!filter) { | ||
| 1420 | wl1271_warning("Failed to alloc rx filter"); | ||
| 1421 | ret = -ENOMEM; | ||
| 1422 | goto err; | ||
| 1423 | } | ||
| 1424 | |||
| 1425 | i = 0; | ||
| 1426 | while (i < p->pattern_len) { | ||
| 1427 | if (!test_bit(i, (unsigned long *)p->mask)) { | ||
| 1428 | i++; | ||
| 1429 | continue; | ||
| 1430 | } | ||
| 1431 | |||
| 1432 | for (j = i; j < p->pattern_len; j++) { | ||
| 1433 | if (!test_bit(j, (unsigned long *)p->mask)) | ||
| 1434 | break; | ||
| 1435 | |||
| 1436 | if (i < WL1271_RX_FILTER_ETH_HEADER_SIZE && | ||
| 1437 | j >= WL1271_RX_FILTER_ETH_HEADER_SIZE) | ||
| 1438 | break; | ||
| 1439 | } | ||
| 1440 | |||
| 1441 | if (i < WL1271_RX_FILTER_ETH_HEADER_SIZE) { | ||
| 1442 | offset = i; | ||
| 1443 | flags = WL1271_RX_FILTER_FLAG_ETHERNET_HEADER; | ||
| 1444 | } else { | ||
| 1445 | offset = i - WL1271_RX_FILTER_ETH_HEADER_SIZE; | ||
| 1446 | flags = WL1271_RX_FILTER_FLAG_IP_HEADER; | ||
| 1447 | } | ||
| 1448 | |||
| 1449 | len = j - i; | ||
| 1450 | |||
| 1451 | ret = wl1271_rx_filter_alloc_field(filter, | ||
| 1452 | offset, | ||
| 1453 | flags, | ||
| 1454 | &p->pattern[i], len); | ||
| 1455 | if (ret) | ||
| 1456 | goto err; | ||
| 1457 | |||
| 1458 | i = j; | ||
| 1459 | } | ||
| 1460 | |||
| 1461 | filter->action = FILTER_SIGNAL; | ||
| 1462 | |||
| 1463 | *f = filter; | ||
| 1464 | return 0; | ||
| 1465 | |||
| 1466 | err: | ||
| 1467 | wl1271_rx_filter_free(filter); | ||
| 1468 | *f = NULL; | ||
| 1469 | |||
| 1470 | return ret; | ||
| 1471 | } | ||
| 1472 | |||
| 1473 | static int wl1271_configure_wowlan(struct wl1271 *wl, | ||
| 1474 | struct cfg80211_wowlan *wow) | ||
| 1475 | { | ||
| 1476 | int i, ret; | ||
| 1477 | |||
| 1478 | if (!wow || wow->any || !wow->n_patterns) { | ||
| 1479 | wl1271_acx_default_rx_filter_enable(wl, 0, FILTER_SIGNAL); | ||
| 1480 | wl1271_rx_filter_clear_all(wl); | ||
| 1481 | return 0; | ||
| 1482 | } | ||
| 1483 | |||
| 1484 | if (WARN_ON(wow->n_patterns > WL1271_MAX_RX_FILTERS)) | ||
| 1485 | return -EINVAL; | ||
| 1486 | |||
| 1487 | /* Validate all incoming patterns before clearing current FW state */ | ||
| 1488 | for (i = 0; i < wow->n_patterns; i++) { | ||
| 1489 | ret = wl1271_validate_wowlan_pattern(&wow->patterns[i]); | ||
| 1490 | if (ret) { | ||
| 1491 | wl1271_warning("Bad wowlan pattern %d", i); | ||
| 1492 | return ret; | ||
| 1493 | } | ||
| 1494 | } | ||
| 1495 | |||
| 1496 | wl1271_acx_default_rx_filter_enable(wl, 0, FILTER_SIGNAL); | ||
| 1497 | wl1271_rx_filter_clear_all(wl); | ||
| 1498 | |||
| 1499 | /* Translate WoWLAN patterns into filters */ | ||
| 1500 | for (i = 0; i < wow->n_patterns; i++) { | ||
| 1501 | struct cfg80211_wowlan_trig_pkt_pattern *p; | ||
| 1502 | struct wl12xx_rx_filter *filter = NULL; | ||
| 1503 | |||
| 1504 | p = &wow->patterns[i]; | ||
| 1505 | |||
| 1506 | ret = wl1271_convert_wowlan_pattern_to_rx_filter(p, &filter); | ||
| 1507 | if (ret) { | ||
| 1508 | wl1271_warning("Failed to create an RX filter from " | ||
| 1509 | "wowlan pattern %d", i); | ||
| 1510 | goto out; | ||
| 1511 | } | ||
| 1512 | |||
| 1513 | ret = wl1271_rx_filter_enable(wl, i, 1, filter); | ||
| 1514 | |||
| 1515 | wl1271_rx_filter_free(filter); | ||
| 1516 | if (ret) | ||
| 1517 | goto out; | ||
| 1518 | } | ||
| 1519 | |||
| 1520 | ret = wl1271_acx_default_rx_filter_enable(wl, 1, FILTER_DROP); | ||
| 1521 | |||
| 1522 | out: | ||
| 1523 | return ret; | ||
| 1524 | } | ||
| 1525 | |||
| 1264 | static int wl1271_configure_suspend_sta(struct wl1271 *wl, | 1526 | static int wl1271_configure_suspend_sta(struct wl1271 *wl, |
| 1265 | struct wl12xx_vif *wlvif) | 1527 | struct wl12xx_vif *wlvif, |
| 1528 | struct cfg80211_wowlan *wow) | ||
| 1266 | { | 1529 | { |
| 1267 | int ret = 0; | 1530 | int ret = 0; |
| 1268 | 1531 | ||
| @@ -1273,6 +1536,7 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl, | |||
| 1273 | if (ret < 0) | 1536 | if (ret < 0) |
| 1274 | goto out; | 1537 | goto out; |
| 1275 | 1538 | ||
| 1539 | wl1271_configure_wowlan(wl, wow); | ||
| 1276 | ret = wl1271_acx_wake_up_conditions(wl, wlvif, | 1540 | ret = wl1271_acx_wake_up_conditions(wl, wlvif, |
| 1277 | wl->conf.conn.suspend_wake_up_event, | 1541 | wl->conf.conn.suspend_wake_up_event, |
| 1278 | wl->conf.conn.suspend_listen_interval); | 1542 | wl->conf.conn.suspend_listen_interval); |
| @@ -1308,10 +1572,11 @@ out: | |||
| 1308 | } | 1572 | } |
| 1309 | 1573 | ||
| 1310 | static int wl1271_configure_suspend(struct wl1271 *wl, | 1574 | static int wl1271_configure_suspend(struct wl1271 *wl, |
| 1311 | struct wl12xx_vif *wlvif) | 1575 | struct wl12xx_vif *wlvif, |
| 1576 | struct cfg80211_wowlan *wow) | ||
| 1312 | { | 1577 | { |
| 1313 | if (wlvif->bss_type == BSS_TYPE_STA_BSS) | 1578 | if (wlvif->bss_type == BSS_TYPE_STA_BSS) |
| 1314 | return wl1271_configure_suspend_sta(wl, wlvif); | 1579 | return wl1271_configure_suspend_sta(wl, wlvif, wow); |
| 1315 | if (wlvif->bss_type == BSS_TYPE_AP_BSS) | 1580 | if (wlvif->bss_type == BSS_TYPE_AP_BSS) |
| 1316 | return wl1271_configure_suspend_ap(wl, wlvif); | 1581 | return wl1271_configure_suspend_ap(wl, wlvif); |
| 1317 | return 0; | 1582 | return 0; |
| @@ -1332,6 +1597,8 @@ static void wl1271_configure_resume(struct wl1271 *wl, | |||
| 1332 | return; | 1597 | return; |
| 1333 | 1598 | ||
| 1334 | if (is_sta) { | 1599 | if (is_sta) { |
| 1600 | wl1271_configure_wowlan(wl, NULL); | ||
| 1601 | |||
| 1335 | ret = wl1271_acx_wake_up_conditions(wl, wlvif, | 1602 | ret = wl1271_acx_wake_up_conditions(wl, wlvif, |
| 1336 | wl->conf.conn.wake_up_event, | 1603 | wl->conf.conn.wake_up_event, |
| 1337 | wl->conf.conn.listen_interval); | 1604 | wl->conf.conn.listen_interval); |
| @@ -1355,15 +1622,16 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, | |||
| 1355 | int ret; | 1622 | int ret; |
| 1356 | 1623 | ||
| 1357 | wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow); | 1624 | wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow); |
| 1358 | WARN_ON(!wow || !wow->any); | 1625 | WARN_ON(!wow); |
| 1359 | 1626 | ||
| 1360 | wl1271_tx_flush(wl); | 1627 | wl1271_tx_flush(wl); |
| 1361 | 1628 | ||
| 1362 | mutex_lock(&wl->mutex); | 1629 | mutex_lock(&wl->mutex); |
| 1363 | wl->wow_enabled = true; | 1630 | wl->wow_enabled = true; |
| 1364 | wl12xx_for_each_wlvif(wl, wlvif) { | 1631 | wl12xx_for_each_wlvif(wl, wlvif) { |
| 1365 | ret = wl1271_configure_suspend(wl, wlvif); | 1632 | ret = wl1271_configure_suspend(wl, wlvif, wow); |
| 1366 | if (ret < 0) { | 1633 | if (ret < 0) { |
| 1634 | mutex_unlock(&wl->mutex); | ||
| 1367 | wl1271_warning("couldn't prepare device to suspend"); | 1635 | wl1271_warning("couldn't prepare device to suspend"); |
| 1368 | return ret; | 1636 | return ret; |
| 1369 | } | 1637 | } |
| @@ -1487,6 +1755,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
| 1487 | cancel_work_sync(&wl->tx_work); | 1755 | cancel_work_sync(&wl->tx_work); |
| 1488 | cancel_delayed_work_sync(&wl->elp_work); | 1756 | cancel_delayed_work_sync(&wl->elp_work); |
| 1489 | cancel_delayed_work_sync(&wl->tx_watchdog_work); | 1757 | cancel_delayed_work_sync(&wl->tx_watchdog_work); |
| 1758 | cancel_delayed_work_sync(&wl->connection_loss_work); | ||
| 1490 | 1759 | ||
| 1491 | /* let's notify MAC80211 about the remaining pending TX frames */ | 1760 | /* let's notify MAC80211 about the remaining pending TX frames */ |
| 1492 | wl12xx_tx_reset(wl, true); | 1761 | wl12xx_tx_reset(wl, true); |
| @@ -3439,6 +3708,9 @@ sta_not_found: | |||
| 3439 | do_join = true; | 3708 | do_join = true; |
| 3440 | set_assoc = true; | 3709 | set_assoc = true; |
| 3441 | 3710 | ||
| 3711 | /* Cancel connection_loss_work */ | ||
| 3712 | cancel_delayed_work_sync(&wl->connection_loss_work); | ||
| 3713 | |||
| 3442 | /* | 3714 | /* |
| 3443 | * use basic rates from AP, and determine lowest rate | 3715 | * use basic rates from AP, and determine lowest rate |
| 3444 | * to use with control frames. | 3716 | * to use with control frames. |
| @@ -4549,6 +4821,34 @@ static struct bin_attribute fwlog_attr = { | |||
| 4549 | .read = wl1271_sysfs_read_fwlog, | 4821 | .read = wl1271_sysfs_read_fwlog, |
| 4550 | }; | 4822 | }; |
| 4551 | 4823 | ||
| 4824 | static void wl1271_connection_loss_work(struct work_struct *work) | ||
| 4825 | { | ||
| 4826 | struct delayed_work *dwork; | ||
| 4827 | struct wl1271 *wl; | ||
| 4828 | struct ieee80211_vif *vif; | ||
| 4829 | struct wl12xx_vif *wlvif; | ||
| 4830 | |||
| 4831 | dwork = container_of(work, struct delayed_work, work); | ||
| 4832 | wl = container_of(dwork, struct wl1271, connection_loss_work); | ||
| 4833 | |||
| 4834 | wl1271_info("Connection loss work."); | ||
| 4835 | |||
| 4836 | mutex_lock(&wl->mutex); | ||
| 4837 | |||
| 4838 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
| 4839 | goto out; | ||
| 4840 | |||
| 4841 | /* Call mac80211 connection loss */ | ||
| 4842 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | ||
| 4843 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) | ||
| 4844 | goto out; | ||
| 4845 | vif = wl12xx_wlvif_to_vif(wlvif); | ||
| 4846 | ieee80211_connection_loss(vif); | ||
| 4847 | } | ||
| 4848 | out: | ||
| 4849 | mutex_unlock(&wl->mutex); | ||
| 4850 | } | ||
| 4851 | |||
| 4552 | static void wl12xx_derive_mac_addresses(struct wl1271 *wl, | 4852 | static void wl12xx_derive_mac_addresses(struct wl1271 *wl, |
| 4553 | u32 oui, u32 nic, int n) | 4853 | u32 oui, u32 nic, int n) |
| 4554 | { | 4854 | { |
| @@ -4804,6 +5104,8 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size) | |||
| 4804 | INIT_WORK(&wl->recovery_work, wl1271_recovery_work); | 5104 | INIT_WORK(&wl->recovery_work, wl1271_recovery_work); |
| 4805 | INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work); | 5105 | INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work); |
| 4806 | INIT_DELAYED_WORK(&wl->tx_watchdog_work, wl12xx_tx_watchdog_work); | 5106 | INIT_DELAYED_WORK(&wl->tx_watchdog_work, wl12xx_tx_watchdog_work); |
| 5107 | INIT_DELAYED_WORK(&wl->connection_loss_work, | ||
| 5108 | wl1271_connection_loss_work); | ||
| 4807 | 5109 | ||
| 4808 | wl->freezable_wq = create_freezable_workqueue("wl12xx_wq"); | 5110 | wl->freezable_wq = create_freezable_workqueue("wl12xx_wq"); |
| 4809 | if (!wl->freezable_wq) { | 5111 | if (!wl->freezable_wq) { |
| @@ -4861,7 +5163,7 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size) | |||
| 4861 | goto err_dummy_packet; | 5163 | goto err_dummy_packet; |
| 4862 | } | 5164 | } |
| 4863 | 5165 | ||
| 4864 | wl->mbox = kmalloc(sizeof(*wl->mbox), GFP_DMA); | 5166 | wl->mbox = kmalloc(sizeof(*wl->mbox), GFP_KERNEL | GFP_DMA); |
| 4865 | if (!wl->mbox) { | 5167 | if (!wl->mbox) { |
| 4866 | ret = -ENOMEM; | 5168 | ret = -ENOMEM; |
| 4867 | goto err_fwlog; | 5169 | goto err_fwlog; |
| @@ -5003,9 +5305,14 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) | |||
| 5003 | if (!ret) { | 5305 | if (!ret) { |
| 5004 | wl->irq_wake_enabled = true; | 5306 | wl->irq_wake_enabled = true; |
| 5005 | device_init_wakeup(wl->dev, 1); | 5307 | device_init_wakeup(wl->dev, 1); |
| 5006 | if (pdata->pwr_in_suspend) | 5308 | if (pdata->pwr_in_suspend) { |
| 5007 | wl->hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY; | 5309 | wl->hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY; |
| 5008 | 5310 | wl->hw->wiphy->wowlan.n_patterns = | |
| 5311 | WL1271_MAX_RX_FILTERS; | ||
| 5312 | wl->hw->wiphy->wowlan.pattern_min_len = 1; | ||
| 5313 | wl->hw->wiphy->wowlan.pattern_max_len = | ||
| 5314 | WL1271_RX_FILTER_MAX_PATTERN_SIZE; | ||
| 5315 | } | ||
| 5009 | } | 5316 | } |
| 5010 | disable_irq(wl->irq); | 5317 | disable_irq(wl->irq); |
| 5011 | 5318 | ||
diff --git a/drivers/net/wireless/ti/wlcore/rx.c b/drivers/net/wireless/ti/wlcore/rx.c index 89bd9385e90..1f1d9488dfb 100644 --- a/drivers/net/wireless/ti/wlcore/rx.c +++ b/drivers/net/wireless/ti/wlcore/rx.c | |||
| @@ -278,3 +278,39 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status *status) | |||
| 278 | 278 | ||
| 279 | wl12xx_rearm_rx_streaming(wl, active_hlids); | 279 | wl12xx_rearm_rx_streaming(wl, active_hlids); |
| 280 | } | 280 | } |
| 281 | |||
| 282 | int wl1271_rx_filter_enable(struct wl1271 *wl, | ||
| 283 | int index, bool enable, | ||
| 284 | struct wl12xx_rx_filter *filter) | ||
| 285 | { | ||
| 286 | int ret; | ||
| 287 | |||
| 288 | if (wl->rx_filter_enabled[index] == enable) { | ||
| 289 | wl1271_warning("Request to enable an already " | ||
| 290 | "enabled rx filter %d", index); | ||
| 291 | return 0; | ||
| 292 | } | ||
| 293 | |||
| 294 | ret = wl1271_acx_set_rx_filter(wl, index, enable, filter); | ||
| 295 | |||
| 296 | if (ret) { | ||
| 297 | wl1271_error("Failed to %s rx data filter %d (err=%d)", | ||
| 298 | enable ? "enable" : "disable", index, ret); | ||
| 299 | return ret; | ||
| 300 | } | ||
| 301 | |||
| 302 | wl->rx_filter_enabled[index] = enable; | ||
| 303 | |||
| 304 | return 0; | ||
| 305 | } | ||
| 306 | |||
| 307 | void wl1271_rx_filter_clear_all(struct wl1271 *wl) | ||
| 308 | { | ||
| 309 | int i; | ||
| 310 | |||
| 311 | for (i = 0; i < WL1271_MAX_RX_FILTERS; i++) { | ||
| 312 | if (!wl->rx_filter_enabled[i]) | ||
| 313 | continue; | ||
| 314 | wl1271_rx_filter_enable(wl, i, 0, NULL); | ||
| 315 | } | ||
| 316 | } | ||
diff --git a/drivers/net/wireless/ti/wlcore/rx.h b/drivers/net/wireless/ti/wlcore/rx.h index 6e129e2a854..e9a162a864c 100644 --- a/drivers/net/wireless/ti/wlcore/rx.h +++ b/drivers/net/wireless/ti/wlcore/rx.h | |||
| @@ -138,5 +138,9 @@ struct wl1271_rx_descriptor { | |||
| 138 | 138 | ||
| 139 | void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status *status); | 139 | void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status *status); |
| 140 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); | 140 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); |
| 141 | int wl1271_rx_filter_enable(struct wl1271 *wl, | ||
| 142 | int index, bool enable, | ||
| 143 | struct wl12xx_rx_filter *filter); | ||
| 144 | void wl1271_rx_filter_clear_all(struct wl1271 *wl); | ||
| 141 | 145 | ||
| 142 | #endif | 146 | #endif |
diff --git a/drivers/net/wireless/ti/wlcore/wl12xx.h b/drivers/net/wireless/ti/wlcore/wl12xx.h index a9b220c43e5..f12bdf74518 100644 --- a/drivers/net/wireless/ti/wlcore/wl12xx.h +++ b/drivers/net/wireless/ti/wlcore/wl12xx.h | |||
| @@ -279,6 +279,39 @@ struct wl1271_link { | |||
| 279 | u8 ba_bitmap; | 279 | u8 ba_bitmap; |
| 280 | }; | 280 | }; |
| 281 | 281 | ||
| 282 | #define WL1271_MAX_RX_FILTERS 5 | ||
| 283 | #define WL1271_RX_FILTER_MAX_FIELDS 8 | ||
| 284 | |||
| 285 | #define WL1271_RX_FILTER_ETH_HEADER_SIZE 14 | ||
| 286 | #define WL1271_RX_FILTER_MAX_FIELDS_SIZE 95 | ||
| 287 | #define RX_FILTER_FIELD_OVERHEAD \ | ||
| 288 | (sizeof(struct wl12xx_rx_filter_field) - sizeof(u8 *)) | ||
| 289 | #define WL1271_RX_FILTER_MAX_PATTERN_SIZE \ | ||
| 290 | (WL1271_RX_FILTER_MAX_FIELDS_SIZE - RX_FILTER_FIELD_OVERHEAD) | ||
| 291 | |||
| 292 | #define WL1271_RX_FILTER_FLAG_MASK BIT(0) | ||
| 293 | #define WL1271_RX_FILTER_FLAG_IP_HEADER 0 | ||
| 294 | #define WL1271_RX_FILTER_FLAG_ETHERNET_HEADER BIT(1) | ||
| 295 | |||
| 296 | enum rx_filter_action { | ||
| 297 | FILTER_DROP = 0, | ||
| 298 | FILTER_SIGNAL = 1, | ||
| 299 | FILTER_FW_HANDLE = 2 | ||
| 300 | }; | ||
| 301 | |||
| 302 | struct wl12xx_rx_filter_field { | ||
| 303 | __le16 offset; | ||
| 304 | u8 len; | ||
| 305 | u8 flags; | ||
| 306 | u8 *pattern; | ||
| 307 | } __packed; | ||
| 308 | |||
| 309 | struct wl12xx_rx_filter { | ||
| 310 | u8 action; | ||
| 311 | int num_fields; | ||
| 312 | struct wl12xx_rx_filter_field fields[WL1271_RX_FILTER_MAX_FIELDS]; | ||
| 313 | }; | ||
| 314 | |||
| 282 | struct wl1271_station { | 315 | struct wl1271_station { |
| 283 | u8 hlid; | 316 | u8 hlid; |
| 284 | }; | 317 | }; |
| @@ -439,6 +472,14 @@ int wl1271_plt_stop(struct wl1271 *wl); | |||
| 439 | int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 472 | int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
| 440 | void wl12xx_queue_recovery_work(struct wl1271 *wl); | 473 | void wl12xx_queue_recovery_work(struct wl1271 *wl); |
| 441 | size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen); | 474 | size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen); |
| 475 | int wl1271_rx_filter_alloc_field(struct wl12xx_rx_filter *filter, | ||
| 476 | u16 offset, u8 flags, | ||
| 477 | u8 *pattern, u8 len); | ||
| 478 | void wl1271_rx_filter_free(struct wl12xx_rx_filter *filter); | ||
| 479 | struct wl12xx_rx_filter *wl1271_rx_filter_alloc(void); | ||
| 480 | int wl1271_rx_filter_get_fields_size(struct wl12xx_rx_filter *filter); | ||
| 481 | void wl1271_rx_filter_flatten_fields(struct wl12xx_rx_filter *filter, | ||
| 482 | u8 *buf); | ||
| 442 | 483 | ||
| 443 | #define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */ | 484 | #define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */ |
| 444 | 485 | ||
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index 39f9fadfebd..0b3f0b586f4 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h | |||
| @@ -243,6 +243,9 @@ struct wl1271 { | |||
| 243 | struct wl1271_scan scan; | 243 | struct wl1271_scan scan; |
| 244 | struct delayed_work scan_complete_work; | 244 | struct delayed_work scan_complete_work; |
| 245 | 245 | ||
| 246 | /* Connection loss work */ | ||
| 247 | struct delayed_work connection_loss_work; | ||
| 248 | |||
| 246 | bool sched_scanning; | 249 | bool sched_scanning; |
| 247 | 250 | ||
| 248 | /* The current band */ | 251 | /* The current band */ |
| @@ -349,6 +352,9 @@ struct wl1271 { | |||
| 349 | 352 | ||
| 350 | /* size of the private FW status data */ | 353 | /* size of the private FW status data */ |
| 351 | size_t fw_status_priv_len; | 354 | size_t fw_status_priv_len; |
| 355 | |||
| 356 | /* RX Data filter rule state - enabled/disabled */ | ||
| 357 | bool rx_filter_enabled[WL1271_MAX_RX_FILTERS]; | ||
| 352 | }; | 358 | }; |
| 353 | 359 | ||
| 354 | int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); | 360 | int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); |
