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
Kirill Smelkov
linux
Commits
55d1cad2
Commit
55d1cad2
authored
Jan 03, 2014
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
39731b78
32db6b54
Changes
28
Hide whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
687 additions
and
90 deletions
+687
-90
drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+1
-1
drivers/net/wireless/mwifiex/main.c
drivers/net/wireless/mwifiex/main.c
+1
-1
include/net/cfg80211.h
include/net/cfg80211.h
+113
-5
include/net/mac80211.h
include/net/mac80211.h
+47
-0
include/uapi/linux/nl80211.h
include/uapi/linux/nl80211.h
+17
-0
net/mac80211/aes_cmac.c
net/mac80211/aes_cmac.c
+1
-1
net/mac80211/aes_cmac.h
net/mac80211/aes_cmac.h
+1
-1
net/mac80211/cfg.c
net/mac80211/cfg.c
+48
-6
net/mac80211/chan.c
net/mac80211/chan.c
+34
-33
net/mac80211/ibss.c
net/mac80211/ibss.c
+7
-0
net/mac80211/ieee80211_i.h
net/mac80211/ieee80211_i.h
+8
-3
net/mac80211/iface.c
net/mac80211/iface.c
+6
-2
net/mac80211/mlme.c
net/mac80211/mlme.c
+20
-5
net/mac80211/rc80211_minstrel.c
net/mac80211/rc80211_minstrel.c
+4
-4
net/mac80211/rc80211_minstrel_ht.c
net/mac80211/rc80211_minstrel_ht.c
+1
-1
net/mac80211/tkip.c
net/mac80211/tkip.c
+1
-1
net/mac80211/trace.h
net/mac80211/trace.h
+1
-1
net/mac80211/tx.c
net/mac80211/tx.c
+2
-2
net/mac80211/util.c
net/mac80211/util.c
+148
-2
net/mac80211/wme.c
net/mac80211/wme.c
+6
-1
net/wireless/ap.c
net/wireless/ap.c
+1
-0
net/wireless/ibss.c
net/wireless/ibss.c
+2
-0
net/wireless/mesh.c
net/wireless/mesh.c
+1
-0
net/wireless/nl80211.c
net/wireless/nl80211.c
+141
-19
net/wireless/rdev-ops.h
net/wireless/rdev-ops.h
+15
-0
net/wireless/sme.c
net/wireless/sme.c
+2
-0
net/wireless/trace.h
net/wireless/trace.h
+40
-0
net/wireless/util.c
net/wireless/util.c
+18
-1
No files found.
drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
View file @
55d1cad2
...
...
@@ -1873,7 +1873,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
brcmf_dbg
(
DATA
,
"tx proto=0x%X
\n
"
,
ntohs
(
eh
->
h_proto
));
/* determine the priority */
if
(
!
skb
->
priority
)
skb
->
priority
=
cfg80211_classify8021d
(
skb
);
skb
->
priority
=
cfg80211_classify8021d
(
skb
,
NULL
);
drvr
->
tx_multicast
+=
!!
multicast
;
if
(
pae
)
...
...
drivers/net/wireless/mwifiex/main.c
View file @
55d1cad2
...
...
@@ -749,7 +749,7 @@ static struct net_device_stats *mwifiex_get_stats(struct net_device *dev)
static
u16
mwifiex_netdev_select_wmm_queue
(
struct
net_device
*
dev
,
struct
sk_buff
*
skb
)
{
skb
->
priority
=
cfg80211_classify8021d
(
skb
);
skb
->
priority
=
cfg80211_classify8021d
(
skb
,
NULL
);
return
mwifiex_1d_to_wmm_queue
[
skb
->
priority
];
}
...
...
include/net/cfg80211.h
View file @
55d1cad2
...
...
@@ -1971,6 +1971,50 @@ struct cfg80211_mgmt_tx_params {
bool
dont_wait_for_ack
;
};
/**
* struct cfg80211_dscp_exception - DSCP exception
*
* @dscp: DSCP value that does not adhere to the user priority range definition
* @up: user priority value to which the corresponding DSCP value belongs
*/
struct
cfg80211_dscp_exception
{
u8
dscp
;
u8
up
;
};
/**
* struct cfg80211_dscp_range - DSCP range definition for user priority
*
* @low: lowest DSCP value of this user priority range, inclusive
* @high: highest DSCP value of this user priority range, inclusive
*/
struct
cfg80211_dscp_range
{
u8
low
;
u8
high
;
};
/* QoS Map Set element length defined in IEEE Std 802.11-2012, 8.4.2.97 */
#define IEEE80211_QOS_MAP_MAX_EX 21
#define IEEE80211_QOS_MAP_LEN_MIN 16
#define IEEE80211_QOS_MAP_LEN_MAX \
(IEEE80211_QOS_MAP_LEN_MIN + 2 * IEEE80211_QOS_MAP_MAX_EX)
/**
* struct cfg80211_qos_map - QoS Map Information
*
* This struct defines the Interworking QoS map setting for DSCP values
*
* @num_des: number of DSCP exceptions (0..21)
* @dscp_exception: optionally up to maximum of 21 DSCP exceptions from
* the user priority DSCP range definition
* @up: DSCP range definition for a particular user priority
*/
struct
cfg80211_qos_map
{
u8
num_des
;
struct
cfg80211_dscp_exception
dscp_exception
[
IEEE80211_QOS_MAP_MAX_EX
];
struct
cfg80211_dscp_range
up
[
8
];
};
/**
* struct cfg80211_ops - backend description for wireless configuration
*
...
...
@@ -2213,6 +2257,8 @@ struct cfg80211_mgmt_tx_params {
* @set_coalesce: Set coalesce parameters.
*
* @channel_switch: initiate channel-switch procedure (with CSA)
*
* @set_qos_map: Set QoS mapping information to the driver
*/
struct
cfg80211_ops
{
int
(
*
suspend
)(
struct
wiphy
*
wiphy
,
struct
cfg80211_wowlan
*
wow
);
...
...
@@ -2454,6 +2500,9 @@ struct cfg80211_ops {
int
(
*
channel_switch
)(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
,
struct
cfg80211_csa_settings
*
params
);
int
(
*
set_qos_map
)(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
,
struct
cfg80211_qos_map
*
qos_map
);
};
/*
...
...
@@ -2824,6 +2873,8 @@ struct wiphy_vendor_command {
*
* @vendor_commands: array of vendor commands supported by the hardware
* @n_vendor_commands: number of vendor commands
* @vendor_events: array of vendor events supported by the hardware
* @n_vendor_events: number of vendor events
*/
struct
wiphy
{
/* assign these fields before you register the wiphy */
...
...
@@ -2936,7 +2987,8 @@ struct wiphy {
const
struct
wiphy_coalesce_support
*
coalesce
;
const
struct
wiphy_vendor_command
*
vendor_commands
;
int
n_vendor_commands
;
const
struct
nl80211_vendor_cmd_info
*
vendor_events
;
int
n_vendor_commands
,
n_vendor_events
;
char
priv
[
0
]
__aligned
(
NETDEV_ALIGN
);
};
...
...
@@ -3429,9 +3481,11 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
/**
* cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame
* @skb: the data frame
* @qos_map: Interworking QoS mapping or %NULL if not in use
* Return: The 802.1p/1d tag.
*/
unsigned
int
cfg80211_classify8021d
(
struct
sk_buff
*
skb
);
unsigned
int
cfg80211_classify8021d
(
struct
sk_buff
*
skb
,
struct
cfg80211_qos_map
*
qos_map
);
/**
* cfg80211_find_ie - find information element in data
...
...
@@ -3907,6 +3961,14 @@ struct sk_buff *__cfg80211_alloc_reply_skb(struct wiphy *wiphy,
enum
nl80211_attrs
attr
,
int
approxlen
);
struct
sk_buff
*
__cfg80211_alloc_event_skb
(
struct
wiphy
*
wiphy
,
enum
nl80211_commands
cmd
,
enum
nl80211_attrs
attr
,
int
vendor_event_idx
,
int
approxlen
,
gfp_t
gfp
);
void
__cfg80211_send_event_skb
(
struct
sk_buff
*
skb
,
gfp_t
gfp
);
/**
* cfg80211_vendor_cmd_alloc_reply_skb - allocate vendor command reply
* @wiphy: the wiphy
...
...
@@ -3951,6 +4013,44 @@ cfg80211_vendor_cmd_alloc_reply_skb(struct wiphy *wiphy, int approxlen)
*/
int
cfg80211_vendor_cmd_reply
(
struct
sk_buff
*
skb
);
/**
* cfg80211_vendor_event_alloc - allocate vendor-specific event skb
* @wiphy: the wiphy
* @event_idx: index of the vendor event in the wiphy's vendor_events
* @approxlen: an upper bound of the length of the data that will
* be put into the skb
* @gfp: allocation flags
*
* This function allocates and pre-fills an skb for an event on the
* vendor-specific multicast group.
*
* When done filling the skb, call cfg80211_vendor_event() with the
* skb to send the event.
*
* Return: An allocated and pre-filled skb. %NULL if any errors happen.
*/
static
inline
struct
sk_buff
*
cfg80211_vendor_event_alloc
(
struct
wiphy
*
wiphy
,
int
approxlen
,
int
event_idx
,
gfp_t
gfp
)
{
return
__cfg80211_alloc_event_skb
(
wiphy
,
NL80211_CMD_VENDOR
,
NL80211_ATTR_VENDOR_DATA
,
event_idx
,
approxlen
,
gfp
);
}
/**
* cfg80211_vendor_event - send the event
* @skb: The skb, must have been allocated with cfg80211_vendor_event_alloc()
* @gfp: allocation flags
*
* This function sends the given @skb, which must have been allocated
* by cfg80211_vendor_event_alloc(), as an event. It always consumes it.
*/
static
inline
void
cfg80211_vendor_event
(
struct
sk_buff
*
skb
,
gfp_t
gfp
)
{
__cfg80211_send_event_skb
(
skb
,
gfp
);
}
#ifdef CONFIG_NL80211_TESTMODE
/**
* DOC: Test mode
...
...
@@ -4031,8 +4131,13 @@ static inline int cfg80211_testmode_reply(struct sk_buff *skb)
*
* Return: An allocated and pre-filled skb. %NULL if any errors happen.
*/
struct
sk_buff
*
cfg80211_testmode_alloc_event_skb
(
struct
wiphy
*
wiphy
,
int
approxlen
,
gfp_t
gfp
);
static
inline
struct
sk_buff
*
cfg80211_testmode_alloc_event_skb
(
struct
wiphy
*
wiphy
,
int
approxlen
,
gfp_t
gfp
)
{
return
__cfg80211_alloc_event_skb
(
wiphy
,
NL80211_CMD_TESTMODE
,
NL80211_ATTR_TESTDATA
,
-
1
,
approxlen
,
gfp
);
}
/**
* cfg80211_testmode_event - send the event
...
...
@@ -4044,7 +4149,10 @@ struct sk_buff *cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy,
* by cfg80211_testmode_alloc_event_skb(), as an event. It always
* consumes it.
*/
void
cfg80211_testmode_event
(
struct
sk_buff
*
skb
,
gfp_t
gfp
);
static
inline
void
cfg80211_testmode_event
(
struct
sk_buff
*
skb
,
gfp_t
gfp
)
{
__cfg80211_send_event_skb
(
skb
,
gfp
);
}
#define CFG80211_TESTMODE_CMD(cmd) .testmode_cmd = (cmd),
#define CFG80211_TESTMODE_DUMP(cmd) .testmode_dump = (cmd),
...
...
include/net/mac80211.h
View file @
55d1cad2
...
...
@@ -4652,4 +4652,51 @@ bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw,
struct
ieee80211_vif
*
vif
,
struct
sk_buff
*
skb
,
int
band
,
struct
ieee80211_sta
**
sta
);
/**
* struct ieee80211_noa_data - holds temporary data for tracking P2P NoA state
*
* @next_tsf: TSF timestamp of the next absent state change
* @has_next_tsf: next absent state change event pending
*
* @absent: descriptor bitmask, set if GO is currently absent
*
* private:
*
* @count: count fields from the NoA descriptors
* @desc: adjusted data from the NoA
*/
struct
ieee80211_noa_data
{
u32
next_tsf
;
bool
has_next_tsf
;
u8
absent
;
u8
count
[
IEEE80211_P2P_NOA_DESC_MAX
];
struct
{
u32
start
;
u32
duration
;
u32
interval
;
}
desc
[
IEEE80211_P2P_NOA_DESC_MAX
];
};
/**
* ieee80211_parse_p2p_noa - initialize NoA tracking data from P2P IE
*
* @attr: P2P NoA IE
* @data: NoA tracking data
* @tsf: current TSF timestamp
*
* Return: number of successfully parsed descriptors
*/
int
ieee80211_parse_p2p_noa
(
const
struct
ieee80211_p2p_noa_attr
*
attr
,
struct
ieee80211_noa_data
*
data
,
u32
tsf
);
/**
* ieee80211_update_p2p_noa - get next pending P2P GO absent state change
*
* @data: NoA tracking data
* @tsf: current TSF timestamp
*/
void
ieee80211_update_p2p_noa
(
struct
ieee80211_noa_data
*
data
,
u32
tsf
);
#endif
/* MAC80211_H */
include/uapi/linux/nl80211.h
View file @
55d1cad2
...
...
@@ -702,6 +702,12 @@
* (&struct nl80211_vendor_cmd_info) of the supported vendor commands.
* This may also be sent as an event with the same attributes.
*
* @NL80211_CMD_SET_QOS_MAP: Set Interworking QoS mapping for IP DSCP values.
* The QoS mapping information is included in %NL80211_ATTR_QOS_MAP. If
* that attribute is not included, QoS mapping is disabled. Since this
* QoS mapping is relevant for IP packets, it is only valid during an
* association. This is cleared on disassociation and AP restart.
*
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
...
...
@@ -871,6 +877,8 @@ enum nl80211_commands {
NL80211_CMD_VENDOR
,
NL80211_CMD_SET_QOS_MAP
,
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
...
...
@@ -1540,6 +1548,12 @@ enum nl80211_commands {
* @NL80211_ATTR_VENDOR_SUBCMD: vendor sub-command
* @NL80211_ATTR_VENDOR_DATA: data for the vendor command, if any; this
* attribute is also used for vendor command feature advertisement
* @NL80211_ATTR_VENDOR_EVENTS: used for event list advertising in the wiphy
* info, containing a nested array of possible events
*
* @NL80211_ATTR_QOS_MAP: IP DSCP mapping for Interworking QoS mapping. This
* data is in the format defined for the payload of the QoS Map Set element
* in IEEE Std 802.11-2012, 8.4.2.97.
*
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
...
...
@@ -1865,6 +1879,9 @@ enum nl80211_attrs {
NL80211_ATTR_VENDOR_ID
,
NL80211_ATTR_VENDOR_SUBCMD
,
NL80211_ATTR_VENDOR_DATA
,
NL80211_ATTR_VENDOR_EVENTS
,
NL80211_ATTR_QOS_MAP
,
/* add attributes here, update the policy in nl80211.c */
...
...
net/mac80211/aes_cmac.c
View file @
55d1cad2
...
...
@@ -111,7 +111,7 @@ void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad,
}
struct
crypto_cipher
*
ieee80211_aes_cmac_key_setup
(
const
u8
key
[])
struct
crypto_cipher
*
ieee80211_aes_cmac_key_setup
(
const
u8
key
[])
{
struct
crypto_cipher
*
tfm
;
...
...
net/mac80211/aes_cmac.h
View file @
55d1cad2
...
...
@@ -11,7 +11,7 @@
#include <linux/crypto.h>
struct
crypto_cipher
*
ieee80211_aes_cmac_key_setup
(
const
u8
key
[]);
struct
crypto_cipher
*
ieee80211_aes_cmac_key_setup
(
const
u8
key
[]);
void
ieee80211_aes_cmac
(
struct
crypto_cipher
*
tfm
,
const
u8
*
aad
,
const
u8
*
data
,
size_t
data_len
,
u8
*
mic
);
void
ieee80211_aes_cmac_key_free
(
struct
crypto_cipher
*
tfm
);
...
...
net/mac80211/cfg.c
View file @
55d1cad2
...
...
@@ -828,6 +828,7 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
if
(
cfg80211_chandef_identical
(
&
local
->
monitor_chandef
,
chandef
))
return
0
;
mutex_lock
(
&
local
->
mtx
);
mutex_lock
(
&
local
->
iflist_mtx
);
if
(
local
->
use_chanctx
)
{
sdata
=
rcu_dereference_protected
(
...
...
@@ -846,6 +847,7 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
if
(
ret
==
0
)
local
->
monitor_chandef
=
*
chandef
;
mutex_unlock
(
&
local
->
iflist_mtx
);
mutex_unlock
(
&
local
->
mtx
);
return
ret
;
}
...
...
@@ -951,6 +953,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
struct
cfg80211_ap_settings
*
params
)
{
struct
ieee80211_sub_if_data
*
sdata
=
IEEE80211_DEV_TO_SUB_IF
(
dev
);
struct
ieee80211_local
*
local
=
sdata
->
local
;
struct
beacon_data
*
old
;
struct
ieee80211_sub_if_data
*
vlan
;
u32
changed
=
BSS_CHANGED_BEACON_INT
|
...
...
@@ -969,8 +972,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
sdata
->
needed_rx_chains
=
sdata
->
local
->
rx_chains
;
sdata
->
radar_required
=
params
->
radar_required
;
mutex_lock
(
&
local
->
mtx
);
err
=
ieee80211_vif_use_channel
(
sdata
,
&
params
->
chandef
,
IEEE80211_CHANCTX_SHARED
);
mutex_unlock
(
&
local
->
mtx
);
if
(
err
)
return
err
;
ieee80211_vif_copy_chanctx_to_vlans
(
sdata
,
false
);
...
...
@@ -1121,7 +1126,9 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
skb_queue_purge
(
&
sdata
->
u
.
ap
.
ps
.
bc_buf
);
ieee80211_vif_copy_chanctx_to_vlans
(
sdata
,
true
);
mutex_lock
(
&
local
->
mtx
);
ieee80211_vif_release_channel
(
sdata
);
mutex_unlock
(
&
local
->
mtx
);
return
0
;
}
...
...
@@ -1944,8 +1951,10 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev,
sdata
->
smps_mode
=
IEEE80211_SMPS_OFF
;
sdata
->
needed_rx_chains
=
sdata
->
local
->
rx_chains
;
mutex_lock
(
&
sdata
->
local
->
mtx
);
err
=
ieee80211_vif_use_channel
(
sdata
,
&
setup
->
chandef
,
IEEE80211_CHANCTX_SHARED
);
mutex_unlock
(
&
sdata
->
local
->
mtx
);
if
(
err
)
return
err
;
...
...
@@ -1957,7 +1966,9 @@ static int ieee80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev)
struct
ieee80211_sub_if_data
*
sdata
=
IEEE80211_DEV_TO_SUB_IF
(
dev
);
ieee80211_stop_mesh
(
sdata
);
mutex_lock
(
&
sdata
->
local
->
mtx
);
ieee80211_vif_release_channel
(
sdata
);
mutex_unlock
(
&
sdata
->
local
->
mtx
);
return
0
;
}
...
...
@@ -2895,26 +2906,29 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
unsigned
long
timeout
;
int
err
;
if
(
!
list_empty
(
&
local
->
roc_list
)
||
local
->
scanning
)
return
-
EBUSY
;
mutex_lock
(
&
local
->
mtx
);
if
(
!
list_empty
(
&
local
->
roc_list
)
||
local
->
scanning
)
{
err
=
-
EBUSY
;
goto
out_unlock
;
}
/* whatever, but channel contexts should not complain about that one */
sdata
->
smps_mode
=
IEEE80211_SMPS_OFF
;
sdata
->
needed_rx_chains
=
local
->
rx_chains
;
sdata
->
radar_required
=
true
;
mutex_lock
(
&
local
->
iflist_mtx
);
err
=
ieee80211_vif_use_channel
(
sdata
,
chandef
,
IEEE80211_CHANCTX_SHARED
);
mutex_unlock
(
&
local
->
iflist_mtx
);
if
(
err
)
return
err
;
goto
out_unlock
;
timeout
=
msecs_to_jiffies
(
IEEE80211_DFS_MIN_CAC_TIME_MS
);
ieee80211_queue_delayed_work
(
&
sdata
->
local
->
hw
,
&
sdata
->
dfs_cac_timer_work
,
timeout
);
return
0
;
out_unlock:
mutex_unlock
(
&
local
->
mtx
);
return
err
;
}
static
struct
cfg80211_beacon_data
*
...
...
@@ -2990,7 +3004,9 @@ void ieee80211_csa_finalize_work(struct work_struct *work)
goto
unlock
;
sdata
->
radar_required
=
sdata
->
csa_radar_required
;
mutex_lock
(
&
local
->
mtx
);
err
=
ieee80211_vif_change_channel
(
sdata
,
&
changed
);
mutex_unlock
(
&
local
->
mtx
);
if
(
WARN_ON
(
err
<
0
))
goto
unlock
;
...
...
@@ -3821,6 +3837,31 @@ static void ieee80211_set_wakeup(struct wiphy *wiphy, bool enabled)
}
#endif
static
int
ieee80211_set_qos_map
(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
,
struct
cfg80211_qos_map
*
qos_map
)
{
struct
ieee80211_sub_if_data
*
sdata
=
IEEE80211_DEV_TO_SUB_IF
(
dev
);
struct
mac80211_qos_map
*
new_qos_map
,
*
old_qos_map
;
if
(
qos_map
)
{
new_qos_map
=
kzalloc
(
sizeof
(
*
new_qos_map
),
GFP_KERNEL
);
if
(
!
new_qos_map
)
return
-
ENOMEM
;
memcpy
(
&
new_qos_map
->
qos_map
,
qos_map
,
sizeof
(
*
qos_map
));
}
else
{
/* A NULL qos_map was passed to disable QoS mapping */
new_qos_map
=
NULL
;
}
old_qos_map
=
rtnl_dereference
(
sdata
->
qos_map
);
rcu_assign_pointer
(
sdata
->
qos_map
,
new_qos_map
);
if
(
old_qos_map
)
kfree_rcu
(
old_qos_map
,
rcu_head
);
return
0
;
}
struct
cfg80211_ops
mac80211_config_ops
=
{
.
add_virtual_intf
=
ieee80211_add_iface
,
.
del_virtual_intf
=
ieee80211_del_iface
,
...
...
@@ -3900,4 +3941,5 @@ struct cfg80211_ops mac80211_config_ops = {
.
get_channel
=
ieee80211_cfg_get_channel
,
.
start_radar_detection
=
ieee80211_start_radar_detection
,
.
channel_switch
=
ieee80211_channel_switch
,
.
set_qos_map
=
ieee80211_set_qos_map
,
};
net/mac80211/chan.c
View file @
55d1cad2
...
...
@@ -232,8 +232,8 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
if
(
!
local
->
use_chanctx
)
local
->
hw
.
conf
.
radar_enabled
=
ctx
->
conf
.
radar_enabled
;
/*
acquir
e mutex to prevent idle from changing */
mutex_lock
(
&
local
->
mtx
);
/*
we hold th
e mutex to prevent idle from changing */
lockdep_assert_held
(
&
local
->
mtx
);
/* turn idle off *before* setting channel -- some drivers need that */
changed
=
ieee80211_idle_off
(
local
);
if
(
changed
)
...
...
@@ -246,19 +246,14 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
err
=
drv_add_chanctx
(
local
,
ctx
);
if
(
err
)
{
kfree
(
ctx
);
ctx
=
ERR_PTR
(
err
);
ieee80211_recalc_idle
(
local
);
goto
out
;
return
ERR_PTR
(
err
)
;
}
}
/* and keep the mutex held until the new chanctx is on the list */
list_add_rcu
(
&
ctx
->
list
,
&
local
->
chanctx_list
);
out:
mutex_unlock
(
&
local
->
mtx
);
return
ctx
;
}
...
...
@@ -294,9 +289,7 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local,
/* throw a warning if this wasn't the only channel context. */
WARN_ON
(
check_single_channel
&&
!
list_empty
(
&
local
->
chanctx_list
));
mutex_lock
(
&
local
->
mtx
);
ieee80211_recalc_idle
(
local
);
mutex_unlock
(
&
local
->
mtx
);
}
static
int
ieee80211_assign_vif_chanctx
(
struct
ieee80211_sub_if_data
*
sdata
,
...
...
@@ -358,6 +351,31 @@ static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
ieee80211_change_chanctx
(
local
,
ctx
,
compat
);
}
static
void
ieee80211_recalc_radar_chanctx
(
struct
ieee80211_local
*
local
,
struct
ieee80211_chanctx
*
chanctx
)
{
bool
radar_enabled
;
lockdep_assert_held
(
&
local
->
chanctx_mtx
);
/* for setting local->radar_detect_enabled */
lockdep_assert_held
(
&
local
->
mtx
);
radar_enabled
=
ieee80211_is_radar_required
(
local
);
if
(
radar_enabled
==
chanctx
->
conf
.
radar_enabled
)
return
;
chanctx
->
conf
.
radar_enabled
=
radar_enabled
;
local
->
radar_detect_enabled
=
chanctx
->
conf
.
radar_enabled
;
if
(
!
local
->
use_chanctx
)
{
local
->
hw
.
conf
.
radar_enabled
=
chanctx
->
conf
.
radar_enabled
;
ieee80211_hw_config
(
local
,
IEEE80211_CONF_CHANGE_CHANNEL
);
}
drv_change_chanctx
(
local
,
chanctx
,
IEEE80211_CHANCTX_CHANGE_RADAR
);
}
static
void
ieee80211_unassign_vif_chanctx
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
ieee80211_chanctx
*
ctx
)
{
...
...
@@ -404,29 +422,6 @@ static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
ieee80211_free_chanctx
(
local
,
ctx
);
}
void
ieee80211_recalc_radar_chanctx
(
struct
ieee80211_local
*
local
,
struct
ieee80211_chanctx
*
chanctx
)
{
bool
radar_enabled
;
lockdep_assert_held
(
&
local
->
chanctx_mtx
);
radar_enabled
=
ieee80211_is_radar_required
(
local
);
if
(
radar_enabled
==
chanctx
->
conf
.
radar_enabled
)
return
;
chanctx
->
conf
.
radar_enabled
=
radar_enabled
;
local
->
radar_detect_enabled
=
chanctx
->
conf
.
radar_enabled
;
if
(
!
local
->
use_chanctx
)
{
local
->
hw
.
conf
.
radar_enabled
=
chanctx
->
conf
.
radar_enabled
;
ieee80211_hw_config
(
local
,
IEEE80211_CONF_CHANGE_CHANNEL
);
}
drv_change_chanctx
(
local
,
chanctx
,
IEEE80211_CHANCTX_CHANGE_RADAR
);
}
void
ieee80211_recalc_smps_chanctx
(
struct
ieee80211_local
*
local
,
struct
ieee80211_chanctx
*
chanctx
)
{
...
...
@@ -518,6 +513,8 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
struct
ieee80211_chanctx
*
ctx
;
int
ret
;
lockdep_assert_held
(
&
local
->
mtx
);
WARN_ON
(
sdata
->
dev
&&
netif_carrier_ok
(
sdata
->
dev
));
mutex_lock
(
&
local
->
chanctx_mtx
);
...
...
@@ -558,6 +555,8 @@ int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
int
ret
;
u32
chanctx_changed
=
0
;
lockdep_assert_held
(
&
local
->
mtx
);
/* should never be called if not performing a channel switch. */
if
(
WARN_ON
(
!
sdata
->
vif
.
csa_active
))
return
-
EINVAL
;
...
...
@@ -655,6 +654,8 @@ void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
{
WARN_ON
(
sdata
->
dev
&&
netif_carrier_ok
(
sdata
->
dev
));
lockdep_assert_held
(
&
sdata
->
local
->
mtx
);
mutex_lock
(
&
sdata
->
local
->
chanctx_mtx
);
__ieee80211_vif_release_channel
(
sdata
);
mutex_unlock
(
&
sdata
->
local
->
chanctx_mtx
);
...
...
net/mac80211/ibss.c
View file @
55d1cad2
...
...
@@ -293,14 +293,17 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
radar_required
=
true
;
}
mutex_lock
(
&
local
->
mtx
);
ieee80211_vif_release_channel
(
sdata
);
if
(
ieee80211_vif_use_channel
(
sdata
,
&
chandef
,
ifibss
->
fixed_channel
?
IEEE80211_CHANCTX_SHARED
:
IEEE80211_CHANCTX_EXCLUSIVE
))
{
sdata_info
(
sdata
,
"Failed to join IBSS, no channel context
\n
"
);
mutex_unlock
(
&
local
->
mtx
);
return
;
}
mutex_unlock
(
&
local
->
mtx
);
memcpy
(
ifibss
->
bssid
,
bssid
,
ETH_ALEN
);
...
...
@@ -363,7 +366,9 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
sdata
->
vif
.
bss_conf
.
ssid_len
=
0
;
RCU_INIT_POINTER
(
ifibss
->
presp
,
NULL
);
kfree_rcu
(
presp
,
rcu_head
);
mutex_lock
(
&
local
->
mtx
);
ieee80211_vif_release_channel
(
sdata
);
mutex_unlock
(
&
local
->
mtx
);
sdata_info
(
sdata
,
"Failed to join IBSS, driver failure: %d
\n
"
,
err
);
return
;
...
...
@@ -747,7 +752,9 @@ static void ieee80211_ibss_disconnect(struct ieee80211_sub_if_data *sdata)
ieee80211_bss_info_change_notify
(
sdata
,
BSS_CHANGED_BEACON_ENABLED
|
BSS_CHANGED_IBSS
);
drv_leave_ibss
(
local
,
sdata
);
mutex_lock
(
&
local
->
mtx
);
ieee80211_vif_release_channel
(
sdata
);
mutex_unlock
(
&
local
->
mtx
);
}
static
void
ieee80211_csa_connection_drop_work
(
struct
work_struct
*
work
)
...
...
net/mac80211/ieee80211_i.h
View file @
55d1cad2
...
...
@@ -246,7 +246,8 @@ struct ps_data {
/* yes, this looks ugly, but guarantees that we can later use
* bitmap_empty :)
* NB: don't touch this bitmap, use sta_info_{set,clear}_tim_bit */
u8
tim
[
sizeof
(
unsigned
long
)
*
BITS_TO_LONGS
(
IEEE80211_MAX_AID
+
1
)];
u8
tim
[
sizeof
(
unsigned
long
)
*
BITS_TO_LONGS
(
IEEE80211_MAX_AID
+
1
)]
__aligned
(
__alignof__
(
unsigned
long
));
struct
sk_buff_head
bc_buf
;
atomic_t
num_sta_ps
;
/* number of stations in PS mode */
int
dtim_count
;
...
...
@@ -693,6 +694,11 @@ struct ieee80211_chanctx {
struct
ieee80211_chanctx_conf
conf
;
};
struct
mac80211_qos_map
{
struct
cfg80211_qos_map
qos_map
;
struct
rcu_head
rcu_head
;
};
struct
ieee80211_sub_if_data
{
struct
list_head
list
;
...
...
@@ -738,6 +744,7 @@ struct ieee80211_sub_if_data {
int
encrypt_headroom
;
struct
ieee80211_tx_queue_params
tx_conf
[
IEEE80211_NUM_ACS
];
struct
mac80211_qos_map
__rcu
*
qos_map
;
struct
work_struct
csa_finalize_work
;
int
csa_counter_offset_beacon
;
...
...
@@ -1775,8 +1782,6 @@ void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
void
ieee80211_recalc_smps_chanctx
(
struct
ieee80211_local
*
local
,
struct
ieee80211_chanctx
*
chanctx
);
void
ieee80211_recalc_radar_chanctx
(
struct
ieee80211_local
*
local
,
struct
ieee80211_chanctx
*
chanctx
);
void
ieee80211_recalc_chanctx_min_def
(
struct
ieee80211_local
*
local
,
struct
ieee80211_chanctx
*
ctx
);
...
...
net/mac80211/iface.c
View file @
55d1cad2
...
...
@@ -418,8 +418,10 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
return
ret
;
}
mutex_lock
(
&
local
->
mtx
);
ret
=
ieee80211_vif_use_channel
(
sdata
,
&
local
->
monitor_chandef
,
IEEE80211_CHANCTX_EXCLUSIVE
);
mutex_unlock
(
&
local
->
mtx
);
if
(
ret
)
{
drv_remove_interface
(
local
,
sdata
);
kfree
(
sdata
);
...
...
@@ -456,7 +458,9 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
synchronize_net
();
mutex_lock
(
&
local
->
mtx
);
ieee80211_vif_release_channel
(
sdata
);
mutex_unlock
(
&
local
->
mtx
);
drv_remove_interface
(
local
,
sdata
);
...
...
@@ -826,9 +830,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
if
(
sdata
->
wdev
.
cac_started
)
{
chandef
=
sdata
->
vif
.
bss_conf
.
chandef
;
WARN_ON
(
local
->
suspended
);
mutex_lock
(
&
local
->
iflist_
mtx
);
mutex_lock
(
&
local
->
mtx
);
ieee80211_vif_release_channel
(
sdata
);
mutex_unlock
(
&
local
->
iflist_
mtx
);
mutex_unlock
(
&
local
->
mtx
);
cfg80211_cac_event
(
sdata
->
dev
,
&
chandef
,
NL80211_RADAR_CAC_ABORTED
,
GFP_KERNEL
);
...
...
net/mac80211/mlme.c
View file @
55d1cad2
...
...
@@ -888,7 +888,9 @@ static void ieee80211_chswitch_work(struct work_struct *work)
if
(
!
ifmgd
->
associated
)
goto
out
;
mutex_lock
(
&
local
->
mtx
);
ret
=
ieee80211_vif_change_channel
(
sdata
,
&
changed
);
mutex_unlock
(
&
local
->
mtx
);
if
(
ret
)
{
sdata_info
(
sdata
,
"vif channel switch failed, disconnecting
\n
"
);
...
...
@@ -1401,10 +1403,14 @@ void ieee80211_dfs_cac_timer_work(struct work_struct *work)
dfs_cac_timer_work
);
struct
cfg80211_chan_def
chandef
=
sdata
->
vif
.
bss_conf
.
chandef
;
ieee80211_vif_release_channel
(
sdata
);
cfg80211_cac_event
(
sdata
->
dev
,
&
chandef
,
NL80211_RADAR_CAC_FINISHED
,
GFP_KERNEL
);
mutex_lock
(
&
sdata
->
local
->
mtx
);
if
(
sdata
->
wdev
.
cac_started
)
{
ieee80211_vif_release_channel
(
sdata
);
cfg80211_cac_event
(
sdata
->
dev
,
&
chandef
,
NL80211_RADAR_CAC_FINISHED
,
GFP_KERNEL
);
}
mutex_unlock
(
&
sdata
->
local
->
mtx
);
}
/* MLME */
...
...
@@ -1747,7 +1753,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
ifmgd
->
have_beacon
=
false
;
ifmgd
->
flags
=
0
;
mutex_lock
(
&
local
->
mtx
);
ieee80211_vif_release_channel
(
sdata
);
mutex_unlock
(
&
local
->
mtx
);
sdata
->
encrypt_headroom
=
IEEE80211_ENCRYPT_HEADROOM
;
}
...
...
@@ -2070,7 +2078,9 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
memset
(
sdata
->
u
.
mgd
.
bssid
,
0
,
ETH_ALEN
);
ieee80211_bss_info_change_notify
(
sdata
,
BSS_CHANGED_BSSID
);
sdata
->
u
.
mgd
.
flags
=
0
;
mutex_lock
(
&
sdata
->
local
->
mtx
);
ieee80211_vif_release_channel
(
sdata
);
mutex_unlock
(
&
sdata
->
local
->
mtx
);
}
cfg80211_put_bss
(
sdata
->
local
->
hw
.
wiphy
,
auth_data
->
bss
);
...
...
@@ -2319,7 +2329,9 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
memset
(
sdata
->
u
.
mgd
.
bssid
,
0
,
ETH_ALEN
);
ieee80211_bss_info_change_notify
(
sdata
,
BSS_CHANGED_BSSID
);
sdata
->
u
.
mgd
.
flags
=
0
;
mutex_lock
(
&
sdata
->
local
->
mtx
);
ieee80211_vif_release_channel
(
sdata
);
mutex_unlock
(
&
sdata
->
local
->
mtx
);
}
kfree
(
assoc_data
);
...
...
@@ -3670,6 +3682,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
/* will change later if needed */
sdata
->
smps_mode
=
IEEE80211_SMPS_OFF
;
mutex_lock
(
&
local
->
mtx
);
/*
* If this fails (possibly due to channel context sharing
* on incompatible channels, e.g. 80+80 and 160 sharing the
...
...
@@ -3681,13 +3694,15 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
/* don't downgrade for 5 and 10 MHz channels, though. */
if
(
chandef
.
width
==
NL80211_CHAN_WIDTH_5
||
chandef
.
width
==
NL80211_CHAN_WIDTH_10
)
return
re
t
;
goto
ou
t
;
while
(
ret
&&
chandef
.
width
!=
NL80211_CHAN_WIDTH_20_NOHT
)
{
ifmgd
->
flags
|=
ieee80211_chandef_downgrade
(
&
chandef
);
ret
=
ieee80211_vif_use_channel
(
sdata
,
&
chandef
,
IEEE80211_CHANCTX_SHARED
);
}
out:
mutex_unlock
(
&
local
->
mtx
);
return
ret
;
}
...
...
net/mac80211/rc80211_minstrel.c
View file @
55d1cad2
...
...
@@ -135,7 +135,7 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
u32
usecs
;
int
i
;
for
(
i
=
0
;
i
<
MAX_THR_RATES
;
i
++
)
for
(
i
=
0
;
i
<
MAX_THR_RATES
;
i
++
)
tmp_tp_rate
[
i
]
=
0
;
for
(
i
=
0
;
i
<
mi
->
n_rates
;
i
++
)
{
...
...
@@ -190,7 +190,7 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
* choose the maximum throughput rate as max_prob_rate
* (2) if all success probabilities < 95%, the rate with
* highest success probability is choosen as max_prob_rate */
if
(
mr
->
probability
>=
MINSTREL_FRAC
(
95
,
100
))
{
if
(
mr
->
probability
>=
MINSTREL_FRAC
(
95
,
100
))
{
if
(
mr
->
cur_tp
>=
mi
->
r
[
tmp_prob_rate
].
cur_tp
)
tmp_prob_rate
=
i
;
}
else
{
...
...
@@ -220,7 +220,7 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
static
void
minstrel_tx_status
(
void
*
priv
,
struct
ieee80211_supported_band
*
sband
,
struct
ieee80211_sta
*
sta
,
void
*
priv_sta
,
struct
ieee80211_sta
*
sta
,
void
*
priv_sta
,
struct
sk_buff
*
skb
)
{
struct
minstrel_priv
*
mp
=
priv
;
...
...
@@ -260,7 +260,7 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
static
inline
unsigned
int
minstrel_get_retry_count
(
struct
minstrel_rate
*
mr
,
struct
ieee80211_tx_info
*
info
)
struct
ieee80211_tx_info
*
info
)
{
unsigned
int
retry
=
mr
->
adjusted_retry_count
;
...
...
net/mac80211/rc80211_minstrel_ht.c
View file @
55d1cad2
...
...
@@ -63,7 +63,7 @@
#define CCK_DURATION(_bitrate, _short, _len) \
(1000 * (10
/* SIFS */
+ \
(_short ? 72 + 24 : 144 + 48
) + \
(_short ? 72 + 24 : 144 + 48) + \
(8 * (_len + 4) * 10) / (_bitrate)))
#define CCK_ACK_DURATION(_bitrate, _short) \
...
...
net/mac80211/tkip.c
View file @
55d1cad2
...
...
@@ -186,7 +186,7 @@ void ieee80211_get_tkip_p1k_iv(struct ieee80211_key_conf *keyconf,
EXPORT_SYMBOL
(
ieee80211_get_tkip_p1k_iv
);
void
ieee80211_get_tkip_rx_p1k
(
struct
ieee80211_key_conf
*
keyconf
,
const
u8
*
ta
,
u32
iv32
,
u16
*
p1k
)
const
u8
*
ta
,
u32
iv32
,
u16
*
p1k
)
{
const
u8
*
tk
=
&
keyconf
->
key
[
NL80211_TKIP_DATA_OFFSET_ENCR_KEY
];
struct
tkip_ctx
ctx
;
...
...
net/mac80211/trace.h
View file @
55d1cad2
...
...
@@ -553,7 +553,7 @@ TRACE_EVENT(drv_update_tkip_key,
TP_printk
(
LOCAL_PR_FMT
VIF_PR_FMT
STA_PR_FMT
" iv32:%#x"
,
LOCAL_PR_ARG
,
VIF_PR_ARG
,
STA_PR_ARG
,
__entry
->
iv32
LOCAL_PR_ARG
,
VIF_PR_ARG
,
STA_PR_ARG
,
__entry
->
iv32
)
);
...
...
net/mac80211/tx.c
View file @
55d1cad2
...
...
@@ -2161,7 +2161,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
if
(
ieee80211_is_data_qos
(
fc
))
{
__le16
*
qos_control
;
qos_control
=
(
__le16
*
)
skb_push
(
skb
,
2
);
qos_control
=
(
__le16
*
)
skb_push
(
skb
,
2
);
memcpy
(
skb_push
(
skb
,
hdrlen
-
2
),
&
hdr
,
hdrlen
-
2
);
/*
* Maybe we could actually set some fields here, for now just
...
...
@@ -2323,7 +2323,7 @@ static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
if
(
atomic_read
(
&
ps
->
num_sta_ps
)
>
0
)
/* in the hope that this is faster than
* checking byte-for-byte */
have_bits
=
!
bitmap_empty
((
unsigned
long
*
)
ps
->
tim
,
have_bits
=
!
bitmap_empty
((
unsigned
long
*
)
ps
->
tim
,
IEEE80211_MAX_AID
+
1
);
if
(
ps
->
dtim_count
==
0
)
...
...
net/mac80211/util.c
View file @
55d1cad2
...
...
@@ -76,7 +76,7 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
}
if
(
ieee80211_is_ctl
(
fc
))
{
if
(
ieee80211_is_pspoll
(
fc
))
if
(
ieee80211_is_pspoll
(
fc
))
return
hdr
->
addr1
;
if
(
ieee80211_is_back_req
(
fc
))
{
...
...
@@ -2315,9 +2315,14 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
struct
ieee80211_sub_if_data
*
sdata
;
struct
cfg80211_chan_def
chandef
;
mutex_lock
(
&
local
->
mtx
);
mutex_lock
(
&
local
->
iflist_mtx
);
list_for_each_entry
(
sdata
,
&
local
->
interfaces
,
list
)
{
cancel_delayed_work_sync
(
&
sdata
->
dfs_cac_timer_work
);
/* it might be waiting for the local->mtx, but then
* by the time it gets it, sdata->wdev.cac_started
* will no longer be true
*/
cancel_delayed_work
(
&
sdata
->
dfs_cac_timer_work
);
if
(
sdata
->
wdev
.
cac_started
)
{
chandef
=
sdata
->
vif
.
bss_conf
.
chandef
;
...
...
@@ -2329,6 +2334,7 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
}
}
mutex_unlock
(
&
local
->
iflist_mtx
);
mutex_unlock
(
&
local
->
mtx
);
}
void
ieee80211_dfs_radar_detected_work
(
struct
work_struct
*
work
)
...
...
@@ -2588,3 +2594,143 @@ int ieee80211_cs_headroom(struct ieee80211_local *local,
return
headroom
;
}
static
bool
ieee80211_extend_noa_desc
(
struct
ieee80211_noa_data
*
data
,
u32
tsf
,
int
i
)
{
s32
end
=
data
->
desc
[
i
].
start
+
data
->
desc
[
i
].
duration
-
(
tsf
+
1
);
int
skip
;
if
(
end
>
0
)
return
false
;
/* End time is in the past, check for repetitions */
skip
=
DIV_ROUND_UP
(
-
end
,
data
->
desc
[
i
].
interval
);
if
(
data
->
count
[
i
]
<
255
)
{
if
(
data
->
count
[
i
]
<=
skip
)
{
data
->
count
[
i
]
=
0
;
return
false
;
}
data
->
count
[
i
]
-=
skip
;
}
data
->
desc
[
i
].
start
+=
skip
*
data
->
desc
[
i
].
interval
;
return
true
;
}
static
bool
ieee80211_extend_absent_time
(
struct
ieee80211_noa_data
*
data
,
u32
tsf
,
s32
*
offset
)
{
bool
ret
=
false
;
int
i
;
for
(
i
=
0
;
i
<
IEEE80211_P2P_NOA_DESC_MAX
;
i
++
)
{
s32
cur
;
if
(
!
data
->
count
[
i
])
continue
;
if
(
ieee80211_extend_noa_desc
(
data
,
tsf
+
*
offset
,
i
))
ret
=
true
;
cur
=
data
->
desc
[
i
].
start
-
tsf
;
if
(
cur
>
*
offset
)
continue
;
cur
=
data
->
desc
[
i
].
start
+
data
->
desc
[
i
].
duration
-
tsf
;
if
(
cur
>
*
offset
)
*
offset
=
cur
;
}
return
ret
;
}
static
u32
ieee80211_get_noa_absent_time
(
struct
ieee80211_noa_data
*
data
,
u32
tsf
)
{
s32
offset
=
0
;
int
tries
=
0
;
/*
* arbitrary limit, used to avoid infinite loops when combined NoA
* descriptors cover the full time period.
*/
int
max_tries
=
5
;
ieee80211_extend_absent_time
(
data
,
tsf
,
&
offset
);
do
{
if
(
!
ieee80211_extend_absent_time
(
data
,
tsf
,
&
offset
))
break
;
tries
++
;
}
while
(
tries
<
max_tries
);
return
offset
;
}
void
ieee80211_update_p2p_noa
(
struct
ieee80211_noa_data
*
data
,
u32
tsf
)
{
u32
next_offset
=
BIT
(
31
)
-
1
;
int
i
;
data
->
absent
=
0
;
data
->
has_next_tsf
=
false
;
for
(
i
=
0
;
i
<
IEEE80211_P2P_NOA_DESC_MAX
;
i
++
)
{
s32
start
;
if
(
!
data
->
count
[
i
])
continue
;
ieee80211_extend_noa_desc
(
data
,
tsf
,
i
);
start
=
data
->
desc
[
i
].
start
-
tsf
;
if
(
start
<=
0
)
data
->
absent
|=
BIT
(
i
);
if
(
next_offset
>
start
)
next_offset
=
start
;
data
->
has_next_tsf
=
true
;
}
if
(
data
->
absent
)
next_offset
=
ieee80211_get_noa_absent_time
(
data
,
tsf
);
data
->
next_tsf
=
tsf
+
next_offset
;
}
EXPORT_SYMBOL
(
ieee80211_update_p2p_noa
);
int
ieee80211_parse_p2p_noa
(
const
struct
ieee80211_p2p_noa_attr
*
attr
,
struct
ieee80211_noa_data
*
data
,
u32
tsf
)
{
int
ret
=
0
;
int
i
;
memset
(
data
,
0
,
sizeof
(
*
data
));
for
(
i
=
0
;
i
<
IEEE80211_P2P_NOA_DESC_MAX
;
i
++
)
{
const
struct
ieee80211_p2p_noa_desc
*
desc
=
&
attr
->
desc
[
i
];
if
(
!
desc
->
count
||
!
desc
->
duration
)
continue
;
data
->
count
[
i
]
=
desc
->
count
;
data
->
desc
[
i
].
start
=
le32_to_cpu
(
desc
->
start_time
);
data
->
desc
[
i
].
duration
=
le32_to_cpu
(
desc
->
duration
);
data
->
desc
[
i
].
interval
=
le32_to_cpu
(
desc
->
interval
);
if
(
data
->
count
[
i
]
>
1
&&
data
->
desc
[
i
].
interval
<
data
->
desc
[
i
].
duration
)
continue
;
ieee80211_extend_noa_desc
(
data
,
tsf
,
i
);
ret
++
;
}
if
(
ret
)
ieee80211_update_p2p_noa
(
data
,
tsf
);
return
ret
;
}
EXPORT_SYMBOL
(
ieee80211_parse_p2p_noa
);
net/mac80211/wme.c
View file @
55d1cad2
...
...
@@ -106,6 +106,7 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
struct
sta_info
*
sta
=
NULL
;
const
u8
*
ra
=
NULL
;
bool
qos
=
false
;
struct
mac80211_qos_map
*
qos_map
;
if
(
local
->
hw
.
queues
<
IEEE80211_NUM_ACS
||
skb
->
len
<
6
)
{
skb
->
priority
=
0
;
/* required for correct WPA/11i MIC */
...
...
@@ -155,7 +156,11 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
/* use the data classifier to determine what 802.1d tag the
* data frame has */
skb
->
priority
=
cfg80211_classify8021d
(
skb
);
rcu_read_lock
();
qos_map
=
rcu_dereference
(
sdata
->
qos_map
);
skb
->
priority
=
cfg80211_classify8021d
(
skb
,
qos_map
?
&
qos_map
->
qos_map
:
NULL
);
rcu_read_unlock
();
return
ieee80211_downgrade_queue
(
sdata
,
skb
);
}
...
...
net/wireless/ap.c
View file @
55d1cad2
...
...
@@ -29,6 +29,7 @@ static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
wdev
->
beacon_interval
=
0
;
wdev
->
channel
=
NULL
;
wdev
->
ssid_len
=
0
;
rdev_set_qos_map
(
rdev
,
dev
,
NULL
);
}
return
err
;
...
...
net/wireless/ibss.c
View file @
55d1cad2
...
...
@@ -183,6 +183,8 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext)
kfree
(
wdev
->
connect_keys
);
wdev
->
connect_keys
=
NULL
;
rdev_set_qos_map
(
rdev
,
dev
,
NULL
);
/*
* Delete all the keys ... pairwise keys can't really
* exist any more anyway, but default keys might.
...
...
net/wireless/mesh.c
View file @
55d1cad2
...
...
@@ -277,6 +277,7 @@ static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
if
(
!
err
)
{
wdev
->
mesh_id_len
=
0
;
wdev
->
channel
=
NULL
;
rdev_set_qos_map
(
rdev
,
dev
,
NULL
);
}
return
err
;
...
...
net/wireless/nl80211.c
View file @
55d1cad2
...
...
@@ -53,6 +53,7 @@ enum nl80211_multicast_groups {
NL80211_MCGRP_SCAN
,
NL80211_MCGRP_REGULATORY
,
NL80211_MCGRP_MLME
,
NL80211_MCGRP_VENDOR
,
NL80211_MCGRP_TESTMODE
/* keep last - ifdef! */
};
...
...
@@ -61,6 +62,7 @@ static const struct genl_multicast_group nl80211_mcgrps[] = {
[
NL80211_MCGRP_SCAN
]
=
{
.
name
=
"scan"
,
},
[
NL80211_MCGRP_REGULATORY
]
=
{
.
name
=
"regulatory"
,
},
[
NL80211_MCGRP_MLME
]
=
{
.
name
=
"mlme"
,
},
[
NL80211_MCGRP_VENDOR
]
=
{
.
name
=
"vendor"
,
},
#ifdef CONFIG_NL80211_TESTMODE
[
NL80211_MCGRP_TESTMODE
]
=
{
.
name
=
"testmode"
,
}
#endif
...
...
@@ -380,6 +382,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[
NL80211_ATTR_VENDOR_ID
]
=
{
.
type
=
NLA_U32
},
[
NL80211_ATTR_VENDOR_SUBCMD
]
=
{
.
type
=
NLA_U32
},
[
NL80211_ATTR_VENDOR_DATA
]
=
{
.
type
=
NLA_BINARY
},
[
NL80211_ATTR_QOS_MAP
]
=
{
.
type
=
NLA_BINARY
,
.
len
=
IEEE80211_QOS_MAP_LEN_MAX
},
};
/* policy for the key attributes */
...
...
@@ -1188,7 +1192,6 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
struct
nlattr
*
nl_bands
,
*
nl_band
;
struct
nlattr
*
nl_freqs
,
*
nl_freq
;
struct
nlattr
*
nl_cmds
;
struct
nlattr
*
nl_vendor_cmds
;
enum
ieee80211_band
band
;
struct
ieee80211_channel
*
chan
;
int
i
;
...
...
@@ -1455,6 +1458,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
if
(
dev
->
wiphy
.
flags
&
WIPHY_FLAG_HAS_CHANNEL_SWITCH
)
CMD
(
channel_switch
,
CHANNEL_SWITCH
);
}
CMD
(
set_qos_map
,
SET_QOS_MAP
);
#ifdef CONFIG_NL80211_TESTMODE
CMD
(
testmode_cmd
,
TESTMODE
);
...
...
@@ -1587,16 +1591,38 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
state
->
split_start
++
;
break
;
case
11
:
nl_vendor_cmds
=
nla_nest_start
(
msg
,
NL80211_ATTR_VENDOR_DATA
);
if
(
!
nl_vendor_cmds
)
goto
nla_put_failure
;
if
(
dev
->
wiphy
.
n_vendor_commands
)
{
const
struct
nl80211_vendor_cmd_info
*
info
;
struct
nlattr
*
nested
;
nested
=
nla_nest_start
(
msg
,
NL80211_ATTR_VENDOR_DATA
);
if
(
!
nested
)
goto
nla_put_failure
;
for
(
i
=
0
;
i
<
dev
->
wiphy
.
n_vendor_commands
;
i
++
)
{
info
=
&
dev
->
wiphy
.
vendor_commands
[
i
].
info
;
if
(
nla_put
(
msg
,
i
+
1
,
sizeof
(
*
info
),
info
))
goto
nla_put_failure
;
}
nla_nest_end
(
msg
,
nested
);
}
if
(
dev
->
wiphy
.
n_vendor_events
)
{
const
struct
nl80211_vendor_cmd_info
*
info
;
struct
nlattr
*
nested
;
for
(
i
=
0
;
i
<
dev
->
wiphy
.
n_vendor_commands
;
i
++
)
if
(
nla_put
(
msg
,
i
+
1
,
sizeof
(
struct
nl80211_vendor_cmd_info
),
&
dev
->
wiphy
.
vendor_commands
[
i
].
info
))
nested
=
nla_nest_start
(
msg
,
NL80211_ATTR_VENDOR_EVENTS
);
if
(
!
nested
)
goto
nla_put_failure
;
nla_nest_end
(
msg
,
nl_vendor_cmds
);
for
(
i
=
0
;
i
<
dev
->
wiphy
.
n_vendor_events
;
i
++
)
{
info
=
&
dev
->
wiphy
.
vendor_events
[
i
];
if
(
nla_put
(
msg
,
i
+
1
,
sizeof
(
*
info
),
info
))
goto
nla_put_failure
;
}
nla_nest_end
(
msg
,
nested
);
}
/* done */
state
->
split_start
=
0
;
...
...
@@ -6726,7 +6752,9 @@ static struct sk_buff *
__cfg80211_alloc_vendor_skb
(
struct
cfg80211_registered_device
*
rdev
,
int
approxlen
,
u32
portid
,
u32
seq
,
enum
nl80211_commands
cmd
,
enum
nl80211_attrs
attr
,
gfp_t
gfp
)
enum
nl80211_attrs
attr
,
const
struct
nl80211_vendor_cmd_info
*
info
,
gfp_t
gfp
)
{
struct
sk_buff
*
skb
;
void
*
hdr
;
...
...
@@ -6744,6 +6772,16 @@ __cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev,
if
(
nla_put_u32
(
skb
,
NL80211_ATTR_WIPHY
,
rdev
->
wiphy_idx
))
goto
nla_put_failure
;
if
(
info
)
{
if
(
nla_put_u32
(
skb
,
NL80211_ATTR_VENDOR_ID
,
info
->
vendor_id
))
goto
nla_put_failure
;
if
(
nla_put_u32
(
skb
,
NL80211_ATTR_VENDOR_SUBCMD
,
info
->
subcmd
))
goto
nla_put_failure
;
}
data
=
nla_nest_start
(
skb
,
attr
);
((
void
**
)
skb
->
cb
)[
0
]
=
rdev
;
...
...
@@ -6884,29 +6922,54 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
return
err
;
}
struct
sk_buff
*
cfg80211_testmode_alloc_event_skb
(
struct
wiphy
*
wiphy
,
int
approxlen
,
gfp_t
gfp
)
struct
sk_buff
*
__cfg80211_alloc_event_skb
(
struct
wiphy
*
wiphy
,
enum
nl80211_commands
cmd
,
enum
nl80211_attrs
attr
,
int
vendor_event_idx
,
int
approxlen
,
gfp_t
gfp
)
{
struct
cfg80211_registered_device
*
rdev
=
wiphy_to_dev
(
wiphy
);
const
struct
nl80211_vendor_cmd_info
*
info
;
switch
(
cmd
)
{
case
NL80211_CMD_TESTMODE
:
if
(
WARN_ON
(
vendor_event_idx
!=
-
1
))
return
NULL
;
info
=
NULL
;
break
;
case
NL80211_CMD_VENDOR
:
if
(
WARN_ON
(
vendor_event_idx
<
0
||
vendor_event_idx
>=
wiphy
->
n_vendor_events
))
return
NULL
;
info
=
&
wiphy
->
vendor_events
[
vendor_event_idx
];
break
;
default:
WARN_ON
(
1
);
return
NULL
;
}
return
__cfg80211_alloc_vendor_skb
(
rdev
,
approxlen
,
0
,
0
,
NL80211_CMD_TESTMODE
,
NL80211_ATTR_TESTDATA
,
gfp
);
cmd
,
attr
,
info
,
gfp
);
}
EXPORT_SYMBOL
(
cfg80211_testmode
_alloc_event_skb
);
EXPORT_SYMBOL
(
__cfg80211
_alloc_event_skb
);
void
cfg80211_testmode_event
(
struct
sk_buff
*
skb
,
gfp_t
gfp
)
void
__cfg80211_send_event_skb
(
struct
sk_buff
*
skb
,
gfp_t
gfp
)
{
struct
cfg80211_registered_device
*
rdev
=
((
void
**
)
skb
->
cb
)[
0
];
void
*
hdr
=
((
void
**
)
skb
->
cb
)[
1
];
struct
nlattr
*
data
=
((
void
**
)
skb
->
cb
)[
2
];
enum
nl80211_multicast_groups
mcgrp
=
NL80211_MCGRP_TESTMODE
;
nla_nest_end
(
skb
,
data
);
genlmsg_end
(
skb
,
hdr
);
if
(
data
->
nla_type
==
NL80211_ATTR_VENDOR_DATA
)
mcgrp
=
NL80211_MCGRP_VENDOR
;
genlmsg_multicast_netns
(
&
nl80211_fam
,
wiphy_net
(
&
rdev
->
wiphy
),
skb
,
0
,
NL80211_MCGRP_TESTMODE
,
gfp
);
mcgrp
,
gfp
);
}
EXPORT_SYMBOL
(
cfg80211_testmode_event
);
EXPORT_SYMBOL
(
__cfg80211_send_event_skb
);
#endif
static
int
nl80211_connect
(
struct
sk_buff
*
skb
,
struct
genl_info
*
info
)
...
...
@@ -9039,7 +9102,7 @@ struct sk_buff *__cfg80211_alloc_reply_skb(struct wiphy *wiphy,
return
__cfg80211_alloc_vendor_skb
(
rdev
,
approxlen
,
rdev
->
cur_cmd_info
->
snd_portid
,
rdev
->
cur_cmd_info
->
snd_seq
,
cmd
,
attr
,
GFP_KERNEL
);
cmd
,
attr
,
NULL
,
GFP_KERNEL
);
}
EXPORT_SYMBOL
(
__cfg80211_alloc_reply_skb
);
...
...
@@ -9061,6 +9124,57 @@ int cfg80211_vendor_cmd_reply(struct sk_buff *skb)
EXPORT_SYMBOL_GPL
(
cfg80211_vendor_cmd_reply
);
static
int
nl80211_set_qos_map
(
struct
sk_buff
*
skb
,
struct
genl_info
*
info
)
{
struct
cfg80211_registered_device
*
rdev
=
info
->
user_ptr
[
0
];
struct
cfg80211_qos_map
*
qos_map
=
NULL
;
struct
net_device
*
dev
=
info
->
user_ptr
[
1
];
u8
*
pos
,
len
,
num_des
,
des_len
,
des
;
int
ret
;
if
(
!
rdev
->
ops
->
set_qos_map
)
return
-
EOPNOTSUPP
;
if
(
info
->
attrs
[
NL80211_ATTR_QOS_MAP
])
{
pos
=
nla_data
(
info
->
attrs
[
NL80211_ATTR_QOS_MAP
]);
len
=
nla_len
(
info
->
attrs
[
NL80211_ATTR_QOS_MAP
]);
if
(
len
%
2
||
len
<
IEEE80211_QOS_MAP_LEN_MIN
||
len
>
IEEE80211_QOS_MAP_LEN_MAX
)
return
-
EINVAL
;
qos_map
=
kzalloc
(
sizeof
(
struct
cfg80211_qos_map
),
GFP_KERNEL
);
if
(
!
qos_map
)
return
-
ENOMEM
;
num_des
=
(
len
-
IEEE80211_QOS_MAP_LEN_MIN
)
>>
1
;
if
(
num_des
)
{
des_len
=
num_des
*
sizeof
(
struct
cfg80211_dscp_exception
);
memcpy
(
qos_map
->
dscp_exception
,
pos
,
des_len
);
qos_map
->
num_des
=
num_des
;
for
(
des
=
0
;
des
<
num_des
;
des
++
)
{
if
(
qos_map
->
dscp_exception
[
des
].
up
>
7
)
{
kfree
(
qos_map
);
return
-
EINVAL
;
}
}
pos
+=
des_len
;
}
memcpy
(
qos_map
->
up
,
pos
,
IEEE80211_QOS_MAP_LEN_MIN
);
}
wdev_lock
(
dev
->
ieee80211_ptr
);
ret
=
nl80211_key_allowed
(
dev
->
ieee80211_ptr
);
if
(
!
ret
)
ret
=
rdev_set_qos_map
(
rdev
,
dev
,
qos_map
);
wdev_unlock
(
dev
->
ieee80211_ptr
);
kfree
(
qos_map
);
return
ret
;
}
#define NL80211_FLAG_NEED_WIPHY 0x01
#define NL80211_FLAG_NEED_NETDEV 0x02
#define NL80211_FLAG_NEED_RTNL 0x04
...
...
@@ -9793,6 +9907,14 @@ static const struct genl_ops nl80211_ops[] = {
.
internal_flags
=
NL80211_FLAG_NEED_WIPHY
|
NL80211_FLAG_NEED_RTNL
,
},
{
.
cmd
=
NL80211_CMD_SET_QOS_MAP
,
.
doit
=
nl80211_set_qos_map
,
.
policy
=
nl80211_policy
,
.
flags
=
GENL_ADMIN_PERM
,
.
internal_flags
=
NL80211_FLAG_NEED_NETDEV_UP
|
NL80211_FLAG_NEED_RTNL
,
},
};
/* notification functions */
...
...
net/wireless/rdev-ops.h
View file @
55d1cad2
...
...
@@ -932,4 +932,19 @@ static inline int rdev_channel_switch(struct cfg80211_registered_device *rdev,
return
ret
;
}
static
inline
int
rdev_set_qos_map
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
dev
,
struct
cfg80211_qos_map
*
qos_map
)
{
int
ret
=
-
EOPNOTSUPP
;
if
(
rdev
->
ops
->
set_qos_map
)
{
trace_rdev_set_qos_map
(
&
rdev
->
wiphy
,
dev
,
qos_map
);
ret
=
rdev
->
ops
->
set_qos_map
(
&
rdev
->
wiphy
,
dev
,
qos_map
);
trace_rdev_return_int
(
&
rdev
->
wiphy
,
ret
);
}
return
ret
;
}
#endif
/* __CFG80211_RDEV_OPS */
net/wireless/sme.c
View file @
55d1cad2
...
...
@@ -870,6 +870,8 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
for
(
i
=
0
;
i
<
6
;
i
++
)
rdev_del_key
(
rdev
,
dev
,
i
,
false
,
NULL
);
rdev_set_qos_map
(
rdev
,
dev
,
NULL
);
#ifdef CONFIG_CFG80211_WEXT
memset
(
&
wrqu
,
0
,
sizeof
(
wrqu
));
wrqu
.
ap_addr
.
sa_family
=
ARPHRD_ETHER
;
...
...
net/wireless/trace.h
View file @
55d1cad2
...
...
@@ -186,6 +186,28 @@
#define BOOL_TO_STR(bo) (bo) ? "true" : "false"
#define QOS_MAP_ENTRY __field(u8, num_des) \
__array(u8, dscp_exception, \
2 * IEEE80211_QOS_MAP_MAX_EX) \
__array(u8, up, IEEE80211_QOS_MAP_LEN_MIN)
#define QOS_MAP_ASSIGN(qos_map) \
do { \
if ((qos_map)) { \
__entry->num_des = (qos_map)->num_des; \
memcpy(__entry->dscp_exception, \
&(qos_map)->dscp_exception, \
2 * IEEE80211_QOS_MAP_MAX_EX); \
memcpy(__entry->up, &(qos_map)->up, \
IEEE80211_QOS_MAP_LEN_MIN); \
} else { \
__entry->num_des = 0; \
memset(__entry->dscp_exception, 0, \
2 * IEEE80211_QOS_MAP_MAX_EX); \
memset(__entry->up, 0, \
IEEE80211_QOS_MAP_LEN_MIN); \
} \
} while (0)
/*************************************************************
* rdev->ops traces *
*************************************************************/
...
...
@@ -1875,6 +1897,24 @@ TRACE_EVENT(rdev_channel_switch,
__entry
->
counter_offset_presp
)
);
TRACE_EVENT
(
rdev_set_qos_map
,
TP_PROTO
(
struct
wiphy
*
wiphy
,
struct
net_device
*
netdev
,
struct
cfg80211_qos_map
*
qos_map
),
TP_ARGS
(
wiphy
,
netdev
,
qos_map
),
TP_STRUCT__entry
(
WIPHY_ENTRY
NETDEV_ENTRY
QOS_MAP_ENTRY
),
TP_fast_assign
(
WIPHY_ASSIGN
;
NETDEV_ASSIGN
;
QOS_MAP_ASSIGN
(
qos_map
);
),
TP_printk
(
WIPHY_PR_FMT
", "
NETDEV_PR_FMT
", num_des: %u"
,
WIPHY_PR_ARG
,
NETDEV_PR_ARG
,
__entry
->
num_des
)
);
/*************************************************************
* cfg80211 exported functions traces *
*************************************************************/
...
...
net/wireless/util.c
View file @
55d1cad2
...
...
@@ -689,7 +689,8 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
EXPORT_SYMBOL
(
ieee80211_amsdu_to_8023s
);
/* Given a data frame determine the 802.1p/1d tag to use. */
unsigned
int
cfg80211_classify8021d
(
struct
sk_buff
*
skb
)
unsigned
int
cfg80211_classify8021d
(
struct
sk_buff
*
skb
,
struct
cfg80211_qos_map
*
qos_map
)
{
unsigned
int
dscp
;
unsigned
char
vlan_priority
;
...
...
@@ -720,6 +721,21 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb)
return
0
;
}
if
(
qos_map
)
{
unsigned
int
i
,
tmp_dscp
=
dscp
>>
2
;
for
(
i
=
0
;
i
<
qos_map
->
num_des
;
i
++
)
{
if
(
tmp_dscp
==
qos_map
->
dscp_exception
[
i
].
dscp
)
return
qos_map
->
dscp_exception
[
i
].
up
;
}
for
(
i
=
0
;
i
<
8
;
i
++
)
{
if
(
tmp_dscp
>=
qos_map
->
up
[
i
].
low
&&
tmp_dscp
<=
qos_map
->
up
[
i
].
high
)
return
i
;
}
}
return
dscp
>>
5
;
}
EXPORT_SYMBOL
(
cfg80211_classify8021d
);
...
...
@@ -863,6 +879,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
dev
->
ieee80211_ptr
->
use_4addr
=
false
;
dev
->
ieee80211_ptr
->
mesh_id_up_len
=
0
;
rdev_set_qos_map
(
rdev
,
dev
,
NULL
);
switch
(
otype
)
{
case
NL80211_IFTYPE_AP
:
...
...
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