1
0

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6

Este cometimento está contido em:
David S. Miller
2009-03-17 15:04:31 -07:00
ascendente 2d6a5e9500 808ff697b3
cometimento af4330631c
72 ficheiros modificados com 7616 adições e 2951 eliminações

Ver ficheiro

@@ -350,7 +350,7 @@ int wiphy_register(struct wiphy *wiphy)
mutex_lock(&cfg80211_mutex);
/* set up regulatory info */
wiphy_update_regulatory(wiphy, REGDOM_SET_BY_CORE);
wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE);
res = device_add(&drv->wiphy.dev);
if (res)
@@ -365,6 +365,17 @@ int wiphy_register(struct wiphy *wiphy)
if (IS_ERR(drv->wiphy.debugfsdir))
drv->wiphy.debugfsdir = NULL;
if (wiphy->custom_regulatory) {
struct regulatory_request request;
request.wiphy_idx = get_wiphy_idx(wiphy);
request.initiator = NL80211_REGDOM_SET_BY_DRIVER;
request.alpha2[0] = '9';
request.alpha2[1] = '9';
nl80211_send_reg_change_event(&request);
}
res = 0;
out_unlock:
mutex_unlock(&cfg80211_mutex);

Ver ficheiro

@@ -136,7 +136,8 @@ extern int cfg80211_dev_rename(struct cfg80211_registered_device *drv,
char *newname);
void ieee80211_set_bitrate_flags(struct wiphy *wiphy);
void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby);
void wiphy_update_regulatory(struct wiphy *wiphy,
enum nl80211_reg_initiator setby);
void cfg80211_bss_expire(struct cfg80211_registered_device *dev);
void cfg80211_bss_age(struct cfg80211_registered_device *dev,

Ver ficheiro

@@ -2739,6 +2739,9 @@ static struct genl_multicast_group nl80211_config_mcgrp = {
static struct genl_multicast_group nl80211_scan_mcgrp = {
.name = "scan",
};
static struct genl_multicast_group nl80211_regulatory_mcgrp = {
.name = "regulatory",
};
/* notification functions */
@@ -2818,6 +2821,61 @@ void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
genlmsg_multicast(msg, 0, nl80211_scan_mcgrp.id, GFP_KERNEL);
}
/*
* This can happen on global regulatory changes or device specific settings
* based on custom world regulatory domains.
*/
void nl80211_send_reg_change_event(struct regulatory_request *request)
{
struct sk_buff *msg;
void *hdr;
msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
if (!msg)
return;
hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_CHANGE);
if (!hdr) {
nlmsg_free(msg);
return;
}
/* Userspace can always count this one always being set */
NLA_PUT_U8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator);
if (request->alpha2[0] == '0' && request->alpha2[1] == '0')
NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE,
NL80211_REGDOM_TYPE_WORLD);
else if (request->alpha2[0] == '9' && request->alpha2[1] == '9')
NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE,
NL80211_REGDOM_TYPE_CUSTOM_WORLD);
else if ((request->alpha2[0] == '9' && request->alpha2[1] == '8') ||
request->intersect)
NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE,
NL80211_REGDOM_TYPE_INTERSECTION);
else {
NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE,
NL80211_REGDOM_TYPE_COUNTRY);
NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, request->alpha2);
}
if (wiphy_idx_valid(request->wiphy_idx))
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx);
if (genlmsg_end(msg, hdr) < 0) {
nlmsg_free(msg);
return;
}
genlmsg_multicast(msg, 0, nl80211_regulatory_mcgrp.id, GFP_KERNEL);
return;
nla_put_failure:
genlmsg_cancel(msg, hdr);
nlmsg_free(msg);
}
/* initialisation/exit functions */
int nl80211_init(void)
@@ -2842,6 +2900,10 @@ int nl80211_init(void)
if (err)
goto err_out;
err = genl_register_mc_group(&nl80211_fam, &nl80211_regulatory_mcgrp);
if (err)
goto err_out;
return 0;
err_out:
genl_unregister_family(&nl80211_fam);

Ver ficheiro

@@ -11,6 +11,7 @@ extern void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
struct net_device *netdev);
extern void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
struct net_device *netdev);
extern void nl80211_send_reg_change_event(struct regulatory_request *request);
#else
static inline int nl80211_init(void)
{
@@ -31,6 +32,10 @@ static inline void nl80211_send_scan_aborted(
struct cfg80211_registered_device *rdev,
struct net_device *netdev)
{}
static inline void
nl80211_send_reg_change_event(struct regulatory_request *request)
{
}
#endif /* CONFIG_NL80211 */
#endif /* __NET_WIRELESS_NL80211_H */

Ver ficheiro

@@ -41,6 +41,7 @@
#include <net/cfg80211.h>
#include "core.h"
#include "reg.h"
#include "nl80211.h"
/* Receipt of information from last regulatory request */
static struct regulatory_request *last_request;
@@ -86,20 +87,31 @@ struct reg_beacon {
/* We keep a static world regulatory domain in case of the absence of CRDA */
static const struct ieee80211_regdomain world_regdom = {
.n_reg_rules = 3,
.n_reg_rules = 5,
.alpha2 = "00",
.reg_rules = {
/* IEEE 802.11b/g, channels 1..11 */
REG_RULE(2412-10, 2462+10, 40, 6, 20, 0),
/* IEEE 802.11a, channel 36..48 */
REG_RULE(5180-10, 5240+10, 40, 6, 23,
/* IEEE 802.11b/g, channels 12..13. No HT40
* channel fits here. */
REG_RULE(2467-10, 2472+10, 20, 6, 20,
NL80211_RRF_PASSIVE_SCAN |
NL80211_RRF_NO_IBSS),
/* IEEE 802.11 channel 14 - Only JP enables
* this and for 802.11b only */
REG_RULE(2484-10, 2484+10, 20, 6, 20,
NL80211_RRF_PASSIVE_SCAN |
NL80211_RRF_NO_IBSS |
NL80211_RRF_NO_OFDM),
/* IEEE 802.11a, channel 36..48 */
REG_RULE(5180-10, 5240+10, 40, 6, 20,
NL80211_RRF_PASSIVE_SCAN |
NL80211_RRF_NO_IBSS),
/* NB: 5260 MHz - 5700 MHz requies DFS */
/* IEEE 802.11a, channel 149..165 */
REG_RULE(5745-10, 5825+10, 40, 6, 23,
REG_RULE(5745-10, 5825+10, 40, 6, 20,
NL80211_RRF_PASSIVE_SCAN |
NL80211_RRF_NO_IBSS),
}
@@ -846,8 +858,8 @@ static int freq_reg_info_regd(struct wiphy *wiphy,
* Follow the driver's regulatory domain, if present, unless a country
* IE has been processed or a user wants to help complaince further
*/
if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE &&
last_request->initiator != REGDOM_SET_BY_USER &&
if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE &&
last_request->initiator != NL80211_REGDOM_SET_BY_USER &&
wiphy->regd)
regd = wiphy->regd;
@@ -932,7 +944,8 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
* http://tinyurl.com/11d-clarification
*/
if (r == -ERANGE &&
last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) {
last_request->initiator ==
NL80211_REGDOM_SET_BY_COUNTRY_IE) {
#ifdef CONFIG_CFG80211_REG_DEBUG
printk(KERN_DEBUG "cfg80211: Leaving channel %d MHz "
"intact on %s - no rule found in band on "
@@ -945,7 +958,8 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
* for the band so we respect its band definitions
*/
#ifdef CONFIG_CFG80211_REG_DEBUG
if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE)
if (last_request->initiator ==
NL80211_REGDOM_SET_BY_COUNTRY_IE)
printk(KERN_DEBUG "cfg80211: Disabling "
"channel %d MHz on %s due to "
"Country IE\n",
@@ -959,7 +973,7 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
power_rule = &reg_rule->power_rule;
if (last_request->initiator == REGDOM_SET_BY_DRIVER &&
if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
request_wiphy && request_wiphy == wiphy &&
request_wiphy->strict_regulatory) {
/*
@@ -1000,11 +1014,12 @@ static void handle_band(struct wiphy *wiphy, enum ieee80211_band band)
handle_channel(wiphy, band, i);
}
static bool ignore_reg_update(struct wiphy *wiphy, enum reg_set_by setby)
static bool ignore_reg_update(struct wiphy *wiphy,
enum nl80211_reg_initiator initiator)
{
if (!last_request)
return true;
if (setby == REGDOM_SET_BY_CORE &&
if (initiator == NL80211_REGDOM_SET_BY_CORE &&
wiphy->custom_regulatory)
return true;
/*
@@ -1017,12 +1032,12 @@ static bool ignore_reg_update(struct wiphy *wiphy, enum reg_set_by setby)
return false;
}
static void update_all_wiphy_regulatory(enum reg_set_by setby)
static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
{
struct cfg80211_registered_device *drv;
list_for_each_entry(drv, &cfg80211_drv_list, list)
wiphy_update_regulatory(&drv->wiphy, setby);
wiphy_update_regulatory(&drv->wiphy, initiator);
}
static void handle_reg_beacon(struct wiphy *wiphy,
@@ -1113,7 +1128,7 @@ static bool reg_is_world_roaming(struct wiphy *wiphy)
if (is_world_regdom(cfg80211_regdomain->alpha2) ||
(wiphy->regd && is_world_regdom(wiphy->regd->alpha2)))
return true;
if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE &&
if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE &&
wiphy->custom_regulatory)
return true;
return false;
@@ -1127,11 +1142,12 @@ static void reg_process_beacons(struct wiphy *wiphy)
wiphy_update_beacon_reg(wiphy);
}
void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby)
void wiphy_update_regulatory(struct wiphy *wiphy,
enum nl80211_reg_initiator initiator)
{
enum ieee80211_band band;
if (ignore_reg_update(wiphy, setby))
if (ignore_reg_update(wiphy, initiator))
goto out;
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
if (wiphy->bands[band])
@@ -1244,17 +1260,16 @@ static int ignore_request(struct wiphy *wiphy,
return 0;
switch (pending_request->initiator) {
case REGDOM_SET_BY_INIT:
case NL80211_REGDOM_SET_BY_CORE:
return -EINVAL;
case REGDOM_SET_BY_CORE:
return -EINVAL;
case REGDOM_SET_BY_COUNTRY_IE:
case NL80211_REGDOM_SET_BY_COUNTRY_IE:
last_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
if (unlikely(!is_an_alpha2(pending_request->alpha2)))
return -EINVAL;
if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) {
if (last_request->initiator ==
NL80211_REGDOM_SET_BY_COUNTRY_IE) {
if (last_wiphy != wiphy) {
/*
* Two cards with two APs claiming different
@@ -1275,8 +1290,8 @@ static int ignore_request(struct wiphy *wiphy,
return -EALREADY;
}
return REG_INTERSECT;
case REGDOM_SET_BY_DRIVER:
if (last_request->initiator == REGDOM_SET_BY_CORE) {
case NL80211_REGDOM_SET_BY_DRIVER:
if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE) {
if (is_old_static_regdom(cfg80211_regdomain))
return 0;
if (regdom_changes(pending_request->alpha2))
@@ -1289,28 +1304,28 @@ static int ignore_request(struct wiphy *wiphy,
* back in or if you add a new device for which the previously
* loaded card also agrees on the regulatory domain.
*/
if (last_request->initiator == REGDOM_SET_BY_DRIVER &&
if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
!regdom_changes(pending_request->alpha2))
return -EALREADY;
return REG_INTERSECT;
case REGDOM_SET_BY_USER:
if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE)
case NL80211_REGDOM_SET_BY_USER:
if (last_request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)
return REG_INTERSECT;
/*
* If the user knows better the user should set the regdom
* to their country before the IE is picked up
*/
if (last_request->initiator == REGDOM_SET_BY_USER &&
if (last_request->initiator == NL80211_REGDOM_SET_BY_USER &&
last_request->intersect)
return -EOPNOTSUPP;
/*
* Process user requests only after previous user/driver/core
* requests have been processed
*/
if (last_request->initiator == REGDOM_SET_BY_CORE ||
last_request->initiator == REGDOM_SET_BY_DRIVER ||
last_request->initiator == REGDOM_SET_BY_USER) {
if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE ||
last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER ||
last_request->initiator == NL80211_REGDOM_SET_BY_USER) {
if (regdom_changes(last_request->alpha2))
return -EAGAIN;
}
@@ -1350,7 +1365,8 @@ static int __regulatory_hint(struct wiphy *wiphy,
r = ignore_request(wiphy, pending_request);
if (r == REG_INTERSECT) {
if (pending_request->initiator == REGDOM_SET_BY_DRIVER) {
if (pending_request->initiator ==
NL80211_REGDOM_SET_BY_DRIVER) {
r = reg_copy_regd(&wiphy->regd, cfg80211_regdomain);
if (r) {
kfree(pending_request);
@@ -1365,7 +1381,8 @@ static int __regulatory_hint(struct wiphy *wiphy,
* wiphy
*/
if (r == -EALREADY &&
pending_request->initiator == REGDOM_SET_BY_DRIVER) {
pending_request->initiator ==
NL80211_REGDOM_SET_BY_DRIVER) {
r = reg_copy_regd(&wiphy->regd, cfg80211_regdomain);
if (r) {
kfree(pending_request);
@@ -1387,8 +1404,16 @@ new_request:
pending_request = NULL;
/* When r == REG_INTERSECT we do need to call CRDA */
if (r < 0)
if (r < 0) {
/*
* Since CRDA will not be called in this case as we already
* have applied the requested regulatory domain before we just
* inform userspace we have processed the request
*/
if (r == -EALREADY)
nl80211_send_reg_change_event(last_request);
return r;
}
/*
* Note: When CONFIG_WIRELESS_OLD_REGULATORY is enabled
@@ -1416,7 +1441,7 @@ static void reg_process_hint(struct regulatory_request *reg_request)
if (wiphy_idx_valid(reg_request->wiphy_idx))
wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx);
if (reg_request->initiator == REGDOM_SET_BY_DRIVER &&
if (reg_request->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
!wiphy) {
kfree(reg_request);
goto out;
@@ -1430,7 +1455,7 @@ out:
mutex_unlock(&cfg80211_mutex);
}
/* Processes regulatory hints, this is all the REGDOM_SET_BY_* */
/* Processes regulatory hints, this is all the NL80211_REGDOM_SET_BY_* */
static void reg_process_pending_hints(void)
{
struct regulatory_request *reg_request;
@@ -1514,7 +1539,7 @@ static int regulatory_hint_core(const char *alpha2)
request->alpha2[0] = alpha2[0];
request->alpha2[1] = alpha2[1];
request->initiator = REGDOM_SET_BY_CORE;
request->initiator = NL80211_REGDOM_SET_BY_CORE;
queue_regulatory_request(request);
@@ -1535,7 +1560,7 @@ int regulatory_hint_user(const char *alpha2)
request->wiphy_idx = WIPHY_IDX_STALE;
request->alpha2[0] = alpha2[0];
request->alpha2[1] = alpha2[1];
request->initiator = REGDOM_SET_BY_USER,
request->initiator = NL80211_REGDOM_SET_BY_USER,
queue_regulatory_request(request);
@@ -1561,7 +1586,7 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
request->alpha2[0] = alpha2[0];
request->alpha2[1] = alpha2[1];
request->initiator = REGDOM_SET_BY_DRIVER;
request->initiator = NL80211_REGDOM_SET_BY_DRIVER;
queue_regulatory_request(request);
@@ -1710,7 +1735,7 @@ void regulatory_hint_11d(struct wiphy *wiphy,
request->wiphy_idx = get_wiphy_idx(wiphy);
request->alpha2[0] = rd->alpha2[0];
request->alpha2[1] = rd->alpha2[1];
request->initiator = REGDOM_SET_BY_COUNTRY_IE;
request->initiator = NL80211_REGDOM_SET_BY_COUNTRY_IE;
request->country_ie_checksum = checksum;
request->country_ie_env = env;
@@ -1818,7 +1843,8 @@ static void print_regdomain(const struct ieee80211_regdomain *rd)
if (is_intersected_alpha2(rd->alpha2)) {
if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) {
if (last_request->initiator ==
NL80211_REGDOM_SET_BY_COUNTRY_IE) {
struct cfg80211_registered_device *drv;
drv = cfg80211_drv_by_wiphy_idx(
last_request->wiphy_idx);
@@ -1910,7 +1936,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
* rd is non static (it means CRDA was present and was used last)
* and the pending request came in from a country IE
*/
if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE) {
if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
/*
* If someone else asked us to change the rd lets only bother
* checking if the alpha2 changes if CRDA was already called
@@ -1942,7 +1968,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
if (!last_request->intersect) {
int r;
if (last_request->initiator != REGDOM_SET_BY_DRIVER) {
if (last_request->initiator != NL80211_REGDOM_SET_BY_DRIVER) {
reset_regdomains();
cfg80211_regdomain = rd;
return 0;
@@ -1966,7 +1992,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
/* Intersection requires a bit more work */
if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE) {
if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
intersected_rd = regdom_intersect(rd, cfg80211_regdomain);
if (!intersected_rd)
@@ -1977,7 +2003,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
* However if a driver requested this specific regulatory
* domain we keep it for its private use
*/
if (last_request->initiator == REGDOM_SET_BY_DRIVER)
if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER)
request_wiphy->regd = rd;
else
kfree(rd);
@@ -2067,6 +2093,8 @@ int set_regdom(const struct ieee80211_regdomain *rd)
print_regdomain(cfg80211_regdomain);
nl80211_send_reg_change_event(last_request);
return r;
}