Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
707be0ae
Commit
707be0ae
authored
Jul 17, 2012
by
John W. Linville
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-john' of
git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
parents
040a7831
88bc40e8
Changes
19
Show whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
432 additions
and
137 deletions
+432
-137
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/mac80211_hwsim.c
+0
-5
include/linux/nl80211.h
include/linux/nl80211.h
+48
-0
include/net/cfg80211.h
include/net/cfg80211.h
+29
-3
include/net/regulatory.h
include/net/regulatory.h
+5
-0
net/mac80211/cfg.c
net/mac80211/cfg.c
+7
-6
net/mac80211/ieee80211_i.h
net/mac80211/ieee80211_i.h
+0
-4
net/mac80211/iface.c
net/mac80211/iface.c
+14
-2
net/mac80211/mlme.c
net/mac80211/mlme.c
+11
-6
net/mac80211/offchannel.c
net/mac80211/offchannel.c
+4
-2
net/wireless/Kconfig
net/wireless/Kconfig
+21
-0
net/wireless/chan.c
net/wireless/chan.c
+10
-10
net/wireless/core.c
net/wireless/core.c
+7
-51
net/wireless/core.h
net/wireless/core.h
+0
-3
net/wireless/mlme.c
net/wireless/mlme.c
+13
-0
net/wireless/nl80211.c
net/wireless/nl80211.c
+132
-24
net/wireless/nl80211.h
net/wireless/nl80211.h
+5
-0
net/wireless/reg.c
net/wireless/reg.c
+114
-16
net/wireless/reg.h
net/wireless/reg.h
+5
-3
net/wireless/wext-compat.c
net/wireless/wext-compat.c
+7
-2
No files found.
drivers/net/wireless/mac80211_hwsim.c
View file @
707be0ae
...
...
@@ -1540,11 +1540,6 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
/* now send back TX status */
txi
=
IEEE80211_SKB_CB
(
skb
);
if
(
txi
->
control
.
vif
)
hwsim_check_magic
(
txi
->
control
.
vif
);
if
(
txi
->
control
.
sta
)
hwsim_check_sta_magic
(
txi
->
control
.
sta
);
ieee80211_tx_info_clear_status
(
txi
);
for
(
i
=
0
;
i
<
IEEE80211_TX_MAX_RATES
;
i
++
)
{
...
...
include/linux/nl80211.h
View file @
707be0ae
...
...
@@ -1245,6 +1245,12 @@ enum nl80211_commands {
* @NL80211_ATTR_BG_SCAN_PERIOD: Background scan period in seconds
* or 0 to disable background scan.
*
* @NL80211_ATTR_USER_REG_HINT_TYPE: type of regulatory hint passed from
* userspace. If unset it is assumed the hint comes directly from
* a user. If set code could specify exactly what type of source
* was used to provide the hint. For the different types of
* allowed user regulatory hints see nl80211_user_reg_hint_type.
*
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
...
...
@@ -1498,6 +1504,8 @@ enum nl80211_attrs {
NL80211_ATTR_WDEV
,
NL80211_ATTR_USER_REG_HINT_TYPE
,
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST
,
...
...
@@ -1550,6 +1558,8 @@ enum nl80211_attrs {
/* default RSSI threshold for scan results if none specified. */
#define NL80211_SCAN_RSSI_THOLD_OFF -300
#define NL80211_CQM_TXE_MAX_INTVL 1800
/**
* enum nl80211_iftype - (virtual) interface types
*
...
...
@@ -2058,6 +2068,26 @@ enum nl80211_dfs_regions {
NL80211_DFS_JP
=
3
,
};
/**
* enum nl80211_user_reg_hint_type - type of user regulatory hint
*
* @NL80211_USER_REG_HINT_USER: a user sent the hint. This is always
* assumed if the attribute is not set.
* @NL80211_USER_REG_HINT_CELL_BASE: the hint comes from a cellular
* base station. Device drivers that have been tested to work
* properly to support this type of hint can enable these hints
* by setting the NL80211_FEATURE_CELL_BASE_REG_HINTS feature
* capability on the struct wiphy. The wireless core will
* ignore all cell base station hints until at least one device
* present has been registered with the wireless core that
* has listed NL80211_FEATURE_CELL_BASE_REG_HINTS as a
* supported feature.
*/
enum
nl80211_user_reg_hint_type
{
NL80211_USER_REG_HINT_USER
=
0
,
NL80211_USER_REG_HINT_CELL_BASE
=
1
,
};
/**
* enum nl80211_survey_info - survey information
*
...
...
@@ -2589,6 +2619,17 @@ enum nl80211_ps_state {
* @NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT: RSSI threshold event
* @NL80211_ATTR_CQM_PKT_LOSS_EVENT: a u32 value indicating that this many
* consecutive packets were not acknowledged by the peer
* @NL80211_ATTR_CQM_TXE_RATE: TX error rate in %. Minimum % of TX failures
* during the given %NL80211_ATTR_CQM_TXE_INTVL before an
* %NL80211_CMD_NOTIFY_CQM with reported %NL80211_ATTR_CQM_TXE_RATE and
* %NL80211_ATTR_CQM_TXE_PKTS is generated.
* @NL80211_ATTR_CQM_TXE_PKTS: number of attempted packets in a given
* %NL80211_ATTR_CQM_TXE_INTVL before %NL80211_ATTR_CQM_TXE_RATE is
* checked.
* @NL80211_ATTR_CQM_TXE_INTVL: interval in seconds. Specifies the periodic
* interval in which %NL80211_ATTR_CQM_TXE_PKTS and
* %NL80211_ATTR_CQM_TXE_RATE must be satisfied before generating an
* %NL80211_CMD_NOTIFY_CQM. Set to 0 to turn off TX error reporting.
* @__NL80211_ATTR_CQM_AFTER_LAST: internal
* @NL80211_ATTR_CQM_MAX: highest key attribute
*/
...
...
@@ -2598,6 +2639,9 @@ enum nl80211_attr_cqm {
NL80211_ATTR_CQM_RSSI_HYST
,
NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT
,
NL80211_ATTR_CQM_PKT_LOSS_EVENT
,
NL80211_ATTR_CQM_TXE_RATE
,
NL80211_ATTR_CQM_TXE_PKTS
,
NL80211_ATTR_CQM_TXE_INTVL
,
/* keep last */
__NL80211_ATTR_CQM_AFTER_LAST
,
...
...
@@ -2947,11 +2991,15 @@ enum nl80211_ap_sme_features {
* @NL80211_FEATURE_HT_IBSS: This driver supports IBSS with HT datarates.
* @NL80211_FEATURE_INACTIVITY_TIMER: This driver takes care of freeing up
* the connected inactive stations in AP mode.
* @NL80211_FEATURE_CELL_BASE_REG_HINTS: This driver has been tested
* to work properly to suppport receiving regulatory hints from
* cellular base stations.
*/
enum
nl80211_feature_flags
{
NL80211_FEATURE_SK_TX_STATUS
=
1
<<
0
,
NL80211_FEATURE_HT_IBSS
=
1
<<
1
,
NL80211_FEATURE_INACTIVITY_TIMER
=
1
<<
2
,
NL80211_FEATURE_CELL_BASE_REG_HINTS
=
1
<<
3
,
};
/**
...
...
include/net/cfg80211.h
View file @
707be0ae
...
...
@@ -1504,8 +1504,6 @@ struct cfg80211_gtk_rekey_data {
* interfaces are active this callback should reject the configuration.
* If no interfaces are active or the device is down, the channel should
* be stored for when a monitor interface becomes active.
* @set_monitor_enabled: Notify driver that there are only monitor
* interfaces running.
*
* @scan: Request to do a scan. If returning zero, the scan request is given
* the driver, and will be valid until passed to cfg80211_scan_done().
...
...
@@ -1575,6 +1573,8 @@ struct cfg80211_gtk_rekey_data {
* @set_power_mgmt: Configure WLAN power management. A timeout value of -1
* allows the driver to adjust the dynamic ps timeout value.
* @set_cqm_rssi_config: Configure connection quality monitor RSSI threshold.
* @set_cqm_txe_config: Configure connection quality monitor TX error
* thresholds.
* @sched_scan_start: Tell the driver to start a scheduled scan.
* @sched_scan_stop: Tell the driver to stop an ongoing scheduled
* scan. The driver_initiated flag specifies whether the driver
...
...
@@ -1612,6 +1612,10 @@ struct cfg80211_gtk_rekey_data {
* @get_et_strings: Ethtool API to get a set of strings to describe stats
* and perhaps other supported types of ethtool data-sets.
* See @ethtool_ops.get_strings
*
* @get_channel: Get the current operating channel for the virtual interface.
* For monitor interfaces, it should return %NULL unless there's a single
* current monitoring channel.
*/
struct
cfg80211_ops
{
int
(
*
suspend
)(
struct
wiphy
*
wiphy
,
struct
cfg80211_wowlan
*
wow
);
...
...
@@ -1781,6 +1785,10 @@ struct cfg80211_ops {
struct
net_device
*
dev
,
s32
rssi_thold
,
u32
rssi_hyst
);
int
(
*
set_cqm_txe_config
)(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
,
u32
rate
,
u32
pkts
,
u32
intvl
);
void
(
*
mgmt_frame_register
)(
struct
wiphy
*
wiphy
,
struct
wireless_dev
*
wdev
,
u16
frame_type
,
bool
reg
);
...
...
@@ -1820,7 +1828,10 @@ struct cfg80211_ops {
void
(
*
get_et_strings
)(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
,
u32
sset
,
u8
*
data
);
void
(
*
set_monitor_enabled
)(
struct
wiphy
*
wiphy
,
bool
enabled
);
struct
ieee80211_channel
*
(
*
get_channel
)(
struct
wiphy
*
wiphy
,
struct
wireless_dev
*
wdev
,
enum
nl80211_channel_type
*
type
);
};
/*
...
...
@@ -3390,6 +3401,21 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
void
cfg80211_cqm_pktloss_notify
(
struct
net_device
*
dev
,
const
u8
*
peer
,
u32
num_packets
,
gfp_t
gfp
);
/**
* cfg80211_cqm_txe_notify - TX error rate event
* @dev: network device
* @peer: peer's MAC address
* @num_packets: how many packets were lost
* @rate: % of packets which failed transmission
* @intvl: interval (in s) over which the TX failure threshold was breached.
* @gfp: context flags
*
* Notify userspace when configured % TX failures over number of packets in a
* given interval is exceeded.
*/
void
cfg80211_cqm_txe_notify
(
struct
net_device
*
dev
,
const
u8
*
peer
,
u32
num_packets
,
u32
rate
,
u32
intvl
,
gfp_t
gfp
);
/**
* cfg80211_gtk_rekey_notify - notify userspace about driver rekeying
* @dev: network device
...
...
include/net/regulatory.h
View file @
707be0ae
...
...
@@ -52,6 +52,10 @@ enum environment_cap {
* DFS master operation on a known DFS region (NL80211_DFS_*),
* dfs_region represents that region. Drivers can use this and the
* @alpha2 to adjust their device's DFS parameters as required.
* @user_reg_hint_type: if the @initiator was of type
* %NL80211_REGDOM_SET_BY_USER, this classifies the type
* of hint passed. This could be any of the %NL80211_USER_REG_HINT_*
* types.
* @intersect: indicates whether the wireless core should intersect
* the requested regulatory domain with the presently set regulatory
* domain.
...
...
@@ -70,6 +74,7 @@ enum environment_cap {
struct
regulatory_request
{
int
wiphy_idx
;
enum
nl80211_reg_initiator
initiator
;
enum
nl80211_user_reg_hint_type
user_reg_hint_type
;
char
alpha2
[
2
];
u8
dfs_region
;
bool
intersect
;
...
...
net/mac80211/cfg.c
View file @
707be0ae
...
...
@@ -2493,6 +2493,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
skb
->
dev
=
sdata
->
dev
;
if
(
!
need_offchan
)
{
*
cookie
=
(
unsigned
long
)
skb
;
ieee80211_tx_skb
(
sdata
,
skb
);
ret
=
0
;
goto
out_unlock
;
...
...
@@ -2982,14 +2983,14 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
return
0
;
}
static
void
ieee80211_set_monitor_enabled
(
struct
wiphy
*
wiphy
,
bool
enabled
)
static
struct
ieee80211_channel
*
ieee80211_cfg_get_channel
(
struct
wiphy
*
wiphy
,
struct
wireless_dev
*
wdev
,
enum
nl80211_channel_type
*
type
)
{
struct
ieee80211_local
*
local
=
wiphy_priv
(
wiphy
);
if
(
enabled
)
WARN_ON
(
ieee80211_add_virtual_monitor
(
local
));
else
ieee80211_del_virtual_monitor
(
local
);
*
type
=
local
->
_oper_channel_type
;
return
local
->
oper_channel
;
}
#ifdef CONFIG_PM
...
...
@@ -3066,11 +3067,11 @@ struct cfg80211_ops mac80211_config_ops = {
.
tdls_mgmt
=
ieee80211_tdls_mgmt
,
.
probe_client
=
ieee80211_probe_client
,
.
set_noack_map
=
ieee80211_set_noack_map
,
.
set_monitor_enabled
=
ieee80211_set_monitor_enabled
,
#ifdef CONFIG_PM
.
set_wakeup
=
ieee80211_set_wakeup
,
#endif
.
get_et_sset_count
=
ieee80211_get_et_sset_count
,
.
get_et_stats
=
ieee80211_get_et_stats
,
.
get_et_strings
=
ieee80211_get_et_strings
,
.
get_channel
=
ieee80211_cfg_get_channel
,
};
net/mac80211/ieee80211_i.h
View file @
707be0ae
...
...
@@ -1491,10 +1491,6 @@ int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata,
int
ieee80211_add_ext_srates_ie
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
sk_buff
*
skb
,
bool
need_basic
);
/* virtual monitor */
int
ieee80211_add_virtual_monitor
(
struct
ieee80211_local
*
local
);
void
ieee80211_del_virtual_monitor
(
struct
ieee80211_local
*
local
);
/* channel management */
enum
ieee80211_chan_mode
{
CHAN_MODE_UNDEFINED
,
...
...
net/mac80211/iface.c
View file @
707be0ae
...
...
@@ -331,7 +331,7 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata)
sdata
->
vif
.
cab_queue
=
IEEE80211_INVAL_HW_QUEUE
;
}
int
ieee80211_add_virtual_monitor
(
struct
ieee80211_local
*
local
)
static
int
ieee80211_add_virtual_monitor
(
struct
ieee80211_local
*
local
)
{
struct
ieee80211_sub_if_data
*
sdata
;
int
ret
=
0
;
...
...
@@ -377,7 +377,7 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
return
ret
;
}
void
ieee80211_del_virtual_monitor
(
struct
ieee80211_local
*
local
)
static
void
ieee80211_del_virtual_monitor
(
struct
ieee80211_local
*
local
)
{
struct
ieee80211_sub_if_data
*
sdata
;
...
...
@@ -497,6 +497,12 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
break
;
}
if
(
local
->
monitors
==
0
&&
local
->
open_count
==
0
)
{
res
=
ieee80211_add_virtual_monitor
(
local
);
if
(
res
)
goto
err_stop
;
}
/* must be before the call to ieee80211_configure_filter */
local
->
monitors
++
;
if
(
local
->
monitors
==
1
)
{
...
...
@@ -511,6 +517,8 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
break
;
default:
if
(
coming_up
)
{
ieee80211_del_virtual_monitor
(
local
);
res
=
drv_add_interface
(
local
,
sdata
);
if
(
res
)
goto
err_stop
;
...
...
@@ -745,6 +753,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
if
(
local
->
monitors
==
0
)
{
local
->
hw
.
conf
.
flags
&=
~
IEEE80211_CONF_MONITOR
;
hw_reconf_flags
|=
IEEE80211_CONF_CHANGE_MONITOR
;
ieee80211_del_virtual_monitor
(
local
);
}
ieee80211_adjust_monitor_flags
(
sdata
,
-
1
);
...
...
@@ -818,6 +827,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
}
}
spin_unlock_irqrestore
(
&
local
->
queue_stop_reason_lock
,
flags
);
if
(
local
->
monitors
==
local
->
open_count
&&
local
->
monitors
>
0
)
ieee80211_add_virtual_monitor
(
local
);
}
static
int
ieee80211_stop
(
struct
net_device
*
dev
)
...
...
net/mac80211/mlme.c
View file @
707be0ae
...
...
@@ -1360,6 +1360,17 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
}
mutex_unlock
(
&
local
->
sta_mtx
);
/*
* if we want to get out of ps before disassoc (why?) we have
* to do it before sending disassoc, as otherwise the null-packet
* won't be valid.
*/
if
(
local
->
hw
.
conf
.
flags
&
IEEE80211_CONF_PS
)
{
local
->
hw
.
conf
.
flags
&=
~
IEEE80211_CONF_PS
;
ieee80211_hw_config
(
local
,
IEEE80211_CONF_CHANGE_PS
);
}
local
->
ps_sdata
=
NULL
;
/* flush out any pending frame (e.g. DELBA) before deauth/disassoc */
if
(
tx
)
drv_flush
(
local
,
false
);
...
...
@@ -1395,12 +1406,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
del_timer_sync
(
&
local
->
dynamic_ps_timer
);
cancel_work_sync
(
&
local
->
dynamic_ps_enable_work
);
if
(
local
->
hw
.
conf
.
flags
&
IEEE80211_CONF_PS
)
{
local
->
hw
.
conf
.
flags
&=
~
IEEE80211_CONF_PS
;
ieee80211_hw_config
(
local
,
IEEE80211_CONF_CHANGE_PS
);
}
local
->
ps_sdata
=
NULL
;
/* Disable ARP filtering */
if
(
sdata
->
vif
.
bss_conf
.
arp_filter_enabled
)
{
sdata
->
vif
.
bss_conf
.
arp_filter_enabled
=
false
;
...
...
net/mac80211/offchannel.c
View file @
707be0ae
...
...
@@ -324,6 +324,7 @@ void ieee80211_sw_roc_work(struct work_struct *work)
container_of
(
work
,
struct
ieee80211_roc_work
,
work
.
work
);
struct
ieee80211_sub_if_data
*
sdata
=
roc
->
sdata
;
struct
ieee80211_local
*
local
=
sdata
->
local
;
bool
started
;
mutex_lock
(
&
local
->
mtx
);
...
...
@@ -366,9 +367,10 @@ void ieee80211_sw_roc_work(struct work_struct *work)
/* finish this ROC */
finish:
list_del
(
&
roc
->
list
);
started
=
roc
->
started
;
ieee80211_roc_notify_destroy
(
roc
);
if
(
roc
->
started
)
{
if
(
started
)
{
drv_flush
(
local
,
false
);
local
->
tmp_channel
=
NULL
;
...
...
@@ -379,7 +381,7 @@ void ieee80211_sw_roc_work(struct work_struct *work)
ieee80211_recalc_idle
(
local
);
if
(
roc
->
started
)
if
(
started
)
ieee80211_start_next_roc
(
local
);
}
...
...
net/wireless/Kconfig
View file @
707be0ae
...
...
@@ -74,6 +74,27 @@ config CFG80211_REG_DEBUG
If unsure, say N.
config CFG80211_CERTIFICATION_ONUS
bool "cfg80211 certification onus"
depends on CFG80211 && EXPERT
default n
---help---
You should disable this option unless you are both capable
and willing to ensure your system will remain regulatory
compliant with the features available under this option.
Some options may still be under heavy development and
for whatever reason regulatory compliance has not or
cannot yet be verified. Regulatory verification may at
times only be possible until you have the final system
in place.
This option should only be enabled by system integrators
or distributions that have done work necessary to ensure
regulatory certification on the system with the enabled
features. Alternatively you can enable this option if
you are a wireless researcher and are working in a controlled
and approved environment by your local regulatory agency.
config CFG80211_DEFAULT_PS
bool "enable powersave by default"
depends on CFG80211
...
...
net/wireless/chan.c
View file @
707be0ae
...
...
@@ -82,7 +82,6 @@ int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
int
freq
,
enum
nl80211_channel_type
chantype
)
{
struct
ieee80211_channel
*
chan
;
int
err
;
if
(
!
rdev
->
ops
->
set_monitor_channel
)
return
-
EOPNOTSUPP
;
...
...
@@ -93,13 +92,7 @@ int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
if
(
!
chan
)
return
-
EINVAL
;
err
=
rdev
->
ops
->
set_monitor_channel
(
&
rdev
->
wiphy
,
chan
,
chantype
);
if
(
!
err
)
{
rdev
->
monitor_channel
=
chan
;
rdev
->
monitor_channel_type
=
chantype
;
}
return
err
;
return
rdev
->
ops
->
set_monitor_channel
(
&
rdev
->
wiphy
,
chan
,
chantype
);
}
void
...
...
@@ -134,9 +127,16 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
break
;
case
NL80211_IFTYPE_AP
:
case
NL80211_IFTYPE_P2P_GO
:
if
(
wdev
->
beacon_interval
)
{
*
chan
=
wdev
->
channel
;
*
chanmode
=
CHAN_MODE_SHARED
;
}
return
;
case
NL80211_IFTYPE_MESH_POINT
:
if
(
wdev
->
mesh_id_len
)
{
*
chan
=
wdev
->
channel
;
*
chanmode
=
CHAN_MODE_SHARED
;
}
return
;
case
NL80211_IFTYPE_MONITOR
:
case
NL80211_IFTYPE_AP_VLAN
:
...
...
net/wireless/core.c
View file @
707be0ae
...
...
@@ -542,7 +542,7 @@ int wiphy_register(struct wiphy *wiphy)
}
/* set up regulatory info */
regulatory_update
(
wiphy
,
NL80211_REGDOM_SET_BY_CORE
);
wiphy_regulatory_register
(
wiphy
);
list_add_rcu
(
&
rdev
->
list
,
&
cfg80211_rdev_list
);
cfg80211_rdev_list_generation
++
;
...
...
@@ -652,9 +652,11 @@ void wiphy_unregister(struct wiphy *wiphy)
/* nothing */
cfg80211_unlock_rdev
(
rdev
);
/* If this device got a regulatory hint tell core its
* free to listen now to a new shiny device regulatory hint */
reg_device_remove
(
wiphy
);
/*
* If this device got a regulatory hint tell core its
* free to listen now to a new shiny device regulatory hint
*/
wiphy_regulatory_deregister
(
wiphy
);
cfg80211_rdev_list_generation
++
;
device_del
(
&
rdev
->
wiphy
.
dev
);
...
...
@@ -736,60 +738,14 @@ static struct device_type wiphy_type = {
.
name
=
"wlan"
,
};
static
struct
ieee80211_channel
*
cfg80211_get_any_chan
(
struct
cfg80211_registered_device
*
rdev
)
{
struct
ieee80211_supported_band
*
sband
;
int
i
;
for
(
i
=
0
;
i
<
IEEE80211_NUM_BANDS
;
i
++
)
{
sband
=
rdev
->
wiphy
.
bands
[
i
];
if
(
sband
&&
sband
->
n_channels
>
0
)
return
&
sband
->
channels
[
0
];
}
return
NULL
;
}
static
void
cfg80211_init_mon_chan
(
struct
cfg80211_registered_device
*
rdev
)
{
struct
ieee80211_channel
*
chan
;
chan
=
cfg80211_get_any_chan
(
rdev
);
if
(
WARN_ON
(
!
chan
))
return
;
mutex_lock
(
&
rdev
->
devlist_mtx
);
WARN_ON
(
cfg80211_set_monitor_channel
(
rdev
,
chan
->
center_freq
,
NL80211_CHAN_NO_HT
));
mutex_unlock
(
&
rdev
->
devlist_mtx
);
}
void
cfg80211_update_iface_num
(
struct
cfg80211_registered_device
*
rdev
,
enum
nl80211_iftype
iftype
,
int
num
)
{
bool
has_monitors_only_old
=
cfg80211_has_monitors_only
(
rdev
);
bool
has_monitors_only_new
;
ASSERT_RTNL
();
rdev
->
num_running_ifaces
+=
num
;
if
(
iftype
==
NL80211_IFTYPE_MONITOR
)
rdev
->
num_running_monitor_ifaces
+=
num
;
has_monitors_only_new
=
cfg80211_has_monitors_only
(
rdev
);
if
(
has_monitors_only_new
!=
has_monitors_only_old
)
{
if
(
rdev
->
ops
->
set_monitor_enabled
)
rdev
->
ops
->
set_monitor_enabled
(
&
rdev
->
wiphy
,
has_monitors_only_new
);
if
(
!
has_monitors_only_new
)
{
rdev
->
monitor_channel
=
NULL
;
rdev
->
monitor_channel_type
=
NL80211_CHAN_NO_HT
;
}
else
{
cfg80211_init_mon_chan
(
rdev
);
}
}
}
static
int
cfg80211_netdev_notifier_call
(
struct
notifier_block
*
nb
,
...
...
@@ -912,6 +868,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
mutex_unlock
(
&
rdev
->
devlist_mtx
);
dev_put
(
dev
);
}
cfg80211_update_iface_num
(
rdev
,
wdev
->
iftype
,
1
);
cfg80211_lock_rdev
(
rdev
);
mutex_lock
(
&
rdev
->
devlist_mtx
);
wdev_lock
(
wdev
);
...
...
@@ -1006,7 +963,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
mutex_unlock
(
&
rdev
->
devlist_mtx
);
if
(
ret
)
return
notifier_from_errno
(
ret
);
cfg80211_update_iface_num
(
rdev
,
wdev
->
iftype
,
1
);
break
;
}
...
...
net/wireless/core.h
View file @
707be0ae
...
...
@@ -61,9 +61,6 @@ struct cfg80211_registered_device {
int
num_running_ifaces
;
int
num_running_monitor_ifaces
;
struct
ieee80211_channel
*
monitor_channel
;
enum
nl80211_channel_type
monitor_channel_type
;
/* BSSes/scanning */
spinlock_t
bss_lock
;
struct
list_head
bss_list
;
...
...
net/wireless/mlme.c
View file @
707be0ae
...
...
@@ -919,6 +919,19 @@ void cfg80211_cqm_pktloss_notify(struct net_device *dev,
}
EXPORT_SYMBOL
(
cfg80211_cqm_pktloss_notify
);
void
cfg80211_cqm_txe_notify
(
struct
net_device
*
dev
,
const
u8
*
peer
,
u32
num_packets
,
u32
rate
,
u32
intvl
,
gfp_t
gfp
)
{
struct
wireless_dev
*
wdev
=
dev
->
ieee80211_ptr
;
struct
wiphy
*
wiphy
=
wdev
->
wiphy
;
struct
cfg80211_registered_device
*
rdev
=
wiphy_to_dev
(
wiphy
);
nl80211_send_cqm_txe_notify
(
rdev
,
dev
,
peer
,
num_packets
,
rate
,
intvl
,
gfp
);
}
EXPORT_SYMBOL
(
cfg80211_cqm_txe_notify
);
void
cfg80211_gtk_rekey_notify
(
struct
net_device
*
dev
,
const
u8
*
bssid
,
const
u8
*
replay_ctr
,
gfp_t
gfp
)
{
...
...
net/wireless/nl80211.c
View file @
707be0ae
...
...
@@ -354,6 +354,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[
NL80211_ATTR_INACTIVITY_TIMEOUT
]
=
{
.
type
=
NLA_U16
},
[
NL80211_ATTR_BG_SCAN_PERIOD
]
=
{
.
type
=
NLA_U16
},
[
NL80211_ATTR_WDEV
]
=
{
.
type
=
NLA_U64
},
[
NL80211_ATTR_USER_REG_HINT_TYPE
]
=
{
.
type
=
NLA_U32
},
};
/* policy for the key attributes */
...
...
@@ -1759,11 +1760,17 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
(
cfg80211_rdev_list_generation
<<
2
)))
goto
nla_put_failure
;
if
(
rdev
->
monitor_channel
)
{
if
(
nla_put_u32
(
msg
,
NL80211_ATTR_WIPHY_FREQ
,
rdev
->
monitor_channel
->
center_freq
)
||
if
(
rdev
->
ops
->
get_channel
)
{
struct
ieee80211_channel
*
chan
;
enum
nl80211_channel_type
channel_type
;
chan
=
rdev
->
ops
->
get_channel
(
&
rdev
->
wiphy
,
wdev
,
&
channel_type
);
if
(
chan
&&
(
nla_put_u32
(
msg
,
NL80211_ATTR_WIPHY_FREQ
,
chan
->
center_freq
)
||
nla_put_u32
(
msg
,
NL80211_ATTR_WIPHY_CHANNEL_TYPE
,
rdev
->
monitor_channel_type
))
channel_type
)
))
goto
nla_put_failure
;
}
...
...
@@ -3576,6 +3583,7 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
{
int
r
;
char
*
data
=
NULL
;
enum
nl80211_user_reg_hint_type
user_reg_hint_type
;
/*
* You should only get this when cfg80211 hasn't yet initialized
...
...
@@ -3595,7 +3603,21 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
data
=
nla_data
(
info
->
attrs
[
NL80211_ATTR_REG_ALPHA2
]);
r
=
regulatory_hint_user
(
data
);
if
(
info
->
attrs
[
NL80211_ATTR_USER_REG_HINT_TYPE
])
user_reg_hint_type
=
nla_get_u32
(
info
->
attrs
[
NL80211_ATTR_USER_REG_HINT_TYPE
]);
else
user_reg_hint_type
=
NL80211_USER_REG_HINT_USER
;
switch
(
user_reg_hint_type
)
{
case
NL80211_USER_REG_HINT_USER
:
case
NL80211_USER_REG_HINT_CELL_BASE
:
break
;
default:
return
-
EINVAL
;
}
r
=
regulatory_hint_user
(
data
,
user_reg_hint_type
);
return
r
;
}
...
...
@@ -3965,6 +3987,11 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
cfg80211_regdomain
->
dfs_region
)))
goto
nla_put_failure
;
if
(
reg_last_request_cell_base
()
&&
nla_put_u32
(
msg
,
NL80211_ATTR_USER_REG_HINT_TYPE
,
NL80211_USER_REG_HINT_CELL_BASE
))
goto
nla_put_failure
;
nl_reg_rules
=
nla_nest_start
(
msg
,
NL80211_ATTR_REG_RULES
);
if
(
!
nl_reg_rules
)
goto
nla_put_failure
;
...
...
@@ -6261,8 +6288,35 @@ nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] __read_mostly = {
[
NL80211_ATTR_CQM_RSSI_THOLD
]
=
{
.
type
=
NLA_U32
},
[
NL80211_ATTR_CQM_RSSI_HYST
]
=
{
.
type
=
NLA_U32
},
[
NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT
]
=
{
.
type
=
NLA_U32
},
[
NL80211_ATTR_CQM_TXE_RATE
]
=
{
.
type
=
NLA_U32
},
[
NL80211_ATTR_CQM_TXE_PKTS
]
=
{
.
type
=
NLA_U32
},
[
NL80211_ATTR_CQM_TXE_INTVL
]
=
{
.
type
=
NLA_U32
},
};
static
int
nl80211_set_cqm_txe
(
struct
genl_info
*
info
,
u32
rate
,
u32
pkts
,
u32
intvl
)
{
struct
cfg80211_registered_device
*
rdev
=
info
->
user_ptr
[
0
];
struct
wireless_dev
*
wdev
;
struct
net_device
*
dev
=
info
->
user_ptr
[
1
];
if
((
rate
<
0
||
rate
>
100
)
||
(
intvl
<
0
||
intvl
>
NL80211_CQM_TXE_MAX_INTVL
))
return
-
EINVAL
;
wdev
=
dev
->
ieee80211_ptr
;
if
(
!
rdev
->
ops
->
set_cqm_txe_config
)
return
-
EOPNOTSUPP
;
if
(
wdev
->
iftype
!=
NL80211_IFTYPE_STATION
&&
wdev
->
iftype
!=
NL80211_IFTYPE_P2P_CLIENT
)
return
-
EOPNOTSUPP
;
return
rdev
->
ops
->
set_cqm_txe_config
(
wdev
->
wiphy
,
dev
,
rate
,
pkts
,
intvl
);
}
static
int
nl80211_set_cqm_rssi
(
struct
genl_info
*
info
,
s32
threshold
,
u32
hysteresis
)
{
...
...
@@ -6310,6 +6364,14 @@ static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
threshold
=
nla_get_u32
(
attrs
[
NL80211_ATTR_CQM_RSSI_THOLD
]);
hysteresis
=
nla_get_u32
(
attrs
[
NL80211_ATTR_CQM_RSSI_HYST
]);
err
=
nl80211_set_cqm_rssi
(
info
,
threshold
,
hysteresis
);
}
else
if
(
attrs
[
NL80211_ATTR_CQM_TXE_RATE
]
&&
attrs
[
NL80211_ATTR_CQM_TXE_PKTS
]
&&
attrs
[
NL80211_ATTR_CQM_TXE_INTVL
])
{
u32
rate
,
pkts
,
intvl
;
rate
=
nla_get_u32
(
attrs
[
NL80211_ATTR_CQM_TXE_RATE
]);
pkts
=
nla_get_u32
(
attrs
[
NL80211_ATTR_CQM_TXE_PKTS
]);
intvl
=
nla_get_u32
(
attrs
[
NL80211_ATTR_CQM_TXE_INTVL
]);
err
=
nl80211_set_cqm_txe
(
info
,
rate
,
pkts
,
intvl
);
}
else
err
=
-
EINVAL
;
...
...
@@ -6466,8 +6528,8 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
{
struct
cfg80211_registered_device
*
rdev
=
info
->
user_ptr
[
0
];
struct
nlattr
*
tb
[
NUM_NL80211_WOWLAN_TRIG
];
struct
cfg80211_wowlan
no_triggers
=
{};
struct
cfg80211_wowlan
new_triggers
=
{};
struct
cfg80211_wowlan
*
ntrig
;
struct
wiphy_wowlan_support
*
wowlan
=
&
rdev
->
wiphy
.
wowlan
;
int
err
,
i
;
bool
prev_enabled
=
rdev
->
wowlan
;
...
...
@@ -6475,8 +6537,11 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
if
(
!
rdev
->
wiphy
.
wowlan
.
flags
&&
!
rdev
->
wiphy
.
wowlan
.
n_patterns
)
return
-
EOPNOTSUPP
;
if
(
!
info
->
attrs
[
NL80211_ATTR_WOWLAN_TRIGGERS
])
goto
no_triggers
;
if
(
!
info
->
attrs
[
NL80211_ATTR_WOWLAN_TRIGGERS
])
{
cfg80211_rdev_free_wowlan
(
rdev
);
rdev
->
wowlan
=
NULL
;
goto
set_wakeup
;
}
err
=
nla_parse
(
tb
,
MAX_NL80211_WOWLAN_TRIG
,
nla_data
(
info
->
attrs
[
NL80211_ATTR_WOWLAN_TRIGGERS
]),
...
...
@@ -6587,22 +6652,15 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
}
}
if
(
memcmp
(
&
new_triggers
,
&
no_triggers
,
sizeof
(
new_triggers
)))
{
struct
cfg80211_wowlan
*
ntrig
;
ntrig
=
kmemdup
(
&
new_triggers
,
sizeof
(
new_triggers
),
GFP_KERNEL
);
ntrig
=
kmemdup
(
&
new_triggers
,
sizeof
(
new_triggers
),
GFP_KERNEL
);
if
(
!
ntrig
)
{
err
=
-
ENOMEM
;
goto
error
;
}
cfg80211_rdev_free_wowlan
(
rdev
);
rdev
->
wowlan
=
ntrig
;
}
else
{
no_triggers:
cfg80211_rdev_free_wowlan
(
rdev
);
rdev
->
wowlan
=
NULL
;
}
set_wakeup:
if
(
rdev
->
ops
->
set_wakeup
&&
prev_enabled
!=
!!
rdev
->
wowlan
)
rdev
->
ops
->
set_wakeup
(
&
rdev
->
wiphy
,
rdev
->
wowlan
);
...
...
@@ -8099,7 +8157,7 @@ static void nl80211_send_remain_on_chan_event(
if
(
nla_put_u32
(
msg
,
NL80211_ATTR_WIPHY
,
rdev
->
wiphy_idx
)
||
(
wdev
->
netdev
&&
nla_put_u32
(
msg
,
NL80211_ATTR_IFINDEX
,
wdev
->
netdev
->
ifindex
))
||
nla_put_u
32
(
msg
,
NL80211_ATTR_WDEV
,
wdev_id
(
wdev
))
||
nla_put_u
64
(
msg
,
NL80211_ATTR_WDEV
,
wdev_id
(
wdev
))
||
nla_put_u32
(
msg
,
NL80211_ATTR_WIPHY_FREQ
,
chan
->
center_freq
)
||
nla_put_u32
(
msg
,
NL80211_ATTR_WIPHY_CHANNEL_TYPE
,
channel_type
)
||
nla_put_u64
(
msg
,
NL80211_ATTR_COOKIE
,
cookie
))
...
...
@@ -8493,6 +8551,56 @@ void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
nlmsg_free
(
msg
);
}
void
nl80211_send_cqm_txe_notify
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
netdev
,
const
u8
*
peer
,
u32
num_packets
,
u32
rate
,
u32
intvl
,
gfp_t
gfp
)
{
struct
sk_buff
*
msg
;
struct
nlattr
*
pinfoattr
;
void
*
hdr
;
msg
=
nlmsg_new
(
NLMSG_GOODSIZE
,
gfp
);
if
(
!
msg
)
return
;
hdr
=
nl80211hdr_put
(
msg
,
0
,
0
,
0
,
NL80211_CMD_NOTIFY_CQM
);
if
(
!
hdr
)
{
nlmsg_free
(
msg
);
return
;
}
if
(
nla_put_u32
(
msg
,
NL80211_ATTR_WIPHY
,
rdev
->
wiphy_idx
)
||
nla_put_u32
(
msg
,
NL80211_ATTR_IFINDEX
,
netdev
->
ifindex
)
||
nla_put
(
msg
,
NL80211_ATTR_MAC
,
ETH_ALEN
,
peer
))
goto
nla_put_failure
;
pinfoattr
=
nla_nest_start
(
msg
,
NL80211_ATTR_CQM
);
if
(
!
pinfoattr
)
goto
nla_put_failure
;
if
(
nla_put_u32
(
msg
,
NL80211_ATTR_CQM_TXE_PKTS
,
num_packets
))
goto
nla_put_failure
;
if
(
nla_put_u32
(
msg
,
NL80211_ATTR_CQM_TXE_RATE
,
rate
))
goto
nla_put_failure
;
if
(
nla_put_u32
(
msg
,
NL80211_ATTR_CQM_TXE_INTVL
,
intvl
))
goto
nla_put_failure
;
nla_nest_end
(
msg
,
pinfoattr
);
genlmsg_end
(
msg
,
hdr
);
genlmsg_multicast_netns
(
wiphy_net
(
&
rdev
->
wiphy
),
msg
,
0
,
nl80211_mlme_mcgrp
.
id
,
gfp
);
return
;
nla_put_failure:
genlmsg_cancel
(
msg
,
hdr
);
nlmsg_free
(
msg
);
}
void
nl80211_send_cqm_pktloss_notify
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
netdev
,
const
u8
*
peer
,
...
...
net/wireless/nl80211.h
View file @
707be0ae
...
...
@@ -110,6 +110,11 @@ nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev,
struct
net_device
*
netdev
,
const
u8
*
peer
,
u32
num_packets
,
gfp_t
gfp
);
void
nl80211_send_cqm_txe_notify
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
netdev
,
const
u8
*
peer
,
u32
num_packets
,
u32
rate
,
u32
intvl
,
gfp_t
gfp
);
void
nl80211_gtk_rekey_notify
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
netdev
,
const
u8
*
bssid
,
const
u8
*
replay_ctr
,
gfp_t
gfp
);
...
...
net/wireless/reg.c
View file @
707be0ae
...
...
@@ -97,9 +97,16 @@ const struct ieee80211_regdomain *cfg80211_regdomain;
* - cfg80211_world_regdom
* - cfg80211_regdom
* - last_request
* - reg_num_devs_support_basehint
*/
static
DEFINE_MUTEX
(
reg_mutex
);
/*
* Number of devices that registered to the core
* that support cellular base station regulatory hints
*/
static
int
reg_num_devs_support_basehint
;
static
inline
void
assert_reg_lock
(
void
)
{
lockdep_assert_held
(
&
reg_mutex
);
...
...
@@ -911,6 +918,59 @@ static void handle_band(struct wiphy *wiphy,
handle_channel
(
wiphy
,
initiator
,
band
,
i
);
}
static
bool
reg_request_cell_base
(
struct
regulatory_request
*
request
)
{
if
(
request
->
initiator
!=
NL80211_REGDOM_SET_BY_USER
)
return
false
;
if
(
request
->
user_reg_hint_type
!=
NL80211_USER_REG_HINT_CELL_BASE
)
return
false
;
return
true
;
}
bool
reg_last_request_cell_base
(
void
)
{
assert_cfg80211_lock
();
mutex_lock
(
&
reg_mutex
);
return
reg_request_cell_base
(
last_request
);
mutex_unlock
(
&
reg_mutex
);
}
#ifdef CONFIG_CFG80211_CERTIFICATION_ONUS
/* Core specific check */
static
int
reg_ignore_cell_hint
(
struct
regulatory_request
*
pending_request
)
{
if
(
!
reg_num_devs_support_basehint
)
return
-
EOPNOTSUPP
;
if
(
reg_request_cell_base
(
last_request
))
{
if
(
!
regdom_changes
(
pending_request
->
alpha2
))
return
-
EALREADY
;
return
0
;
}
return
0
;
}
/* Device specific check */
static
bool
reg_dev_ignore_cell_hint
(
struct
wiphy
*
wiphy
)
{
if
(
!
(
wiphy
->
features
&
NL80211_FEATURE_CELL_BASE_REG_HINTS
))
return
true
;
return
false
;
}
#else
static
int
reg_ignore_cell_hint
(
struct
regulatory_request
*
pending_request
)
{
return
-
EOPNOTSUPP
;
}
static
int
reg_dev_ignore_cell_hint
(
struct
wiphy
*
wiphy
)
{
return
true
;
}
#endif
static
bool
ignore_reg_update
(
struct
wiphy
*
wiphy
,
enum
nl80211_reg_initiator
initiator
)
{
...
...
@@ -944,6 +1004,9 @@ static bool ignore_reg_update(struct wiphy *wiphy,
return
true
;
}
if
(
reg_request_cell_base
(
last_request
))
return
reg_dev_ignore_cell_hint
(
wiphy
);
return
false
;
}
...
...
@@ -1169,14 +1232,6 @@ static void wiphy_update_regulatory(struct wiphy *wiphy,
wiphy
->
reg_notifier
(
wiphy
,
last_request
);
}
void
regulatory_update
(
struct
wiphy
*
wiphy
,
enum
nl80211_reg_initiator
setby
)
{
mutex_lock
(
&
reg_mutex
);
wiphy_update_regulatory
(
wiphy
,
setby
);
mutex_unlock
(
&
reg_mutex
);
}
static
void
update_all_wiphy_regulatory
(
enum
nl80211_reg_initiator
initiator
)
{
struct
cfg80211_registered_device
*
rdev
;
...
...
@@ -1307,6 +1362,13 @@ static int ignore_request(struct wiphy *wiphy,
return
0
;
case
NL80211_REGDOM_SET_BY_COUNTRY_IE
:
if
(
reg_request_cell_base
(
last_request
))
{
/* Trust a Cell base station over the AP's country IE */
if
(
regdom_changes
(
pending_request
->
alpha2
))
return
-
EOPNOTSUPP
;
return
-
EALREADY
;
}
last_wiphy
=
wiphy_idx_to_wiphy
(
last_request
->
wiphy_idx
);
if
(
unlikely
(
!
is_an_alpha2
(
pending_request
->
alpha2
)))
...
...
@@ -1351,6 +1413,12 @@ static int ignore_request(struct wiphy *wiphy,
return
REG_INTERSECT
;
case
NL80211_REGDOM_SET_BY_USER
:
if
(
reg_request_cell_base
(
pending_request
))
return
reg_ignore_cell_hint
(
pending_request
);
if
(
reg_request_cell_base
(
last_request
))
return
-
EOPNOTSUPP
;
if
(
last_request
->
initiator
==
NL80211_REGDOM_SET_BY_COUNTRY_IE
)
return
REG_INTERSECT
;
/*
...
...
@@ -1640,7 +1708,8 @@ static int regulatory_hint_core(const char *alpha2)
}
/* User hints */
int
regulatory_hint_user
(
const
char
*
alpha2
)
int
regulatory_hint_user
(
const
char
*
alpha2
,
enum
nl80211_user_reg_hint_type
user_reg_hint_type
)
{
struct
regulatory_request
*
request
;
...
...
@@ -1654,6 +1723,7 @@ int regulatory_hint_user(const char *alpha2)
request
->
alpha2
[
0
]
=
alpha2
[
0
];
request
->
alpha2
[
1
]
=
alpha2
[
1
];
request
->
initiator
=
NL80211_REGDOM_SET_BY_USER
;
request
->
user_reg_hint_type
=
user_reg_hint_type
;
queue_regulatory_request
(
request
);
...
...
@@ -1906,7 +1976,7 @@ static void restore_regulatory_settings(bool reset_user)
* settings, user regulatory settings takes precedence.
*/
if
(
is_an_alpha2
(
alpha2
))
regulatory_hint_user
(
user_alpha2
);
regulatory_hint_user
(
user_alpha2
,
NL80211_USER_REG_HINT_USER
);
if
(
list_empty
(
&
tmp_reg_req_list
))
return
;
...
...
@@ -2081,10 +2151,17 @@ static void print_regdomain(const struct ieee80211_regdomain *rd)
else
{
if
(
is_unknown_alpha2
(
rd
->
alpha2
))
pr_info
(
"Regulatory domain changed to driver built-in settings (unknown country)
\n
"
);
else
{
if
(
reg_request_cell_base
(
last_request
))
pr_info
(
"Regulatory domain changed "
"to country: %c%c by Cell Station
\n
"
,
rd
->
alpha2
[
0
],
rd
->
alpha2
[
1
]);
else
pr_info
(
"Regulatory domain changed to country: %c%c
\n
"
,
pr_info
(
"Regulatory domain changed "
"to country: %c%c
\n
"
,
rd
->
alpha2
[
0
],
rd
->
alpha2
[
1
]);
}
}
print_dfs_region
(
rd
->
dfs_region
);
print_rd_rules
(
rd
);
}
...
...
@@ -2128,7 +2205,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
* checking if the alpha2 changes if CRDA was already called
*/
if
(
!
regdom_changes
(
rd
->
alpha2
))
return
-
E
INVAL
;
return
-
E
ALREADY
;
}
/*
...
...
@@ -2248,6 +2325,9 @@ int set_regdom(const struct ieee80211_regdomain *rd)
/* Note that this doesn't update the wiphys, this is done below */
r
=
__set_regdom
(
rd
);
if
(
r
)
{
if
(
r
==
-
EALREADY
)
reg_set_request_processed
();
kfree
(
rd
);
mutex_unlock
(
&
reg_mutex
);
return
r
;
...
...
@@ -2290,8 +2370,22 @@ int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env)
}
#endif
/* CONFIG_HOTPLUG */
void
wiphy_regulatory_register
(
struct
wiphy
*
wiphy
)
{
assert_cfg80211_lock
();
mutex_lock
(
&
reg_mutex
);
if
(
!
reg_dev_ignore_cell_hint
(
wiphy
))
reg_num_devs_support_basehint
++
;
wiphy_update_regulatory
(
wiphy
,
NL80211_REGDOM_SET_BY_CORE
);
mutex_unlock
(
&
reg_mutex
);
}
/* Caller must hold cfg80211_mutex */
void
reg_device_remove
(
struct
wiphy
*
wiphy
)
void
wiphy_regulatory_deregister
(
struct
wiphy
*
wiphy
)
{
struct
wiphy
*
request_wiphy
=
NULL
;
...
...
@@ -2299,6 +2393,9 @@ void reg_device_remove(struct wiphy *wiphy)
mutex_lock
(
&
reg_mutex
);
if
(
!
reg_dev_ignore_cell_hint
(
wiphy
))
reg_num_devs_support_basehint
--
;
kfree
(
wiphy
->
regd
);
if
(
last_request
)
...
...
@@ -2364,7 +2461,8 @@ int __init regulatory_init(void)
* as a user hint.
*/
if
(
!
is_world_regdom
(
ieee80211_regdom
))
regulatory_hint_user
(
ieee80211_regdom
);
regulatory_hint_user
(
ieee80211_regdom
,
NL80211_USER_REG_HINT_USER
);
return
0
;
}
...
...
net/wireless/reg.h
View file @
707be0ae
...
...
@@ -22,17 +22,19 @@ bool is_world_regdom(const char *alpha2);
bool
reg_is_valid_request
(
const
char
*
alpha2
);
bool
reg_supported_dfs_region
(
u8
dfs_region
);
int
regulatory_hint_user
(
const
char
*
alpha2
);
int
regulatory_hint_user
(
const
char
*
alpha2
,
enum
nl80211_user_reg_hint_type
user_reg_hint_type
);
int
reg_device_uevent
(
struct
device
*
dev
,
struct
kobj_uevent_env
*
env
);
void
reg_device_remove
(
struct
wiphy
*
wiphy
);
void
wiphy_regulatory_register
(
struct
wiphy
*
wiphy
);
void
wiphy_regulatory_deregister
(
struct
wiphy
*
wiphy
);
int
__init
regulatory_init
(
void
);
void
regulatory_exit
(
void
);
int
set_regdom
(
const
struct
ieee80211_regdomain
*
rd
);
void
regulatory_update
(
struct
wiphy
*
wiphy
,
enum
nl80211_reg_initiator
setby
);
bool
reg_last_request_cell_base
(
void
);
/**
* regulatory_hint_found_beacon - hints a beacon was found on a channel
...
...
net/wireless/wext-compat.c
View file @
707be0ae
...
...
@@ -827,6 +827,8 @@ static int cfg80211_wext_giwfreq(struct net_device *dev,
{
struct
wireless_dev
*
wdev
=
dev
->
ieee80211_ptr
;
struct
cfg80211_registered_device
*
rdev
=
wiphy_to_dev
(
wdev
->
wiphy
);
struct
ieee80211_channel
*
chan
;
enum
nl80211_channel_type
channel_type
;
switch
(
wdev
->
iftype
)
{
case
NL80211_IFTYPE_STATION
:
...
...
@@ -834,10 +836,13 @@ static int cfg80211_wext_giwfreq(struct net_device *dev,
case
NL80211_IFTYPE_ADHOC
:
return
cfg80211_ibss_wext_giwfreq
(
dev
,
info
,
freq
,
extra
);
case
NL80211_IFTYPE_MONITOR
:
if
(
!
rdev
->
monitor
_channel
)
if
(
!
rdev
->
ops
->
get
_channel
)
return
-
EINVAL
;
freq
->
m
=
rdev
->
monitor_channel
->
center_freq
;
chan
=
rdev
->
ops
->
get_channel
(
wdev
->
wiphy
,
wdev
,
&
channel_type
);
if
(
!
chan
)
return
-
EINVAL
;
freq
->
m
=
chan
->
center_freq
;
freq
->
e
=
6
;
return
0
;
default:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment