diff options
Diffstat (limited to 'net/wireless/wext-compat.c')
| -rw-r--r-- | net/wireless/wext-compat.c | 79 |
1 files changed, 56 insertions, 23 deletions
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 54face3d4424..7e5c3a45f811 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <linux/nl80211.h> | 12 | #include <linux/nl80211.h> |
| 13 | #include <linux/if_arp.h> | 13 | #include <linux/if_arp.h> |
| 14 | #include <linux/etherdevice.h> | 14 | #include <linux/etherdevice.h> |
| 15 | #include <linux/slab.h> | ||
| 15 | #include <net/iw_handler.h> | 16 | #include <net/iw_handler.h> |
| 16 | #include <net/cfg80211.h> | 17 | #include <net/cfg80211.h> |
| 17 | #include "wext-compat.h" | 18 | #include "wext-compat.h" |
| @@ -781,16 +782,22 @@ int cfg80211_wext_siwfreq(struct net_device *dev, | |||
| 781 | return cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra); | 782 | return cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra); |
| 782 | case NL80211_IFTYPE_ADHOC: | 783 | case NL80211_IFTYPE_ADHOC: |
| 783 | return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra); | 784 | return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra); |
| 784 | default: | 785 | case NL80211_IFTYPE_MONITOR: |
| 786 | case NL80211_IFTYPE_WDS: | ||
| 787 | case NL80211_IFTYPE_MESH_POINT: | ||
| 785 | freq = cfg80211_wext_freq(wdev->wiphy, wextfreq); | 788 | freq = cfg80211_wext_freq(wdev->wiphy, wextfreq); |
| 786 | if (freq < 0) | 789 | if (freq < 0) |
| 787 | return freq; | 790 | return freq; |
| 788 | if (freq == 0) | 791 | if (freq == 0) |
| 789 | return -EINVAL; | 792 | return -EINVAL; |
| 793 | wdev_lock(wdev); | ||
| 790 | mutex_lock(&rdev->devlist_mtx); | 794 | mutex_lock(&rdev->devlist_mtx); |
| 791 | err = rdev_set_freq(rdev, NULL, freq, NL80211_CHAN_NO_HT); | 795 | err = cfg80211_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT); |
| 792 | mutex_unlock(&rdev->devlist_mtx); | 796 | mutex_unlock(&rdev->devlist_mtx); |
| 797 | wdev_unlock(wdev); | ||
| 793 | return err; | 798 | return err; |
| 799 | default: | ||
| 800 | return -EOPNOTSUPP; | ||
| 794 | } | 801 | } |
| 795 | } | 802 | } |
| 796 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwfreq); | 803 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwfreq); |
| @@ -800,7 +807,6 @@ int cfg80211_wext_giwfreq(struct net_device *dev, | |||
| 800 | struct iw_freq *freq, char *extra) | 807 | struct iw_freq *freq, char *extra) |
| 801 | { | 808 | { |
| 802 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 809 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 803 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | ||
| 804 | 810 | ||
| 805 | switch (wdev->iftype) { | 811 | switch (wdev->iftype) { |
| 806 | case NL80211_IFTYPE_STATION: | 812 | case NL80211_IFTYPE_STATION: |
| @@ -808,9 +814,9 @@ int cfg80211_wext_giwfreq(struct net_device *dev, | |||
| 808 | case NL80211_IFTYPE_ADHOC: | 814 | case NL80211_IFTYPE_ADHOC: |
| 809 | return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); | 815 | return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); |
| 810 | default: | 816 | default: |
| 811 | if (!rdev->channel) | 817 | if (!wdev->channel) |
| 812 | return -EINVAL; | 818 | return -EINVAL; |
| 813 | freq->m = rdev->channel->center_freq; | 819 | freq->m = wdev->channel->center_freq; |
| 814 | freq->e = 6; | 820 | freq->e = 6; |
| 815 | return 0; | 821 | return 0; |
| 816 | } | 822 | } |
| @@ -823,7 +829,7 @@ int cfg80211_wext_siwtxpower(struct net_device *dev, | |||
| 823 | { | 829 | { |
| 824 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 830 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 825 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | 831 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); |
| 826 | enum tx_power_setting type; | 832 | enum nl80211_tx_power_setting type; |
| 827 | int dbm = 0; | 833 | int dbm = 0; |
| 828 | 834 | ||
| 829 | if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) | 835 | if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) |
| @@ -846,7 +852,7 @@ int cfg80211_wext_siwtxpower(struct net_device *dev, | |||
| 846 | if (data->txpower.value < 0) | 852 | if (data->txpower.value < 0) |
| 847 | return -EINVAL; | 853 | return -EINVAL; |
| 848 | dbm = data->txpower.value; | 854 | dbm = data->txpower.value; |
| 849 | type = TX_POWER_FIXED; | 855 | type = NL80211_TX_POWER_FIXED; |
| 850 | /* TODO: do regulatory check! */ | 856 | /* TODO: do regulatory check! */ |
| 851 | } else { | 857 | } else { |
| 852 | /* | 858 | /* |
| @@ -854,10 +860,10 @@ int cfg80211_wext_siwtxpower(struct net_device *dev, | |||
| 854 | * passed in from userland. | 860 | * passed in from userland. |
| 855 | */ | 861 | */ |
| 856 | if (data->txpower.value < 0) { | 862 | if (data->txpower.value < 0) { |
| 857 | type = TX_POWER_AUTOMATIC; | 863 | type = NL80211_TX_POWER_AUTOMATIC; |
| 858 | } else { | 864 | } else { |
| 859 | dbm = data->txpower.value; | 865 | dbm = data->txpower.value; |
| 860 | type = TX_POWER_LIMITED; | 866 | type = NL80211_TX_POWER_LIMITED; |
| 861 | } | 867 | } |
| 862 | } | 868 | } |
| 863 | } else { | 869 | } else { |
| @@ -866,7 +872,7 @@ int cfg80211_wext_siwtxpower(struct net_device *dev, | |||
| 866 | return 0; | 872 | return 0; |
| 867 | } | 873 | } |
| 868 | 874 | ||
| 869 | return rdev->ops->set_tx_power(wdev->wiphy, type, dbm); | 875 | return rdev->ops->set_tx_power(wdev->wiphy, type, DBM_TO_MBM(dbm)); |
| 870 | } | 876 | } |
| 871 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwtxpower); | 877 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwtxpower); |
| 872 | 878 | ||
| @@ -1099,8 +1105,8 @@ int cfg80211_wext_siwpower(struct net_device *dev, | |||
| 1099 | { | 1105 | { |
| 1100 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 1106 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 1101 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | 1107 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); |
| 1102 | bool ps = wdev->wext.ps; | 1108 | bool ps = wdev->ps; |
| 1103 | int timeout = wdev->wext.ps_timeout; | 1109 | int timeout = wdev->ps_timeout; |
| 1104 | int err; | 1110 | int err; |
| 1105 | 1111 | ||
| 1106 | if (wdev->iftype != NL80211_IFTYPE_STATION) | 1112 | if (wdev->iftype != NL80211_IFTYPE_STATION) |
| @@ -1133,8 +1139,8 @@ int cfg80211_wext_siwpower(struct net_device *dev, | |||
| 1133 | if (err) | 1139 | if (err) |
| 1134 | return err; | 1140 | return err; |
| 1135 | 1141 | ||
| 1136 | wdev->wext.ps = ps; | 1142 | wdev->ps = ps; |
| 1137 | wdev->wext.ps_timeout = timeout; | 1143 | wdev->ps_timeout = timeout; |
| 1138 | 1144 | ||
| 1139 | return 0; | 1145 | return 0; |
| 1140 | 1146 | ||
| @@ -1147,7 +1153,7 @@ int cfg80211_wext_giwpower(struct net_device *dev, | |||
| 1147 | { | 1153 | { |
| 1148 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 1154 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 1149 | 1155 | ||
| 1150 | wrq->disabled = !wdev->wext.ps; | 1156 | wrq->disabled = !wdev->ps; |
| 1151 | 1157 | ||
| 1152 | return 0; | 1158 | return 0; |
| 1153 | } | 1159 | } |
| @@ -1204,21 +1210,47 @@ int cfg80211_wext_siwrate(struct net_device *dev, | |||
| 1204 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 1210 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 1205 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | 1211 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); |
| 1206 | struct cfg80211_bitrate_mask mask; | 1212 | struct cfg80211_bitrate_mask mask; |
| 1213 | u32 fixed, maxrate; | ||
| 1214 | struct ieee80211_supported_band *sband; | ||
| 1215 | int band, ridx; | ||
| 1216 | bool match = false; | ||
| 1207 | 1217 | ||
| 1208 | if (!rdev->ops->set_bitrate_mask) | 1218 | if (!rdev->ops->set_bitrate_mask) |
| 1209 | return -EOPNOTSUPP; | 1219 | return -EOPNOTSUPP; |
| 1210 | 1220 | ||
| 1211 | mask.fixed = 0; | 1221 | memset(&mask, 0, sizeof(mask)); |
| 1212 | mask.maxrate = 0; | 1222 | fixed = 0; |
| 1223 | maxrate = (u32)-1; | ||
| 1213 | 1224 | ||
| 1214 | if (rate->value < 0) { | 1225 | if (rate->value < 0) { |
| 1215 | /* nothing */ | 1226 | /* nothing */ |
| 1216 | } else if (rate->fixed) { | 1227 | } else if (rate->fixed) { |
| 1217 | mask.fixed = rate->value / 1000; /* kbps */ | 1228 | fixed = rate->value / 100000; |
| 1218 | } else { | 1229 | } else { |
| 1219 | mask.maxrate = rate->value / 1000; /* kbps */ | 1230 | maxrate = rate->value / 100000; |
| 1231 | } | ||
| 1232 | |||
| 1233 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
| 1234 | sband = wdev->wiphy->bands[band]; | ||
| 1235 | if (sband == NULL) | ||
| 1236 | continue; | ||
| 1237 | for (ridx = 0; ridx < sband->n_bitrates; ridx++) { | ||
| 1238 | struct ieee80211_rate *srate = &sband->bitrates[ridx]; | ||
| 1239 | if (fixed == srate->bitrate) { | ||
| 1240 | mask.control[band].legacy = 1 << ridx; | ||
| 1241 | match = true; | ||
| 1242 | break; | ||
| 1243 | } | ||
| 1244 | if (srate->bitrate <= maxrate) { | ||
| 1245 | mask.control[band].legacy |= 1 << ridx; | ||
| 1246 | match = true; | ||
| 1247 | } | ||
| 1248 | } | ||
| 1220 | } | 1249 | } |
| 1221 | 1250 | ||
| 1251 | if (!match) | ||
| 1252 | return -EINVAL; | ||
| 1253 | |||
| 1222 | return rdev->ops->set_bitrate_mask(wdev->wiphy, dev, NULL, &mask); | 1254 | return rdev->ops->set_bitrate_mask(wdev->wiphy, dev, NULL, &mask); |
| 1223 | } | 1255 | } |
| 1224 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwrate); | 1256 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwrate); |
| @@ -1257,10 +1289,7 @@ int cfg80211_wext_giwrate(struct net_device *dev, | |||
| 1257 | if (!(sinfo.filled & STATION_INFO_TX_BITRATE)) | 1289 | if (!(sinfo.filled & STATION_INFO_TX_BITRATE)) |
| 1258 | return -EOPNOTSUPP; | 1290 | return -EOPNOTSUPP; |
| 1259 | 1291 | ||
| 1260 | rate->value = 0; | 1292 | rate->value = 100000 * cfg80211_calculate_bitrate(&sinfo.txrate); |
| 1261 | |||
| 1262 | if (!(sinfo.txrate.flags & RATE_INFO_FLAGS_MCS)) | ||
| 1263 | rate->value = 100000 * sinfo.txrate.legacy; | ||
| 1264 | 1293 | ||
| 1265 | return 0; | 1294 | return 0; |
| 1266 | } | 1295 | } |
| @@ -1391,6 +1420,9 @@ int cfg80211_wext_giwessid(struct net_device *dev, | |||
| 1391 | { | 1420 | { |
| 1392 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 1421 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 1393 | 1422 | ||
| 1423 | data->flags = 0; | ||
| 1424 | data->length = 0; | ||
| 1425 | |||
| 1394 | switch (wdev->iftype) { | 1426 | switch (wdev->iftype) { |
| 1395 | case NL80211_IFTYPE_ADHOC: | 1427 | case NL80211_IFTYPE_ADHOC: |
| 1396 | return cfg80211_ibss_wext_giwessid(dev, info, data, ssid); | 1428 | return cfg80211_ibss_wext_giwessid(dev, info, data, ssid); |
| @@ -1442,6 +1474,7 @@ int cfg80211_wext_siwpmksa(struct net_device *dev, | |||
| 1442 | return -EOPNOTSUPP; | 1474 | return -EOPNOTSUPP; |
| 1443 | } | 1475 | } |
| 1444 | } | 1476 | } |
| 1477 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwpmksa); | ||
| 1445 | 1478 | ||
| 1446 | static const iw_handler cfg80211_handlers[] = { | 1479 | static const iw_handler cfg80211_handlers[] = { |
| 1447 | [IW_IOCTL_IDX(SIOCGIWNAME)] = (iw_handler) cfg80211_wext_giwname, | 1480 | [IW_IOCTL_IDX(SIOCGIWNAME)] = (iw_handler) cfg80211_wext_giwname, |
