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
a5abbcb2
Commit
a5abbcb2
authored
Oct 03, 2011
by
John W. Linville
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-linville' of
git://github.com/kvalo/ath6kl
parents
49a59543
62c83ac4
Changes
21
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
4050 additions
and
1549 deletions
+4050
-1549
drivers/net/wireless/ath/ath6kl/Makefile
drivers/net/wireless/ath/ath6kl/Makefile
+3
-1
drivers/net/wireless/ath/ath6kl/bmi.c
drivers/net/wireless/ath/ath6kl/bmi.c
+10
-13
drivers/net/wireless/ath/ath6kl/bmi.h
drivers/net/wireless/ath/ath6kl/bmi.h
+2
-2
drivers/net/wireless/ath/ath6kl/cfg80211.c
drivers/net/wireless/ath/ath6kl/cfg80211.c
+635
-259
drivers/net/wireless/ath/ath6kl/common.h
drivers/net/wireless/ath/ath6kl/common.h
+0
-83
drivers/net/wireless/ath/ath6kl/core.h
drivers/net/wireless/ath/ath6kl/core.h
+119
-26
drivers/net/wireless/ath/ath6kl/debug.c
drivers/net/wireless/ath/ath6kl/debug.c
+784
-0
drivers/net/wireless/ath/ath6kl/debug.h
drivers/net/wireless/ath/ath6kl/debug.h
+41
-8
drivers/net/wireless/ath/ath6kl/hif-ops.h
drivers/net/wireless/ath/ath6kl/hif-ops.h
+5
-0
drivers/net/wireless/ath/ath6kl/hif.h
drivers/net/wireless/ath/ath6kl/hif.h
+1
-0
drivers/net/wireless/ath/ath6kl/htc.c
drivers/net/wireless/ath/ath6kl/htc.c
+146
-125
drivers/net/wireless/ath/ath6kl/init.c
drivers/net/wireless/ath/ath6kl/init.c
+609
-185
drivers/net/wireless/ath/ath6kl/main.c
drivers/net/wireless/ath/ath6kl/main.c
+294
-154
drivers/net/wireless/ath/ath6kl/node.c
drivers/net/wireless/ath/ath6kl/node.c
+0
-234
drivers/net/wireless/ath/ath6kl/sdio.c
drivers/net/wireless/ath/ath6kl/sdio.c
+58
-21
drivers/net/wireless/ath/ath6kl/target.h
drivers/net/wireless/ath/ath6kl/target.h
+37
-4
drivers/net/wireless/ath/ath6kl/testmode.c
drivers/net/wireless/ath/ath6kl/testmode.c
+167
-0
drivers/net/wireless/ath/ath6kl/testmode.h
drivers/net/wireless/ath/ath6kl/testmode.h
+36
-0
drivers/net/wireless/ath/ath6kl/txrx.c
drivers/net/wireless/ath/ath6kl/txrx.c
+41
-20
drivers/net/wireless/ath/ath6kl/wmi.c
drivers/net/wireless/ath/ath6kl/wmi.c
+755
-371
drivers/net/wireless/ath/ath6kl/wmi.h
drivers/net/wireless/ath/ath6kl/wmi.h
+307
-43
No files found.
drivers/net/wireless/ath/ath6kl/Makefile
View file @
a5abbcb2
...
@@ -31,5 +31,7 @@ ath6kl-y += init.o
...
@@ -31,5 +31,7 @@ ath6kl-y += init.o
ath6kl-y
+=
main.o
ath6kl-y
+=
main.o
ath6kl-y
+=
txrx.o
ath6kl-y
+=
txrx.o
ath6kl-y
+=
wmi.o
ath6kl-y
+=
wmi.o
ath6kl-y
+=
node.o
ath6kl-y
+=
sdio.o
ath6kl-y
+=
sdio.o
ath6kl-$(CONFIG_NL80211_TESTMODE)
+=
testmode.o
ccflags-y
+=
-D__CHECK_ENDIAN__
drivers/net/wireless/ath/ath6kl/bmi.c
View file @
a5abbcb2
...
@@ -62,14 +62,14 @@ static int ath6kl_get_bmi_cmd_credits(struct ath6kl *ar)
...
@@ -62,14 +62,14 @@ static int ath6kl_get_bmi_cmd_credits(struct ath6kl *ar)
return
0
;
return
0
;
}
}
static
int
ath6kl_bmi_get_rx_lkahd
(
struct
ath6kl
*
ar
,
bool
need_timeout
)
static
int
ath6kl_bmi_get_rx_lkahd
(
struct
ath6kl
*
ar
)
{
{
unsigned
long
timeout
;
unsigned
long
timeout
;
u32
rx_word
=
0
;
u32
rx_word
=
0
;
int
ret
=
0
;
int
ret
=
0
;
timeout
=
jiffies
+
msecs_to_jiffies
(
BMI_COMMUNICATION_TIMEOUT
);
timeout
=
jiffies
+
msecs_to_jiffies
(
BMI_COMMUNICATION_TIMEOUT
);
while
(
(
!
need_timeout
||
time_before
(
jiffies
,
timeout
)
)
&&
!
rx_word
)
{
while
(
time_before
(
jiffies
,
timeout
)
&&
!
rx_word
)
{
ret
=
hif_read_write_sync
(
ar
,
RX_LOOKAHEAD_VALID_ADDRESS
,
ret
=
hif_read_write_sync
(
ar
,
RX_LOOKAHEAD_VALID_ADDRESS
,
(
u8
*
)
&
rx_word
,
sizeof
(
rx_word
),
(
u8
*
)
&
rx_word
,
sizeof
(
rx_word
),
HIF_RD_SYNC_BYTE_INC
);
HIF_RD_SYNC_BYTE_INC
);
...
@@ -109,8 +109,7 @@ static int ath6kl_bmi_send_buf(struct ath6kl *ar, u8 *buf, u32 len)
...
@@ -109,8 +109,7 @@ static int ath6kl_bmi_send_buf(struct ath6kl *ar, u8 *buf, u32 len)
return
ret
;
return
ret
;
}
}
static
int
ath6kl_bmi_recv_buf
(
struct
ath6kl
*
ar
,
static
int
ath6kl_bmi_recv_buf
(
struct
ath6kl
*
ar
,
u8
*
buf
,
u32
len
)
u8
*
buf
,
u32
len
,
bool
want_timeout
)
{
{
int
ret
;
int
ret
;
u32
addr
;
u32
addr
;
...
@@ -162,7 +161,7 @@ static int ath6kl_bmi_recv_buf(struct ath6kl *ar,
...
@@ -162,7 +161,7 @@ static int ath6kl_bmi_recv_buf(struct ath6kl *ar,
* a function of Host processor speed.
* a function of Host processor speed.
*/
*/
if
(
len
>=
4
)
{
/* NB: Currently, always true */
if
(
len
>=
4
)
{
/* NB: Currently, always true */
ret
=
ath6kl_bmi_get_rx_lkahd
(
ar
,
want_timeout
);
ret
=
ath6kl_bmi_get_rx_lkahd
(
ar
);
if
(
ret
)
if
(
ret
)
return
ret
;
return
ret
;
}
}
...
@@ -220,7 +219,7 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar,
...
@@ -220,7 +219,7 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar,
}
}
ret
=
ath6kl_bmi_recv_buf
(
ar
,
(
u8
*
)
&
targ_info
->
version
,
ret
=
ath6kl_bmi_recv_buf
(
ar
,
(
u8
*
)
&
targ_info
->
version
,
sizeof
(
targ_info
->
version
),
true
);
sizeof
(
targ_info
->
version
)
);
if
(
ret
)
{
if
(
ret
)
{
ath6kl_err
(
"Unable to recv target info: %d
\n
"
,
ret
);
ath6kl_err
(
"Unable to recv target info: %d
\n
"
,
ret
);
return
ret
;
return
ret
;
...
@@ -230,8 +229,7 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar,
...
@@ -230,8 +229,7 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar,
/* Determine how many bytes are in the Target's targ_info */
/* Determine how many bytes are in the Target's targ_info */
ret
=
ath6kl_bmi_recv_buf
(
ar
,
ret
=
ath6kl_bmi_recv_buf
(
ar
,
(
u8
*
)
&
targ_info
->
byte_count
,
(
u8
*
)
&
targ_info
->
byte_count
,
sizeof
(
targ_info
->
byte_count
),
sizeof
(
targ_info
->
byte_count
));
true
);
if
(
ret
)
{
if
(
ret
)
{
ath6kl_err
(
"unable to read target info byte count: %d
\n
"
,
ath6kl_err
(
"unable to read target info byte count: %d
\n
"
,
ret
);
ret
);
...
@@ -252,8 +250,7 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar,
...
@@ -252,8 +250,7 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar,
((
u8
*
)
targ_info
)
+
((
u8
*
)
targ_info
)
+
sizeof
(
targ_info
->
byte_count
),
sizeof
(
targ_info
->
byte_count
),
sizeof
(
*
targ_info
)
-
sizeof
(
*
targ_info
)
-
sizeof
(
targ_info
->
byte_count
),
sizeof
(
targ_info
->
byte_count
));
true
);
if
(
ret
)
{
if
(
ret
)
{
ath6kl_err
(
"Unable to read target info (%d bytes): %d
\n
"
,
ath6kl_err
(
"Unable to read target info (%d bytes): %d
\n
"
,
...
@@ -311,7 +308,7 @@ int ath6kl_bmi_read(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
...
@@ -311,7 +308,7 @@ int ath6kl_bmi_read(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
ret
);
ret
);
return
ret
;
return
ret
;
}
}
ret
=
ath6kl_bmi_recv_buf
(
ar
,
ar
->
bmi
.
cmd_buf
,
rx_len
,
true
);
ret
=
ath6kl_bmi_recv_buf
(
ar
,
ar
->
bmi
.
cmd_buf
,
rx_len
);
if
(
ret
)
{
if
(
ret
)
{
ath6kl_err
(
"Unable to read from the device: %d
\n
"
,
ath6kl_err
(
"Unable to read from the device: %d
\n
"
,
ret
);
ret
);
...
@@ -424,7 +421,7 @@ int ath6kl_bmi_execute(struct ath6kl *ar, u32 addr, u32 *param)
...
@@ -424,7 +421,7 @@ int ath6kl_bmi_execute(struct ath6kl *ar, u32 addr, u32 *param)
return
ret
;
return
ret
;
}
}
ret
=
ath6kl_bmi_recv_buf
(
ar
,
ar
->
bmi
.
cmd_buf
,
sizeof
(
*
param
)
,
false
);
ret
=
ath6kl_bmi_recv_buf
(
ar
,
ar
->
bmi
.
cmd_buf
,
sizeof
(
*
param
));
if
(
ret
)
{
if
(
ret
)
{
ath6kl_err
(
"Unable to read from the device: %d
\n
"
,
ret
);
ath6kl_err
(
"Unable to read from the device: %d
\n
"
,
ret
);
return
ret
;
return
ret
;
...
@@ -504,7 +501,7 @@ int ath6kl_bmi_reg_read(struct ath6kl *ar, u32 addr, u32 *param)
...
@@ -504,7 +501,7 @@ int ath6kl_bmi_reg_read(struct ath6kl *ar, u32 addr, u32 *param)
return
ret
;
return
ret
;
}
}
ret
=
ath6kl_bmi_recv_buf
(
ar
,
ar
->
bmi
.
cmd_buf
,
sizeof
(
*
param
)
,
true
);
ret
=
ath6kl_bmi_recv_buf
(
ar
,
ar
->
bmi
.
cmd_buf
,
sizeof
(
*
param
));
if
(
ret
)
{
if
(
ret
)
{
ath6kl_err
(
"Unable to read from the device: %d
\n
"
,
ret
);
ath6kl_err
(
"Unable to read from the device: %d
\n
"
,
ret
);
return
ret
;
return
ret
;
...
...
drivers/net/wireless/ath/ath6kl/bmi.h
View file @
a5abbcb2
...
@@ -139,8 +139,8 @@
...
@@ -139,8 +139,8 @@
*/
*/
#define TARGET_VERSION_SENTINAL 0xffffffff
#define TARGET_VERSION_SENTINAL 0xffffffff
#define TARGET_TYPE_AR6003
3
#define TARGET_TYPE_AR6003
3
#define TARGET_TYPE_AR6004 5
#define BMI_ROMPATCH_INSTALL 9
#define BMI_ROMPATCH_INSTALL 9
/*
/*
* Semantics: Install a ROM Patch.
* Semantics: Install a ROM Patch.
...
...
drivers/net/wireless/ath/ath6kl/cfg80211.c
View file @
a5abbcb2
...
@@ -17,6 +17,12 @@
...
@@ -17,6 +17,12 @@
#include "core.h"
#include "core.h"
#include "cfg80211.h"
#include "cfg80211.h"
#include "debug.h"
#include "debug.h"
#include "hif-ops.h"
#include "testmode.h"
static
unsigned
int
ath6kl_p2p
;
module_param
(
ath6kl_p2p
,
uint
,
0644
);
#define RATETAB_ENT(_rate, _rateid, _flags) { \
#define RATETAB_ENT(_rate, _rateid, _flags) { \
.bitrate = (_rate), \
.bitrate = (_rate), \
...
@@ -152,8 +158,7 @@ static int ath6kl_set_auth_type(struct ath6kl *ar,
...
@@ -152,8 +158,7 @@ static int ath6kl_set_auth_type(struct ath6kl *ar,
break
;
break
;
case
NL80211_AUTHTYPE_AUTOMATIC
:
case
NL80211_AUTHTYPE_AUTOMATIC
:
ar
->
dot11_auth_mode
=
OPEN_AUTH
;
ar
->
dot11_auth_mode
=
OPEN_AUTH
|
SHARED_AUTH
;
ar
->
auto_auth_stage
=
AUTH_OPEN_IN_PROGRESS
;
break
;
break
;
default:
default:
...
@@ -167,7 +172,8 @@ static int ath6kl_set_auth_type(struct ath6kl *ar,
...
@@ -167,7 +172,8 @@ static int ath6kl_set_auth_type(struct ath6kl *ar,
static
int
ath6kl_set_cipher
(
struct
ath6kl
*
ar
,
u32
cipher
,
bool
ucast
)
static
int
ath6kl_set_cipher
(
struct
ath6kl
*
ar
,
u32
cipher
,
bool
ucast
)
{
{
u8
*
ar_cipher
=
ucast
?
&
ar
->
prwise_crypto
:
&
ar
->
grp_crypto
;
u8
*
ar_cipher
=
ucast
?
&
ar
->
prwise_crypto
:
&
ar
->
grp_crypto
;
u8
*
ar_cipher_len
=
ucast
?
&
ar
->
prwise_crypto_len
:
&
ar
->
grp_crpto_len
;
u8
*
ar_cipher_len
=
ucast
?
&
ar
->
prwise_crypto_len
:
&
ar
->
grp_crypto_len
;
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"%s: cipher 0x%x, ucast %u
\n
"
,
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"%s: cipher 0x%x, ucast %u
\n
"
,
__func__
,
cipher
,
ucast
);
__func__
,
cipher
,
ucast
);
...
@@ -354,6 +360,7 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
...
@@ -354,6 +360,7 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
}
}
if
(
!
ar
->
usr_bss_filter
)
{
if
(
!
ar
->
usr_bss_filter
)
{
clear_bit
(
CLEAR_BSSFILTER_ON_BEACON
,
&
ar
->
flag
);
if
(
ath6kl_wmi_bssfilter_cmd
(
ar
->
wmi
,
ALL_BSS_FILTER
,
0
)
!=
0
)
{
if
(
ath6kl_wmi_bssfilter_cmd
(
ar
->
wmi
,
ALL_BSS_FILTER
,
0
)
!=
0
)
{
ath6kl_err
(
"couldn't set bss filtering
\n
"
);
ath6kl_err
(
"couldn't set bss filtering
\n
"
);
up
(
&
ar
->
sem
);
up
(
&
ar
->
sem
);
...
@@ -370,14 +377,14 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
...
@@ -370,14 +377,14 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
__func__
,
__func__
,
ar
->
auth_mode
,
ar
->
dot11_auth_mode
,
ar
->
prwise_crypto
,
ar
->
auth_mode
,
ar
->
dot11_auth_mode
,
ar
->
prwise_crypto
,
ar
->
prwise_crypto_len
,
ar
->
grp_crypto
,
ar
->
prwise_crypto_len
,
ar
->
grp_crypto
,
ar
->
grp_crpto_len
,
ar
->
ch_hint
);
ar
->
grp_cr
y
pto_len
,
ar
->
ch_hint
);
ar
->
reconnect_flag
=
0
;
ar
->
reconnect_flag
=
0
;
status
=
ath6kl_wmi_connect_cmd
(
ar
->
wmi
,
ar
->
nw_type
,
status
=
ath6kl_wmi_connect_cmd
(
ar
->
wmi
,
ar
->
nw_type
,
ar
->
dot11_auth_mode
,
ar
->
auth_mode
,
ar
->
dot11_auth_mode
,
ar
->
auth_mode
,
ar
->
prwise_crypto
,
ar
->
prwise_crypto
,
ar
->
prwise_crypto_len
,
ar
->
prwise_crypto_len
,
ar
->
grp_crypto
,
ar
->
grp_crpto_len
,
ar
->
grp_crypto
,
ar
->
grp_cr
y
pto_len
,
ar
->
ssid_len
,
ar
->
ssid
,
ar
->
ssid_len
,
ar
->
ssid
,
ar
->
req_bssid
,
ar
->
ch_hint
,
ar
->
req_bssid
,
ar
->
ch_hint
,
ar
->
connect_ctrl_flags
);
ar
->
connect_ctrl_flags
);
...
@@ -407,6 +414,53 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
...
@@ -407,6 +414,53 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
return
0
;
return
0
;
}
}
static
int
ath6kl_add_bss_if_needed
(
struct
ath6kl
*
ar
,
const
u8
*
bssid
,
struct
ieee80211_channel
*
chan
,
const
u8
*
beacon_ie
,
size_t
beacon_ie_len
)
{
struct
cfg80211_bss
*
bss
;
u8
*
ie
;
bss
=
cfg80211_get_bss
(
ar
->
wdev
->
wiphy
,
chan
,
bssid
,
ar
->
ssid
,
ar
->
ssid_len
,
WLAN_CAPABILITY_ESS
,
WLAN_CAPABILITY_ESS
);
if
(
bss
==
NULL
)
{
/*
* Since cfg80211 may not yet know about the BSS,
* generate a partial entry until the first BSS info
* event becomes available.
*
* Prepend SSID element since it is not included in the Beacon
* IEs from the target.
*/
ie
=
kmalloc
(
2
+
ar
->
ssid_len
+
beacon_ie_len
,
GFP_KERNEL
);
if
(
ie
==
NULL
)
return
-
ENOMEM
;
ie
[
0
]
=
WLAN_EID_SSID
;
ie
[
1
]
=
ar
->
ssid_len
;
memcpy
(
ie
+
2
,
ar
->
ssid
,
ar
->
ssid_len
);
memcpy
(
ie
+
2
+
ar
->
ssid_len
,
beacon_ie
,
beacon_ie_len
);
bss
=
cfg80211_inform_bss
(
ar
->
wdev
->
wiphy
,
chan
,
bssid
,
0
,
WLAN_CAPABILITY_ESS
,
100
,
ie
,
2
+
ar
->
ssid_len
+
beacon_ie_len
,
0
,
GFP_KERNEL
);
if
(
bss
)
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"added dummy bss for "
"%pM prior to indicating connect/roamed "
"event
\n
"
,
bssid
);
kfree
(
ie
);
}
else
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"cfg80211 already has a bss "
"entry
\n
"
);
if
(
bss
==
NULL
)
return
-
ENOMEM
;
cfg80211_put_bss
(
bss
);
return
0
;
}
void
ath6kl_cfg80211_connect_event
(
struct
ath6kl
*
ar
,
u16
channel
,
void
ath6kl_cfg80211_connect_event
(
struct
ath6kl
*
ar
,
u16
channel
,
u8
*
bssid
,
u16
listen_intvl
,
u8
*
bssid
,
u16
listen_intvl
,
u16
beacon_intvl
,
u16
beacon_intvl
,
...
@@ -414,19 +468,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel,
...
@@ -414,19 +468,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel,
u8
beacon_ie_len
,
u8
assoc_req_len
,
u8
beacon_ie_len
,
u8
assoc_req_len
,
u8
assoc_resp_len
,
u8
*
assoc_info
)
u8
assoc_resp_len
,
u8
*
assoc_info
)
{
{
u16
size
=
0
;
struct
ieee80211_channel
*
chan
;
u16
capability
=
0
;
struct
cfg80211_bss
*
bss
=
NULL
;
struct
ieee80211_mgmt
*
mgmt
=
NULL
;
struct
ieee80211_channel
*
ibss_ch
=
NULL
;
s32
signal
=
50
*
100
;
u8
ie_buf_len
=
0
;
unsigned
char
ie_buf
[
256
];
unsigned
char
*
ptr_ie_buf
=
ie_buf
;
unsigned
char
*
ieeemgmtbuf
=
NULL
;
u8
source_mac
[
ETH_ALEN
];
u16
capa_mask
;
u16
capa_val
;
/* capinfo + listen interval */
/* capinfo + listen interval */
u8
assoc_req_ie_offset
=
sizeof
(
u16
)
+
sizeof
(
u16
);
u8
assoc_req_ie_offset
=
sizeof
(
u16
)
+
sizeof
(
u16
);
...
@@ -441,7 +483,12 @@ void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel,
...
@@ -441,7 +483,12 @@ void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel,
assoc_req_len
-=
assoc_req_ie_offset
;
assoc_req_len
-=
assoc_req_ie_offset
;
assoc_resp_len
-=
assoc_resp_ie_offset
;
assoc_resp_len
-=
assoc_resp_ie_offset
;
ar
->
auto_auth_stage
=
AUTH_IDLE
;
/*
* Store Beacon interval here; DTIM period will be available only once
* a Beacon frame from the AP is seen.
*/
ar
->
assoc_bss_beacon_int
=
beacon_intvl
;
clear_bit
(
DTIM_PERIOD_AVAIL
,
&
ar
->
flag
);
if
(
nw_type
&
ADHOC_NETWORK
)
{
if
(
nw_type
&
ADHOC_NETWORK
)
{
if
(
ar
->
wdev
->
iftype
!=
NL80211_IFTYPE_ADHOC
)
{
if
(
ar
->
wdev
->
iftype
!=
NL80211_IFTYPE_ADHOC
)
{
...
@@ -452,110 +499,26 @@ void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel,
...
@@ -452,110 +499,26 @@ void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel,
}
}
if
(
nw_type
&
INFRA_NETWORK
)
{
if
(
nw_type
&
INFRA_NETWORK
)
{
if
(
ar
->
wdev
->
iftype
!=
NL80211_IFTYPE_STATION
)
{
if
(
ar
->
wdev
->
iftype
!=
NL80211_IFTYPE_STATION
&&
ar
->
wdev
->
iftype
!=
NL80211_IFTYPE_P2P_CLIENT
)
{
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"%s: ath6k not in station mode
\n
"
,
__func__
);
"%s: ath6k not in station mode
\n
"
,
__func__
);
return
;
return
;
}
}
}
}
if
(
nw_type
&
ADHOC_NETWORK
)
{
chan
=
ieee80211_get_channel
(
ar
->
wdev
->
wiphy
,
(
int
)
channel
);
capa_mask
=
WLAN_CAPABILITY_IBSS
;
capa_val
=
WLAN_CAPABILITY_IBSS
;
}
else
{
capa_mask
=
WLAN_CAPABILITY_ESS
;
capa_val
=
WLAN_CAPABILITY_ESS
;
}
/* Before informing the join/connect event, make sure that
* bss entry is present in scan list, if it not present
* construct and insert into scan list, otherwise that
* event will be dropped on the way by cfg80211, due to
* this keys will not be plumbed in case of WEP and
* application will not be aware of join/connect status. */
bss
=
cfg80211_get_bss
(
ar
->
wdev
->
wiphy
,
NULL
,
bssid
,
ar
->
wdev
->
ssid
,
ar
->
wdev
->
ssid_len
,
capa_mask
,
capa_val
);
/*
* Earlier we were updating the cfg about bss by making a beacon frame
* only if the entry for bss is not there. This can have some issue if
* ROAM event is generated and a heavy traffic is ongoing. The ROAM
* event is handled through a work queue and by the time it really gets
* handled, BSS would have been aged out. So it is better to update the
* cfg about BSS irrespective of its entry being present right now or
* not.
*/
if
(
nw_type
&
ADHOC_NETWORK
)
{
if
(
nw_type
&
ADHOC_NETWORK
)
{
/* construct 802.11 mgmt beacon */
cfg80211_ibss_joined
(
ar
->
net_dev
,
bssid
,
GFP_KERNEL
);
if
(
ptr_ie_buf
)
{
*
ptr_ie_buf
++
=
WLAN_EID_SSID
;
*
ptr_ie_buf
++
=
ar
->
ssid_len
;
memcpy
(
ptr_ie_buf
,
ar
->
ssid
,
ar
->
ssid_len
);
ptr_ie_buf
+=
ar
->
ssid_len
;
*
ptr_ie_buf
++
=
WLAN_EID_IBSS_PARAMS
;
*
ptr_ie_buf
++
=
2
;
/* length */
*
ptr_ie_buf
++
=
0
;
/* ATIM window */
*
ptr_ie_buf
++
=
0
;
/* ATIM window */
/* TODO: update ibss params and include supported rates,
* DS param set, extened support rates, wmm. */
ie_buf_len
=
ptr_ie_buf
-
ie_buf
;
}
capability
|=
WLAN_CAPABILITY_IBSS
;
if
(
ar
->
prwise_crypto
==
WEP_CRYPT
)
capability
|=
WLAN_CAPABILITY_PRIVACY
;
memcpy
(
source_mac
,
ar
->
net_dev
->
dev_addr
,
ETH_ALEN
);
ptr_ie_buf
=
ie_buf
;
}
else
{
capability
=
*
(
u16
*
)
(
&
assoc_info
[
beacon_ie_len
]);
memcpy
(
source_mac
,
bssid
,
ETH_ALEN
);
ptr_ie_buf
=
assoc_req_ie
;
ie_buf_len
=
assoc_req_len
;
}
size
=
offsetof
(
struct
ieee80211_mgmt
,
u
)
+
sizeof
(
mgmt
->
u
.
beacon
)
+
ie_buf_len
;
ieeemgmtbuf
=
kzalloc
(
size
,
GFP_ATOMIC
);
if
(
!
ieeemgmtbuf
)
{
ath6kl_err
(
"ieee mgmt buf alloc error
\n
"
);
cfg80211_put_bss
(
bss
);
return
;
return
;
}
}
mgmt
=
(
struct
ieee80211_mgmt
*
)
ieeemgmtbuf
;
if
(
ath6kl_add_bss_if_needed
(
ar
,
bssid
,
chan
,
assoc_info
,
mgmt
->
frame_control
=
cpu_to_le16
(
IEEE80211_FTYPE_MGMT
|
beacon_ie_len
)
<
0
)
{
IEEE80211_STYPE_BEACON
);
ath6kl_err
(
"could not add cfg80211 bss entry for "
memset
(
mgmt
->
da
,
0xff
,
ETH_ALEN
);
/* broadcast addr */
"connect/roamed notification
\n
"
);
memcpy
(
mgmt
->
sa
,
source_mac
,
ETH_ALEN
);
memcpy
(
mgmt
->
bssid
,
bssid
,
ETH_ALEN
);
mgmt
->
u
.
beacon
.
beacon_int
=
cpu_to_le16
(
beacon_intvl
);
mgmt
->
u
.
beacon
.
capab_info
=
cpu_to_le16
(
capability
);
memcpy
(
mgmt
->
u
.
beacon
.
variable
,
ptr_ie_buf
,
ie_buf_len
);
ibss_ch
=
ieee80211_get_channel
(
ar
->
wdev
->
wiphy
,
(
int
)
channel
);
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"%s: inform bss with bssid %pM channel %d beacon_intvl %d capability 0x%x
\n
"
,
__func__
,
mgmt
->
bssid
,
ibss_ch
->
hw_value
,
beacon_intvl
,
capability
);
bss
=
cfg80211_inform_bss_frame
(
ar
->
wdev
->
wiphy
,
ibss_ch
,
mgmt
,
size
,
signal
,
GFP_KERNEL
);
kfree
(
ieeemgmtbuf
);
cfg80211_put_bss
(
bss
);
if
(
nw_type
&
ADHOC_NETWORK
)
{
cfg80211_ibss_joined
(
ar
->
net_dev
,
bssid
,
GFP_KERNEL
);
return
;
return
;
}
}
...
@@ -568,7 +531,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel,
...
@@ -568,7 +531,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel,
WLAN_STATUS_SUCCESS
,
GFP_KERNEL
);
WLAN_STATUS_SUCCESS
,
GFP_KERNEL
);
}
else
if
(
ar
->
sme_state
==
SME_CONNECTED
)
{
}
else
if
(
ar
->
sme_state
==
SME_CONNECTED
)
{
/* inform roam event to cfg80211 */
/* inform roam event to cfg80211 */
cfg80211_roamed
(
ar
->
net_dev
,
ibss_ch
,
bssid
,
cfg80211_roamed
(
ar
->
net_dev
,
chan
,
bssid
,
assoc_req_ie
,
assoc_req_len
,
assoc_req_ie
,
assoc_req_len
,
assoc_resp_ie
,
assoc_resp_len
,
GFP_KERNEL
);
assoc_resp_ie
,
assoc_resp_len
,
GFP_KERNEL
);
}
}
...
@@ -605,6 +568,8 @@ static int ath6kl_cfg80211_disconnect(struct wiphy *wiphy,
...
@@ -605,6 +568,8 @@ static int ath6kl_cfg80211_disconnect(struct wiphy *wiphy,
up
(
&
ar
->
sem
);
up
(
&
ar
->
sem
);
ar
->
sme_state
=
SME_DISCONNECTED
;
return
0
;
return
0
;
}
}
...
@@ -612,9 +577,6 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl *ar, u8 reason,
...
@@ -612,9 +577,6 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl *ar, u8 reason,
u8
*
bssid
,
u8
assoc_resp_len
,
u8
*
bssid
,
u8
assoc_resp_len
,
u8
*
assoc_info
,
u16
proto_reason
)
u8
*
assoc_info
,
u16
proto_reason
)
{
{
struct
ath6kl_key
*
key
=
NULL
;
u16
status
;
if
(
ar
->
scan_req
)
{
if
(
ar
->
scan_req
)
{
cfg80211_scan_done
(
ar
->
scan_req
,
true
);
cfg80211_scan_done
(
ar
->
scan_req
,
true
);
ar
->
scan_req
=
NULL
;
ar
->
scan_req
=
NULL
;
...
@@ -632,164 +594,64 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl *ar, u8 reason,
...
@@ -632,164 +594,64 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl *ar, u8 reason,
}
}
if
(
ar
->
nw_type
&
INFRA_NETWORK
)
{
if
(
ar
->
nw_type
&
INFRA_NETWORK
)
{
if
(
ar
->
wdev
->
iftype
!=
NL80211_IFTYPE_STATION
)
{
if
(
ar
->
wdev
->
iftype
!=
NL80211_IFTYPE_STATION
&&
ar
->
wdev
->
iftype
!=
NL80211_IFTYPE_P2P_CLIENT
)
{
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"%s: ath6k not in station mode
\n
"
,
__func__
);
"%s: ath6k not in station mode
\n
"
,
__func__
);
return
;
return
;
}
}
}
}
if
(
!
test_bit
(
CONNECT_PEND
,
&
ar
->
flag
))
{
if
(
reason
!=
DISCONNECT_CMD
)
ath6kl_wmi_disconnect_cmd
(
ar
->
wmi
);
return
;
}
if
(
reason
==
NO_NETWORK_AVAIL
)
{
/* connect cmd failed */
ath6kl_wmi_disconnect_cmd
(
ar
->
wmi
);
return
;
}
if
(
reason
!=
DISCONNECT_CMD
)
return
;
if
(
!
ar
->
auto_auth_stage
)
{
clear_bit
(
CONNECT_PEND
,
&
ar
->
flag
);
if
(
ar
->
sme_state
==
SME_CONNECTING
)
{
cfg80211_connect_result
(
ar
->
net_dev
,
bssid
,
NULL
,
0
,
NULL
,
0
,
WLAN_STATUS_UNSPECIFIED_FAILURE
,
GFP_KERNEL
);
}
else
{
cfg80211_disconnected
(
ar
->
net_dev
,
reason
,
NULL
,
0
,
GFP_KERNEL
);
}
ar
->
sme_state
=
SME_DISCONNECTED
;
return
;
}
if
(
ar
->
dot11_auth_mode
!=
OPEN_AUTH
)
return
;
/*
/*
* If the current auth algorithm is open, try shared and
* Send a disconnect command to target when a disconnect event is
* make autoAuthStage idle. We do not make it leap for now
* received with reason code other than 3 (DISCONNECT_CMD - disconnect
* being.
* request from host) to make the firmware stop trying to connect even
* after giving disconnect event. There will be one more disconnect
* event for this disconnect command with reason code DISCONNECT_CMD
* which will be notified to cfg80211.
*/
*/
key
=
&
ar
->
keys
[
ar
->
def_txkey_index
];
if
(
down_interruptible
(
&
ar
->
sem
))
{
ath6kl_err
(
"busy, couldn't get access
\n
"
);
return
;
}
ar
->
dot11_auth_mode
=
SHARED_AUTH
;
ar
->
auto_auth_stage
=
AUTH_IDLE
;
ath6kl_wmi_addkey_cmd
(
ar
->
wmi
,
if
(
reason
!=
DISCONNECT_CMD
)
{
ar
->
def_txkey_index
,
ath6kl_wmi_disconnect_cmd
(
ar
->
wmi
);
ar
->
prwise_crypto
,
GROUP_USAGE
|
TX_USAGE
,
key
->
key_len
,
NULL
,
key
->
key
,
KEY_OP_INIT_VAL
,
NULL
,
NO_SYNC_WMIFLAG
);
status
=
ath6kl_wmi_connect_cmd
(
ar
->
wmi
,
ar
->
nw_type
,
ar
->
dot11_auth_mode
,
ar
->
auth_mode
,
ar
->
prwise_crypto
,
ar
->
prwise_crypto_len
,
ar
->
grp_crypto
,
ar
->
grp_crpto_len
,
ar
->
ssid_len
,
ar
->
ssid
,
ar
->
req_bssid
,
ar
->
ch_hint
,
ar
->
connect_ctrl_flags
);
up
(
&
ar
->
sem
);
}
static
inline
bool
is_ch_11a
(
u16
ch
)
{
return
(
!
((
ch
>=
2412
)
&&
(
ch
<=
2484
)));
}
/* struct ath6kl_node_table::nt_nodelock is locked when calling this */
void
ath6kl_cfg80211_scan_node
(
struct
wiphy
*
wiphy
,
struct
bss
*
ni
)
{
u16
size
;
unsigned
char
*
ieeemgmtbuf
=
NULL
;
struct
ieee80211_mgmt
*
mgmt
;
struct
ieee80211_channel
*
channel
;
struct
ieee80211_supported_band
*
band
;
struct
ath6kl_common_ie
*
cie
;
s32
signal
;
int
freq
;
cie
=
&
ni
->
ni_cie
;
if
(
is_ch_11a
(
cie
->
ie_chan
))
band
=
wiphy
->
bands
[
IEEE80211_BAND_5GHZ
];
/* 11a */
else
if
((
cie
->
ie_erp
)
||
(
cie
->
ie_xrates
))
band
=
wiphy
->
bands
[
IEEE80211_BAND_2GHZ
];
/* 11g */
else
band
=
wiphy
->
bands
[
IEEE80211_BAND_2GHZ
];
/* 11b */
size
=
ni
->
ni_framelen
+
offsetof
(
struct
ieee80211_mgmt
,
u
);
ieeemgmtbuf
=
kmalloc
(
size
,
GFP_ATOMIC
);
if
(
!
ieeemgmtbuf
)
{
ath6kl_err
(
"ieee mgmt buf alloc error
\n
"
);
return
;
return
;
}
}
/*
clear_bit
(
CONNECT_PEND
,
&
ar
->
flag
);
* TODO: Update target to include 802.11 mac header while sending
* bss info. Target removes 802.11 mac header while sending the bss
* info to host, cfg80211 needs it, for time being just filling the
* da, sa and bssid fields alone.
*/
mgmt
=
(
struct
ieee80211_mgmt
*
)
ieeemgmtbuf
;
memset
(
mgmt
->
da
,
0xff
,
ETH_ALEN
);
/*broadcast addr */
memcpy
(
mgmt
->
sa
,
ni
->
ni_macaddr
,
ETH_ALEN
);
memcpy
(
mgmt
->
bssid
,
ni
->
ni_macaddr
,
ETH_ALEN
);
memcpy
(
ieeemgmtbuf
+
offsetof
(
struct
ieee80211_mgmt
,
u
),
ni
->
ni_buf
,
ni
->
ni_framelen
);
freq
=
cie
->
ie_chan
;
channel
=
ieee80211_get_channel
(
wiphy
,
freq
);
signal
=
ni
->
ni_snr
*
100
;
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
if
(
ar
->
sme_state
==
SME_CONNECTING
)
{
"%s: bssid %pM ch %d freq %d size %d
\n
"
,
__func__
,
cfg80211_connect_result
(
ar
->
net_dev
,
mgmt
->
bssid
,
channel
->
hw_value
,
freq
,
size
);
bssid
,
NULL
,
0
,
cfg80211_inform_bss_frame
(
wiphy
,
channel
,
mgmt
,
NULL
,
0
,
size
,
signal
,
GFP_ATOMIC
);
WLAN_STATUS_UNSPECIFIED_FAILURE
,
GFP_KERNEL
);
}
else
if
(
ar
->
sme_state
==
SME_CONNECTED
)
{
cfg80211_disconnected
(
ar
->
net_dev
,
reason
,
NULL
,
0
,
GFP_KERNEL
);
}
kfree
(
ieeemgmtbuf
)
;
ar
->
sme_state
=
SME_DISCONNECTED
;
}
}
static
int
ath6kl_cfg80211_scan
(
struct
wiphy
*
wiphy
,
struct
net_device
*
ndev
,
static
int
ath6kl_cfg80211_scan
(
struct
wiphy
*
wiphy
,
struct
net_device
*
ndev
,
struct
cfg80211_scan_request
*
request
)
struct
cfg80211_scan_request
*
request
)
{
{
struct
ath6kl
*
ar
=
(
struct
ath6kl
*
)
ath6kl_priv
(
ndev
);
struct
ath6kl
*
ar
=
(
struct
ath6kl
*
)
ath6kl_priv
(
ndev
);
s8
n_channels
=
0
;
u16
*
channels
=
NULL
;
int
ret
=
0
;
int
ret
=
0
;
if
(
!
ath6kl_cfg80211_ready
(
ar
))
if
(
!
ath6kl_cfg80211_ready
(
ar
))
return
-
EIO
;
return
-
EIO
;
if
(
!
ar
->
usr_bss_filter
)
{
if
(
!
ar
->
usr_bss_filter
)
{
if
(
ath6kl_wmi_bssfilter_cmd
(
ar
->
wmi
,
clear_bit
(
CLEAR_BSSFILTER_ON_BEACON
,
&
ar
->
flag
);
(
test_bit
(
CONNECTED
,
&
ar
->
flag
)
?
ret
=
ath6kl_wmi_bssfilter_cmd
(
ALL_BUT_BSS_FILTER
:
ar
->
wmi
,
ALL_BSS_FILTER
),
0
)
!=
0
)
{
(
test_bit
(
CONNECTED
,
&
ar
->
flag
)
?
ALL_BUT_BSS_FILTER
:
ALL_BSS_FILTER
),
0
);
if
(
ret
)
{
ath6kl_err
(
"couldn't set bss filtering
\n
"
);
ath6kl_err
(
"couldn't set bss filtering
\n
"
);
return
-
EIO
;
return
ret
;
}
}
}
}
...
@@ -806,13 +668,46 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
...
@@ -806,13 +668,46 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
request
->
ssids
[
i
].
ssid
);
request
->
ssids
[
i
].
ssid
);
}
}
if
(
ath6kl_wmi_startscan_cmd
(
ar
->
wmi
,
WMI_LONG_SCAN
,
0
,
if
(
request
->
ie
)
{
false
,
0
,
0
,
0
,
NULL
)
!=
0
)
{
ret
=
ath6kl_wmi_set_appie_cmd
(
ar
->
wmi
,
WMI_FRAME_PROBE_REQ
,
ath6kl_err
(
"wmi_startscan_cmd failed
\n
"
);
request
->
ie
,
request
->
ie_len
);
ret
=
-
EIO
;
if
(
ret
)
{
ath6kl_err
(
"failed to set Probe Request appie for "
"scan"
);
return
ret
;
}
}
}
ar
->
scan_req
=
request
;
/*
* Scan only the requested channels if the request specifies a set of
* channels. If the list is longer than the target supports, do not
* configure the list and instead, scan all available channels.
*/
if
(
request
->
n_channels
>
0
&&
request
->
n_channels
<=
WMI_MAX_CHANNELS
)
{
u8
i
;
n_channels
=
request
->
n_channels
;
channels
=
kzalloc
(
n_channels
*
sizeof
(
u16
),
GFP_KERNEL
);
if
(
channels
==
NULL
)
{
ath6kl_warn
(
"failed to set scan channels, "
"scan all channels"
);
n_channels
=
0
;
}
for
(
i
=
0
;
i
<
n_channels
;
i
++
)
channels
[
i
]
=
request
->
channels
[
i
]
->
center_freq
;
}
ret
=
ath6kl_wmi_startscan_cmd
(
ar
->
wmi
,
WMI_LONG_SCAN
,
0
,
false
,
0
,
0
,
n_channels
,
channels
);
if
(
ret
)
ath6kl_err
(
"wmi_startscan_cmd failed
\n
"
);
else
ar
->
scan_req
=
request
;
kfree
(
channels
);
return
ret
;
return
ret
;
}
}
...
@@ -831,9 +726,6 @@ void ath6kl_cfg80211_scan_complete_event(struct ath6kl *ar, int status)
...
@@ -831,9 +726,6 @@ void ath6kl_cfg80211_scan_complete_event(struct ath6kl *ar, int status)
goto
out
;
goto
out
;
}
}
/* Translate data to cfg80211 mgmt format */
wlan_iterate_nodes
(
&
ar
->
scan_table
,
ar
->
wdev
->
wiphy
);
cfg80211_scan_done
(
ar
->
scan_req
,
false
);
cfg80211_scan_done
(
ar
->
scan_req
,
false
);
if
(
ar
->
scan_req
->
n_ssids
&&
ar
->
scan_req
->
ssids
[
0
].
ssid_len
)
{
if
(
ar
->
scan_req
->
n_ssids
&&
ar
->
scan_req
->
ssids
[
0
].
ssid_len
)
{
...
@@ -918,6 +810,40 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
...
@@ -918,6 +810,40 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
key_usage
,
key
->
seq_len
);
key_usage
,
key
->
seq_len
);
ar
->
def_txkey_index
=
key_index
;
ar
->
def_txkey_index
=
key_index
;
if
(
ar
->
nw_type
==
AP_NETWORK
&&
!
pairwise
&&
(
key_type
==
TKIP_CRYPT
||
key_type
==
AES_CRYPT
)
&&
params
)
{
ar
->
ap_mode_bkey
.
valid
=
true
;
ar
->
ap_mode_bkey
.
key_index
=
key_index
;
ar
->
ap_mode_bkey
.
key_type
=
key_type
;
ar
->
ap_mode_bkey
.
key_len
=
key
->
key_len
;
memcpy
(
ar
->
ap_mode_bkey
.
key
,
key
->
key
,
key
->
key_len
);
if
(
!
test_bit
(
CONNECTED
,
&
ar
->
flag
))
{
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"Delay initial group "
"key configuration until AP mode has been "
"started
\n
"
);
/*
* The key will be set in ath6kl_connect_ap_mode() once
* the connected event is received from the target.
*/
return
0
;
}
}
if
(
ar
->
next_mode
==
AP_NETWORK
&&
key_type
==
WEP_CRYPT
&&
!
test_bit
(
CONNECTED
,
&
ar
->
flag
))
{
/*
* Store the key locally so that it can be re-configured after
* the AP mode has properly started
* (ath6kl_install_statioc_wep_keys).
*/
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"Delay WEP key configuration "
"until AP mode has been started
\n
"
);
ar
->
wep_key_list
[
key_index
].
key_len
=
key
->
key_len
;
memcpy
(
ar
->
wep_key_list
[
key_index
].
key
,
key
->
key
,
key
->
key_len
);
return
0
;
}
status
=
ath6kl_wmi_addkey_cmd
(
ar
->
wmi
,
ar
->
def_txkey_index
,
status
=
ath6kl_wmi_addkey_cmd
(
ar
->
wmi
,
ar
->
def_txkey_index
,
key_type
,
key_usage
,
key
->
key_len
,
key_type
,
key_usage
,
key
->
key_len
,
key
->
seq
,
key
->
key
,
KEY_OP_INIT_VAL
,
key
->
seq
,
key
->
key
,
KEY_OP_INIT_VAL
,
...
@@ -1002,6 +928,7 @@ static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy,
...
@@ -1002,6 +928,7 @@ static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy,
struct
ath6kl_key
*
key
=
NULL
;
struct
ath6kl_key
*
key
=
NULL
;
int
status
=
0
;
int
status
=
0
;
u8
key_usage
;
u8
key_usage
;
enum
crypto_type
key_type
=
NONE_CRYPT
;
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"%s: index %d
\n
"
,
__func__
,
key_index
);
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"%s: index %d
\n
"
,
__func__
,
key_index
);
...
@@ -1026,9 +953,16 @@ static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy,
...
@@ -1026,9 +953,16 @@ static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy,
key_usage
=
GROUP_USAGE
;
key_usage
=
GROUP_USAGE
;
if
(
ar
->
prwise_crypto
==
WEP_CRYPT
)
if
(
ar
->
prwise_crypto
==
WEP_CRYPT
)
key_usage
|=
TX_USAGE
;
key_usage
|=
TX_USAGE
;
if
(
unicast
)
key_type
=
ar
->
prwise_crypto
;
if
(
multicast
)
key_type
=
ar
->
grp_crypto
;
if
(
ar
->
next_mode
==
AP_NETWORK
&&
!
test_bit
(
CONNECTED
,
&
ar
->
flag
))
return
0
;
/* Delay until AP mode has been started */
status
=
ath6kl_wmi_addkey_cmd
(
ar
->
wmi
,
ar
->
def_txkey_index
,
status
=
ath6kl_wmi_addkey_cmd
(
ar
->
wmi
,
ar
->
def_txkey_index
,
ar
->
prwise_crypto
,
key_usage
,
key_type
,
key_usage
,
key
->
key_len
,
key
->
seq
,
key
->
key
,
key
->
key_len
,
key
->
seq
,
key
->
key
,
KEY_OP_INIT_VAL
,
NULL
,
KEY_OP_INIT_VAL
,
NULL
,
SYNC_BOTH_WMIFLAG
);
SYNC_BOTH_WMIFLAG
);
...
@@ -1183,6 +1117,15 @@ static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy,
...
@@ -1183,6 +1117,15 @@ static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy,
case
NL80211_IFTYPE_ADHOC
:
case
NL80211_IFTYPE_ADHOC
:
ar
->
next_mode
=
ADHOC_NETWORK
;
ar
->
next_mode
=
ADHOC_NETWORK
;
break
;
break
;
case
NL80211_IFTYPE_AP
:
ar
->
next_mode
=
AP_NETWORK
;
break
;
case
NL80211_IFTYPE_P2P_CLIENT
:
ar
->
next_mode
=
INFRA_NETWORK
;
break
;
case
NL80211_IFTYPE_P2P_GO
:
ar
->
next_mode
=
AP_NETWORK
;
break
;
default:
default:
ath6kl_err
(
"invalid interface type %u
\n
"
,
type
);
ath6kl_err
(
"invalid interface type %u
\n
"
,
type
);
return
-
EOPNOTSUPP
;
return
-
EOPNOTSUPP
;
...
@@ -1246,13 +1189,13 @@ static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy,
...
@@ -1246,13 +1189,13 @@ static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy,
__func__
,
__func__
,
ar
->
auth_mode
,
ar
->
dot11_auth_mode
,
ar
->
prwise_crypto
,
ar
->
auth_mode
,
ar
->
dot11_auth_mode
,
ar
->
prwise_crypto
,
ar
->
prwise_crypto_len
,
ar
->
grp_crypto
,
ar
->
prwise_crypto_len
,
ar
->
grp_crypto
,
ar
->
grp_crpto_len
,
ar
->
ch_hint
);
ar
->
grp_cr
y
pto_len
,
ar
->
ch_hint
);
status
=
ath6kl_wmi_connect_cmd
(
ar
->
wmi
,
ar
->
nw_type
,
status
=
ath6kl_wmi_connect_cmd
(
ar
->
wmi
,
ar
->
nw_type
,
ar
->
dot11_auth_mode
,
ar
->
auth_mode
,
ar
->
dot11_auth_mode
,
ar
->
auth_mode
,
ar
->
prwise_crypto
,
ar
->
prwise_crypto
,
ar
->
prwise_crypto_len
,
ar
->
prwise_crypto_len
,
ar
->
grp_crypto
,
ar
->
grp_crpto_len
,
ar
->
grp_crypto
,
ar
->
grp_cr
y
pto_len
,
ar
->
ssid_len
,
ar
->
ssid
,
ar
->
ssid_len
,
ar
->
ssid
,
ar
->
req_bssid
,
ar
->
ch_hint
,
ar
->
req_bssid
,
ar
->
ch_hint
,
ar
->
connect_ctrl_flags
);
ar
->
connect_ctrl_flags
);
...
@@ -1422,12 +1365,23 @@ static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev,
...
@@ -1422,12 +1365,23 @@ static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev,
sinfo
->
txrate
.
flags
|=
RATE_INFO_FLAGS_40_MHZ_WIDTH
;
sinfo
->
txrate
.
flags
|=
RATE_INFO_FLAGS_40_MHZ_WIDTH
;
sinfo
->
txrate
.
flags
|=
RATE_INFO_FLAGS_MCS
;
sinfo
->
txrate
.
flags
|=
RATE_INFO_FLAGS_MCS
;
}
else
{
}
else
{
ath6kl_warn
(
"invalid rate: %d
\n
"
,
rate
);
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"invalid rate from stats: %d
\n
"
,
rate
);
ath6kl_debug_war
(
ar
,
ATH6KL_WAR_INVALID_RATE
);
return
0
;
return
0
;
}
}
sinfo
->
filled
|=
STATION_INFO_TX_BITRATE
;
sinfo
->
filled
|=
STATION_INFO_TX_BITRATE
;
if
(
test_bit
(
CONNECTED
,
&
ar
->
flag
)
&&
test_bit
(
DTIM_PERIOD_AVAIL
,
&
ar
->
flag
)
&&
ar
->
nw_type
==
INFRA_NETWORK
)
{
sinfo
->
filled
|=
STATION_INFO_BSS_PARAM
;
sinfo
->
bss_param
.
flags
=
0
;
sinfo
->
bss_param
.
dtim_period
=
ar
->
assoc_bss_dtim_period
;
sinfo
->
bss_param
.
beacon_interval
=
ar
->
assoc_bss_beacon_int
;
}
return
0
;
return
0
;
}
}
...
@@ -1455,6 +1409,402 @@ static int ath6kl_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
...
@@ -1455,6 +1409,402 @@ static int ath6kl_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM
static
int
ar6k_cfg80211_suspend
(
struct
wiphy
*
wiphy
,
struct
cfg80211_wowlan
*
wow
)
{
struct
ath6kl
*
ar
=
wiphy_priv
(
wiphy
);
return
ath6kl_hif_suspend
(
ar
);
}
#endif
static
int
ath6kl_set_channel
(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
,
struct
ieee80211_channel
*
chan
,
enum
nl80211_channel_type
channel_type
)
{
struct
ath6kl
*
ar
=
ath6kl_priv
(
dev
);
if
(
!
ath6kl_cfg80211_ready
(
ar
))
return
-
EIO
;
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"%s: center_freq=%u hw_value=%u
\n
"
,
__func__
,
chan
->
center_freq
,
chan
->
hw_value
);
ar
->
next_chan
=
chan
->
center_freq
;
return
0
;
}
static
bool
ath6kl_is_p2p_ie
(
const
u8
*
pos
)
{
return
pos
[
0
]
==
WLAN_EID_VENDOR_SPECIFIC
&&
pos
[
1
]
>=
4
&&
pos
[
2
]
==
0x50
&&
pos
[
3
]
==
0x6f
&&
pos
[
4
]
==
0x9a
&&
pos
[
5
]
==
0x09
;
}
static
int
ath6kl_set_ap_probe_resp_ies
(
struct
ath6kl
*
ar
,
const
u8
*
ies
,
size_t
ies_len
)
{
const
u8
*
pos
;
u8
*
buf
=
NULL
;
size_t
len
=
0
;
int
ret
;
/*
* Filter out P2P IE(s) since they will be included depending on
* the Probe Request frame in ath6kl_send_go_probe_resp().
*/
if
(
ies
&&
ies_len
)
{
buf
=
kmalloc
(
ies_len
,
GFP_KERNEL
);
if
(
buf
==
NULL
)
return
-
ENOMEM
;
pos
=
ies
;
while
(
pos
+
1
<
ies
+
ies_len
)
{
if
(
pos
+
2
+
pos
[
1
]
>
ies
+
ies_len
)
break
;
if
(
!
ath6kl_is_p2p_ie
(
pos
))
{
memcpy
(
buf
+
len
,
pos
,
2
+
pos
[
1
]);
len
+=
2
+
pos
[
1
];
}
pos
+=
2
+
pos
[
1
];
}
}
ret
=
ath6kl_wmi_set_appie_cmd
(
ar
->
wmi
,
WMI_FRAME_PROBE_RESP
,
buf
,
len
);
kfree
(
buf
);
return
ret
;
}
static
int
ath6kl_ap_beacon
(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
,
struct
beacon_parameters
*
info
,
bool
add
)
{
struct
ath6kl
*
ar
=
ath6kl_priv
(
dev
);
struct
ieee80211_mgmt
*
mgmt
;
u8
*
ies
;
int
ies_len
;
struct
wmi_connect_cmd
p
;
int
res
;
int
i
;
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"%s: add=%d
\n
"
,
__func__
,
add
);
if
(
!
ath6kl_cfg80211_ready
(
ar
))
return
-
EIO
;
if
(
ar
->
next_mode
!=
AP_NETWORK
)
return
-
EOPNOTSUPP
;
if
(
info
->
beacon_ies
)
{
res
=
ath6kl_wmi_set_appie_cmd
(
ar
->
wmi
,
WMI_FRAME_BEACON
,
info
->
beacon_ies
,
info
->
beacon_ies_len
);
if
(
res
)
return
res
;
}
if
(
info
->
proberesp_ies
)
{
res
=
ath6kl_set_ap_probe_resp_ies
(
ar
,
info
->
proberesp_ies
,
info
->
proberesp_ies_len
);
if
(
res
)
return
res
;
}
if
(
info
->
assocresp_ies
)
{
res
=
ath6kl_wmi_set_appie_cmd
(
ar
->
wmi
,
WMI_FRAME_ASSOC_RESP
,
info
->
assocresp_ies
,
info
->
assocresp_ies_len
);
if
(
res
)
return
res
;
}
if
(
!
add
)
return
0
;
ar
->
ap_mode_bkey
.
valid
=
false
;
/* TODO:
* info->interval
* info->dtim_period
*/
if
(
info
->
head
==
NULL
)
return
-
EINVAL
;
mgmt
=
(
struct
ieee80211_mgmt
*
)
info
->
head
;
ies
=
mgmt
->
u
.
beacon
.
variable
;
if
(
ies
>
info
->
head
+
info
->
head_len
)
return
-
EINVAL
;
ies_len
=
info
->
head
+
info
->
head_len
-
ies
;
if
(
info
->
ssid
==
NULL
)
return
-
EINVAL
;
memcpy
(
ar
->
ssid
,
info
->
ssid
,
info
->
ssid_len
);
ar
->
ssid_len
=
info
->
ssid_len
;
if
(
info
->
hidden_ssid
!=
NL80211_HIDDEN_SSID_NOT_IN_USE
)
return
-
EOPNOTSUPP
;
/* TODO */
ar
->
dot11_auth_mode
=
OPEN_AUTH
;
memset
(
&
p
,
0
,
sizeof
(
p
));
for
(
i
=
0
;
i
<
info
->
crypto
.
n_akm_suites
;
i
++
)
{
switch
(
info
->
crypto
.
akm_suites
[
i
])
{
case
WLAN_AKM_SUITE_8021X
:
if
(
info
->
crypto
.
wpa_versions
&
NL80211_WPA_VERSION_1
)
p
.
auth_mode
|=
WPA_AUTH
;
if
(
info
->
crypto
.
wpa_versions
&
NL80211_WPA_VERSION_2
)
p
.
auth_mode
|=
WPA2_AUTH
;
break
;
case
WLAN_AKM_SUITE_PSK
:
if
(
info
->
crypto
.
wpa_versions
&
NL80211_WPA_VERSION_1
)
p
.
auth_mode
|=
WPA_PSK_AUTH
;
if
(
info
->
crypto
.
wpa_versions
&
NL80211_WPA_VERSION_2
)
p
.
auth_mode
|=
WPA2_PSK_AUTH
;
break
;
}
}
if
(
p
.
auth_mode
==
0
)
p
.
auth_mode
=
NONE_AUTH
;
ar
->
auth_mode
=
p
.
auth_mode
;
for
(
i
=
0
;
i
<
info
->
crypto
.
n_ciphers_pairwise
;
i
++
)
{
switch
(
info
->
crypto
.
ciphers_pairwise
[
i
])
{
case
WLAN_CIPHER_SUITE_WEP40
:
case
WLAN_CIPHER_SUITE_WEP104
:
p
.
prwise_crypto_type
|=
WEP_CRYPT
;
break
;
case
WLAN_CIPHER_SUITE_TKIP
:
p
.
prwise_crypto_type
|=
TKIP_CRYPT
;
break
;
case
WLAN_CIPHER_SUITE_CCMP
:
p
.
prwise_crypto_type
|=
AES_CRYPT
;
break
;
}
}
if
(
p
.
prwise_crypto_type
==
0
)
{
p
.
prwise_crypto_type
=
NONE_CRYPT
;
ath6kl_set_cipher
(
ar
,
0
,
true
);
}
else
if
(
info
->
crypto
.
n_ciphers_pairwise
==
1
)
ath6kl_set_cipher
(
ar
,
info
->
crypto
.
ciphers_pairwise
[
0
],
true
);
switch
(
info
->
crypto
.
cipher_group
)
{
case
WLAN_CIPHER_SUITE_WEP40
:
case
WLAN_CIPHER_SUITE_WEP104
:
p
.
grp_crypto_type
=
WEP_CRYPT
;
break
;
case
WLAN_CIPHER_SUITE_TKIP
:
p
.
grp_crypto_type
=
TKIP_CRYPT
;
break
;
case
WLAN_CIPHER_SUITE_CCMP
:
p
.
grp_crypto_type
=
AES_CRYPT
;
break
;
default:
p
.
grp_crypto_type
=
NONE_CRYPT
;
break
;
}
ath6kl_set_cipher
(
ar
,
info
->
crypto
.
cipher_group
,
false
);
p
.
nw_type
=
AP_NETWORK
;
ar
->
nw_type
=
ar
->
next_mode
;
p
.
ssid_len
=
ar
->
ssid_len
;
memcpy
(
p
.
ssid
,
ar
->
ssid
,
ar
->
ssid_len
);
p
.
dot11_auth_mode
=
ar
->
dot11_auth_mode
;
p
.
ch
=
cpu_to_le16
(
ar
->
next_chan
);
res
=
ath6kl_wmi_ap_profile_commit
(
ar
->
wmi
,
&
p
);
if
(
res
<
0
)
return
res
;
return
0
;
}
static
int
ath6kl_add_beacon
(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
,
struct
beacon_parameters
*
info
)
{
return
ath6kl_ap_beacon
(
wiphy
,
dev
,
info
,
true
);
}
static
int
ath6kl_set_beacon
(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
,
struct
beacon_parameters
*
info
)
{
return
ath6kl_ap_beacon
(
wiphy
,
dev
,
info
,
false
);
}
static
int
ath6kl_del_beacon
(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
)
{
struct
ath6kl
*
ar
=
ath6kl_priv
(
dev
);
if
(
ar
->
nw_type
!=
AP_NETWORK
)
return
-
EOPNOTSUPP
;
if
(
!
test_bit
(
CONNECTED
,
&
ar
->
flag
))
return
-
ENOTCONN
;
ath6kl_wmi_disconnect_cmd
(
ar
->
wmi
);
clear_bit
(
CONNECTED
,
&
ar
->
flag
);
return
0
;
}
static
int
ath6kl_change_station
(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
,
u8
*
mac
,
struct
station_parameters
*
params
)
{
struct
ath6kl
*
ar
=
ath6kl_priv
(
dev
);
if
(
ar
->
nw_type
!=
AP_NETWORK
)
return
-
EOPNOTSUPP
;
/* Use this only for authorizing/unauthorizing a station */
if
(
!
(
params
->
sta_flags_mask
&
BIT
(
NL80211_STA_FLAG_AUTHORIZED
)))
return
-
EOPNOTSUPP
;
if
(
params
->
sta_flags_set
&
BIT
(
NL80211_STA_FLAG_AUTHORIZED
))
return
ath6kl_wmi_ap_set_mlme
(
ar
->
wmi
,
WMI_AP_MLME_AUTHORIZE
,
mac
,
0
);
return
ath6kl_wmi_ap_set_mlme
(
ar
->
wmi
,
WMI_AP_MLME_UNAUTHORIZE
,
mac
,
0
);
}
static
int
ath6kl_remain_on_channel
(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
,
struct
ieee80211_channel
*
chan
,
enum
nl80211_channel_type
channel_type
,
unsigned
int
duration
,
u64
*
cookie
)
{
struct
ath6kl
*
ar
=
ath6kl_priv
(
dev
);
/* TODO: if already pending or ongoing remain-on-channel,
* return -EBUSY */
*
cookie
=
1
;
/* only a single pending request is supported */
return
ath6kl_wmi_remain_on_chnl_cmd
(
ar
->
wmi
,
chan
->
center_freq
,
duration
);
}
static
int
ath6kl_cancel_remain_on_channel
(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
,
u64
cookie
)
{
struct
ath6kl
*
ar
=
ath6kl_priv
(
dev
);
if
(
cookie
!=
1
)
return
-
ENOENT
;
return
ath6kl_wmi_cancel_remain_on_chnl_cmd
(
ar
->
wmi
);
}
static
int
ath6kl_send_go_probe_resp
(
struct
ath6kl
*
ar
,
const
u8
*
buf
,
size_t
len
,
unsigned
int
freq
)
{
const
u8
*
pos
;
u8
*
p2p
;
int
p2p_len
;
int
ret
;
const
struct
ieee80211_mgmt
*
mgmt
;
mgmt
=
(
const
struct
ieee80211_mgmt
*
)
buf
;
/* Include P2P IE(s) from the frame generated in user space. */
p2p
=
kmalloc
(
len
,
GFP_KERNEL
);
if
(
p2p
==
NULL
)
return
-
ENOMEM
;
p2p_len
=
0
;
pos
=
mgmt
->
u
.
probe_resp
.
variable
;
while
(
pos
+
1
<
buf
+
len
)
{
if
(
pos
+
2
+
pos
[
1
]
>
buf
+
len
)
break
;
if
(
ath6kl_is_p2p_ie
(
pos
))
{
memcpy
(
p2p
+
p2p_len
,
pos
,
2
+
pos
[
1
]);
p2p_len
+=
2
+
pos
[
1
];
}
pos
+=
2
+
pos
[
1
];
}
ret
=
ath6kl_wmi_send_probe_response_cmd
(
ar
->
wmi
,
freq
,
mgmt
->
da
,
p2p
,
p2p_len
);
kfree
(
p2p
);
return
ret
;
}
static
int
ath6kl_mgmt_tx
(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
,
struct
ieee80211_channel
*
chan
,
bool
offchan
,
enum
nl80211_channel_type
channel_type
,
bool
channel_type_valid
,
unsigned
int
wait
,
const
u8
*
buf
,
size_t
len
,
u64
*
cookie
)
{
struct
ath6kl
*
ar
=
ath6kl_priv
(
dev
);
u32
id
;
const
struct
ieee80211_mgmt
*
mgmt
;
mgmt
=
(
const
struct
ieee80211_mgmt
*
)
buf
;
if
(
buf
+
len
>=
mgmt
->
u
.
probe_resp
.
variable
&&
ar
->
nw_type
==
AP_NETWORK
&&
test_bit
(
CONNECTED
,
&
ar
->
flag
)
&&
ieee80211_is_probe_resp
(
mgmt
->
frame_control
))
{
/*
* Send Probe Response frame in AP mode using a separate WMI
* command to allow the target to fill in the generic IEs.
*/
*
cookie
=
0
;
/* TX status not supported */
return
ath6kl_send_go_probe_resp
(
ar
,
buf
,
len
,
chan
->
center_freq
);
}
id
=
ar
->
send_action_id
++
;
if
(
id
==
0
)
{
/*
* 0 is a reserved value in the WMI command and shall not be
* used for the command.
*/
id
=
ar
->
send_action_id
++
;
}
*
cookie
=
id
;
return
ath6kl_wmi_send_action_cmd
(
ar
->
wmi
,
id
,
chan
->
center_freq
,
wait
,
buf
,
len
);
}
static
void
ath6kl_mgmt_frame_register
(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
,
u16
frame_type
,
bool
reg
)
{
struct
ath6kl
*
ar
=
ath6kl_priv
(
dev
);
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"%s: frame_type=0x%x reg=%d
\n
"
,
__func__
,
frame_type
,
reg
);
if
(
frame_type
==
IEEE80211_STYPE_PROBE_REQ
)
{
/*
* Note: This notification callback is not allowed to sleep, so
* we cannot send WMI_PROBE_REQ_REPORT_CMD here. Instead, we
* hardcode target to report Probe Request frames all the time.
*/
ar
->
probe_req_report
=
reg
;
}
}
static
const
struct
ieee80211_txrx_stypes
ath6kl_mgmt_stypes
[
NUM_NL80211_IFTYPES
]
=
{
[
NL80211_IFTYPE_STATION
]
=
{
.
tx
=
BIT
(
IEEE80211_STYPE_ACTION
>>
4
)
|
BIT
(
IEEE80211_STYPE_PROBE_RESP
>>
4
),
.
rx
=
BIT
(
IEEE80211_STYPE_ACTION
>>
4
)
|
BIT
(
IEEE80211_STYPE_PROBE_REQ
>>
4
)
},
[
NL80211_IFTYPE_P2P_CLIENT
]
=
{
.
tx
=
BIT
(
IEEE80211_STYPE_ACTION
>>
4
)
|
BIT
(
IEEE80211_STYPE_PROBE_RESP
>>
4
),
.
rx
=
BIT
(
IEEE80211_STYPE_ACTION
>>
4
)
|
BIT
(
IEEE80211_STYPE_PROBE_REQ
>>
4
)
},
[
NL80211_IFTYPE_P2P_GO
]
=
{
.
tx
=
BIT
(
IEEE80211_STYPE_ACTION
>>
4
)
|
BIT
(
IEEE80211_STYPE_PROBE_RESP
>>
4
),
.
rx
=
BIT
(
IEEE80211_STYPE_ACTION
>>
4
)
|
BIT
(
IEEE80211_STYPE_PROBE_REQ
>>
4
)
},
};
static
struct
cfg80211_ops
ath6kl_cfg80211_ops
=
{
static
struct
cfg80211_ops
ath6kl_cfg80211_ops
=
{
.
change_virtual_intf
=
ath6kl_cfg80211_change_iface
,
.
change_virtual_intf
=
ath6kl_cfg80211_change_iface
,
.
scan
=
ath6kl_cfg80211_scan
,
.
scan
=
ath6kl_cfg80211_scan
,
...
@@ -1474,12 +1824,26 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = {
...
@@ -1474,12 +1824,26 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = {
.
set_pmksa
=
ath6kl_set_pmksa
,
.
set_pmksa
=
ath6kl_set_pmksa
,
.
del_pmksa
=
ath6kl_del_pmksa
,
.
del_pmksa
=
ath6kl_del_pmksa
,
.
flush_pmksa
=
ath6kl_flush_pmksa
,
.
flush_pmksa
=
ath6kl_flush_pmksa
,
CFG80211_TESTMODE_CMD
(
ath6kl_tm_cmd
)
#ifdef CONFIG_PM
.
suspend
=
ar6k_cfg80211_suspend
,
#endif
.
set_channel
=
ath6kl_set_channel
,
.
add_beacon
=
ath6kl_add_beacon
,
.
set_beacon
=
ath6kl_set_beacon
,
.
del_beacon
=
ath6kl_del_beacon
,
.
change_station
=
ath6kl_change_station
,
.
remain_on_channel
=
ath6kl_remain_on_channel
,
.
cancel_remain_on_channel
=
ath6kl_cancel_remain_on_channel
,
.
mgmt_tx
=
ath6kl_mgmt_tx
,
.
mgmt_frame_register
=
ath6kl_mgmt_frame_register
,
};
};
struct
wireless_dev
*
ath6kl_cfg80211_init
(
struct
device
*
dev
)
struct
wireless_dev
*
ath6kl_cfg80211_init
(
struct
device
*
dev
)
{
{
int
ret
=
0
;
int
ret
=
0
;
struct
wireless_dev
*
wdev
;
struct
wireless_dev
*
wdev
;
struct
ath6kl
*
ar
;
wdev
=
kzalloc
(
sizeof
(
struct
wireless_dev
),
GFP_KERNEL
);
wdev
=
kzalloc
(
sizeof
(
struct
wireless_dev
),
GFP_KERNEL
);
if
(
!
wdev
)
{
if
(
!
wdev
)
{
...
@@ -1495,13 +1859,25 @@ struct wireless_dev *ath6kl_cfg80211_init(struct device *dev)
...
@@ -1495,13 +1859,25 @@ struct wireless_dev *ath6kl_cfg80211_init(struct device *dev)
return
NULL
;
return
NULL
;
}
}
ar
=
wiphy_priv
(
wdev
->
wiphy
);
ar
->
p2p
=
!!
ath6kl_p2p
;
wdev
->
wiphy
->
mgmt_stypes
=
ath6kl_mgmt_stypes
;
wdev
->
wiphy
->
max_remain_on_channel_duration
=
5000
;
/* set device pointer for wiphy */
/* set device pointer for wiphy */
set_wiphy_dev
(
wdev
->
wiphy
,
dev
);
set_wiphy_dev
(
wdev
->
wiphy
,
dev
);
wdev
->
wiphy
->
interface_modes
=
BIT
(
NL80211_IFTYPE_STATION
)
|
wdev
->
wiphy
->
interface_modes
=
BIT
(
NL80211_IFTYPE_STATION
)
|
BIT
(
NL80211_IFTYPE_ADHOC
);
BIT
(
NL80211_IFTYPE_ADHOC
)
|
BIT
(
NL80211_IFTYPE_AP
);
if
(
ar
->
p2p
)
{
wdev
->
wiphy
->
interface_modes
|=
BIT
(
NL80211_IFTYPE_P2P_GO
)
|
BIT
(
NL80211_IFTYPE_P2P_CLIENT
);
}
/* max num of ssids that can be probed during scanning */
/* max num of ssids that can be probed during scanning */
wdev
->
wiphy
->
max_scan_ssids
=
MAX_PROBED_SSID_INDEX
;
wdev
->
wiphy
->
max_scan_ssids
=
MAX_PROBED_SSID_INDEX
;
wdev
->
wiphy
->
max_scan_ie_len
=
1000
;
/* FIX: what is correct limit? */
wdev
->
wiphy
->
bands
[
IEEE80211_BAND_2GHZ
]
=
&
ath6kl_band_2ghz
;
wdev
->
wiphy
->
bands
[
IEEE80211_BAND_2GHZ
]
=
&
ath6kl_band_2ghz
;
wdev
->
wiphy
->
bands
[
IEEE80211_BAND_5GHZ
]
=
&
ath6kl_band_5ghz
;
wdev
->
wiphy
->
bands
[
IEEE80211_BAND_5GHZ
]
=
&
ath6kl_band_5ghz
;
wdev
->
wiphy
->
signal_type
=
CFG80211_SIGNAL_TYPE_MBM
;
wdev
->
wiphy
->
signal_type
=
CFG80211_SIGNAL_TYPE_MBM
;
...
...
drivers/net/wireless/ath/ath6kl/common.h
View file @
a5abbcb2
...
@@ -75,94 +75,11 @@ enum crypto_type {
...
@@ -75,94 +75,11 @@ enum crypto_type {
AES_CRYPT
=
0x08
,
AES_CRYPT
=
0x08
,
};
};
#define ATH6KL_NODE_HASHSIZE 32
/* simple hash is enough for variation of macaddr */
#define ATH6KL_NODE_HASH(addr) \
(((const u8 *)(addr))[ETH_ALEN - 1] % \
ATH6KL_NODE_HASHSIZE)
/*
* Table of ath6kl_node instances. Each ieee80211com
* has at least one for holding the scan candidates.
* When operating as an access point or in ibss mode there
* is a second table for associated stations or neighbors.
*/
struct
ath6kl_node_table
{
spinlock_t
nt_nodelock
;
/* on node table */
struct
bss
*
nt_node_first
;
/* information of all nodes */
struct
bss
*
nt_node_last
;
/* information of all nodes */
struct
bss
*
nt_hash
[
ATH6KL_NODE_HASHSIZE
];
const
char
*
nt_name
;
/* for debugging */
u32
nt_node_age
;
/* node aging time */
};
#define WLAN_NODE_INACT_TIMEOUT_MSEC 120000
#define WLAN_NODE_INACT_CNT 4
struct
ath6kl_common_ie
{
u16
ie_chan
;
u8
*
ie_tstamp
;
u8
*
ie_ssid
;
u8
*
ie_rates
;
u8
*
ie_xrates
;
u8
*
ie_country
;
u8
*
ie_wpa
;
u8
*
ie_rsn
;
u8
*
ie_wmm
;
u8
*
ie_ath
;
u16
ie_capInfo
;
u16
ie_beaconInt
;
u8
*
ie_tim
;
u8
*
ie_chswitch
;
u8
ie_erp
;
u8
*
ie_wsc
;
u8
*
ie_htcap
;
u8
*
ie_htop
;
};
struct
bss
{
u8
ni_macaddr
[
ETH_ALEN
];
u8
ni_snr
;
s16
ni_rssi
;
struct
bss
*
ni_list_next
;
struct
bss
*
ni_list_prev
;
struct
bss
*
ni_hash_next
;
struct
bss
*
ni_hash_prev
;
struct
ath6kl_common_ie
ni_cie
;
u8
*
ni_buf
;
u16
ni_framelen
;
struct
ath6kl_node_table
*
ni_table
;
u32
ni_refcnt
;
u32
ni_tstamp
;
u32
ni_actcnt
;
};
struct
htc_endpoint_credit_dist
;
struct
htc_endpoint_credit_dist
;
struct
ath6kl
;
struct
ath6kl
;
enum
htc_credit_dist_reason
;
enum
htc_credit_dist_reason
;
struct
htc_credit_state_info
;
struct
htc_credit_state_info
;
struct
bss
*
wlan_node_alloc
(
int
wh_size
);
void
wlan_node_free
(
struct
bss
*
ni
);
void
wlan_setup_node
(
struct
ath6kl_node_table
*
nt
,
struct
bss
*
ni
,
const
u8
*
mac_addr
);
struct
bss
*
wlan_find_node
(
struct
ath6kl_node_table
*
nt
,
const
u8
*
mac_addr
);
void
wlan_node_reclaim
(
struct
ath6kl_node_table
*
nt
,
struct
bss
*
ni
);
void
wlan_free_allnodes
(
struct
ath6kl_node_table
*
nt
);
void
wlan_iterate_nodes
(
struct
ath6kl_node_table
*
nt
,
void
*
arg
);
void
wlan_node_table_init
(
struct
ath6kl_node_table
*
nt
);
void
wlan_node_table_cleanup
(
struct
ath6kl_node_table
*
nt
);
void
wlan_refresh_inactive_nodes
(
struct
ath6kl
*
ar
);
struct
bss
*
wlan_find_ssid_node
(
struct
ath6kl_node_table
*
nt
,
u8
*
ssid
,
u32
ssid_len
,
bool
is_wpa2
,
bool
match_ssid
);
void
wlan_node_return
(
struct
ath6kl_node_table
*
nt
,
struct
bss
*
ni
);
int
ath6k_setup_credit_dist
(
void
*
htc_handle
,
int
ath6k_setup_credit_dist
(
void
*
htc_handle
,
struct
htc_credit_state_info
*
cred_info
);
struct
htc_credit_state_info
*
cred_info
);
void
ath6k_credit_distribute
(
struct
htc_credit_state_info
*
cred_inf
,
void
ath6k_credit_distribute
(
struct
htc_credit_state_info
*
cred_inf
,
...
...
drivers/net/wireless/ath/ath6kl/core.h
View file @
a5abbcb2
...
@@ -21,10 +21,12 @@
...
@@ -21,10 +21,12 @@
#include <linux/rtnetlink.h>
#include <linux/rtnetlink.h>
#include <linux/firmware.h>
#include <linux/firmware.h>
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/circ_buf.h>
#include <net/cfg80211.h>
#include <net/cfg80211.h>
#include "htc.h"
#include "htc.h"
#include "wmi.h"
#include "wmi.h"
#include "bmi.h"
#include "bmi.h"
#include "target.h"
#define MAX_ATH6KL 1
#define MAX_ATH6KL 1
#define ATH6KL_MAX_RX_BUFFERS 16
#define ATH6KL_MAX_RX_BUFFERS 16
...
@@ -42,6 +44,9 @@
...
@@ -42,6 +44,9 @@
#define ATH6KL_MAX_ENDPOINTS 4
#define ATH6KL_MAX_ENDPOINTS 4
#define MAX_NODE_NUM 15
#define MAX_NODE_NUM 15
/* Extra bytes for htc header alignment */
#define ATH6KL_HTC_ALIGN_BYTES 3
/* MAX_HI_COOKIE_NUM are reserved for high priority traffic */
/* MAX_HI_COOKIE_NUM are reserved for high priority traffic */
#define MAX_DEF_COOKIE_NUM 180
#define MAX_DEF_COOKIE_NUM 180
#define MAX_HI_COOKIE_NUM 18
/* 10% of MAX_COOKIE_NUM */
#define MAX_HI_COOKIE_NUM 18
/* 10% of MAX_COOKIE_NUM */
...
@@ -53,6 +58,35 @@
...
@@ -53,6 +58,35 @@
#define A_DEFAULT_LISTEN_INTERVAL 100
#define A_DEFAULT_LISTEN_INTERVAL 100
#define A_MAX_WOW_LISTEN_INTERVAL 1000
#define A_MAX_WOW_LISTEN_INTERVAL 1000
/* includes also the null byte */
#define ATH6KL_FIRMWARE_MAGIC "QCA-ATH6KL"
enum
ath6kl_fw_ie_type
{
ATH6KL_FW_IE_FW_VERSION
=
0
,
ATH6KL_FW_IE_TIMESTAMP
=
1
,
ATH6KL_FW_IE_OTP_IMAGE
=
2
,
ATH6KL_FW_IE_FW_IMAGE
=
3
,
ATH6KL_FW_IE_PATCH_IMAGE
=
4
,
ATH6KL_FW_IE_RESERVED_RAM_SIZE
=
5
,
ATH6KL_FW_IE_CAPABILITIES
=
6
,
ATH6KL_FW_IE_PATCH_ADDR
=
7
,
};
enum
ath6kl_fw_capability
{
ATH6KL_FW_CAPABILITY_HOST_P2P
=
0
,
/* this needs to be last */
ATH6KL_FW_CAPABILITY_MAX
,
};
#define ATH6KL_CAPABILITY_LEN (ALIGN(ATH6KL_FW_CAPABILITY_MAX, 32) / 32)
struct
ath6kl_fw_ie
{
__le32
id
;
__le32
len
;
u8
data
[
0
];
};
/* AR6003 1.0 definitions */
/* AR6003 1.0 definitions */
#define AR6003_REV1_VERSION 0x300002ba
#define AR6003_REV1_VERSION 0x300002ba
...
@@ -61,7 +95,9 @@
...
@@ -61,7 +95,9 @@
#define AR6003_REV2_PATCH_DOWNLOAD_ADDRESS 0x57e910
#define AR6003_REV2_PATCH_DOWNLOAD_ADDRESS 0x57e910
#define AR6003_REV2_OTP_FILE "ath6k/AR6003/hw2.0/otp.bin.z77"
#define AR6003_REV2_OTP_FILE "ath6k/AR6003/hw2.0/otp.bin.z77"
#define AR6003_REV2_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athwlan.bin.z77"
#define AR6003_REV2_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athwlan.bin.z77"
#define AR6003_REV2_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athtcmd_ram.bin"
#define AR6003_REV2_PATCH_FILE "ath6k/AR6003/hw2.0/data.patch.bin"
#define AR6003_REV2_PATCH_FILE "ath6k/AR6003/hw2.0/data.patch.bin"
#define AR6003_REV2_FIRMWARE_2_FILE "ath6k/AR6003/hw2.0/fw-2.bin"
#define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.bin"
#define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.bin"
#define AR6003_REV2_DEFAULT_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.SD31.bin"
#define AR6003_REV2_DEFAULT_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.SD31.bin"
...
@@ -69,11 +105,21 @@
...
@@ -69,11 +105,21 @@
#define AR6003_REV3_VERSION 0x30000582
#define AR6003_REV3_VERSION 0x30000582
#define AR6003_REV3_OTP_FILE "ath6k/AR6003/hw2.1.1/otp.bin"
#define AR6003_REV3_OTP_FILE "ath6k/AR6003/hw2.1.1/otp.bin"
#define AR6003_REV3_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athwlan.bin"
#define AR6003_REV3_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athwlan.bin"
#define AR6003_REV3_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athtcmd_ram.bin"
#define AR6003_REV3_PATCH_FILE "ath6k/AR6003/hw2.1.1/data.patch.bin"
#define AR6003_REV3_PATCH_FILE "ath6k/AR6003/hw2.1.1/data.patch.bin"
#define AR6003_REV3_FIRMWARE_2_FILE "ath6k/AR6003/hw2.1.1/fw-2.bin"
#define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.bin"
#define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.bin"
#define AR6003_REV3_DEFAULT_BOARD_DATA_FILE \
#define AR6003_REV3_DEFAULT_BOARD_DATA_FILE \
"ath6k/AR6003/hw2.1.1/bdata.SD31.bin"
"ath6k/AR6003/hw2.1.1/bdata.SD31.bin"
/* AR6004 1.0 definitions */
#define AR6004_REV1_VERSION 0x30000623
#define AR6004_REV1_FIRMWARE_FILE "ath6k/AR6004/hw6.1/fw.ram.bin"
#define AR6004_REV1_FIRMWARE_2_FILE "ath6k/AR6004/hw6.1/fw-2.bin"
#define AR6004_REV1_BOARD_DATA_FILE "ath6k/AR6004/hw6.1/bdata.bin"
#define AR6004_REV1_DEFAULT_BOARD_DATA_FILE "ath6k/AR6004/hw6.1/bdata.DB132.bin"
#define AR6004_REV1_EPPING_FIRMWARE_FILE "ath6k/AR6004/hw6.1/endpointping.bin"
/* Per STA data, used in AP mode */
/* Per STA data, used in AP mode */
#define STA_PS_AWAKE BIT(0)
#define STA_PS_AWAKE BIT(0)
#define STA_PS_SLEEP BIT(1)
#define STA_PS_SLEEP BIT(1)
...
@@ -325,26 +371,13 @@ struct ath6kl_mbox_info {
...
@@ -325,26 +371,13 @@ struct ath6kl_mbox_info {
#define ATH6KL_KEY_RECV 0x02
#define ATH6KL_KEY_RECV 0x02
#define ATH6KL_KEY_DEFAULT 0x80
/* default xmit key */
#define ATH6KL_KEY_DEFAULT 0x80
/* default xmit key */
/*
/* Initial group key for AP mode */
* WPA/RSN get/set key request. Specify the key/cipher
* type and whether the key is to be used for sending and/or
* receiving. The key index should be set only when working
* with global keys (use IEEE80211_KEYIX_NONE for ``no index'').
* Otherwise a unicast/pairwise key is specified by the bssid
* (on a station) or mac address (on an ap). They key length
* must include any MIC key data; otherwise it should be no
* more than ATH6KL_KEYBUF_SIZE.
*/
struct
ath6kl_req_key
{
struct
ath6kl_req_key
{
u8
ik_type
;
/* key/cipher type */
bool
valid
;
u8
ik_pad
;
u8
key_index
;
u16
ik_keyix
;
/* key index */
int
key_type
;
u8
ik_keylen
;
/* key length in bytes */
u8
key
[
WLAN_MAX_KEY_LEN
];
u8
ik_flags
;
u8
key_len
;
u8
ik_macaddr
[
ETH_ALEN
];
u64
ik_keyrsc
;
/* key receive sequence counter */
u64
ik_keytsc
;
/* key transmit sequence counter */
u8
ik_keydata
[
ATH6KL_KEYBUF_SIZE
+
ATH6KL_MICBUF_SIZE
];
};
};
/* Flag info */
/* Flag info */
...
@@ -361,6 +394,9 @@ struct ath6kl_req_key {
...
@@ -361,6 +394,9 @@ struct ath6kl_req_key {
#define NETDEV_REGISTERED 10
#define NETDEV_REGISTERED 10
#define SKIP_SCAN 11
#define SKIP_SCAN 11
#define WLAN_ENABLED 12
#define WLAN_ENABLED 12
#define TESTMODE 13
#define CLEAR_BSSFILTER_ON_BEACON 14
#define DTIM_PERIOD_AVAIL 15
struct
ath6kl
{
struct
ath6kl
{
struct
device
*
dev
;
struct
device
*
dev
;
...
@@ -383,7 +419,7 @@ struct ath6kl {
...
@@ -383,7 +419,7 @@ struct ath6kl {
u8
prwise_crypto
;
u8
prwise_crypto
;
u8
prwise_crypto_len
;
u8
prwise_crypto_len
;
u8
grp_crypto
;
u8
grp_crypto
;
u8
grp_crpto_len
;
u8
grp_cr
y
pto_len
;
u8
def_txkey_index
;
u8
def_txkey_index
;
struct
ath6kl_wep_key
wep_key_list
[
WMI_MAX_KEY_INDEX
+
1
];
struct
ath6kl_wep_key
wep_key_list
[
WMI_MAX_KEY_INDEX
+
1
];
u8
bssid
[
ETH_ALEN
];
u8
bssid
[
ETH_ALEN
];
...
@@ -392,6 +428,7 @@ struct ath6kl {
...
@@ -392,6 +428,7 @@ struct ath6kl {
u16
bss_ch
;
u16
bss_ch
;
u16
listen_intvl_b
;
u16
listen_intvl_b
;
u16
listen_intvl_t
;
u16
listen_intvl_t
;
u8
lrssi_roam_threshold
;
struct
ath6kl_version
version
;
struct
ath6kl_version
version
;
u32
target_type
;
u32
target_type
;
u8
tx_pwr
;
u8
tx_pwr
;
...
@@ -432,7 +469,18 @@ struct ath6kl {
...
@@ -432,7 +469,18 @@ struct ath6kl {
enum
wlan_low_pwr_state
wlan_pwr_state
;
enum
wlan_low_pwr_state
wlan_pwr_state
;
struct
wmi_scan_params_cmd
sc_params
;
struct
wmi_scan_params_cmd
sc_params
;
#define AR_MCAST_FILTER_MAC_ADDR_SIZE 4
#define AR_MCAST_FILTER_MAC_ADDR_SIZE 4
u8
auto_auth_stage
;
struct
{
void
*
rx_report
;
size_t
rx_report_len
;
}
tm
;
struct
{
u32
dataset_patch_addr
;
u32
app_load_addr
;
u32
app_start_override_addr
;
u32
board_ext_data_addr
;
u32
reserved_ram_size
;
}
hw
;
u16
conf_flags
;
u16
conf_flags
;
wait_queue_head_t
event_wq
;
wait_queue_head_t
event_wq
;
...
@@ -454,9 +502,35 @@ struct ath6kl {
...
@@ -454,9 +502,35 @@ struct ath6kl {
u8
*
fw_patch
;
u8
*
fw_patch
;
size_t
fw_patch_len
;
size_t
fw_patch_len
;
unsigned
long
fw_capabilities
[
ATH6KL_CAPABILITY_LEN
];
struct
workqueue_struct
*
ath6kl_wq
;
struct
workqueue_struct
*
ath6kl_wq
;
struct
ath6kl_node_table
scan_table
;
struct
dentry
*
debugfs_phy
;
u32
send_action_id
;
bool
probe_req_report
;
u16
next_chan
;
bool
p2p
;
u16
assoc_bss_beacon_int
;
u8
assoc_bss_dtim_period
;
#ifdef CONFIG_ATH6KL_DEBUG
struct
{
struct
circ_buf
fwlog_buf
;
spinlock_t
fwlog_lock
;
void
*
fwlog_tmp
;
u32
fwlog_mask
;
unsigned
int
dbgfs_diag_reg
;
u32
diag_reg_addr_wr
;
u32
diag_reg_val_wr
;
struct
{
unsigned
int
invalid_rate
;
}
war_stats
;
}
debug
;
#endif
/* CONFIG_ATH6KL_DEBUG */
};
};
static
inline
void
*
ath6kl_priv
(
struct
net_device
*
dev
)
static
inline
void
*
ath6kl_priv
(
struct
net_device
*
dev
)
...
@@ -474,6 +548,19 @@ static inline void ath6kl_deposit_credit_to_ep(struct htc_credit_state_info
...
@@ -474,6 +548,19 @@ static inline void ath6kl_deposit_credit_to_ep(struct htc_credit_state_info
cred_info
->
cur_free_credits
-=
credits
;
cred_info
->
cur_free_credits
-=
credits
;
}
}
static
inline
u32
ath6kl_get_hi_item_addr
(
struct
ath6kl
*
ar
,
u32
item_offset
)
{
u32
addr
=
0
;
if
(
ar
->
target_type
==
TARGET_TYPE_AR6003
)
addr
=
ATH6KL_AR6003_HI_START_ADDR
+
item_offset
;
else
if
(
ar
->
target_type
==
TARGET_TYPE_AR6004
)
addr
=
ATH6KL_AR6004_HI_START_ADDR
+
item_offset
;
return
addr
;
}
void
ath6kl_destroy
(
struct
net_device
*
dev
,
unsigned
int
unregister
);
void
ath6kl_destroy
(
struct
net_device
*
dev
,
unsigned
int
unregister
);
int
ath6kl_configure_target
(
struct
ath6kl
*
ar
);
int
ath6kl_configure_target
(
struct
ath6kl
*
ar
);
void
ath6kl_detect_error
(
unsigned
long
ptr
);
void
ath6kl_detect_error
(
unsigned
long
ptr
);
...
@@ -487,9 +574,11 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
...
@@ -487,9 +574,11 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
struct
htc_packet
*
packet
);
struct
htc_packet
*
packet
);
void
ath6kl_stop_txrx
(
struct
ath6kl
*
ar
);
void
ath6kl_stop_txrx
(
struct
ath6kl
*
ar
);
void
ath6kl_cleanup_amsdu_rxbufs
(
struct
ath6kl
*
ar
);
void
ath6kl_cleanup_amsdu_rxbufs
(
struct
ath6kl
*
ar
);
int
ath6kl_access_datadiag
(
struct
ath6kl
*
ar
,
u32
address
,
int
ath6kl_diag_write32
(
struct
ath6kl
*
ar
,
u32
address
,
__le32
value
);
u8
*
data
,
u32
length
,
bool
read
);
int
ath6kl_diag_write
(
struct
ath6kl
*
ar
,
u32
address
,
void
*
data
,
u32
length
);
int
ath6kl_read_reg_diag
(
struct
ath6kl
*
ar
,
u32
*
address
,
u32
*
data
);
int
ath6kl_diag_read32
(
struct
ath6kl
*
ar
,
u32
address
,
u32
*
value
);
int
ath6kl_diag_read
(
struct
ath6kl
*
ar
,
u32
address
,
void
*
data
,
u32
length
);
int
ath6kl_read_fwlogs
(
struct
ath6kl
*
ar
);
void
ath6kl_init_profile_info
(
struct
ath6kl
*
ar
);
void
ath6kl_init_profile_info
(
struct
ath6kl
*
ar
);
void
ath6kl_tx_data_cleanup
(
struct
ath6kl
*
ar
);
void
ath6kl_tx_data_cleanup
(
struct
ath6kl
*
ar
);
void
ath6kl_stop_endpoint
(
struct
net_device
*
dev
,
bool
keep_profile
,
void
ath6kl_stop_endpoint
(
struct
net_device
*
dev
,
bool
keep_profile
,
...
@@ -520,6 +609,10 @@ void ath6kl_connect_event(struct ath6kl *ar, u16 channel,
...
@@ -520,6 +609,10 @@ void ath6kl_connect_event(struct ath6kl *ar, u16 channel,
u16
beacon_int
,
enum
network_type
net_type
,
u16
beacon_int
,
enum
network_type
net_type
,
u8
beacon_ie_len
,
u8
assoc_req_len
,
u8
beacon_ie_len
,
u8
assoc_req_len
,
u8
assoc_resp_len
,
u8
*
assoc_info
);
u8
assoc_resp_len
,
u8
*
assoc_info
);
void
ath6kl_connect_ap_mode_bss
(
struct
ath6kl
*
ar
,
u16
channel
);
void
ath6kl_connect_ap_mode_sta
(
struct
ath6kl
*
ar
,
u16
aid
,
u8
*
mac_addr
,
u8
keymgmt
,
u8
ucipher
,
u8
auth
,
u8
assoc_req_len
,
u8
*
assoc_info
);
void
ath6kl_disconnect_event
(
struct
ath6kl
*
ar
,
u8
reason
,
void
ath6kl_disconnect_event
(
struct
ath6kl
*
ar
,
u8
reason
,
u8
*
bssid
,
u8
assoc_resp_len
,
u8
*
bssid
,
u8
assoc_resp_len
,
u8
*
assoc_info
,
u16
prot_reason_status
);
u8
*
assoc_info
,
u16
prot_reason_status
);
...
@@ -534,11 +627,11 @@ void ath6kl_pspoll_event(struct ath6kl *ar, u8 aid);
...
@@ -534,11 +627,11 @@ void ath6kl_pspoll_event(struct ath6kl *ar, u8 aid);
void
ath6kl_dtimexpiry_event
(
struct
ath6kl
*
ar
);
void
ath6kl_dtimexpiry_event
(
struct
ath6kl
*
ar
);
void
ath6kl_disconnect
(
struct
ath6kl
*
ar
);
void
ath6kl_disconnect
(
struct
ath6kl
*
ar
);
void
ath6kl_deep_sleep_enable
(
struct
ath6kl
*
ar
);
void
aggr_recv_delba_req_evt
(
struct
ath6kl
*
ar
,
u8
tid
);
void
aggr_recv_delba_req_evt
(
struct
ath6kl
*
ar
,
u8
tid
);
void
aggr_recv_addba_req_evt
(
struct
ath6kl
*
ar
,
u8
tid
,
u16
seq_no
,
void
aggr_recv_addba_req_evt
(
struct
ath6kl
*
ar
,
u8
tid
,
u16
seq_no
,
u8
win_sz
);
u8
win_sz
);
void
ath6kl_wakeup_event
(
void
*
dev
);
void
ath6kl_wakeup_event
(
void
*
dev
);
void
ath6kl_target_failure
(
struct
ath6kl
*
ar
);
void
ath6kl_target_failure
(
struct
ath6kl
*
ar
);
void
ath6kl_cfg80211_scan_node
(
struct
wiphy
*
wiphy
,
struct
bss
*
ni
);
#endif
/* CORE_H */
#endif
/* CORE_H */
drivers/net/wireless/ath/ath6kl/debug.c
View file @
a5abbcb2
...
@@ -15,7 +15,26 @@
...
@@ -15,7 +15,26 @@
*/
*/
#include "core.h"
#include "core.h"
#include <linux/circ_buf.h>
#include <linux/fs.h>
#include <linux/vmalloc.h>
#include "debug.h"
#include "debug.h"
#include "target.h"
struct
ath6kl_fwlog_slot
{
__le32
timestamp
;
__le32
length
;
/* max ATH6KL_FWLOG_PAYLOAD_SIZE bytes */
u8
payload
[
0
];
};
#define ATH6KL_FWLOG_SIZE 32768
#define ATH6KL_FWLOG_SLOT_SIZE (sizeof(struct ath6kl_fwlog_slot) + \
ATH6KL_FWLOG_PAYLOAD_SIZE)
#define ATH6KL_FWLOG_VALID_MASK 0x1ffff
int
ath6kl_printk
(
const
char
*
level
,
const
char
*
fmt
,
...)
int
ath6kl_printk
(
const
char
*
level
,
const
char
*
fmt
,
...)
{
{
...
@@ -36,6 +55,27 @@ int ath6kl_printk(const char *level, const char *fmt, ...)
...
@@ -36,6 +55,27 @@ int ath6kl_printk(const char *level, const char *fmt, ...)
}
}
#ifdef CONFIG_ATH6KL_DEBUG
#ifdef CONFIG_ATH6KL_DEBUG
#define REG_OUTPUT_LEN_PER_LINE 25
#define REGTYPE_STR_LEN 100
struct
ath6kl_diag_reg_info
{
u32
reg_start
;
u32
reg_end
;
const
char
*
reg_info
;
};
static
const
struct
ath6kl_diag_reg_info
diag_reg
[]
=
{
{
0x20000
,
0x200fc
,
"General DMA and Rx registers"
},
{
0x28000
,
0x28900
,
"MAC PCU register & keycache"
},
{
0x20800
,
0x20a40
,
"QCU"
},
{
0x21000
,
0x212f0
,
"DCU"
},
{
0x4000
,
0x42e4
,
"RTC"
},
{
0x540000
,
0x540000
+
(
256
*
1024
),
"RAM"
},
{
0x29800
,
0x2B210
,
"Base Band"
},
{
0x1C000
,
0x1C748
,
"Analog"
},
};
void
ath6kl_dump_registers
(
struct
ath6kl_device
*
dev
,
void
ath6kl_dump_registers
(
struct
ath6kl_device
*
dev
,
struct
ath6kl_irq_proc_registers
*
irq_proc_reg
,
struct
ath6kl_irq_proc_registers
*
irq_proc_reg
,
struct
ath6kl_irq_enable_reg
*
irq_enable_reg
)
struct
ath6kl_irq_enable_reg
*
irq_enable_reg
)
...
@@ -147,4 +187,748 @@ void dump_cred_dist_stats(struct htc_target *target)
...
@@ -147,4 +187,748 @@ void dump_cred_dist_stats(struct htc_target *target)
target
->
cred_dist_cntxt
->
cur_free_credits
);
target
->
cred_dist_cntxt
->
cur_free_credits
);
}
}
static
int
ath6kl_debugfs_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
file
->
private_data
=
inode
->
i_private
;
return
0
;
}
void
ath6kl_debug_war
(
struct
ath6kl
*
ar
,
enum
ath6kl_war
war
)
{
switch
(
war
)
{
case
ATH6KL_WAR_INVALID_RATE
:
ar
->
debug
.
war_stats
.
invalid_rate
++
;
break
;
}
}
static
ssize_t
read_file_war_stats
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
ath6kl
*
ar
=
file
->
private_data
;
char
*
buf
;
unsigned
int
len
=
0
,
buf_len
=
1500
;
ssize_t
ret_cnt
;
buf
=
kzalloc
(
buf_len
,
GFP_KERNEL
);
if
(
!
buf
)
return
-
ENOMEM
;
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"
\n
"
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%25s
\n
"
,
"Workaround stats"
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%25s
\n\n
"
,
"================="
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10u
\n
"
,
"Invalid rates"
,
ar
->
debug
.
war_stats
.
invalid_rate
);
if
(
WARN_ON
(
len
>
buf_len
))
len
=
buf_len
;
ret_cnt
=
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
buf
,
len
);
kfree
(
buf
);
return
ret_cnt
;
}
static
const
struct
file_operations
fops_war_stats
=
{
.
read
=
read_file_war_stats
,
.
open
=
ath6kl_debugfs_open
,
.
owner
=
THIS_MODULE
,
.
llseek
=
default_llseek
,
};
static
void
ath6kl_debug_fwlog_add
(
struct
ath6kl
*
ar
,
const
void
*
buf
,
size_t
buf_len
)
{
struct
circ_buf
*
fwlog
=
&
ar
->
debug
.
fwlog_buf
;
size_t
space
;
int
i
;
/* entries must all be equal size */
if
(
WARN_ON
(
buf_len
!=
ATH6KL_FWLOG_SLOT_SIZE
))
return
;
space
=
CIRC_SPACE
(
fwlog
->
head
,
fwlog
->
tail
,
ATH6KL_FWLOG_SIZE
);
if
(
space
<
buf_len
)
/* discard oldest slot */
fwlog
->
tail
=
(
fwlog
->
tail
+
ATH6KL_FWLOG_SLOT_SIZE
)
&
(
ATH6KL_FWLOG_SIZE
-
1
);
for
(
i
=
0
;
i
<
buf_len
;
i
+=
space
)
{
space
=
CIRC_SPACE_TO_END
(
fwlog
->
head
,
fwlog
->
tail
,
ATH6KL_FWLOG_SIZE
);
if
((
size_t
)
space
>
buf_len
-
i
)
space
=
buf_len
-
i
;
memcpy
(
&
fwlog
->
buf
[
fwlog
->
head
],
buf
,
space
);
fwlog
->
head
=
(
fwlog
->
head
+
space
)
&
(
ATH6KL_FWLOG_SIZE
-
1
);
}
}
void
ath6kl_debug_fwlog_event
(
struct
ath6kl
*
ar
,
const
void
*
buf
,
size_t
len
)
{
struct
ath6kl_fwlog_slot
*
slot
=
ar
->
debug
.
fwlog_tmp
;
size_t
slot_len
;
if
(
WARN_ON
(
len
>
ATH6KL_FWLOG_PAYLOAD_SIZE
))
return
;
spin_lock_bh
(
&
ar
->
debug
.
fwlog_lock
);
slot
->
timestamp
=
cpu_to_le32
(
jiffies
);
slot
->
length
=
cpu_to_le32
(
len
);
memcpy
(
slot
->
payload
,
buf
,
len
);
slot_len
=
sizeof
(
*
slot
)
+
len
;
if
(
slot_len
<
ATH6KL_FWLOG_SLOT_SIZE
)
memset
(
slot
->
payload
+
len
,
0
,
ATH6KL_FWLOG_SLOT_SIZE
-
slot_len
);
ath6kl_debug_fwlog_add
(
ar
,
slot
,
ATH6KL_FWLOG_SLOT_SIZE
);
spin_unlock_bh
(
&
ar
->
debug
.
fwlog_lock
);
}
static
bool
ath6kl_debug_fwlog_empty
(
struct
ath6kl
*
ar
)
{
return
CIRC_CNT
(
ar
->
debug
.
fwlog_buf
.
head
,
ar
->
debug
.
fwlog_buf
.
tail
,
ATH6KL_FWLOG_SLOT_SIZE
)
==
0
;
}
static
ssize_t
ath6kl_fwlog_read
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
ath6kl
*
ar
=
file
->
private_data
;
struct
circ_buf
*
fwlog
=
&
ar
->
debug
.
fwlog_buf
;
size_t
len
=
0
,
buf_len
=
count
;
ssize_t
ret_cnt
;
char
*
buf
;
int
ccnt
;
buf
=
vmalloc
(
buf_len
);
if
(
!
buf
)
return
-
ENOMEM
;
/* read undelivered logs from firmware */
ath6kl_read_fwlogs
(
ar
);
spin_lock_bh
(
&
ar
->
debug
.
fwlog_lock
);
while
(
len
<
buf_len
&&
!
ath6kl_debug_fwlog_empty
(
ar
))
{
ccnt
=
CIRC_CNT_TO_END
(
fwlog
->
head
,
fwlog
->
tail
,
ATH6KL_FWLOG_SIZE
);
if
((
size_t
)
ccnt
>
buf_len
-
len
)
ccnt
=
buf_len
-
len
;
memcpy
(
buf
+
len
,
&
fwlog
->
buf
[
fwlog
->
tail
],
ccnt
);
len
+=
ccnt
;
fwlog
->
tail
=
(
fwlog
->
tail
+
ccnt
)
&
(
ATH6KL_FWLOG_SIZE
-
1
);
}
spin_unlock_bh
(
&
ar
->
debug
.
fwlog_lock
);
if
(
WARN_ON
(
len
>
buf_len
))
len
=
buf_len
;
ret_cnt
=
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
buf
,
len
);
vfree
(
buf
);
return
ret_cnt
;
}
static
const
struct
file_operations
fops_fwlog
=
{
.
open
=
ath6kl_debugfs_open
,
.
read
=
ath6kl_fwlog_read
,
.
owner
=
THIS_MODULE
,
.
llseek
=
default_llseek
,
};
static
ssize_t
ath6kl_fwlog_mask_read
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
ath6kl
*
ar
=
file
->
private_data
;
char
buf
[
16
];
int
len
;
len
=
snprintf
(
buf
,
sizeof
(
buf
),
"0x%x
\n
"
,
ar
->
debug
.
fwlog_mask
);
return
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
buf
,
len
);
}
static
ssize_t
ath6kl_fwlog_mask_write
(
struct
file
*
file
,
const
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
ath6kl
*
ar
=
file
->
private_data
;
int
ret
;
ret
=
kstrtou32_from_user
(
user_buf
,
count
,
0
,
&
ar
->
debug
.
fwlog_mask
);
if
(
ret
)
return
ret
;
ret
=
ath6kl_wmi_config_debug_module_cmd
(
ar
->
wmi
,
ATH6KL_FWLOG_VALID_MASK
,
ar
->
debug
.
fwlog_mask
);
if
(
ret
)
return
ret
;
return
count
;
}
static
const
struct
file_operations
fops_fwlog_mask
=
{
.
open
=
ath6kl_debugfs_open
,
.
read
=
ath6kl_fwlog_mask_read
,
.
write
=
ath6kl_fwlog_mask_write
,
.
owner
=
THIS_MODULE
,
.
llseek
=
default_llseek
,
};
static
ssize_t
read_file_tgt_stats
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
ath6kl
*
ar
=
file
->
private_data
;
struct
target_stats
*
tgt_stats
=
&
ar
->
target_stats
;
char
*
buf
;
unsigned
int
len
=
0
,
buf_len
=
1500
;
int
i
;
long
left
;
ssize_t
ret_cnt
;
buf
=
kzalloc
(
buf_len
,
GFP_KERNEL
);
if
(
!
buf
)
return
-
ENOMEM
;
if
(
down_interruptible
(
&
ar
->
sem
))
{
kfree
(
buf
);
return
-
EBUSY
;
}
set_bit
(
STATS_UPDATE_PEND
,
&
ar
->
flag
);
if
(
ath6kl_wmi_get_stats_cmd
(
ar
->
wmi
))
{
up
(
&
ar
->
sem
);
kfree
(
buf
);
return
-
EIO
;
}
left
=
wait_event_interruptible_timeout
(
ar
->
event_wq
,
!
test_bit
(
STATS_UPDATE_PEND
,
&
ar
->
flag
),
WMI_TIMEOUT
);
up
(
&
ar
->
sem
);
if
(
left
<=
0
)
{
kfree
(
buf
);
return
-
ETIMEDOUT
;
}
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"
\n
"
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%25s
\n
"
,
"Target Tx stats"
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%25s
\n\n
"
,
"================="
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"Ucast packets"
,
tgt_stats
->
tx_ucast_pkt
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"Bcast packets"
,
tgt_stats
->
tx_bcast_pkt
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"Ucast byte"
,
tgt_stats
->
tx_ucast_byte
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"Bcast byte"
,
tgt_stats
->
tx_bcast_byte
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"Rts success cnt"
,
tgt_stats
->
tx_rts_success_cnt
);
for
(
i
=
0
;
i
<
4
;
i
++
)
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%18s %d %10llu
\n
"
,
"PER on ac"
,
i
,
tgt_stats
->
tx_pkt_per_ac
[
i
]);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"Error"
,
tgt_stats
->
tx_err
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"Fail count"
,
tgt_stats
->
tx_fail_cnt
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"Retry count"
,
tgt_stats
->
tx_retry_cnt
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"Multi retry cnt"
,
tgt_stats
->
tx_mult_retry_cnt
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"Rts fail cnt"
,
tgt_stats
->
tx_rts_fail_cnt
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%25s %10llu
\n\n
"
,
"TKIP counter measure used"
,
tgt_stats
->
tkip_cnter_measures_invoked
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%25s
\n
"
,
"Target Rx stats"
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%25s
\n
"
,
"================="
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"Ucast packets"
,
tgt_stats
->
rx_ucast_pkt
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10d
\n
"
,
"Ucast Rate"
,
tgt_stats
->
rx_ucast_rate
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"Bcast packets"
,
tgt_stats
->
rx_bcast_pkt
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"Ucast byte"
,
tgt_stats
->
rx_ucast_byte
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"Bcast byte"
,
tgt_stats
->
rx_bcast_byte
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"Fragmented pkt"
,
tgt_stats
->
rx_frgment_pkt
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"Error"
,
tgt_stats
->
rx_err
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"CRC Err"
,
tgt_stats
->
rx_crc_err
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"Key chache miss"
,
tgt_stats
->
rx_key_cache_miss
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"Decrypt Err"
,
tgt_stats
->
rx_decrypt_err
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"Duplicate frame"
,
tgt_stats
->
rx_dupl_frame
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"Tkip Mic failure"
,
tgt_stats
->
tkip_local_mic_fail
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"TKIP format err"
,
tgt_stats
->
tkip_fmt_err
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"CCMP format Err"
,
tgt_stats
->
ccmp_fmt_err
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n\n
"
,
"CCMP Replay Err"
,
tgt_stats
->
ccmp_replays
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%25s
\n
"
,
"Misc Target stats"
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%25s
\n
"
,
"================="
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"Beacon Miss count"
,
tgt_stats
->
cs_bmiss_cnt
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"Num Connects"
,
tgt_stats
->
cs_connect_cnt
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10llu
\n
"
,
"Num disconnects"
,
tgt_stats
->
cs_discon_cnt
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%20s %10d
\n
"
,
"Beacon avg rssi"
,
tgt_stats
->
cs_ave_beacon_rssi
);
if
(
len
>
buf_len
)
len
=
buf_len
;
ret_cnt
=
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
buf
,
len
);
kfree
(
buf
);
return
ret_cnt
;
}
static
const
struct
file_operations
fops_tgt_stats
=
{
.
read
=
read_file_tgt_stats
,
.
open
=
ath6kl_debugfs_open
,
.
owner
=
THIS_MODULE
,
.
llseek
=
default_llseek
,
};
#define print_credit_info(fmt_str, ep_list_field) \
(len += scnprintf(buf + len, buf_len - len, fmt_str, \
ep_list->ep_list_field))
#define CREDIT_INFO_DISPLAY_STRING_LEN 200
#define CREDIT_INFO_LEN 128
static
ssize_t
read_file_credit_dist_stats
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
ath6kl
*
ar
=
file
->
private_data
;
struct
htc_target
*
target
=
ar
->
htc_target
;
struct
htc_endpoint_credit_dist
*
ep_list
;
char
*
buf
;
unsigned
int
buf_len
,
len
=
0
;
ssize_t
ret_cnt
;
buf_len
=
CREDIT_INFO_DISPLAY_STRING_LEN
+
get_queue_depth
(
&
target
->
cred_dist_list
)
*
CREDIT_INFO_LEN
;
buf
=
kzalloc
(
buf_len
,
GFP_KERNEL
);
if
(
!
buf
)
return
-
ENOMEM
;
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%25s%5d
\n
"
,
"Total Avail Credits: "
,
target
->
cred_dist_cntxt
->
total_avail_credits
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%25s%5d
\n
"
,
"Free credits :"
,
target
->
cred_dist_cntxt
->
cur_free_credits
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
" Epid Flags Cred_norm Cred_min Credits Cred_assngd"
" Seek_cred Cred_sz Cred_per_msg Cred_to_dist"
" qdepth
\n
"
);
list_for_each_entry
(
ep_list
,
&
target
->
cred_dist_list
,
list
)
{
print_credit_info
(
" %2d"
,
endpoint
);
print_credit_info
(
"%10x"
,
dist_flags
);
print_credit_info
(
"%8d"
,
cred_norm
);
print_credit_info
(
"%9d"
,
cred_min
);
print_credit_info
(
"%9d"
,
credits
);
print_credit_info
(
"%10d"
,
cred_assngd
);
print_credit_info
(
"%13d"
,
seek_cred
);
print_credit_info
(
"%12d"
,
cred_sz
);
print_credit_info
(
"%9d"
,
cred_per_msg
);
print_credit_info
(
"%14d"
,
cred_to_dist
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%12d
\n
"
,
get_queue_depth
(
&
((
struct
htc_endpoint
*
)
ep_list
->
htc_rsvd
)
->
txq
));
}
if
(
len
>
buf_len
)
len
=
buf_len
;
ret_cnt
=
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
buf
,
len
);
kfree
(
buf
);
return
ret_cnt
;
}
static
const
struct
file_operations
fops_credit_dist_stats
=
{
.
read
=
read_file_credit_dist_stats
,
.
open
=
ath6kl_debugfs_open
,
.
owner
=
THIS_MODULE
,
.
llseek
=
default_llseek
,
};
static
unsigned
long
ath6kl_get_num_reg
(
void
)
{
int
i
;
unsigned
long
n_reg
=
0
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
diag_reg
);
i
++
)
n_reg
=
n_reg
+
(
diag_reg
[
i
].
reg_end
-
diag_reg
[
i
].
reg_start
)
/
4
+
1
;
return
n_reg
;
}
static
bool
ath6kl_dbg_is_diag_reg_valid
(
u32
reg_addr
)
{
int
i
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
diag_reg
);
i
++
)
{
if
(
reg_addr
>=
diag_reg
[
i
].
reg_start
&&
reg_addr
<=
diag_reg
[
i
].
reg_end
)
return
true
;
}
return
false
;
}
static
ssize_t
ath6kl_regread_read
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
ath6kl
*
ar
=
file
->
private_data
;
u8
buf
[
50
];
unsigned
int
len
=
0
;
if
(
ar
->
debug
.
dbgfs_diag_reg
)
len
+=
scnprintf
(
buf
+
len
,
sizeof
(
buf
)
-
len
,
"0x%x
\n
"
,
ar
->
debug
.
dbgfs_diag_reg
);
else
len
+=
scnprintf
(
buf
+
len
,
sizeof
(
buf
)
-
len
,
"All diag registers
\n
"
);
return
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
buf
,
len
);
}
static
ssize_t
ath6kl_regread_write
(
struct
file
*
file
,
const
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
ath6kl
*
ar
=
file
->
private_data
;
u8
buf
[
50
];
unsigned
int
len
;
unsigned
long
reg_addr
;
len
=
min
(
count
,
sizeof
(
buf
)
-
1
);
if
(
copy_from_user
(
buf
,
user_buf
,
len
))
return
-
EFAULT
;
buf
[
len
]
=
'\0'
;
if
(
strict_strtoul
(
buf
,
0
,
&
reg_addr
))
return
-
EINVAL
;
if
((
reg_addr
%
4
)
!=
0
)
return
-
EINVAL
;
if
(
reg_addr
&&
!
ath6kl_dbg_is_diag_reg_valid
(
reg_addr
))
return
-
EINVAL
;
ar
->
debug
.
dbgfs_diag_reg
=
reg_addr
;
return
count
;
}
static
const
struct
file_operations
fops_diag_reg_read
=
{
.
read
=
ath6kl_regread_read
,
.
write
=
ath6kl_regread_write
,
.
open
=
ath6kl_debugfs_open
,
.
owner
=
THIS_MODULE
,
.
llseek
=
default_llseek
,
};
static
int
ath6kl_regdump_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
ath6kl
*
ar
=
inode
->
i_private
;
u8
*
buf
;
unsigned
long
int
reg_len
;
unsigned
int
len
=
0
,
n_reg
;
u32
addr
;
__le32
reg_val
;
int
i
,
status
;
/* Dump all the registers if no register is specified */
if
(
!
ar
->
debug
.
dbgfs_diag_reg
)
n_reg
=
ath6kl_get_num_reg
();
else
n_reg
=
1
;
reg_len
=
n_reg
*
REG_OUTPUT_LEN_PER_LINE
;
if
(
n_reg
>
1
)
reg_len
+=
REGTYPE_STR_LEN
;
buf
=
vmalloc
(
reg_len
);
if
(
!
buf
)
return
-
ENOMEM
;
if
(
n_reg
==
1
)
{
addr
=
ar
->
debug
.
dbgfs_diag_reg
;
status
=
ath6kl_diag_read32
(
ar
,
TARG_VTOP
(
ar
->
target_type
,
addr
),
(
u32
*
)
&
reg_val
);
if
(
status
)
goto
fail_reg_read
;
len
+=
scnprintf
(
buf
+
len
,
reg_len
-
len
,
"0x%06x 0x%08x
\n
"
,
addr
,
le32_to_cpu
(
reg_val
));
goto
done
;
}
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
diag_reg
);
i
++
)
{
len
+=
scnprintf
(
buf
+
len
,
reg_len
-
len
,
"%s
\n
"
,
diag_reg
[
i
].
reg_info
);
for
(
addr
=
diag_reg
[
i
].
reg_start
;
addr
<=
diag_reg
[
i
].
reg_end
;
addr
+=
4
)
{
status
=
ath6kl_diag_read32
(
ar
,
TARG_VTOP
(
ar
->
target_type
,
addr
),
(
u32
*
)
&
reg_val
);
if
(
status
)
goto
fail_reg_read
;
len
+=
scnprintf
(
buf
+
len
,
reg_len
-
len
,
"0x%06x 0x%08x
\n
"
,
addr
,
le32_to_cpu
(
reg_val
));
}
}
done:
file
->
private_data
=
buf
;
return
0
;
fail_reg_read:
ath6kl_warn
(
"Unable to read memory:%u
\n
"
,
addr
);
vfree
(
buf
);
return
-
EIO
;
}
static
ssize_t
ath6kl_regdump_read
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
u8
*
buf
=
file
->
private_data
;
return
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
buf
,
strlen
(
buf
));
}
static
int
ath6kl_regdump_release
(
struct
inode
*
inode
,
struct
file
*
file
)
{
vfree
(
file
->
private_data
);
return
0
;
}
static
const
struct
file_operations
fops_reg_dump
=
{
.
open
=
ath6kl_regdump_open
,
.
read
=
ath6kl_regdump_read
,
.
release
=
ath6kl_regdump_release
,
.
owner
=
THIS_MODULE
,
.
llseek
=
default_llseek
,
};
static
ssize_t
ath6kl_lrssi_roam_write
(
struct
file
*
file
,
const
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
ath6kl
*
ar
=
file
->
private_data
;
unsigned
long
lrssi_roam_threshold
;
char
buf
[
32
];
ssize_t
len
;
len
=
min
(
count
,
sizeof
(
buf
)
-
1
);
if
(
copy_from_user
(
buf
,
user_buf
,
len
))
return
-
EFAULT
;
buf
[
len
]
=
'\0'
;
if
(
strict_strtoul
(
buf
,
0
,
&
lrssi_roam_threshold
))
return
-
EINVAL
;
ar
->
lrssi_roam_threshold
=
lrssi_roam_threshold
;
ath6kl_wmi_set_roam_lrssi_cmd
(
ar
->
wmi
,
ar
->
lrssi_roam_threshold
);
return
count
;
}
static
ssize_t
ath6kl_lrssi_roam_read
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
ath6kl
*
ar
=
file
->
private_data
;
char
buf
[
32
];
unsigned
int
len
;
len
=
snprintf
(
buf
,
sizeof
(
buf
),
"%u
\n
"
,
ar
->
lrssi_roam_threshold
);
return
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
buf
,
len
);
}
static
const
struct
file_operations
fops_lrssi_roam_threshold
=
{
.
read
=
ath6kl_lrssi_roam_read
,
.
write
=
ath6kl_lrssi_roam_write
,
.
open
=
ath6kl_debugfs_open
,
.
owner
=
THIS_MODULE
,
.
llseek
=
default_llseek
,
};
static
ssize_t
ath6kl_regwrite_read
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
ath6kl
*
ar
=
file
->
private_data
;
u8
buf
[
32
];
unsigned
int
len
=
0
;
len
=
scnprintf
(
buf
,
sizeof
(
buf
),
"Addr: 0x%x Val: 0x%x
\n
"
,
ar
->
debug
.
diag_reg_addr_wr
,
ar
->
debug
.
diag_reg_val_wr
);
return
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
buf
,
len
);
}
static
ssize_t
ath6kl_regwrite_write
(
struct
file
*
file
,
const
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
ath6kl
*
ar
=
file
->
private_data
;
char
buf
[
32
];
char
*
sptr
,
*
token
;
unsigned
int
len
=
0
;
u32
reg_addr
,
reg_val
;
len
=
min
(
count
,
sizeof
(
buf
)
-
1
);
if
(
copy_from_user
(
buf
,
user_buf
,
len
))
return
-
EFAULT
;
buf
[
len
]
=
'\0'
;
sptr
=
buf
;
token
=
strsep
(
&
sptr
,
"="
);
if
(
!
token
)
return
-
EINVAL
;
if
(
kstrtou32
(
token
,
0
,
&
reg_addr
))
return
-
EINVAL
;
if
(
!
ath6kl_dbg_is_diag_reg_valid
(
reg_addr
))
return
-
EINVAL
;
if
(
kstrtou32
(
sptr
,
0
,
&
reg_val
))
return
-
EINVAL
;
ar
->
debug
.
diag_reg_addr_wr
=
reg_addr
;
ar
->
debug
.
diag_reg_val_wr
=
reg_val
;
if
(
ath6kl_diag_write32
(
ar
,
ar
->
debug
.
diag_reg_addr_wr
,
cpu_to_le32
(
ar
->
debug
.
diag_reg_val_wr
)))
return
-
EIO
;
return
count
;
}
static
const
struct
file_operations
fops_diag_reg_write
=
{
.
read
=
ath6kl_regwrite_read
,
.
write
=
ath6kl_regwrite_write
,
.
open
=
ath6kl_debugfs_open
,
.
owner
=
THIS_MODULE
,
.
llseek
=
default_llseek
,
};
int
ath6kl_debug_init
(
struct
ath6kl
*
ar
)
{
ar
->
debug
.
fwlog_buf
.
buf
=
vmalloc
(
ATH6KL_FWLOG_SIZE
);
if
(
ar
->
debug
.
fwlog_buf
.
buf
==
NULL
)
return
-
ENOMEM
;
ar
->
debug
.
fwlog_tmp
=
kmalloc
(
ATH6KL_FWLOG_SLOT_SIZE
,
GFP_KERNEL
);
if
(
ar
->
debug
.
fwlog_tmp
==
NULL
)
{
vfree
(
ar
->
debug
.
fwlog_buf
.
buf
);
return
-
ENOMEM
;
}
spin_lock_init
(
&
ar
->
debug
.
fwlog_lock
);
/*
* Actually we are lying here but don't know how to read the mask
* value from the firmware.
*/
ar
->
debug
.
fwlog_mask
=
0
;
ar
->
debugfs_phy
=
debugfs_create_dir
(
"ath6kl"
,
ar
->
wdev
->
wiphy
->
debugfsdir
);
if
(
!
ar
->
debugfs_phy
)
{
vfree
(
ar
->
debug
.
fwlog_buf
.
buf
);
kfree
(
ar
->
debug
.
fwlog_tmp
);
return
-
ENOMEM
;
}
debugfs_create_file
(
"tgt_stats"
,
S_IRUSR
,
ar
->
debugfs_phy
,
ar
,
&
fops_tgt_stats
);
debugfs_create_file
(
"credit_dist_stats"
,
S_IRUSR
,
ar
->
debugfs_phy
,
ar
,
&
fops_credit_dist_stats
);
debugfs_create_file
(
"fwlog"
,
S_IRUSR
,
ar
->
debugfs_phy
,
ar
,
&
fops_fwlog
);
debugfs_create_file
(
"fwlog_mask"
,
S_IRUSR
|
S_IWUSR
,
ar
->
debugfs_phy
,
ar
,
&
fops_fwlog_mask
);
debugfs_create_file
(
"reg_addr"
,
S_IRUSR
|
S_IWUSR
,
ar
->
debugfs_phy
,
ar
,
&
fops_diag_reg_read
);
debugfs_create_file
(
"reg_dump"
,
S_IRUSR
,
ar
->
debugfs_phy
,
ar
,
&
fops_reg_dump
);
debugfs_create_file
(
"lrssi_roam_threshold"
,
S_IRUSR
|
S_IWUSR
,
ar
->
debugfs_phy
,
ar
,
&
fops_lrssi_roam_threshold
);
debugfs_create_file
(
"reg_write"
,
S_IRUSR
|
S_IWUSR
,
ar
->
debugfs_phy
,
ar
,
&
fops_diag_reg_write
);
debugfs_create_file
(
"war_stats"
,
S_IRUSR
,
ar
->
debugfs_phy
,
ar
,
&
fops_war_stats
);
return
0
;
}
void
ath6kl_debug_cleanup
(
struct
ath6kl
*
ar
)
{
vfree
(
ar
->
debug
.
fwlog_buf
.
buf
);
kfree
(
ar
->
debug
.
fwlog_tmp
);
}
#endif
#endif
drivers/net/wireless/ath/ath6kl/debug.h
View file @
a5abbcb2
...
@@ -34,8 +34,12 @@ enum ATH6K_DEBUG_MASK {
...
@@ -34,8 +34,12 @@ enum ATH6K_DEBUG_MASK {
ATH6KL_DBG_TRC
=
BIT
(
11
),
/* generic func tracing */
ATH6KL_DBG_TRC
=
BIT
(
11
),
/* generic func tracing */
ATH6KL_DBG_SCATTER
=
BIT
(
12
),
/* hif scatter tracing */
ATH6KL_DBG_SCATTER
=
BIT
(
12
),
/* hif scatter tracing */
ATH6KL_DBG_WLAN_CFG
=
BIT
(
13
),
/* cfg80211 i/f file tracing */
ATH6KL_DBG_WLAN_CFG
=
BIT
(
13
),
/* cfg80211 i/f file tracing */
ATH6KL_DBG_RAW_BYTES
=
BIT
(
14
),
/* dump tx/rx
and wmi
frames */
ATH6KL_DBG_RAW_BYTES
=
BIT
(
14
),
/* dump tx/rx frames */
ATH6KL_DBG_AGGR
=
BIT
(
15
),
/* aggregation */
ATH6KL_DBG_AGGR
=
BIT
(
15
),
/* aggregation */
ATH6KL_DBG_SDIO
=
BIT
(
16
),
ATH6KL_DBG_SDIO_DUMP
=
BIT
(
17
),
ATH6KL_DBG_BOOT
=
BIT
(
18
),
/* driver init and fw boot */
ATH6KL_DBG_WMI_DUMP
=
BIT
(
19
),
ATH6KL_DBG_ANY
=
0xffffffff
/* enable all logs */
ATH6KL_DBG_ANY
=
0xffffffff
/* enable all logs */
};
};
...
@@ -52,6 +56,10 @@ extern int ath6kl_printk(const char *level, const char *fmt, ...)
...
@@ -52,6 +56,10 @@ extern int ath6kl_printk(const char *level, const char *fmt, ...)
#define AR_DBG_LVL_CHECK(mask) (debug_mask & mask)
#define AR_DBG_LVL_CHECK(mask) (debug_mask & mask)
enum
ath6kl_war
{
ATH6KL_WAR_INVALID_RATE
,
};
#ifdef CONFIG_ATH6KL_DEBUG
#ifdef CONFIG_ATH6KL_DEBUG
#define ath6kl_dbg(mask, fmt, ...) \
#define ath6kl_dbg(mask, fmt, ...) \
({ \
({ \
...
@@ -65,12 +73,14 @@ extern int ath6kl_printk(const char *level, const char *fmt, ...)
...
@@ -65,12 +73,14 @@ extern int ath6kl_printk(const char *level, const char *fmt, ...)
})
})
static
inline
void
ath6kl_dbg_dump
(
enum
ATH6K_DEBUG_MASK
mask
,
static
inline
void
ath6kl_dbg_dump
(
enum
ATH6K_DEBUG_MASK
mask
,
const
char
*
msg
,
const
void
*
buf
,
const
char
*
msg
,
const
char
*
prefix
,
size_t
len
)
const
void
*
buf
,
size_t
len
)
{
{
if
(
debug_mask
&
mask
)
{
if
(
debug_mask
&
mask
)
{
ath6kl_dbg
(
mask
,
"%s
\n
"
,
msg
);
if
(
msg
)
print_hex_dump_bytes
(
""
,
DUMP_PREFIX_OFFSET
,
buf
,
len
);
ath6kl_dbg
(
mask
,
"%s
\n
"
,
msg
);
print_hex_dump_bytes
(
prefix
,
DUMP_PREFIX_OFFSET
,
buf
,
len
);
}
}
}
}
...
@@ -78,6 +88,11 @@ void ath6kl_dump_registers(struct ath6kl_device *dev,
...
@@ -78,6 +88,11 @@ void ath6kl_dump_registers(struct ath6kl_device *dev,
struct
ath6kl_irq_proc_registers
*
irq_proc_reg
,
struct
ath6kl_irq_proc_registers
*
irq_proc_reg
,
struct
ath6kl_irq_enable_reg
*
irq_en_reg
);
struct
ath6kl_irq_enable_reg
*
irq_en_reg
);
void
dump_cred_dist_stats
(
struct
htc_target
*
target
);
void
dump_cred_dist_stats
(
struct
htc_target
*
target
);
void
ath6kl_debug_fwlog_event
(
struct
ath6kl
*
ar
,
const
void
*
buf
,
size_t
len
);
void
ath6kl_debug_war
(
struct
ath6kl
*
ar
,
enum
ath6kl_war
war
);
int
ath6kl_debug_init
(
struct
ath6kl
*
ar
);
void
ath6kl_debug_cleanup
(
struct
ath6kl
*
ar
);
#else
#else
static
inline
int
ath6kl_dbg
(
enum
ATH6K_DEBUG_MASK
dbg_mask
,
static
inline
int
ath6kl_dbg
(
enum
ATH6K_DEBUG_MASK
dbg_mask
,
const
char
*
fmt
,
...)
const
char
*
fmt
,
...)
...
@@ -86,8 +101,8 @@ static inline int ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask,
...
@@ -86,8 +101,8 @@ static inline int ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask,
}
}
static
inline
void
ath6kl_dbg_dump
(
enum
ATH6K_DEBUG_MASK
mask
,
static
inline
void
ath6kl_dbg_dump
(
enum
ATH6K_DEBUG_MASK
mask
,
const
char
*
msg
,
const
void
*
buf
,
const
char
*
msg
,
const
char
*
prefix
,
size_t
len
)
const
void
*
buf
,
size_t
len
)
{
{
}
}
...
@@ -100,6 +115,24 @@ static inline void ath6kl_dump_registers(struct ath6kl_device *dev,
...
@@ -100,6 +115,24 @@ static inline void ath6kl_dump_registers(struct ath6kl_device *dev,
static
inline
void
dump_cred_dist_stats
(
struct
htc_target
*
target
)
static
inline
void
dump_cred_dist_stats
(
struct
htc_target
*
target
)
{
{
}
}
#endif
static
inline
void
ath6kl_debug_fwlog_event
(
struct
ath6kl
*
ar
,
const
void
*
buf
,
size_t
len
)
{
}
static
inline
void
ath6kl_debug_war
(
struct
ath6kl
*
ar
,
enum
ath6kl_war
war
)
{
}
static
inline
int
ath6kl_debug_init
(
struct
ath6kl
*
ar
)
{
return
0
;
}
static
inline
void
ath6kl_debug_cleanup
(
struct
ath6kl
*
ar
)
{
}
#endif
#endif
#endif
drivers/net/wireless/ath/ath6kl/hif-ops.h
View file @
a5abbcb2
...
@@ -69,4 +69,9 @@ static inline void ath6kl_hif_cleanup_scatter(struct ath6kl *ar)
...
@@ -69,4 +69,9 @@ static inline void ath6kl_hif_cleanup_scatter(struct ath6kl *ar)
return
ar
->
hif_ops
->
cleanup_scatter
(
ar
);
return
ar
->
hif_ops
->
cleanup_scatter
(
ar
);
}
}
static
inline
int
ath6kl_hif_suspend
(
struct
ath6kl
*
ar
)
{
return
ar
->
hif_ops
->
suspend
(
ar
);
}
#endif
#endif
drivers/net/wireless/ath/ath6kl/hif.h
View file @
a5abbcb2
...
@@ -202,6 +202,7 @@ struct ath6kl_hif_ops {
...
@@ -202,6 +202,7 @@ struct ath6kl_hif_ops {
int
(
*
scat_req_rw
)
(
struct
ath6kl
*
ar
,
int
(
*
scat_req_rw
)
(
struct
ath6kl
*
ar
,
struct
hif_scatter_req
*
scat_req
);
struct
hif_scatter_req
*
scat_req
);
void
(
*
cleanup_scatter
)(
struct
ath6kl
*
ar
);
void
(
*
cleanup_scatter
)(
struct
ath6kl
*
ar
);
int
(
*
suspend
)(
struct
ath6kl
*
ar
);
};
};
#endif
#endif
drivers/net/wireless/ath/ath6kl/htc.c
View file @
a5abbcb2
...
@@ -22,8 +22,19 @@
...
@@ -22,8 +22,19 @@
#define CALC_TXRX_PADDED_LEN(dev, len) (__ALIGN_MASK((len), (dev)->block_mask))
#define CALC_TXRX_PADDED_LEN(dev, len) (__ALIGN_MASK((len), (dev)->block_mask))
static
void
htc_prep_send_pkt
(
struct
htc_packet
*
packet
,
u8
flags
,
int
ctrl0
,
static
void
ath6kl_htc_tx_buf_align
(
u8
**
buf
,
unsigned
long
len
)
int
ctrl1
)
{
u8
*
align_addr
;
if
(
!
IS_ALIGNED
((
unsigned
long
)
*
buf
,
4
))
{
align_addr
=
PTR_ALIGN
(
*
buf
-
4
,
4
);
memmove
(
align_addr
,
*
buf
,
len
);
*
buf
=
align_addr
;
}
}
static
void
ath6kl_htc_tx_prep_pkt
(
struct
htc_packet
*
packet
,
u8
flags
,
int
ctrl0
,
int
ctrl1
)
{
{
struct
htc_frame_hdr
*
hdr
;
struct
htc_frame_hdr
*
hdr
;
...
@@ -167,7 +178,8 @@ static void htc_async_tx_scat_complete(struct htc_target *target,
...
@@ -167,7 +178,8 @@ static void htc_async_tx_scat_complete(struct htc_target *target,
htc_tx_complete
(
endpoint
,
&
tx_compq
);
htc_tx_complete
(
endpoint
,
&
tx_compq
);
}
}
static
int
htc_issue_send
(
struct
htc_target
*
target
,
struct
htc_packet
*
packet
)
static
int
ath6kl_htc_tx_issue
(
struct
htc_target
*
target
,
struct
htc_packet
*
packet
)
{
{
int
status
;
int
status
;
bool
sync
=
false
;
bool
sync
=
false
;
...
@@ -196,7 +208,7 @@ static int htc_issue_send(struct htc_target *target, struct htc_packet *packet)
...
@@ -196,7 +208,7 @@ static int htc_issue_send(struct htc_target *target, struct htc_packet *packet)
HIF_WR_SYNC_BLOCK_INC
);
HIF_WR_SYNC_BLOCK_INC
);
packet
->
status
=
status
;
packet
->
status
=
status
;
packet
->
buf
+=
HTC_HDR_LENGTH
;
packet
->
buf
+=
HTC_HDR_LENGTH
;
}
else
}
else
status
=
hif_write_async
(
target
->
dev
->
ar
,
status
=
hif_write_async
(
target
->
dev
->
ar
,
target
->
dev
->
ar
->
mbox_info
.
htc_addr
,
target
->
dev
->
ar
->
mbox_info
.
htc_addr
,
...
@@ -265,9 +277,9 @@ static int htc_check_credits(struct htc_target *target,
...
@@ -265,9 +277,9 @@ static int htc_check_credits(struct htc_target *target,
return
0
;
return
0
;
}
}
static
void
htc_tx_pkts_get
(
struct
htc_target
*
target
,
static
void
ath6kl_
htc_tx_pkts_get
(
struct
htc_target
*
target
,
struct
htc_endpoint
*
endpoint
,
struct
htc_endpoint
*
endpoint
,
struct
list_head
*
queue
)
struct
list_head
*
queue
)
{
{
int
req_cred
;
int
req_cred
;
u8
flags
;
u8
flags
;
...
@@ -346,11 +358,11 @@ static int htc_get_credit_padding(unsigned int cred_sz, int *len,
...
@@ -346,11 +358,11 @@ static int htc_get_credit_padding(unsigned int cred_sz, int *len,
return
cred_pad
;
return
cred_pad
;
}
}
static
int
htc_setup_send
_scat_list
(
struct
htc_target
*
target
,
static
int
ath6kl_htc_tx_setup
_scat_list
(
struct
htc_target
*
target
,
struct
htc_endpoint
*
endpoint
,
struct
htc_endpoint
*
endpoint
,
struct
hif_scatter_req
*
scat_req
,
struct
hif_scatter_req
*
scat_req
,
int
n_scat
,
int
n_scat
,
struct
list_head
*
queue
)
struct
list_head
*
queue
)
{
{
struct
htc_packet
*
packet
;
struct
htc_packet
*
packet
;
int
i
,
len
,
rem_scat
,
cred_pad
;
int
i
,
len
,
rem_scat
,
cred_pad
;
...
@@ -370,27 +382,23 @@ static int htc_setup_send_scat_list(struct htc_target *target,
...
@@ -370,27 +382,23 @@ static int htc_setup_send_scat_list(struct htc_target *target,
cred_pad
=
htc_get_credit_padding
(
target
->
tgt_cred_sz
,
cred_pad
=
htc_get_credit_padding
(
target
->
tgt_cred_sz
,
&
len
,
endpoint
);
&
len
,
endpoint
);
if
(
cred_pad
<
0
)
{
if
(
cred_pad
<
0
||
rem_scat
<
len
)
{
status
=
-
EINVAL
;
break
;
}
if
(
rem_scat
<
len
)
{
/* exceeds what we can transfer */
status
=
-
ENOSPC
;
status
=
-
ENOSPC
;
break
;
break
;
}
}
rem_scat
-=
len
;
rem_scat
-=
len
;
/* now remove it from the queue */
/* now remove it from the queue */
packet
=
list_first_entry
(
queue
,
struct
htc_packet
,
list
);
list_del
(
&
packet
->
list
);
list_del
(
&
packet
->
list
);
scat_req
->
scat_list
[
i
].
packet
=
packet
;
scat_req
->
scat_list
[
i
].
packet
=
packet
;
/* prepare packet and flag message as part of a send bundle */
/* prepare packet and flag message as part of a send bundle */
htc_prep_send
_pkt
(
packet
,
ath6kl_htc_tx_prep
_pkt
(
packet
,
packet
->
info
.
tx
.
flags
|
HTC_FLAGS_SEND_BUNDLE
,
packet
->
info
.
tx
.
flags
|
HTC_FLAGS_SEND_BUNDLE
,
cred_pad
,
packet
->
info
.
tx
.
seqno
);
cred_pad
,
packet
->
info
.
tx
.
seqno
);
/* Make sure the buffer is 4-byte aligned */
ath6kl_htc_tx_buf_align
(
&
packet
->
buf
,
packet
->
act_len
+
HTC_HDR_LENGTH
);
scat_req
->
scat_list
[
i
].
buf
=
packet
->
buf
;
scat_req
->
scat_list
[
i
].
buf
=
packet
->
buf
;
scat_req
->
scat_list
[
i
].
len
=
len
;
scat_req
->
scat_list
[
i
].
len
=
len
;
...
@@ -402,7 +410,7 @@ static int htc_setup_send_scat_list(struct htc_target *target,
...
@@ -402,7 +410,7 @@ static int htc_setup_send_scat_list(struct htc_target *target,
}
}
/* Roll back scatter setup in case of any failure */
/* Roll back scatter setup in case of any failure */
if
(
s
tatus
||
(
scat_req
->
scat_entries
<
HTC_MIN_HTC_MSGS_TO_BUNDLE
)
)
{
if
(
s
cat_req
->
scat_entries
<
HTC_MIN_HTC_MSGS_TO_BUNDLE
)
{
for
(
i
=
scat_req
->
scat_entries
-
1
;
i
>=
0
;
i
--
)
{
for
(
i
=
scat_req
->
scat_entries
-
1
;
i
>=
0
;
i
--
)
{
packet
=
scat_req
->
scat_list
[
i
].
packet
;
packet
=
scat_req
->
scat_list
[
i
].
packet
;
if
(
packet
)
{
if
(
packet
)
{
...
@@ -410,31 +418,32 @@ static int htc_setup_send_scat_list(struct htc_target *target,
...
@@ -410,31 +418,32 @@ static int htc_setup_send_scat_list(struct htc_target *target,
list_add
(
&
packet
->
list
,
queue
);
list_add
(
&
packet
->
list
,
queue
);
}
}
}
}
return
-
E
INVAL
;
return
-
E
AGAIN
;
}
}
return
0
;
return
status
;
}
}
/*
/*
* htc_issue_send_bundle: drain a queue and send as bundles
* Drain a queue and send as bundles this function may return without fully
* this function may return without fully draining the queue
* draining the queue when
* when
*
*
* 1. scatter resources are exhausted
* 1. scatter resources are exhausted
* 2. a message that will consume a partial credit will stop the
* 2. a message that will consume a partial credit will stop the
* bundling process early
* bundling process early
* 3. we drop below the minimum number of messages for a bundle
* 3. we drop below the minimum number of messages for a bundle
*/
*/
static
void
htc_issue_send
_bundle
(
struct
htc_endpoint
*
endpoint
,
static
void
ath6kl_htc_tx
_bundle
(
struct
htc_endpoint
*
endpoint
,
struct
list_head
*
queue
,
struct
list_head
*
queue
,
int
*
sent_bundle
,
int
*
n_bundle_pkts
)
int
*
sent_bundle
,
int
*
n_bundle_pkts
)
{
{
struct
htc_target
*
target
=
endpoint
->
target
;
struct
htc_target
*
target
=
endpoint
->
target
;
struct
hif_scatter_req
*
scat_req
=
NULL
;
struct
hif_scatter_req
*
scat_req
=
NULL
;
int
n_scat
,
n_sent_bundle
=
0
,
tot_pkts_bundle
=
0
;
int
n_scat
,
n_sent_bundle
=
0
,
tot_pkts_bundle
=
0
;
int
status
;
while
(
true
)
{
while
(
true
)
{
status
=
0
;
n_scat
=
get_queue_depth
(
queue
);
n_scat
=
get_queue_depth
(
queue
);
n_scat
=
min
(
n_scat
,
target
->
msg_per_bndl_max
);
n_scat
=
min
(
n_scat
,
target
->
msg_per_bndl_max
);
...
@@ -457,8 +466,10 @@ static void htc_issue_send_bundle(struct htc_endpoint *endpoint,
...
@@ -457,8 +466,10 @@ static void htc_issue_send_bundle(struct htc_endpoint *endpoint,
scat_req
->
len
=
0
;
scat_req
->
len
=
0
;
scat_req
->
scat_entries
=
0
;
scat_req
->
scat_entries
=
0
;
if
(
htc_setup_send_scat_list
(
target
,
endpoint
,
scat_req
,
status
=
ath6kl_htc_tx_setup_scat_list
(
target
,
endpoint
,
n_scat
,
queue
))
{
scat_req
,
n_scat
,
queue
);
if
(
status
==
-
EAGAIN
)
{
hif_scatter_req_add
(
target
->
dev
->
ar
,
scat_req
);
hif_scatter_req_add
(
target
->
dev
->
ar
,
scat_req
);
break
;
break
;
}
}
...
@@ -472,18 +483,21 @@ static void htc_issue_send_bundle(struct htc_endpoint *endpoint,
...
@@ -472,18 +483,21 @@ static void htc_issue_send_bundle(struct htc_endpoint *endpoint,
"send scatter total bytes: %d , entries: %d
\n
"
,
"send scatter total bytes: %d , entries: %d
\n
"
,
scat_req
->
len
,
scat_req
->
scat_entries
);
scat_req
->
len
,
scat_req
->
scat_entries
);
ath6kldev_submit_scat_req
(
target
->
dev
,
scat_req
,
false
);
ath6kldev_submit_scat_req
(
target
->
dev
,
scat_req
,
false
);
if
(
status
)
break
;
}
}
*
sent_bundle
=
n_sent_bundle
;
*
sent_bundle
=
n_sent_bundle
;
*
n_bundle_pkts
=
tot_pkts_bundle
;
*
n_bundle_pkts
=
tot_pkts_bundle
;
ath6kl_dbg
(
ATH6KL_DBG_HTC_SEND
,
"
htc_issue_send_bundle
(sent:%d)
\n
"
,
ath6kl_dbg
(
ATH6KL_DBG_HTC_SEND
,
"
%s
(sent:%d)
\n
"
,
n_sent_bundle
);
__func__
,
n_sent_bundle
);
return
;
return
;
}
}
static
void
htc_tx_from_ep_txq
(
struct
htc_target
*
target
,
static
void
ath6kl_htc_tx_from_queue
(
struct
htc_target
*
target
,
struct
htc_endpoint
*
endpoint
)
struct
htc_endpoint
*
endpoint
)
{
{
struct
list_head
txq
;
struct
list_head
txq
;
struct
htc_packet
*
packet
;
struct
htc_packet
*
packet
;
...
@@ -511,7 +525,7 @@ static void htc_tx_from_ep_txq(struct htc_target *target,
...
@@ -511,7 +525,7 @@ static void htc_tx_from_ep_txq(struct htc_target *target,
if
(
list_empty
(
&
endpoint
->
txq
))
if
(
list_empty
(
&
endpoint
->
txq
))
break
;
break
;
htc_tx_pkts_get
(
target
,
endpoint
,
&
txq
);
ath6kl_
htc_tx_pkts_get
(
target
,
endpoint
,
&
txq
);
if
(
list_empty
(
&
txq
))
if
(
list_empty
(
&
txq
))
break
;
break
;
...
@@ -528,8 +542,8 @@ static void htc_tx_from_ep_txq(struct htc_target *target,
...
@@ -528,8 +542,8 @@ static void htc_tx_from_ep_txq(struct htc_target *target,
HTC_MIN_HTC_MSGS_TO_BUNDLE
))
{
HTC_MIN_HTC_MSGS_TO_BUNDLE
))
{
int
temp1
=
0
,
temp2
=
0
;
int
temp1
=
0
,
temp2
=
0
;
htc_issue_send
_bundle
(
endpoint
,
&
txq
,
ath6kl_htc_tx
_bundle
(
endpoint
,
&
txq
,
&
temp1
,
&
temp2
);
&
temp1
,
&
temp2
);
bundle_sent
+=
temp1
;
bundle_sent
+=
temp1
;
n_pkts_bundle
+=
temp2
;
n_pkts_bundle
+=
temp2
;
}
}
...
@@ -541,9 +555,9 @@ static void htc_tx_from_ep_txq(struct htc_target *target,
...
@@ -541,9 +555,9 @@ static void htc_tx_from_ep_txq(struct htc_target *target,
list
);
list
);
list_del
(
&
packet
->
list
);
list_del
(
&
packet
->
list
);
htc_prep_send
_pkt
(
packet
,
packet
->
info
.
tx
.
flags
,
ath6kl_htc_tx_prep
_pkt
(
packet
,
packet
->
info
.
tx
.
flags
,
0
,
packet
->
info
.
tx
.
seqno
);
0
,
packet
->
info
.
tx
.
seqno
);
htc_issue_send
(
target
,
packet
);
ath6kl_htc_tx_issue
(
target
,
packet
);
}
}
spin_lock_bh
(
&
target
->
tx_lock
);
spin_lock_bh
(
&
target
->
tx_lock
);
...
@@ -556,9 +570,9 @@ static void htc_tx_from_ep_txq(struct htc_target *target,
...
@@ -556,9 +570,9 @@ static void htc_tx_from_ep_txq(struct htc_target *target,
spin_unlock_bh
(
&
target
->
tx_lock
);
spin_unlock_bh
(
&
target
->
tx_lock
);
}
}
static
bool
htc_try_send
(
struct
htc_target
*
target
,
static
bool
ath6kl_htc_tx_try
(
struct
htc_target
*
target
,
struct
htc_endpoint
*
endpoint
,
struct
htc_endpoint
*
endpoint
,
struct
htc_packet
*
tx_pkt
)
struct
htc_packet
*
tx_pkt
)
{
{
struct
htc_ep_callbacks
ep_cb
;
struct
htc_ep_callbacks
ep_cb
;
int
txq_depth
;
int
txq_depth
;
...
@@ -594,7 +608,7 @@ static bool htc_try_send(struct htc_target *target,
...
@@ -594,7 +608,7 @@ static bool htc_try_send(struct htc_target *target,
list_add_tail
(
&
tx_pkt
->
list
,
&
endpoint
->
txq
);
list_add_tail
(
&
tx_pkt
->
list
,
&
endpoint
->
txq
);
spin_unlock_bh
(
&
target
->
tx_lock
);
spin_unlock_bh
(
&
target
->
tx_lock
);
htc_tx_from_ep_txq
(
target
,
endpoint
);
ath6kl_htc_tx_from_queue
(
target
,
endpoint
);
return
true
;
return
true
;
}
}
...
@@ -628,7 +642,7 @@ static void htc_chk_ep_txq(struct htc_target *target)
...
@@ -628,7 +642,7 @@ static void htc_chk_ep_txq(struct htc_target *target)
* chance to reclaim credits from lower priority
* chance to reclaim credits from lower priority
* ones.
* ones.
*/
*/
htc_tx_from_ep_txq
(
target
,
endpoint
);
ath6kl_htc_tx_from_queue
(
target
,
endpoint
);
spin_lock_bh
(
&
target
->
tx_lock
);
spin_lock_bh
(
&
target
->
tx_lock
);
}
}
spin_unlock_bh
(
&
target
->
tx_lock
);
spin_unlock_bh
(
&
target
->
tx_lock
);
...
@@ -680,8 +694,8 @@ static int htc_setup_tx_complete(struct htc_target *target)
...
@@ -680,8 +694,8 @@ static int htc_setup_tx_complete(struct htc_target *target)
/* we want synchronous operation */
/* we want synchronous operation */
send_pkt
->
completion
=
NULL
;
send_pkt
->
completion
=
NULL
;
htc_prep_send
_pkt
(
send_pkt
,
0
,
0
,
0
);
ath6kl_htc_tx_prep
_pkt
(
send_pkt
,
0
,
0
,
0
);
status
=
htc_issue_send
(
target
,
send_pkt
);
status
=
ath6kl_htc_tx_issue
(
target
,
send_pkt
);
if
(
send_pkt
!=
NULL
)
if
(
send_pkt
!=
NULL
)
htc_reclaim_txctrl_buf
(
target
,
send_pkt
);
htc_reclaim_txctrl_buf
(
target
,
send_pkt
);
...
@@ -733,7 +747,7 @@ int ath6kl_htc_tx(struct htc_target *target, struct htc_packet *packet)
...
@@ -733,7 +747,7 @@ int ath6kl_htc_tx(struct htc_target *target, struct htc_packet *packet)
endpoint
=
&
target
->
endpoint
[
packet
->
endpoint
];
endpoint
=
&
target
->
endpoint
[
packet
->
endpoint
];
if
(
!
htc_try_send
(
target
,
endpoint
,
packet
))
{
if
(
!
ath6kl_htc_tx_try
(
target
,
endpoint
,
packet
))
{
packet
->
status
=
(
target
->
htc_flags
&
HTC_OP_STATE_STOPPING
)
?
packet
->
status
=
(
target
->
htc_flags
&
HTC_OP_STATE_STOPPING
)
?
-
ECANCELED
:
-
ENOSPC
;
-
ECANCELED
:
-
ENOSPC
;
INIT_LIST_HEAD
(
&
queue
);
INIT_LIST_HEAD
(
&
queue
);
...
@@ -846,8 +860,8 @@ void ath6kl_htc_indicate_activity_change(struct htc_target *target,
...
@@ -846,8 +860,8 @@ void ath6kl_htc_indicate_activity_change(struct htc_target *target,
/* HTC Rx */
/* HTC Rx */
static
inline
void
htc_update_rx
_stats
(
struct
htc_endpoint
*
endpoint
,
static
inline
void
ath6kl_htc_rx_update
_stats
(
struct
htc_endpoint
*
endpoint
,
int
n_look_ahds
)
int
n_look_ahds
)
{
{
endpoint
->
ep_st
.
rx_pkts
++
;
endpoint
->
ep_st
.
rx_pkts
++
;
if
(
n_look_ahds
==
1
)
if
(
n_look_ahds
==
1
)
...
@@ -894,8 +908,9 @@ static void reclaim_rx_ctrl_buf(struct htc_target *target,
...
@@ -894,8 +908,9 @@ static void reclaim_rx_ctrl_buf(struct htc_target *target,
spin_unlock_bh
(
&
target
->
htc_lock
);
spin_unlock_bh
(
&
target
->
htc_lock
);
}
}
static
int
dev_rx_pkt
(
struct
htc_target
*
target
,
struct
htc_packet
*
packet
,
static
int
ath6kl_htc_rx_packet
(
struct
htc_target
*
target
,
u32
rx_len
)
struct
htc_packet
*
packet
,
u32
rx_len
)
{
{
struct
ath6kl_device
*
dev
=
target
->
dev
;
struct
ath6kl_device
*
dev
=
target
->
dev
;
u32
padded_len
;
u32
padded_len
;
...
@@ -929,9 +944,9 @@ static int dev_rx_pkt(struct htc_target *target, struct htc_packet *packet,
...
@@ -929,9 +944,9 @@ static int dev_rx_pkt(struct htc_target *target, struct htc_packet *packet,
* "hint" that there are more single-packets to fetch
* "hint" that there are more single-packets to fetch
* on this endpoint.
* on this endpoint.
*/
*/
static
void
set_rxpkt_indication_flag
(
u32
lk_ahd
,
static
void
ath6kl_htc_rx_set_indicate
(
u32
lk_ahd
,
struct
htc_endpoint
*
endpoint
,
struct
htc_endpoint
*
endpoint
,
struct
htc_packet
*
packet
)
struct
htc_packet
*
packet
)
{
{
struct
htc_frame_hdr
*
htc_hdr
=
(
struct
htc_frame_hdr
*
)
&
lk_ahd
;
struct
htc_frame_hdr
*
htc_hdr
=
(
struct
htc_frame_hdr
*
)
&
lk_ahd
;
...
@@ -942,7 +957,7 @@ static void set_rxpkt_indication_flag(u32 lk_ahd,
...
@@ -942,7 +957,7 @@ static void set_rxpkt_indication_flag(u32 lk_ahd,
}
}
}
}
static
void
chk_rx
_water_mark
(
struct
htc_endpoint
*
endpoint
)
static
void
ath6kl_htc_rx_chk
_water_mark
(
struct
htc_endpoint
*
endpoint
)
{
{
struct
htc_ep_callbacks
ep_cb
=
endpoint
->
ep_cb
;
struct
htc_ep_callbacks
ep_cb
=
endpoint
->
ep_cb
;
...
@@ -959,8 +974,9 @@ static void chk_rx_water_mark(struct htc_endpoint *endpoint)
...
@@ -959,8 +974,9 @@ static void chk_rx_water_mark(struct htc_endpoint *endpoint)
}
}
/* This function is called with rx_lock held */
/* This function is called with rx_lock held */
static
int
htc_setup_rxpkts
(
struct
htc_target
*
target
,
struct
htc_endpoint
*
ep
,
static
int
ath6kl_htc_rx_setup
(
struct
htc_target
*
target
,
u32
*
lk_ahds
,
struct
list_head
*
queue
,
int
n_msg
)
struct
htc_endpoint
*
ep
,
u32
*
lk_ahds
,
struct
list_head
*
queue
,
int
n_msg
)
{
{
struct
htc_packet
*
packet
;
struct
htc_packet
*
packet
;
/* FIXME: type of lk_ahds can't be right */
/* FIXME: type of lk_ahds can't be right */
...
@@ -1060,10 +1076,10 @@ static int htc_setup_rxpkts(struct htc_target *target, struct htc_endpoint *ep,
...
@@ -1060,10 +1076,10 @@ static int htc_setup_rxpkts(struct htc_target *target, struct htc_endpoint *ep,
return
status
;
return
status
;
}
}
static
int
a
lloc_and_prep_rxpkts
(
struct
htc_target
*
target
,
static
int
a
th6kl_htc_rx_alloc
(
struct
htc_target
*
target
,
u32
lk_ahds
[],
int
msg
,
u32
lk_ahds
[],
int
msg
,
struct
htc_endpoint
*
endpoint
,
struct
htc_endpoint
*
endpoint
,
struct
list_head
*
queue
)
struct
list_head
*
queue
)
{
{
int
status
=
0
;
int
status
=
0
;
struct
htc_packet
*
packet
,
*
tmp_pkt
;
struct
htc_packet
*
packet
,
*
tmp_pkt
;
...
@@ -1129,8 +1145,8 @@ static int alloc_and_prep_rxpkts(struct htc_target *target,
...
@@ -1129,8 +1145,8 @@ static int alloc_and_prep_rxpkts(struct htc_target *target,
n_msg
=
1
;
n_msg
=
1
;
/* Setup packet buffers for each message */
/* Setup packet buffers for each message */
status
=
htc_setup_rxpkts
(
target
,
endpoint
,
&
lk_ahds
[
i
],
queue
,
status
=
ath6kl_htc_rx_setup
(
target
,
endpoint
,
&
lk_ahds
[
i
]
,
n_msg
);
queue
,
n_msg
);
/*
/*
* This is due to unavailabilty of buffers to rx entire data.
* This is due to unavailabilty of buffers to rx entire data.
...
@@ -1176,9 +1192,9 @@ static void htc_ctrl_rx(struct htc_target *context, struct htc_packet *packets)
...
@@ -1176,9 +1192,9 @@ static void htc_ctrl_rx(struct htc_target *context, struct htc_packet *packets)
packets
->
act_len
+
HTC_HDR_LENGTH
);
packets
->
act_len
+
HTC_HDR_LENGTH
);
ath6kl_dbg_dump
(
ATH6KL_DBG_RAW_BYTES
,
ath6kl_dbg_dump
(
ATH6KL_DBG_RAW_BYTES
,
"Unexpected ENDPOINT 0 Message
"
,
"Unexpected ENDPOINT 0 Message"
,
"
"
,
packets
->
buf
-
HTC_HDR_LENGTH
,
packets
->
buf
-
HTC_HDR_LENGTH
,
packets
->
act_len
+
HTC_HDR_LENGTH
);
packets
->
act_len
+
HTC_HDR_LENGTH
);
}
}
htc_reclaim_rxbuf
(
context
,
packets
,
&
context
->
endpoint
[
0
]);
htc_reclaim_rxbuf
(
context
,
packets
,
&
context
->
endpoint
[
0
]);
...
@@ -1312,7 +1328,7 @@ static int htc_parse_trailer(struct htc_target *target,
...
@@ -1312,7 +1328,7 @@ static int htc_parse_trailer(struct htc_target *target,
memcpy
((
u8
*
)
&
next_lk_ahds
[
0
],
lk_ahd
->
lk_ahd
,
4
);
memcpy
((
u8
*
)
&
next_lk_ahds
[
0
],
lk_ahd
->
lk_ahd
,
4
);
ath6kl_dbg_dump
(
ATH6KL_DBG_RAW_BYTES
,
"Next Look Ahead"
,
ath6kl_dbg_dump
(
ATH6KL_DBG_RAW_BYTES
,
"Next Look Ahead"
,
next_lk_ahds
,
4
);
""
,
next_lk_ahds
,
4
);
*
n_lk_ahds
=
1
;
*
n_lk_ahds
=
1
;
}
}
...
@@ -1331,7 +1347,7 @@ static int htc_parse_trailer(struct htc_target *target,
...
@@ -1331,7 +1347,7 @@ static int htc_parse_trailer(struct htc_target *target,
(
struct
htc_bundle_lkahd_rpt
*
)
record_buf
;
(
struct
htc_bundle_lkahd_rpt
*
)
record_buf
;
ath6kl_dbg_dump
(
ATH6KL_DBG_RAW_BYTES
,
"Bundle lk_ahd"
,
ath6kl_dbg_dump
(
ATH6KL_DBG_RAW_BYTES
,
"Bundle lk_ahd"
,
record_buf
,
record
->
len
);
""
,
record_buf
,
record
->
len
);
for
(
i
=
0
;
i
<
len
;
i
++
)
{
for
(
i
=
0
;
i
<
len
;
i
++
)
{
memcpy
((
u8
*
)
&
next_lk_ahds
[
i
],
memcpy
((
u8
*
)
&
next_lk_ahds
[
i
],
...
@@ -1364,7 +1380,8 @@ static int htc_proc_trailer(struct htc_target *target,
...
@@ -1364,7 +1380,8 @@ static int htc_proc_trailer(struct htc_target *target,
ath6kl_dbg
(
ATH6KL_DBG_HTC_RECV
,
"+htc_proc_trailer (len:%d)
\n
"
,
len
);
ath6kl_dbg
(
ATH6KL_DBG_HTC_RECV
,
"+htc_proc_trailer (len:%d)
\n
"
,
len
);
ath6kl_dbg_dump
(
ATH6KL_DBG_RAW_BYTES
,
"Recv Trailer"
,
buf
,
len
);
ath6kl_dbg_dump
(
ATH6KL_DBG_RAW_BYTES
,
"Recv Trailer"
,
""
,
buf
,
len
);
orig_buf
=
buf
;
orig_buf
=
buf
;
orig_len
=
len
;
orig_len
=
len
;
...
@@ -1402,14 +1419,14 @@ static int htc_proc_trailer(struct htc_target *target,
...
@@ -1402,14 +1419,14 @@ static int htc_proc_trailer(struct htc_target *target,
if
(
status
)
if
(
status
)
ath6kl_dbg_dump
(
ATH6KL_DBG_RAW_BYTES
,
"BAD Recv Trailer"
,
ath6kl_dbg_dump
(
ATH6KL_DBG_RAW_BYTES
,
"BAD Recv Trailer"
,
orig_buf
,
orig_len
);
""
,
orig_buf
,
orig_len
);
return
status
;
return
status
;
}
}
static
int
htc_proc_rx
hdr
(
struct
htc_target
*
target
,
static
int
ath6kl_htc_rx_process_
hdr
(
struct
htc_target
*
target
,
struct
htc_packet
*
packet
,
struct
htc_packet
*
packet
,
u32
*
next_lkahds
,
int
*
n_lkahds
)
u32
*
next_lkahds
,
int
*
n_lkahds
)
{
{
int
status
=
0
;
int
status
=
0
;
u16
payload_len
;
u16
payload_len
;
...
@@ -1419,8 +1436,8 @@ static int htc_proc_rxhdr(struct htc_target *target,
...
@@ -1419,8 +1436,8 @@ static int htc_proc_rxhdr(struct htc_target *target,
if
(
n_lkahds
!=
NULL
)
if
(
n_lkahds
!=
NULL
)
*
n_lkahds
=
0
;
*
n_lkahds
=
0
;
ath6kl_dbg_dump
(
ATH6KL_DBG_RAW_BYTES
,
"HTC Recv PKT"
,
packet
->
buf
,
ath6kl_dbg_dump
(
ATH6KL_DBG_RAW_BYTES
,
"HTC Recv PKT"
,
"htc "
,
packet
->
act_len
);
packet
->
buf
,
packet
->
act_len
);
/*
/*
* NOTE: we cannot assume the alignment of buf, so we use the safe
* NOTE: we cannot assume the alignment of buf, so we use the safe
...
@@ -1461,12 +1478,12 @@ static int htc_proc_rxhdr(struct htc_target *target,
...
@@ -1461,12 +1478,12 @@ static int htc_proc_rxhdr(struct htc_target *target,
}
}
if
(
lk_ahd
!=
packet
->
info
.
rx
.
exp_hdr
)
{
if
(
lk_ahd
!=
packet
->
info
.
rx
.
exp_hdr
)
{
ath6kl_err
(
"
htc_proc_rxhdr,
lk_ahd mismatch! (pPkt:0x%p flags:0x%X)
\n
"
,
ath6kl_err
(
"
%s():
lk_ahd mismatch! (pPkt:0x%p flags:0x%X)
\n
"
,
packet
,
packet
->
info
.
rx
.
rx_flags
);
__func__
,
packet
,
packet
->
info
.
rx
.
rx_flags
);
ath6kl_dbg_dump
(
ATH6KL_DBG_RAW_BYTES
,
"Expected Message lk_ahd"
,
ath6kl_dbg_dump
(
ATH6KL_DBG_RAW_BYTES
,
"Expected Message lk_ahd"
,
&
packet
->
info
.
rx
.
exp_hdr
,
4
);
""
,
&
packet
->
info
.
rx
.
exp_hdr
,
4
);
ath6kl_dbg_dump
(
ATH6KL_DBG_RAW_BYTES
,
"Current Frame Header"
,
ath6kl_dbg_dump
(
ATH6KL_DBG_RAW_BYTES
,
"Current Frame Header"
,
(
u8
*
)
&
lk_ahd
,
sizeof
(
lk_ahd
));
""
,
(
u8
*
)
&
lk_ahd
,
sizeof
(
lk_ahd
));
status
=
-
ENOMEM
;
status
=
-
ENOMEM
;
goto
fail_rx
;
goto
fail_rx
;
}
}
...
@@ -1474,8 +1491,8 @@ static int htc_proc_rxhdr(struct htc_target *target,
...
@@ -1474,8 +1491,8 @@ static int htc_proc_rxhdr(struct htc_target *target,
if
(
htc_hdr
->
flags
&
HTC_FLG_RX_TRAILER
)
{
if
(
htc_hdr
->
flags
&
HTC_FLG_RX_TRAILER
)
{
if
(
htc_hdr
->
ctrl
[
0
]
<
sizeof
(
struct
htc_record_hdr
)
||
if
(
htc_hdr
->
ctrl
[
0
]
<
sizeof
(
struct
htc_record_hdr
)
||
htc_hdr
->
ctrl
[
0
]
>
payload_len
)
{
htc_hdr
->
ctrl
[
0
]
>
payload_len
)
{
ath6kl_err
(
"
htc_proc_rxhdr,
invalid hdr (payload len should be :%d, CB[0] is:%d)
\n
"
,
ath6kl_err
(
"
%s():
invalid hdr (payload len should be :%d, CB[0] is:%d)
\n
"
,
payload_len
,
htc_hdr
->
ctrl
[
0
]);
__func__
,
payload_len
,
htc_hdr
->
ctrl
[
0
]);
status
=
-
ENOMEM
;
status
=
-
ENOMEM
;
goto
fail_rx
;
goto
fail_rx
;
}
}
...
@@ -1502,20 +1519,20 @@ static int htc_proc_rxhdr(struct htc_target *target,
...
@@ -1502,20 +1519,20 @@ static int htc_proc_rxhdr(struct htc_target *target,
fail_rx:
fail_rx:
if
(
status
)
if
(
status
)
ath6kl_dbg_dump
(
ATH6KL_DBG_RAW_BYTES
,
"BAD HTC Recv PKT"
,
ath6kl_dbg_dump
(
ATH6KL_DBG_RAW_BYTES
,
"BAD HTC Recv PKT"
,
packet
->
buf
,
""
,
packet
->
buf
,
packet
->
act_len
<
256
?
packet
->
act_len
:
256
);
packet
->
act_len
<
256
?
packet
->
act_len
:
256
);
else
{
else
{
if
(
packet
->
act_len
>
0
)
if
(
packet
->
act_len
>
0
)
ath6kl_dbg_dump
(
ATH6KL_DBG_RAW_BYTES
,
ath6kl_dbg_dump
(
ATH6KL_DBG_RAW_BYTES
,
"HTC - Application Msg"
,
"HTC - Application Msg"
,
""
,
packet
->
buf
,
packet
->
act_len
);
packet
->
buf
,
packet
->
act_len
);
}
}
return
status
;
return
status
;
}
}
static
void
do_rx_completion
(
struct
htc_endpoint
*
endpoint
,
static
void
ath6kl_htc_rx_complete
(
struct
htc_endpoint
*
endpoint
,
struct
htc_packet
*
packet
)
struct
htc_packet
*
packet
)
{
{
ath6kl_dbg
(
ATH6KL_DBG_HTC_RECV
,
ath6kl_dbg
(
ATH6KL_DBG_HTC_RECV
,
"htc calling ep %d recv callback on packet 0x%p
\n
"
,
"htc calling ep %d recv callback on packet 0x%p
\n
"
,
...
@@ -1523,10 +1540,10 @@ static void do_rx_completion(struct htc_endpoint *endpoint,
...
@@ -1523,10 +1540,10 @@ static void do_rx_completion(struct htc_endpoint *endpoint,
endpoint
->
ep_cb
.
rx
(
endpoint
->
target
,
packet
);
endpoint
->
ep_cb
.
rx
(
endpoint
->
target
,
packet
);
}
}
static
int
htc_issue_rxpkt
_bundle
(
struct
htc_target
*
target
,
static
int
ath6kl_htc_rx
_bundle
(
struct
htc_target
*
target
,
struct
list_head
*
rxq
,
struct
list_head
*
rxq
,
struct
list_head
*
sync_compq
,
struct
list_head
*
sync_compq
,
int
*
n_pkt_fetched
,
bool
part_bundle
)
int
*
n_pkt_fetched
,
bool
part_bundle
)
{
{
struct
hif_scatter_req
*
scat_req
;
struct
hif_scatter_req
*
scat_req
;
struct
htc_packet
*
packet
;
struct
htc_packet
*
packet
;
...
@@ -1548,15 +1565,15 @@ static int htc_issue_rxpkt_bundle(struct htc_target *target,
...
@@ -1548,15 +1565,15 @@ static int htc_issue_rxpkt_bundle(struct htc_target *target,
* This would only happen if the target ignored our max
* This would only happen if the target ignored our max
* bundle limit.
* bundle limit.
*/
*/
ath6kl_warn
(
"
htc_issue_rxpkt_bundle
: partial bundle detected num:%d , %d
\n
"
,
ath6kl_warn
(
"
%s()
: partial bundle detected num:%d , %d
\n
"
,
get_queue_depth
(
rxq
),
n_scat_pkt
);
__func__
,
get_queue_depth
(
rxq
),
n_scat_pkt
);
}
}
len
=
0
;
len
=
0
;
ath6kl_dbg
(
ATH6KL_DBG_HTC_RECV
,
ath6kl_dbg
(
ATH6KL_DBG_HTC_RECV
,
"htc_issue_rxpkt_bundle
(numpackets: %d , actual : %d)
\n
"
,
"%s():
(numpackets: %d , actual : %d)
\n
"
,
get_queue_depth
(
rxq
),
n_scat_pkt
);
__func__
,
get_queue_depth
(
rxq
),
n_scat_pkt
);
scat_req
=
hif_scatter_req_get
(
target
->
dev
->
ar
);
scat_req
=
hif_scatter_req_get
(
target
->
dev
->
ar
);
...
@@ -1616,9 +1633,10 @@ static int htc_issue_rxpkt_bundle(struct htc_target *target,
...
@@ -1616,9 +1633,10 @@ static int htc_issue_rxpkt_bundle(struct htc_target *target,
return
status
;
return
status
;
}
}
static
int
htc_proc_fetched_rxpkts
(
struct
htc_target
*
target
,
static
int
ath6kl_htc_rx_process_packets
(
struct
htc_target
*
target
,
struct
list_head
*
comp_pktq
,
u32
lk_ahds
[],
struct
list_head
*
comp_pktq
,
int
*
n_lk_ahd
)
u32
lk_ahds
[],
int
*
n_lk_ahd
)
{
{
struct
htc_packet
*
packet
,
*
tmp_pkt
;
struct
htc_packet
*
packet
,
*
tmp_pkt
;
struct
htc_endpoint
*
ep
;
struct
htc_endpoint
*
ep
;
...
@@ -1629,7 +1647,8 @@ static int htc_proc_fetched_rxpkts(struct htc_target *target,
...
@@ -1629,7 +1647,8 @@ static int htc_proc_fetched_rxpkts(struct htc_target *target,
ep
=
&
target
->
endpoint
[
packet
->
endpoint
];
ep
=
&
target
->
endpoint
[
packet
->
endpoint
];
/* process header for each of the recv packet */
/* process header for each of the recv packet */
status
=
htc_proc_rxhdr
(
target
,
packet
,
lk_ahds
,
n_lk_ahd
);
status
=
ath6kl_htc_rx_process_hdr
(
target
,
packet
,
lk_ahds
,
n_lk_ahd
);
if
(
status
)
if
(
status
)
return
status
;
return
status
;
...
@@ -1639,8 +1658,8 @@ static int htc_proc_fetched_rxpkts(struct htc_target *target,
...
@@ -1639,8 +1658,8 @@ static int htc_proc_fetched_rxpkts(struct htc_target *target,
* based on the lookahead.
* based on the lookahead.
*/
*/
if
(
*
n_lk_ahd
>
0
)
if
(
*
n_lk_ahd
>
0
)
set_rxpkt_indication_flag
(
lk_ahds
[
0
],
ath6kl_htc_rx_set_indicate
(
lk_ahds
[
0
],
ep
,
packet
);
ep
,
packet
);
}
else
}
else
/*
/*
* Packets in a bundle automatically have
* Packets in a bundle automatically have
...
@@ -1649,20 +1668,20 @@ static int htc_proc_fetched_rxpkts(struct htc_target *target,
...
@@ -1649,20 +1668,20 @@ static int htc_proc_fetched_rxpkts(struct htc_target *target,
packet
->
info
.
rx
.
indicat_flags
|=
packet
->
info
.
rx
.
indicat_flags
|=
HTC_RX_FLAGS_INDICATE_MORE_PKTS
;
HTC_RX_FLAGS_INDICATE_MORE_PKTS
;
htc_update_rx
_stats
(
ep
,
*
n_lk_ahd
);
ath6kl_htc_rx_update
_stats
(
ep
,
*
n_lk_ahd
);
if
(
packet
->
info
.
rx
.
rx_flags
&
HTC_RX_PKT_PART_OF_BUNDLE
)
if
(
packet
->
info
.
rx
.
rx_flags
&
HTC_RX_PKT_PART_OF_BUNDLE
)
ep
->
ep_st
.
rx_bundl
+=
1
;
ep
->
ep_st
.
rx_bundl
+=
1
;
do_rx_completion
(
ep
,
packet
);
ath6kl_htc_rx_complete
(
ep
,
packet
);
}
}
return
status
;
return
status
;
}
}
static
int
htc_fetch_rxpkts
(
struct
htc_target
*
target
,
static
int
ath6kl_htc_rx_fetch
(
struct
htc_target
*
target
,
struct
list_head
*
rx_pktq
,
struct
list_head
*
rx_pktq
,
struct
list_head
*
comp_pktq
)
struct
list_head
*
comp_pktq
)
{
{
int
fetched_pkts
;
int
fetched_pkts
;
bool
part_bundle
=
false
;
bool
part_bundle
=
false
;
...
@@ -1678,10 +1697,10 @@ static int htc_fetch_rxpkts(struct htc_target *target,
...
@@ -1678,10 +1697,10 @@ static int htc_fetch_rxpkts(struct htc_target *target,
* bundle transfer and recv bundling is
* bundle transfer and recv bundling is
* allowed.
* allowed.
*/
*/
status
=
htc_issue_rxpkt
_bundle
(
target
,
rx_pktq
,
status
=
ath6kl_htc_rx
_bundle
(
target
,
rx_pktq
,
comp_pktq
,
comp_pktq
,
&
fetched_pkts
,
&
fetched_pkts
,
part_bundle
);
part_bundle
);
if
(
status
)
if
(
status
)
return
status
;
return
status
;
...
@@ -1710,7 +1729,8 @@ static int htc_fetch_rxpkts(struct htc_target *target,
...
@@ -1710,7 +1729,8 @@ static int htc_fetch_rxpkts(struct htc_target *target,
HTC_RX_PKT_IGNORE_LOOKAHEAD
;
HTC_RX_PKT_IGNORE_LOOKAHEAD
;
/* go fetch the packet */
/* go fetch the packet */
status
=
dev_rx_pkt
(
target
,
packet
,
packet
->
act_len
);
status
=
ath6kl_htc_rx_packet
(
target
,
packet
,
packet
->
act_len
);
if
(
status
)
if
(
status
)
return
status
;
return
status
;
...
@@ -1764,9 +1784,9 @@ int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target,
...
@@ -1764,9 +1784,9 @@ int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target,
* Try to allocate as many HTC RX packets indicated by the
* Try to allocate as many HTC RX packets indicated by the
* look_aheads.
* look_aheads.
*/
*/
status
=
a
lloc_and_prep_rxpkts
(
target
,
look_aheads
,
status
=
a
th6kl_htc_rx_alloc
(
target
,
look_aheads
,
num_look_ahead
,
endpoint
,
num_look_ahead
,
endpoint
,
&
rx_pktq
);
&
rx_pktq
);
if
(
status
)
if
(
status
)
break
;
break
;
...
@@ -1781,14 +1801,15 @@ int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target,
...
@@ -1781,14 +1801,15 @@ int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target,
num_look_ahead
=
0
;
num_look_ahead
=
0
;
status
=
htc_fetch_rxpkts
(
target
,
&
rx_pktq
,
&
comp_pktq
);
status
=
ath6kl_htc_rx_fetch
(
target
,
&
rx_pktq
,
&
comp_pktq
);
if
(
!
status
)
if
(
!
status
)
chk_rx
_water_mark
(
endpoint
);
ath6kl_htc_rx_chk
_water_mark
(
endpoint
);
/* Process fetched packets */
/* Process fetched packets */
status
=
htc_proc_fetched_rxpkts
(
target
,
&
comp_pktq
,
status
=
ath6kl_htc_rx_process_packets
(
target
,
&
comp_pktq
,
look_aheads
,
&
num_look_ahead
);
look_aheads
,
&
num_look_ahead
);
if
(
!
num_look_ahead
||
status
)
if
(
!
num_look_ahead
||
status
)
break
;
break
;
...
@@ -1881,14 +1902,14 @@ static struct htc_packet *htc_wait_for_ctrl_msg(struct htc_target *target)
...
@@ -1881,14 +1902,14 @@ static struct htc_packet *htc_wait_for_ctrl_msg(struct htc_target *target)
packet
->
completion
=
NULL
;
packet
->
completion
=
NULL
;
/* get the message from the device, this will block */
/* get the message from the device, this will block */
if
(
dev_rx_pk
t
(
target
,
packet
,
packet
->
act_len
))
if
(
ath6kl_htc_rx_packe
t
(
target
,
packet
,
packet
->
act_len
))
goto
fail_ctrl_rx
;
goto
fail_ctrl_rx
;
/* process receive header */
/* process receive header */
packet
->
status
=
htc_proc_rx
hdr
(
target
,
packet
,
NULL
,
NULL
);
packet
->
status
=
ath6kl_htc_rx_process_
hdr
(
target
,
packet
,
NULL
,
NULL
);
if
(
packet
->
status
)
{
if
(
packet
->
status
)
{
ath6kl_err
(
"htc_wait_for_ctrl_msg,
htc_proc_rx
hdr failed (status = %d)
\n
"
,
ath6kl_err
(
"htc_wait_for_ctrl_msg,
ath6kl_htc_rx_process_
hdr failed (status = %d)
\n
"
,
packet
->
status
);
packet
->
status
);
goto
fail_ctrl_rx
;
goto
fail_ctrl_rx
;
}
}
...
@@ -1935,7 +1956,7 @@ int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target,
...
@@ -1935,7 +1956,7 @@ int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target,
list_for_each_entry_safe
(
packet
,
tmp_pkt
,
pkt_queue
,
list
)
{
list_for_each_entry_safe
(
packet
,
tmp_pkt
,
pkt_queue
,
list
)
{
packet
->
status
=
-
ECANCELED
;
packet
->
status
=
-
ECANCELED
;
list_del
(
&
packet
->
list
);
list_del
(
&
packet
->
list
);
do_rx_completion
(
endpoint
,
packet
);
ath6kl_htc_rx_complete
(
endpoint
,
packet
);
}
}
return
status
;
return
status
;
...
@@ -2034,8 +2055,8 @@ int ath6kl_htc_conn_service(struct htc_target *target,
...
@@ -2034,8 +2055,8 @@ int ath6kl_htc_conn_service(struct htc_target *target,
/* we want synchronous operation */
/* we want synchronous operation */
tx_pkt
->
completion
=
NULL
;
tx_pkt
->
completion
=
NULL
;
htc_prep_send
_pkt
(
tx_pkt
,
0
,
0
,
0
);
ath6kl_htc_tx_prep
_pkt
(
tx_pkt
,
0
,
0
,
0
);
status
=
htc_issue_send
(
target
,
tx_pkt
);
status
=
ath6kl_htc_tx_issue
(
target
,
tx_pkt
);
if
(
status
)
if
(
status
)
goto
fail_tx
;
goto
fail_tx
;
...
...
drivers/net/wireless/ath/ath6kl/init.c
View file @
a5abbcb2
...
@@ -15,6 +15,8 @@
...
@@ -15,6 +15,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
*/
#include <linux/moduleparam.h>
#include <linux/of.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_func.h>
#include "core.h"
#include "core.h"
#include "cfg80211.h"
#include "cfg80211.h"
...
@@ -23,8 +25,10 @@
...
@@ -23,8 +25,10 @@
#include "hif-ops.h"
#include "hif-ops.h"
unsigned
int
debug_mask
;
unsigned
int
debug_mask
;
static
unsigned
int
testmode
;
module_param
(
debug_mask
,
uint
,
0644
);
module_param
(
debug_mask
,
uint
,
0644
);
module_param
(
testmode
,
uint
,
0644
);
/*
/*
* Include definitions here that can be used to tune the WLAN module
* Include definitions here that can be used to tune the WLAN module
...
@@ -53,12 +57,6 @@ module_param(debug_mask, uint, 0644);
...
@@ -53,12 +57,6 @@ module_param(debug_mask, uint, 0644);
#define CONFIG_AR600x_DEBUG_UART_TX_PIN 8
#define CONFIG_AR600x_DEBUG_UART_TX_PIN 8
enum
addr_type
{
DATASET_PATCH_ADDR
,
APP_LOAD_ADDR
,
APP_START_OVERRIDE_ADDR
,
};
#define ATH6KL_DATA_OFFSET 64
#define ATH6KL_DATA_OFFSET 64
struct
sk_buff
*
ath6kl_buf_alloc
(
int
size
)
struct
sk_buff
*
ath6kl_buf_alloc
(
int
size
)
{
{
...
@@ -67,7 +65,7 @@ struct sk_buff *ath6kl_buf_alloc(int size)
...
@@ -67,7 +65,7 @@ struct sk_buff *ath6kl_buf_alloc(int size)
/* Add chacheline space at front and back of buffer */
/* Add chacheline space at front and back of buffer */
reserved
=
(
2
*
L1_CACHE_BYTES
)
+
ATH6KL_DATA_OFFSET
+
reserved
=
(
2
*
L1_CACHE_BYTES
)
+
ATH6KL_DATA_OFFSET
+
sizeof
(
struct
htc_packet
);
sizeof
(
struct
htc_packet
)
+
ATH6KL_HTC_ALIGN_BYTES
;
skb
=
dev_alloc_skb
(
size
+
reserved
);
skb
=
dev_alloc_skb
(
size
+
reserved
);
if
(
skb
)
if
(
skb
)
...
@@ -85,7 +83,7 @@ void ath6kl_init_profile_info(struct ath6kl *ar)
...
@@ -85,7 +83,7 @@ void ath6kl_init_profile_info(struct ath6kl *ar)
ar
->
prwise_crypto
=
NONE_CRYPT
;
ar
->
prwise_crypto
=
NONE_CRYPT
;
ar
->
prwise_crypto_len
=
0
;
ar
->
prwise_crypto_len
=
0
;
ar
->
grp_crypto
=
NONE_CRYPT
;
ar
->
grp_crypto
=
NONE_CRYPT
;
ar
->
grp_crpto_len
=
0
;
ar
->
grp_cr
y
pto_len
=
0
;
memset
(
ar
->
wep_key_list
,
0
,
sizeof
(
ar
->
wep_key_list
));
memset
(
ar
->
wep_key_list
,
0
,
sizeof
(
ar
->
wep_key_list
));
memset
(
ar
->
req_bssid
,
0
,
sizeof
(
ar
->
req_bssid
));
memset
(
ar
->
req_bssid
,
0
,
sizeof
(
ar
->
req_bssid
));
memset
(
ar
->
bssid
,
0
,
sizeof
(
ar
->
bssid
));
memset
(
ar
->
bssid
,
0
,
sizeof
(
ar
->
bssid
));
...
@@ -108,17 +106,6 @@ static u8 ath6kl_get_fw_iftype(struct ath6kl *ar)
...
@@ -108,17 +106,6 @@ static u8 ath6kl_get_fw_iftype(struct ath6kl *ar)
}
}
}
}
static
inline
u32
ath6kl_get_hi_item_addr
(
struct
ath6kl
*
ar
,
u32
item_offset
)
{
u32
addr
=
0
;
if
(
ar
->
target_type
==
TARGET_TYPE_AR6003
)
addr
=
ATH6KL_HI_START_ADDR
+
item_offset
;
return
addr
;
}
static
int
ath6kl_set_host_app_area
(
struct
ath6kl
*
ar
)
static
int
ath6kl_set_host_app_area
(
struct
ath6kl
*
ar
)
{
{
u32
address
,
data
;
u32
address
,
data
;
...
@@ -127,16 +114,15 @@ static int ath6kl_set_host_app_area(struct ath6kl *ar)
...
@@ -127,16 +114,15 @@ static int ath6kl_set_host_app_area(struct ath6kl *ar)
/* Fetch the address of the host_app_area_s
/* Fetch the address of the host_app_area_s
* instance in the host interest area */
* instance in the host interest area */
address
=
ath6kl_get_hi_item_addr
(
ar
,
HI_ITEM
(
hi_app_host_interest
));
address
=
ath6kl_get_hi_item_addr
(
ar
,
HI_ITEM
(
hi_app_host_interest
));
address
=
TARG_VTOP
(
address
);
address
=
TARG_VTOP
(
a
r
->
target_type
,
a
ddress
);
if
(
ath6kl_
read_reg_diag
(
ar
,
&
address
,
&
data
))
if
(
ath6kl_
diag_read32
(
ar
,
address
,
&
data
))
return
-
EIO
;
return
-
EIO
;
address
=
TARG_VTOP
(
data
);
address
=
TARG_VTOP
(
ar
->
target_type
,
data
);
host_app_area
.
wmi_protocol_ver
=
WMI_PROTOCOL_VERSION
;
host_app_area
.
wmi_protocol_ver
=
WMI_PROTOCOL_VERSION
;
if
(
ath6kl_access_datadiag
(
ar
,
address
,
if
(
ath6kl_diag_write
(
ar
,
address
,
(
u8
*
)
&
host_app_area
,
(
u8
*
)
&
host_app_area
,
sizeof
(
struct
host_app_area
)))
sizeof
(
struct
host_app_area
),
false
))
return
-
EIO
;
return
-
EIO
;
return
0
;
return
0
;
...
@@ -290,6 +276,7 @@ static void ath6kl_init_control_info(struct ath6kl *ar)
...
@@ -290,6 +276,7 @@ static void ath6kl_init_control_info(struct ath6kl *ar)
memset
(
&
ar
->
sc_params
,
0
,
sizeof
(
ar
->
sc_params
));
memset
(
&
ar
->
sc_params
,
0
,
sizeof
(
ar
->
sc_params
));
ar
->
sc_params
.
short_scan_ratio
=
WMI_SHORTSCANRATIO_DEFAULT
;
ar
->
sc_params
.
short_scan_ratio
=
WMI_SHORTSCANRATIO_DEFAULT
;
ar
->
sc_params
.
scan_ctrl_flags
=
DEFAULT_SCAN_CTRL_FLAGS
;
ar
->
sc_params
.
scan_ctrl_flags
=
DEFAULT_SCAN_CTRL_FLAGS
;
ar
->
lrssi_roam_threshold
=
DEF_LRSSI_ROAM_THRESHOLD
;
memset
((
u8
*
)
ar
->
sta_list
,
0
,
memset
((
u8
*
)
ar
->
sta_list
,
0
,
AP_MAX_NUM_STA
*
sizeof
(
struct
ath6kl_sta
));
AP_MAX_NUM_STA
*
sizeof
(
struct
ath6kl_sta
));
...
@@ -370,10 +357,10 @@ static void ath6kl_dump_target_assert_info(struct ath6kl *ar)
...
@@ -370,10 +357,10 @@ static void ath6kl_dump_target_assert_info(struct ath6kl *ar)
/* the reg dump pointer is copied to the host interest area */
/* the reg dump pointer is copied to the host interest area */
address
=
ath6kl_get_hi_item_addr
(
ar
,
HI_ITEM
(
hi_failure_state
));
address
=
ath6kl_get_hi_item_addr
(
ar
,
HI_ITEM
(
hi_failure_state
));
address
=
TARG_VTOP
(
address
);
address
=
TARG_VTOP
(
a
r
->
target_type
,
a
ddress
);
/* read RAM location through diagnostic window */
/* read RAM location through diagnostic window */
status
=
ath6kl_
read_reg_diag
(
ar
,
&
address
,
&
regdump_loc
);
status
=
ath6kl_
diag_read32
(
ar
,
address
,
&
regdump_loc
);
if
(
status
||
!
regdump_loc
)
{
if
(
status
||
!
regdump_loc
)
{
ath6kl_err
(
"failed to get ptr to register dump area
\n
"
);
ath6kl_err
(
"failed to get ptr to register dump area
\n
"
);
...
@@ -382,15 +369,11 @@ static void ath6kl_dump_target_assert_info(struct ath6kl *ar)
...
@@ -382,15 +369,11 @@ static void ath6kl_dump_target_assert_info(struct ath6kl *ar)
ath6kl_dbg
(
ATH6KL_DBG_TRC
,
"location of register dump data: 0x%X
\n
"
,
ath6kl_dbg
(
ATH6KL_DBG_TRC
,
"location of register dump data: 0x%X
\n
"
,
regdump_loc
);
regdump_loc
);
regdump_loc
=
TARG_VTOP
(
ar
->
target_type
,
regdump_loc
);
regdump_loc
=
TARG_VTOP
(
regdump_loc
);
/* fetch register dump data */
/* fetch register dump data */
status
=
ath6kl_access_datadiag
(
ar
,
status
=
ath6kl_diag_read
(
ar
,
regdump_loc
,
(
u8
*
)
&
regdump_val
[
0
],
regdump_loc
,
REG_DUMP_COUNT_AR6003
*
(
sizeof
(
u32
)));
(
u8
*
)
&
regdump_val
[
0
],
REG_DUMP_COUNT_AR6003
*
(
sizeof
(
u32
)),
true
);
if
(
status
)
{
if
(
status
)
{
ath6kl_err
(
"failed to get register dump
\n
"
);
ath6kl_err
(
"failed to get register dump
\n
"
);
...
@@ -416,6 +399,7 @@ void ath6kl_target_failure(struct ath6kl *ar)
...
@@ -416,6 +399,7 @@ void ath6kl_target_failure(struct ath6kl *ar)
static
int
ath6kl_target_config_wlan_params
(
struct
ath6kl
*
ar
)
static
int
ath6kl_target_config_wlan_params
(
struct
ath6kl
*
ar
)
{
{
int
status
=
0
;
int
status
=
0
;
int
ret
;
/*
/*
* Configure the device for rx dot11 header rules. "0,0" are the
* Configure the device for rx dot11 header rules. "0,0" are the
...
@@ -460,6 +444,28 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar)
...
@@ -460,6 +444,28 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar)
status
=
-
EIO
;
status
=
-
EIO
;
}
}
if
(
ar
->
p2p
)
{
ret
=
ath6kl_wmi_info_req_cmd
(
ar
->
wmi
,
P2P_FLAG_CAPABILITIES_REQ
|
P2P_FLAG_MACADDR_REQ
|
P2P_FLAG_HMODEL_REQ
);
if
(
ret
)
{
ath6kl_dbg
(
ATH6KL_DBG_TRC
,
"failed to request P2P "
"capabilities (%d) - assuming P2P not "
"supported
\n
"
,
ret
);
ar
->
p2p
=
0
;
}
}
if
(
ar
->
p2p
)
{
/* Enable Probe Request reporting for P2P */
ret
=
ath6kl_wmi_probe_report_req_cmd
(
ar
->
wmi
,
true
);
if
(
ret
)
{
ath6kl_dbg
(
ATH6KL_DBG_TRC
,
"failed to enable Probe "
"Request reporting (%d)
\n
"
,
ret
);
}
}
return
status
;
return
status
;
}
}
...
@@ -495,6 +501,10 @@ int ath6kl_configure_target(struct ath6kl *ar)
...
@@ -495,6 +501,10 @@ int ath6kl_configure_target(struct ath6kl *ar)
param
|=
(
1
<<
HI_OPTION_NUM_DEV_SHIFT
);
param
|=
(
1
<<
HI_OPTION_NUM_DEV_SHIFT
);
param
|=
(
fw_iftype
<<
HI_OPTION_FW_MODE_SHIFT
);
param
|=
(
fw_iftype
<<
HI_OPTION_FW_MODE_SHIFT
);
if
(
ar
->
p2p
&&
fw_iftype
==
HI_OPTION_FW_MODE_BSS_STA
)
{
param
|=
HI_OPTION_FW_SUBMODE_P2PDEV
<<
HI_OPTION_FW_SUBMODE_SHIFT
;
}
param
|=
(
0
<<
HI_OPTION_MAC_ADDR_METHOD_SHIFT
);
param
|=
(
0
<<
HI_OPTION_MAC_ADDR_METHOD_SHIFT
);
param
|=
(
0
<<
HI_OPTION_FW_BRIDGE_SHIFT
);
param
|=
(
0
<<
HI_OPTION_FW_BRIDGE_SHIFT
);
...
@@ -518,29 +528,21 @@ int ath6kl_configure_target(struct ath6kl *ar)
...
@@ -518,29 +528,21 @@ int ath6kl_configure_target(struct ath6kl *ar)
* but possible in theory.
* but possible in theory.
*/
*/
if
(
ar
->
target_type
==
TARGET_TYPE_AR6003
)
{
param
=
ar
->
hw
.
board_ext_data_addr
;
if
(
ar
->
version
.
target_ver
==
AR6003_REV2_VERSION
)
{
ram_reserved_size
=
ar
->
hw
.
reserved_ram_size
;
param
=
AR6003_REV2_BOARD_EXT_DATA_ADDRESS
;
ram_reserved_size
=
AR6003_REV2_RAM_RESERVE_SIZE
;
}
else
{
param
=
AR6003_REV3_BOARD_EXT_DATA_ADDRESS
;
ram_reserved_size
=
AR6003_REV3_RAM_RESERVE_SIZE
;
}
if
(
ath6kl_bmi_write
(
ar
,
if
(
ath6kl_bmi_write
(
ar
,
ath6kl_get_hi_item_addr
(
ar
,
ath6kl_get_hi_item_addr
(
ar
,
HI_ITEM
(
hi_board_ext_data
)),
HI_ITEM
(
hi_board_ext_data
)),
(
u8
*
)
&
param
,
4
)
!=
0
)
{
(
u8
*
)
&
param
,
4
)
!=
0
)
{
ath6kl_err
(
"bmi_write_memory for hi_board_ext_data failed
\n
"
);
ath6kl_err
(
"bmi_write_memory for hi_board_ext_data failed
\n
"
);
return
-
EIO
;
return
-
EIO
;
}
}
if
(
ath6kl_bmi_write
(
ar
,
if
(
ath6kl_bmi_write
(
ar
,
ath6kl_get_hi_item_addr
(
ar
,
ath6kl_get_hi_item_addr
(
ar
,
HI_ITEM
(
hi_end_ram_reserve_sz
)),
HI_ITEM
(
hi_end_ram_reserve_sz
)),
(
u8
*
)
&
ram_reserved_size
,
4
)
!=
0
)
{
(
u8
*
)
&
ram_reserved_size
,
4
)
!=
0
)
{
ath6kl_err
(
"bmi_write_memory for hi_end_ram_reserve_sz failed
\n
"
);
ath6kl_err
(
"bmi_write_memory for hi_end_ram_reserve_sz failed
\n
"
);
return
-
EIO
;
return
-
EIO
;
}
}
}
/* set the block size for the target */
/* set the block size for the target */
...
@@ -568,6 +570,12 @@ struct ath6kl *ath6kl_core_alloc(struct device *sdev)
...
@@ -568,6 +570,12 @@ struct ath6kl *ath6kl_core_alloc(struct device *sdev)
ar
->
wdev
=
wdev
;
ar
->
wdev
=
wdev
;
wdev
->
iftype
=
NL80211_IFTYPE_STATION
;
wdev
->
iftype
=
NL80211_IFTYPE_STATION
;
if
(
ath6kl_debug_init
(
ar
))
{
ath6kl_err
(
"Failed to initialize debugfs
\n
"
);
ath6kl_cfg80211_deinit
(
ar
);
return
NULL
;
}
dev
=
alloc_netdev
(
0
,
"wlan%d"
,
ether_setup
);
dev
=
alloc_netdev
(
0
,
"wlan%d"
,
ether_setup
);
if
(
!
dev
)
{
if
(
!
dev
)
{
ath6kl_err
(
"no memory for network device instance
\n
"
);
ath6kl_err
(
"no memory for network device instance
\n
"
);
...
@@ -579,7 +587,6 @@ struct ath6kl *ath6kl_core_alloc(struct device *sdev)
...
@@ -579,7 +587,6 @@ struct ath6kl *ath6kl_core_alloc(struct device *sdev)
SET_NETDEV_DEV
(
dev
,
wiphy_dev
(
wdev
->
wiphy
));
SET_NETDEV_DEV
(
dev
,
wiphy_dev
(
wdev
->
wiphy
));
wdev
->
netdev
=
dev
;
wdev
->
netdev
=
dev
;
ar
->
sme_state
=
SME_DISCONNECTED
;
ar
->
sme_state
=
SME_DISCONNECTED
;
ar
->
auto_auth_stage
=
AUTH_IDLE
;
init_netdev
(
dev
);
init_netdev
(
dev
);
...
@@ -611,29 +618,6 @@ int ath6kl_unavail_ev(struct ath6kl *ar)
...
@@ -611,29 +618,6 @@ int ath6kl_unavail_ev(struct ath6kl *ar)
}
}
/* firmware upload */
/* firmware upload */
static
u32
ath6kl_get_load_address
(
u32
target_ver
,
enum
addr_type
type
)
{
WARN_ON
(
target_ver
!=
AR6003_REV2_VERSION
&&
target_ver
!=
AR6003_REV3_VERSION
);
switch
(
type
)
{
case
DATASET_PATCH_ADDR
:
return
(
target_ver
==
AR6003_REV2_VERSION
)
?
AR6003_REV2_DATASET_PATCH_ADDRESS
:
AR6003_REV3_DATASET_PATCH_ADDRESS
;
case
APP_LOAD_ADDR
:
return
(
target_ver
==
AR6003_REV2_VERSION
)
?
AR6003_REV2_APP_LOAD_ADDRESS
:
0x1234
;
case
APP_START_OVERRIDE_ADDR
:
return
(
target_ver
==
AR6003_REV2_VERSION
)
?
AR6003_REV2_APP_START_OVERRIDE
:
AR6003_REV3_APP_START_OVERRIDE
;
default:
return
0
;
}
}
static
int
ath6kl_get_fw
(
struct
ath6kl
*
ar
,
const
char
*
filename
,
static
int
ath6kl_get_fw
(
struct
ath6kl
*
ar
,
const
char
*
filename
,
u8
**
fw
,
size_t
*
fw_len
)
u8
**
fw
,
size_t
*
fw_len
)
{
{
...
@@ -655,15 +639,79 @@ static int ath6kl_get_fw(struct ath6kl *ar, const char *filename,
...
@@ -655,15 +639,79 @@ static int ath6kl_get_fw(struct ath6kl *ar, const char *filename,
return
ret
;
return
ret
;
}
}
#ifdef CONFIG_OF
static
const
char
*
get_target_ver_dir
(
const
struct
ath6kl
*
ar
)
{
switch
(
ar
->
version
.
target_ver
)
{
case
AR6003_REV1_VERSION
:
return
"ath6k/AR6003/hw1.0"
;
case
AR6003_REV2_VERSION
:
return
"ath6k/AR6003/hw2.0"
;
case
AR6003_REV3_VERSION
:
return
"ath6k/AR6003/hw2.1.1"
;
}
ath6kl_warn
(
"%s: unsupported target version 0x%x.
\n
"
,
__func__
,
ar
->
version
.
target_ver
);
return
NULL
;
}
/*
* Check the device tree for a board-id and use it to construct
* the pathname to the firmware file. Used (for now) to find a
* fallback to the "bdata.bin" file--typically a symlink to the
* appropriate board-specific file.
*/
static
bool
check_device_tree
(
struct
ath6kl
*
ar
)
{
static
const
char
*
board_id_prop
=
"atheros,board-id"
;
struct
device_node
*
node
;
char
board_filename
[
64
];
const
char
*
board_id
;
int
ret
;
for_each_compatible_node
(
node
,
NULL
,
"atheros,ath6kl"
)
{
board_id
=
of_get_property
(
node
,
board_id_prop
,
NULL
);
if
(
board_id
==
NULL
)
{
ath6kl_warn
(
"No
\"
%s
\"
property on %s node.
\n
"
,
board_id_prop
,
node
->
name
);
continue
;
}
snprintf
(
board_filename
,
sizeof
(
board_filename
),
"%s/bdata.%s.bin"
,
get_target_ver_dir
(
ar
),
board_id
);
ret
=
ath6kl_get_fw
(
ar
,
board_filename
,
&
ar
->
fw_board
,
&
ar
->
fw_board_len
);
if
(
ret
)
{
ath6kl_err
(
"Failed to get DT board file %s: %d
\n
"
,
board_filename
,
ret
);
continue
;
}
return
true
;
}
return
false
;
}
#else
static
bool
check_device_tree
(
struct
ath6kl
*
ar
)
{
return
false
;
}
#endif
/* CONFIG_OF */
static
int
ath6kl_fetch_board_file
(
struct
ath6kl
*
ar
)
static
int
ath6kl_fetch_board_file
(
struct
ath6kl
*
ar
)
{
{
const
char
*
filename
;
const
char
*
filename
;
int
ret
;
int
ret
;
if
(
ar
->
fw_board
!=
NULL
)
return
0
;
switch
(
ar
->
version
.
target_ver
)
{
switch
(
ar
->
version
.
target_ver
)
{
case
AR6003_REV2_VERSION
:
case
AR6003_REV2_VERSION
:
filename
=
AR6003_REV2_BOARD_DATA_FILE
;
filename
=
AR6003_REV2_BOARD_DATA_FILE
;
break
;
break
;
case
AR6004_REV1_VERSION
:
filename
=
AR6004_REV1_BOARD_DATA_FILE
;
break
;
default:
default:
filename
=
AR6003_REV3_BOARD_DATA_FILE
;
filename
=
AR6003_REV3_BOARD_DATA_FILE
;
break
;
break
;
...
@@ -676,6 +724,11 @@ static int ath6kl_fetch_board_file(struct ath6kl *ar)
...
@@ -676,6 +724,11 @@ static int ath6kl_fetch_board_file(struct ath6kl *ar)
return
0
;
return
0
;
}
}
if
(
check_device_tree
(
ar
))
{
/* got board file from device tree */
return
0
;
}
/* there was no proper board file, try to use default instead */
/* there was no proper board file, try to use default instead */
ath6kl_warn
(
"Failed to get board file %s (%d), trying to find default board file.
\n
"
,
ath6kl_warn
(
"Failed to get board file %s (%d), trying to find default board file.
\n
"
,
filename
,
ret
);
filename
,
ret
);
...
@@ -684,6 +737,9 @@ static int ath6kl_fetch_board_file(struct ath6kl *ar)
...
@@ -684,6 +737,9 @@ static int ath6kl_fetch_board_file(struct ath6kl *ar)
case
AR6003_REV2_VERSION
:
case
AR6003_REV2_VERSION
:
filename
=
AR6003_REV2_DEFAULT_BOARD_DATA_FILE
;
filename
=
AR6003_REV2_DEFAULT_BOARD_DATA_FILE
;
break
;
break
;
case
AR6004_REV1_VERSION
:
filename
=
AR6004_REV1_DEFAULT_BOARD_DATA_FILE
;
break
;
default:
default:
filename
=
AR6003_REV3_DEFAULT_BOARD_DATA_FILE
;
filename
=
AR6003_REV3_DEFAULT_BOARD_DATA_FILE
;
break
;
break
;
...
@@ -703,25 +759,346 @@ static int ath6kl_fetch_board_file(struct ath6kl *ar)
...
@@ -703,25 +759,346 @@ static int ath6kl_fetch_board_file(struct ath6kl *ar)
return
0
;
return
0
;
}
}
static
int
ath6kl_fetch_otp_file
(
struct
ath6kl
*
ar
)
{
const
char
*
filename
;
int
ret
;
static
int
ath6kl_upload_board_file
(
struct
ath6kl
*
ar
)
if
(
ar
->
fw_otp
!=
NULL
)
return
0
;
switch
(
ar
->
version
.
target_ver
)
{
case
AR6003_REV2_VERSION
:
filename
=
AR6003_REV2_OTP_FILE
;
break
;
case
AR6004_REV1_VERSION
:
ath6kl_dbg
(
ATH6KL_DBG_TRC
,
"AR6004 doesn't need OTP file
\n
"
);
return
0
;
break
;
default:
filename
=
AR6003_REV3_OTP_FILE
;
break
;
}
ret
=
ath6kl_get_fw
(
ar
,
filename
,
&
ar
->
fw_otp
,
&
ar
->
fw_otp_len
);
if
(
ret
)
{
ath6kl_err
(
"Failed to get OTP file %s: %d
\n
"
,
filename
,
ret
);
return
ret
;
}
return
0
;
}
static
int
ath6kl_fetch_fw_file
(
struct
ath6kl
*
ar
)
{
{
u32
board_address
,
board_ext_address
,
param
;
const
char
*
filename
;
int
ret
;
if
(
ar
->
fw
!=
NULL
)
return
0
;
if
(
testmode
)
{
switch
(
ar
->
version
.
target_ver
)
{
case
AR6003_REV2_VERSION
:
filename
=
AR6003_REV2_TCMD_FIRMWARE_FILE
;
break
;
case
AR6003_REV3_VERSION
:
filename
=
AR6003_REV3_TCMD_FIRMWARE_FILE
;
break
;
case
AR6004_REV1_VERSION
:
ath6kl_warn
(
"testmode not supported with ar6004
\n
"
);
return
-
EOPNOTSUPP
;
default:
ath6kl_warn
(
"unknown target version: 0x%x
\n
"
,
ar
->
version
.
target_ver
);
return
-
EINVAL
;
}
set_bit
(
TESTMODE
,
&
ar
->
flag
);
goto
get_fw
;
}
switch
(
ar
->
version
.
target_ver
)
{
case
AR6003_REV2_VERSION
:
filename
=
AR6003_REV2_FIRMWARE_FILE
;
break
;
case
AR6004_REV1_VERSION
:
filename
=
AR6004_REV1_FIRMWARE_FILE
;
break
;
default:
filename
=
AR6003_REV3_FIRMWARE_FILE
;
break
;
}
get_fw:
ret
=
ath6kl_get_fw
(
ar
,
filename
,
&
ar
->
fw
,
&
ar
->
fw_len
);
if
(
ret
)
{
ath6kl_err
(
"Failed to get firmware file %s: %d
\n
"
,
filename
,
ret
);
return
ret
;
}
return
0
;
}
static
int
ath6kl_fetch_patch_file
(
struct
ath6kl
*
ar
)
{
const
char
*
filename
;
int
ret
;
int
ret
;
if
(
ar
->
fw_board
==
NULL
)
{
switch
(
ar
->
version
.
target_ver
)
{
ret
=
ath6kl_fetch_board_file
(
ar
);
case
AR6003_REV2_VERSION
:
if
(
ret
)
filename
=
AR6003_REV2_PATCH_FILE
;
break
;
case
AR6004_REV1_VERSION
:
/* FIXME: implement for AR6004 */
return
0
;
break
;
default:
filename
=
AR6003_REV3_PATCH_FILE
;
break
;
}
if
(
ar
->
fw_patch
==
NULL
)
{
ret
=
ath6kl_get_fw
(
ar
,
filename
,
&
ar
->
fw_patch
,
&
ar
->
fw_patch_len
);
if
(
ret
)
{
ath6kl_err
(
"Failed to get patch file %s: %d
\n
"
,
filename
,
ret
);
return
ret
;
return
ret
;
}
}
}
/* Determine where in Target RAM to write Board Data */
return
0
;
ath6kl_bmi_read
(
ar
,
}
ath6kl_get_hi_item_addr
(
ar
,
HI_ITEM
(
hi_board_data
)),
static
int
ath6kl_fetch_fw_api1
(
struct
ath6kl
*
ar
)
(
u8
*
)
&
board_address
,
4
);
{
ath6kl_dbg
(
ATH6KL_DBG_TRC
,
"board data download addr: 0x%x
\n
"
,
int
ret
;
board_address
);
ret
=
ath6kl_fetch_otp_file
(
ar
);
if
(
ret
)
return
ret
;
ret
=
ath6kl_fetch_fw_file
(
ar
);
if
(
ret
)
return
ret
;
ret
=
ath6kl_fetch_patch_file
(
ar
);
if
(
ret
)
return
ret
;
return
0
;
}
static
int
ath6kl_fetch_fw_api2
(
struct
ath6kl
*
ar
)
{
size_t
magic_len
,
len
,
ie_len
;
const
struct
firmware
*
fw
;
struct
ath6kl_fw_ie
*
hdr
;
const
char
*
filename
;
const
u8
*
data
;
int
ret
,
ie_id
,
i
,
index
,
bit
;
__le32
*
val
;
switch
(
ar
->
version
.
target_ver
)
{
case
AR6003_REV2_VERSION
:
filename
=
AR6003_REV2_FIRMWARE_2_FILE
;
break
;
case
AR6003_REV3_VERSION
:
filename
=
AR6003_REV3_FIRMWARE_2_FILE
;
break
;
case
AR6004_REV1_VERSION
:
filename
=
AR6004_REV1_FIRMWARE_2_FILE
;
break
;
default:
return
-
EOPNOTSUPP
;
}
ret
=
request_firmware
(
&
fw
,
filename
,
ar
->
dev
);
if
(
ret
)
return
ret
;
data
=
fw
->
data
;
len
=
fw
->
size
;
/* magic also includes the null byte, check that as well */
magic_len
=
strlen
(
ATH6KL_FIRMWARE_MAGIC
)
+
1
;
if
(
len
<
magic_len
)
{
ret
=
-
EINVAL
;
goto
out
;
}
if
(
memcmp
(
data
,
ATH6KL_FIRMWARE_MAGIC
,
magic_len
)
!=
0
)
{
ret
=
-
EINVAL
;
goto
out
;
}
len
-=
magic_len
;
data
+=
magic_len
;
/* loop elements */
while
(
len
>
sizeof
(
struct
ath6kl_fw_ie
))
{
/* hdr is unaligned! */
hdr
=
(
struct
ath6kl_fw_ie
*
)
data
;
ie_id
=
le32_to_cpup
(
&
hdr
->
id
);
ie_len
=
le32_to_cpup
(
&
hdr
->
len
);
len
-=
sizeof
(
*
hdr
);
data
+=
sizeof
(
*
hdr
);
if
(
len
<
ie_len
)
{
ret
=
-
EINVAL
;
goto
out
;
}
switch
(
ie_id
)
{
case
ATH6KL_FW_IE_OTP_IMAGE
:
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
"found otp image ie (%zd B)
\n
"
,
ie_len
);
ar
->
fw_otp
=
kmemdup
(
data
,
ie_len
,
GFP_KERNEL
);
if
(
ar
->
fw_otp
==
NULL
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
ar
->
fw_otp_len
=
ie_len
;
break
;
case
ATH6KL_FW_IE_FW_IMAGE
:
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
"found fw image ie (%zd B)
\n
"
,
ie_len
);
ar
->
fw
=
kmemdup
(
data
,
ie_len
,
GFP_KERNEL
);
if
(
ar
->
fw
==
NULL
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
ar
->
fw_len
=
ie_len
;
break
;
case
ATH6KL_FW_IE_PATCH_IMAGE
:
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
"found patch image ie (%zd B)
\n
"
,
ie_len
);
ar
->
fw_patch
=
kmemdup
(
data
,
ie_len
,
GFP_KERNEL
);
if
(
ar
->
fw_patch
==
NULL
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
ar
->
fw_patch_len
=
ie_len
;
break
;
case
ATH6KL_FW_IE_RESERVED_RAM_SIZE
:
val
=
(
__le32
*
)
data
;
ar
->
hw
.
reserved_ram_size
=
le32_to_cpup
(
val
);
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
"found reserved ram size ie 0x%d
\n
"
,
ar
->
hw
.
reserved_ram_size
);
break
;
case
ATH6KL_FW_IE_CAPABILITIES
:
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
"found firmware capabilities ie (%zd B)
\n
"
,
ie_len
);
for
(
i
=
0
;
i
<
ATH6KL_FW_CAPABILITY_MAX
;
i
++
)
{
index
=
ALIGN
(
i
,
8
)
/
8
;
bit
=
i
%
8
;
if
(
data
[
index
]
&
(
1
<<
bit
))
__set_bit
(
i
,
ar
->
fw_capabilities
);
}
ath6kl_dbg_dump
(
ATH6KL_DBG_BOOT
,
"capabilities"
,
""
,
ar
->
fw_capabilities
,
sizeof
(
ar
->
fw_capabilities
));
break
;
case
ATH6KL_FW_IE_PATCH_ADDR
:
if
(
ie_len
!=
sizeof
(
*
val
))
break
;
val
=
(
__le32
*
)
data
;
ar
->
hw
.
dataset_patch_addr
=
le32_to_cpup
(
val
);
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
"found patch address ie 0x%d
\n
"
,
ar
->
hw
.
dataset_patch_addr
);
break
;
default:
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
"Unknown fw ie: %u
\n
"
,
le32_to_cpup
(
&
hdr
->
id
));
break
;
}
len
-=
ie_len
;
data
+=
ie_len
;
};
ret
=
0
;
out:
release_firmware
(
fw
);
return
ret
;
}
static
int
ath6kl_fetch_firmwares
(
struct
ath6kl
*
ar
)
{
int
ret
;
ret
=
ath6kl_fetch_board_file
(
ar
);
if
(
ret
)
return
ret
;
ret
=
ath6kl_fetch_fw_api2
(
ar
);
if
(
ret
==
0
)
{
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
"using fw api 2
\n
"
);
return
0
;
}
ret
=
ath6kl_fetch_fw_api1
(
ar
);
if
(
ret
)
return
ret
;
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
"using fw api 1
\n
"
);
return
0
;
}
static
int
ath6kl_upload_board_file
(
struct
ath6kl
*
ar
)
{
u32
board_address
,
board_ext_address
,
param
;
u32
board_data_size
,
board_ext_data_size
;
int
ret
;
if
(
WARN_ON
(
ar
->
fw_board
==
NULL
))
return
-
ENOENT
;
/*
* Determine where in Target RAM to write Board Data.
* For AR6004, host determine Target RAM address for
* writing board data.
*/
if
(
ar
->
target_type
==
TARGET_TYPE_AR6004
)
{
board_address
=
AR6004_REV1_BOARD_DATA_ADDRESS
;
ath6kl_bmi_write
(
ar
,
ath6kl_get_hi_item_addr
(
ar
,
HI_ITEM
(
hi_board_data
)),
(
u8
*
)
&
board_address
,
4
);
}
else
{
ath6kl_bmi_read
(
ar
,
ath6kl_get_hi_item_addr
(
ar
,
HI_ITEM
(
hi_board_data
)),
(
u8
*
)
&
board_address
,
4
);
}
/* determine where in target ram to write extended board data */
/* determine where in target ram to write extended board data */
ath6kl_bmi_read
(
ar
,
ath6kl_bmi_read
(
ar
,
...
@@ -729,21 +1106,37 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
...
@@ -729,21 +1106,37 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
HI_ITEM
(
hi_board_ext_data
)),
HI_ITEM
(
hi_board_ext_data
)),
(
u8
*
)
&
board_ext_address
,
4
);
(
u8
*
)
&
board_ext_address
,
4
);
ath6kl_dbg
(
ATH6KL_DBG_TRC
,
"board file download addr: 0x%x
\n
"
,
board_ext_address
);
if
(
board_ext_address
==
0
)
{
if
(
board_ext_address
==
0
)
{
ath6kl_err
(
"Failed to get board file target address.
\n
"
);
ath6kl_err
(
"Failed to get board file target address.
\n
"
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
if
(
ar
->
fw_board_len
==
(
AR6003_BOARD_DATA_SZ
+
switch
(
ar
->
target_type
)
{
AR6003_BOARD_EXT_DATA_SZ
))
{
case
TARGET_TYPE_AR6003
:
board_data_size
=
AR6003_BOARD_DATA_SZ
;
board_ext_data_size
=
AR6003_BOARD_EXT_DATA_SZ
;
break
;
case
TARGET_TYPE_AR6004
:
board_data_size
=
AR6004_BOARD_DATA_SZ
;
board_ext_data_size
=
AR6004_BOARD_EXT_DATA_SZ
;
break
;
default:
WARN_ON
(
1
);
return
-
EINVAL
;
break
;
}
if
(
ar
->
fw_board_len
==
(
board_data_size
+
board_ext_data_size
))
{
/* write extended board data */
/* write extended board data */
ret
=
ath6kl_bmi_write
(
ar
,
board_ext_address
,
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
ar
->
fw_board
+
AR6003_BOARD_DATA_SZ
,
"writing extended board data to 0x%x (%d B)
\n
"
,
AR6003_BOARD_EXT_DATA_SZ
);
board_ext_address
,
board_ext_data_size
);
ret
=
ath6kl_bmi_write
(
ar
,
board_ext_address
,
ar
->
fw_board
+
board_data_size
,
board_ext_data_size
);
if
(
ret
)
{
if
(
ret
)
{
ath6kl_err
(
"Failed to write extended board data: %d
\n
"
,
ath6kl_err
(
"Failed to write extended board data: %d
\n
"
,
ret
);
ret
);
...
@@ -751,21 +1144,25 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
...
@@ -751,21 +1144,25 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
}
}
/* record that extended board data is initialized */
/* record that extended board data is initialized */
param
=
(
AR6003_BOARD_EXT_DATA_SZ
<<
16
)
|
1
;
param
=
(
board_ext_data_size
<<
16
)
|
1
;
ath6kl_bmi_write
(
ar
,
ath6kl_bmi_write
(
ar
,
ath6kl_get_hi_item_addr
(
ar
,
ath6kl_get_hi_item_addr
(
ar
,
HI_ITEM
(
hi_board_ext_data_config
)),
HI_ITEM
(
hi_board_ext_data_config
)),
(
unsigned
char
*
)
&
param
,
4
);
(
unsigned
char
*
)
&
param
,
4
);
}
}
if
(
ar
->
fw_board_len
<
AR6003_BOARD_DATA_SZ
)
{
if
(
ar
->
fw_board_len
<
board_data_size
)
{
ath6kl_err
(
"Too small board file: %zu
\n
"
,
ar
->
fw_board_len
);
ath6kl_err
(
"Too small board file: %zu
\n
"
,
ar
->
fw_board_len
);
ret
=
-
EINVAL
;
ret
=
-
EINVAL
;
return
ret
;
return
ret
;
}
}
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
"writing board file to 0x%x (%d B)
\n
"
,
board_address
,
board_data_size
);
ret
=
ath6kl_bmi_write
(
ar
,
board_address
,
ar
->
fw_board
,
ret
=
ath6kl_bmi_write
(
ar
,
board_address
,
ar
->
fw_board
,
AR6003_BOARD_DATA_SZ
);
board_data_size
);
if
(
ret
)
{
if
(
ret
)
{
ath6kl_err
(
"Board file bmi write failed: %d
\n
"
,
ret
);
ath6kl_err
(
"Board file bmi write failed: %d
\n
"
,
ret
);
...
@@ -784,31 +1181,16 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
...
@@ -784,31 +1181,16 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
static
int
ath6kl_upload_otp
(
struct
ath6kl
*
ar
)
static
int
ath6kl_upload_otp
(
struct
ath6kl
*
ar
)
{
{
const
char
*
filename
;
u32
address
,
param
;
u32
address
,
param
;
int
ret
;
int
ret
;
switch
(
ar
->
version
.
target_ver
)
{
if
(
WARN_ON
(
ar
->
fw_otp
==
NULL
))
case
AR6003_REV2_VERSION
:
return
-
ENOENT
;
filename
=
AR6003_REV2_OTP_FILE
;
break
;
default:
filename
=
AR6003_REV3_OTP_FILE
;
break
;
}
if
(
ar
->
fw_otp
==
NULL
)
{
address
=
ar
->
hw
.
app_load_addr
;
ret
=
ath6kl_get_fw
(
ar
,
filename
,
&
ar
->
fw_otp
,
&
ar
->
fw_otp_len
);
if
(
ret
)
{
ath6kl_err
(
"Failed to get OTP file %s: %d
\n
"
,
filename
,
ret
);
return
ret
;
}
}
a
ddress
=
ath6kl_get_load_address
(
ar
->
version
.
target_ver
,
a
th6kl_dbg
(
ATH6KL_DBG_BOOT
,
"writing otp to 0x%x (%zd B)
\n
"
,
address
,
APP_LOAD_ADDR
);
ar
->
fw_otp_len
);
ret
=
ath6kl_bmi_fast_download
(
ar
,
address
,
ar
->
fw_otp
,
ret
=
ath6kl_bmi_fast_download
(
ar
,
address
,
ar
->
fw_otp
,
ar
->
fw_otp_len
);
ar
->
fw_otp_len
);
...
@@ -817,10 +1199,25 @@ static int ath6kl_upload_otp(struct ath6kl *ar)
...
@@ -817,10 +1199,25 @@ static int ath6kl_upload_otp(struct ath6kl *ar)
return
ret
;
return
ret
;
}
}
/* read firmware start address */
ret
=
ath6kl_bmi_read
(
ar
,
ath6kl_get_hi_item_addr
(
ar
,
HI_ITEM
(
hi_app_start
)),
(
u8
*
)
&
address
,
sizeof
(
address
));
if
(
ret
)
{
ath6kl_err
(
"Failed to read hi_app_start: %d
\n
"
,
ret
);
return
ret
;
}
ar
->
hw
.
app_start_override_addr
=
address
;
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
"app_start_override_addr 0x%x
\n
"
,
ar
->
hw
.
app_start_override_addr
);
/* execute the OTP code */
/* execute the OTP code */
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
"executing OTP at 0x%x
\n
"
,
address
);
param
=
0
;
param
=
0
;
address
=
ath6kl_get_load_address
(
ar
->
version
.
target_ver
,
APP_START_OVERRIDE_ADDR
);
ath6kl_bmi_execute
(
ar
,
address
,
&
param
);
ath6kl_bmi_execute
(
ar
,
address
,
&
param
);
return
ret
;
return
ret
;
...
@@ -828,30 +1225,16 @@ static int ath6kl_upload_otp(struct ath6kl *ar)
...
@@ -828,30 +1225,16 @@ static int ath6kl_upload_otp(struct ath6kl *ar)
static
int
ath6kl_upload_firmware
(
struct
ath6kl
*
ar
)
static
int
ath6kl_upload_firmware
(
struct
ath6kl
*
ar
)
{
{
const
char
*
filename
;
u32
address
;
u32
address
;
int
ret
;
int
ret
;
switch
(
ar
->
version
.
target_ver
)
{
if
(
WARN_ON
(
ar
->
fw
==
NULL
))
case
AR6003_REV2_VERSION
:
return
-
ENOENT
;
filename
=
AR6003_REV2_FIRMWARE_FILE
;
break
;
default:
filename
=
AR6003_REV3_FIRMWARE_FILE
;
break
;
}
if
(
ar
->
fw
==
NULL
)
{
address
=
ar
->
hw
.
app_load_addr
;
ret
=
ath6kl_get_fw
(
ar
,
filename
,
&
ar
->
fw
,
&
ar
->
fw_len
);
if
(
ret
)
{
ath6kl_err
(
"Failed to get firmware file %s: %d
\n
"
,
filename
,
ret
);
return
ret
;
}
}
a
ddress
=
ath6kl_get_load_address
(
ar
->
version
.
target_ver
,
a
th6kl_dbg
(
ATH6KL_DBG_BOOT
,
"writing firmware to 0x%x (%zd B)
\n
"
,
APP_LOAD_ADDR
);
address
,
ar
->
fw_len
);
ret
=
ath6kl_bmi_fast_download
(
ar
,
address
,
ar
->
fw
,
ar
->
fw_len
);
ret
=
ath6kl_bmi_fast_download
(
ar
,
address
,
ar
->
fw
,
ar
->
fw_len
);
...
@@ -860,41 +1243,29 @@ static int ath6kl_upload_firmware(struct ath6kl *ar)
...
@@ -860,41 +1243,29 @@ static int ath6kl_upload_firmware(struct ath6kl *ar)
return
ret
;
return
ret
;
}
}
/* Set starting address for firmware */
/*
address
=
ath6kl_get_load_address
(
ar
->
version
.
target_ver
,
* Set starting address for firmware
APP_START_OVERRIDE_ADDR
);
* Don't need to setup app_start override addr on AR6004
ath6kl_bmi_set_app_start
(
ar
,
address
);
*/
if
(
ar
->
target_type
!=
TARGET_TYPE_AR6004
)
{
address
=
ar
->
hw
.
app_start_override_addr
;
ath6kl_bmi_set_app_start
(
ar
,
address
);
}
return
ret
;
return
ret
;
}
}
static
int
ath6kl_upload_patch
(
struct
ath6kl
*
ar
)
static
int
ath6kl_upload_patch
(
struct
ath6kl
*
ar
)
{
{
const
char
*
filename
;
u32
address
,
param
;
u32
address
,
param
;
int
ret
;
int
ret
;
switch
(
ar
->
version
.
target_ver
)
{
if
(
WARN_ON
(
ar
->
fw_patch
==
NULL
))
case
AR6003_REV2_VERSION
:
return
-
ENOENT
;
filename
=
AR6003_REV2_PATCH_FILE
;
break
;
default:
filename
=
AR6003_REV3_PATCH_FILE
;
break
;
}
if
(
ar
->
fw_patch
==
NULL
)
{
address
=
ar
->
hw
.
dataset_patch_addr
;
ret
=
ath6kl_get_fw
(
ar
,
filename
,
&
ar
->
fw_patch
,
&
ar
->
fw_patch_len
);
if
(
ret
)
{
ath6kl_err
(
"Failed to get patch file %s: %d
\n
"
,
filename
,
ret
);
return
ret
;
}
}
a
ddress
=
ath6kl_get_load_address
(
ar
->
version
.
target_ver
,
a
th6kl_dbg
(
ATH6KL_DBG_BOOT
,
"writing patch to 0x%x (%zd B)
\n
"
,
DATASET_PATCH_ADDR
);
address
,
ar
->
fw_patch_len
);
ret
=
ath6kl_bmi_write
(
ar
,
address
,
ar
->
fw_patch
,
ar
->
fw_patch_len
);
ret
=
ath6kl_bmi_write
(
ar
,
address
,
ar
->
fw_patch
,
ar
->
fw_patch_len
);
if
(
ret
)
{
if
(
ret
)
{
...
@@ -916,7 +1287,8 @@ static int ath6kl_init_upload(struct ath6kl *ar)
...
@@ -916,7 +1287,8 @@ static int ath6kl_init_upload(struct ath6kl *ar)
u32
param
,
options
,
sleep
,
address
;
u32
param
,
options
,
sleep
,
address
;
int
status
=
0
;
int
status
=
0
;
if
(
ar
->
target_type
!=
TARGET_TYPE_AR6003
)
if
(
ar
->
target_type
!=
TARGET_TYPE_AR6003
&&
ar
->
target_type
!=
TARGET_TYPE_AR6004
)
return
-
EINVAL
;
return
-
EINVAL
;
/* temporarily disable system sleep */
/* temporarily disable system sleep */
...
@@ -948,18 +1320,22 @@ static int ath6kl_init_upload(struct ath6kl *ar)
...
@@ -948,18 +1320,22 @@ static int ath6kl_init_upload(struct ath6kl *ar)
options
,
sleep
);
options
,
sleep
);
/* program analog PLL register */
/* program analog PLL register */
status
=
ath6kl_bmi_reg_write
(
ar
,
ATH6KL_ANALOG_PLL_REGISTER
,
/* no need to control 40/44MHz clock on AR6004 */
0xF9104001
);
if
(
ar
->
target_type
!=
TARGET_TYPE_AR6004
)
{
if
(
status
)
status
=
ath6kl_bmi_reg_write
(
ar
,
ATH6KL_ANALOG_PLL_REGISTER
,
return
status
;
0xF9104001
)
;
/* Run at 80/88MHz by default */
if
(
status
)
param
=
SM
(
CPU_CLOCK_STANDARD
,
1
)
;
return
status
;
address
=
RTC_BASE_ADDRESS
+
CPU_CLOCK_ADDRESS
;
/* Run at 80/88MHz by default */
status
=
ath6kl_bmi_reg_write
(
ar
,
address
,
param
);
param
=
SM
(
CPU_CLOCK_STANDARD
,
1
);
if
(
status
)
return
status
;
address
=
RTC_BASE_ADDRESS
+
CPU_CLOCK_ADDRESS
;
status
=
ath6kl_bmi_reg_write
(
ar
,
address
,
param
);
if
(
status
)
return
status
;
}
param
=
0
;
param
=
0
;
address
=
RTC_BASE_ADDRESS
+
LPO_CAL_ADDRESS
;
address
=
RTC_BASE_ADDRESS
+
LPO_CAL_ADDRESS
;
...
@@ -1036,6 +1412,45 @@ static int ath6kl_init_upload(struct ath6kl *ar)
...
@@ -1036,6 +1412,45 @@ static int ath6kl_init_upload(struct ath6kl *ar)
return
status
;
return
status
;
}
}
static
int
ath6kl_init_hw_params
(
struct
ath6kl
*
ar
)
{
switch
(
ar
->
version
.
target_ver
)
{
case
AR6003_REV2_VERSION
:
ar
->
hw
.
dataset_patch_addr
=
AR6003_REV2_DATASET_PATCH_ADDRESS
;
ar
->
hw
.
app_load_addr
=
AR6003_REV2_APP_LOAD_ADDRESS
;
ar
->
hw
.
board_ext_data_addr
=
AR6003_REV2_BOARD_EXT_DATA_ADDRESS
;
ar
->
hw
.
reserved_ram_size
=
AR6003_REV2_RAM_RESERVE_SIZE
;
break
;
case
AR6003_REV3_VERSION
:
ar
->
hw
.
dataset_patch_addr
=
AR6003_REV3_DATASET_PATCH_ADDRESS
;
ar
->
hw
.
app_load_addr
=
0x1234
;
ar
->
hw
.
board_ext_data_addr
=
AR6003_REV3_BOARD_EXT_DATA_ADDRESS
;
ar
->
hw
.
reserved_ram_size
=
AR6003_REV3_RAM_RESERVE_SIZE
;
break
;
case
AR6004_REV1_VERSION
:
ar
->
hw
.
dataset_patch_addr
=
AR6003_REV2_DATASET_PATCH_ADDRESS
;
ar
->
hw
.
app_load_addr
=
AR6003_REV3_APP_LOAD_ADDRESS
;
ar
->
hw
.
board_ext_data_addr
=
AR6004_REV1_BOARD_EXT_DATA_ADDRESS
;
ar
->
hw
.
reserved_ram_size
=
AR6004_REV1_RAM_RESERVE_SIZE
;
break
;
default:
ath6kl_err
(
"Unsupported hardware version: 0x%x
\n
"
,
ar
->
version
.
target_ver
);
return
-
EINVAL
;
}
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
"target_ver 0x%x target_type 0x%x dataset_patch 0x%x app_load_addr 0x%x
\n
"
,
ar
->
version
.
target_ver
,
ar
->
target_type
,
ar
->
hw
.
dataset_patch_addr
,
ar
->
hw
.
app_load_addr
);
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
"app_start_override_addr 0x%x board_ext_data_addr 0x%x reserved_ram_size 0x%x"
,
ar
->
hw
.
app_start_override_addr
,
ar
->
hw
.
board_ext_data_addr
,
ar
->
hw
.
reserved_ram_size
);
return
0
;
}
static
int
ath6kl_init
(
struct
net_device
*
dev
)
static
int
ath6kl_init
(
struct
net_device
*
dev
)
{
{
struct
ath6kl
*
ar
=
ath6kl_priv
(
dev
);
struct
ath6kl
*
ar
=
ath6kl_priv
(
dev
);
...
@@ -1062,8 +1477,6 @@ static int ath6kl_init(struct net_device *dev)
...
@@ -1062,8 +1477,6 @@ static int ath6kl_init(struct net_device *dev)
ath6kl_dbg
(
ATH6KL_DBG_TRC
,
"%s: got wmi @ 0x%p.
\n
"
,
__func__
,
ar
->
wmi
);
ath6kl_dbg
(
ATH6KL_DBG_TRC
,
"%s: got wmi @ 0x%p.
\n
"
,
__func__
,
ar
->
wmi
);
wlan_node_table_init
(
&
ar
->
scan_table
);
/*
/*
* The reason we have to wait for the target here is that the
* The reason we have to wait for the target here is that the
* driver layer has to init BMI in order to set the host block
* driver layer has to init BMI in order to set the host block
...
@@ -1111,6 +1524,8 @@ static int ath6kl_init(struct net_device *dev)
...
@@ -1111,6 +1524,8 @@ static int ath6kl_init(struct net_device *dev)
&
ar
->
flag
),
&
ar
->
flag
),
WMI_TIMEOUT
);
WMI_TIMEOUT
);
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
"firmware booted
\n
"
);
if
(
ar
->
version
.
abi_ver
!=
ATH6KL_ABI_VERSION
)
{
if
(
ar
->
version
.
abi_ver
!=
ATH6KL_ABI_VERSION
)
{
ath6kl_err
(
"abi version mismatch: host(0x%x), target(0x%x)
\n
"
,
ath6kl_err
(
"abi version mismatch: host(0x%x), target(0x%x)
\n
"
,
ATH6KL_ABI_VERSION
,
ar
->
version
.
abi_ver
);
ATH6KL_ABI_VERSION
,
ar
->
version
.
abi_ver
);
...
@@ -1133,6 +1548,8 @@ static int ath6kl_init(struct net_device *dev)
...
@@ -1133,6 +1548,8 @@ static int ath6kl_init(struct net_device *dev)
ar
->
conf_flags
=
ATH6KL_CONF_IGNORE_ERP_BARKER
|
ar
->
conf_flags
=
ATH6KL_CONF_IGNORE_ERP_BARKER
|
ATH6KL_CONF_ENABLE_11N
|
ATH6KL_CONF_ENABLE_TX_BURST
;
ATH6KL_CONF_ENABLE_11N
|
ATH6KL_CONF_ENABLE_TX_BURST
;
ar
->
wdev
->
wiphy
->
flags
|=
WIPHY_FLAG_SUPPORTS_FW_ROAM
;
status
=
ath6kl_target_config_wlan_params
(
ar
);
status
=
ath6kl_target_config_wlan_params
(
ar
);
if
(
!
status
)
if
(
!
status
)
goto
ath6kl_init_done
;
goto
ath6kl_init_done
;
...
@@ -1145,7 +1562,6 @@ static int ath6kl_init(struct net_device *dev)
...
@@ -1145,7 +1562,6 @@ static int ath6kl_init(struct net_device *dev)
err_cleanup_scatter:
err_cleanup_scatter:
ath6kl_hif_cleanup_scatter
(
ar
);
ath6kl_hif_cleanup_scatter
(
ar
);
err_node_cleanup:
err_node_cleanup:
wlan_node_table_cleanup
(
&
ar
->
scan_table
);
ath6kl_wmi_shutdown
(
ar
->
wmi
);
ath6kl_wmi_shutdown
(
ar
->
wmi
);
clear_bit
(
WMI_ENABLED
,
&
ar
->
flag
);
clear_bit
(
WMI_ENABLED
,
&
ar
->
flag
);
ar
->
wmi
=
NULL
;
ar
->
wmi
=
NULL
;
...
@@ -1175,6 +1591,10 @@ int ath6kl_core_init(struct ath6kl *ar)
...
@@ -1175,6 +1591,10 @@ int ath6kl_core_init(struct ath6kl *ar)
ar
->
target_type
=
le32_to_cpu
(
targ_info
.
type
);
ar
->
target_type
=
le32_to_cpu
(
targ_info
.
type
);
ar
->
wdev
->
wiphy
->
hw_version
=
le32_to_cpu
(
targ_info
.
version
);
ar
->
wdev
->
wiphy
->
hw_version
=
le32_to_cpu
(
targ_info
.
version
);
ret
=
ath6kl_init_hw_params
(
ar
);
if
(
ret
)
goto
err_bmi_cleanup
;
ret
=
ath6kl_configure_target
(
ar
);
ret
=
ath6kl_configure_target
(
ar
);
if
(
ret
)
if
(
ret
)
goto
err_bmi_cleanup
;
goto
err_bmi_cleanup
;
...
@@ -1193,6 +1613,10 @@ int ath6kl_core_init(struct ath6kl *ar)
...
@@ -1193,6 +1613,10 @@ int ath6kl_core_init(struct ath6kl *ar)
goto
err_htc_cleanup
;
goto
err_htc_cleanup
;
}
}
ret
=
ath6kl_fetch_firmwares
(
ar
);
if
(
ret
)
goto
err_htc_cleanup
;
ret
=
ath6kl_init_upload
(
ar
);
ret
=
ath6kl_init_upload
(
ar
);
if
(
ret
)
if
(
ret
)
goto
err_htc_cleanup
;
goto
err_htc_cleanup
;
...
@@ -1285,6 +1709,8 @@ void ath6kl_destroy(struct net_device *dev, unsigned int unregister)
...
@@ -1285,6 +1709,8 @@ void ath6kl_destroy(struct net_device *dev, unsigned int unregister)
ath6kl_bmi_cleanup
(
ar
);
ath6kl_bmi_cleanup
(
ar
);
ath6kl_debug_cleanup
(
ar
);
if
(
unregister
&&
test_bit
(
NETDEV_REGISTERED
,
&
ar
->
flag
))
{
if
(
unregister
&&
test_bit
(
NETDEV_REGISTERED
,
&
ar
->
flag
))
{
unregister_netdev
(
dev
);
unregister_netdev
(
dev
);
clear_bit
(
NETDEV_REGISTERED
,
&
ar
->
flag
);
clear_bit
(
NETDEV_REGISTERED
,
&
ar
->
flag
);
...
@@ -1292,8 +1718,6 @@ void ath6kl_destroy(struct net_device *dev, unsigned int unregister)
...
@@ -1292,8 +1718,6 @@ void ath6kl_destroy(struct net_device *dev, unsigned int unregister)
free_netdev
(
dev
);
free_netdev
(
dev
);
wlan_node_table_cleanup
(
&
ar
->
scan_table
);
kfree
(
ar
->
fw_board
);
kfree
(
ar
->
fw_board
);
kfree
(
ar
->
fw_otp
);
kfree
(
ar
->
fw_otp
);
kfree
(
ar
->
fw
);
kfree
(
ar
->
fw
);
...
...
drivers/net/wireless/ath/ath6kl/main.c
View file @
a5abbcb2
...
@@ -61,7 +61,8 @@ static void ath6kl_add_new_sta(struct ath6kl *ar, u8 *mac, u16 aid, u8 *wpaie,
...
@@ -61,7 +61,8 @@ static void ath6kl_add_new_sta(struct ath6kl *ar, u8 *mac, u16 aid, u8 *wpaie,
sta
=
&
ar
->
sta_list
[
free_slot
];
sta
=
&
ar
->
sta_list
[
free_slot
];
memcpy
(
sta
->
mac
,
mac
,
ETH_ALEN
);
memcpy
(
sta
->
mac
,
mac
,
ETH_ALEN
);
memcpy
(
sta
->
wpa_ie
,
wpaie
,
ielen
);
if
(
ielen
<=
ATH6KL_MAX_IE
)
memcpy
(
sta
->
wpa_ie
,
wpaie
,
ielen
);
sta
->
aid
=
aid
;
sta
->
aid
=
aid
;
sta
->
keymgmt
=
keymgmt
;
sta
->
keymgmt
=
keymgmt
;
sta
->
ucipher
=
ucipher
;
sta
->
ucipher
=
ucipher
;
...
@@ -177,8 +178,8 @@ void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie)
...
@@ -177,8 +178,8 @@ void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie)
static
int
ath6kl_set_addrwin_reg
(
struct
ath6kl
*
ar
,
u32
reg_addr
,
u32
addr
)
static
int
ath6kl_set_addrwin_reg
(
struct
ath6kl
*
ar
,
u32
reg_addr
,
u32
addr
)
{
{
int
status
;
int
status
;
u8
addr_val
[
4
];
s32
i
;
s32
i
;
__le32
addr_val
;
/*
/*
* Write bytes 1,2,3 of the register to set the upper address bytes,
* Write bytes 1,2,3 of the register to set the upper address bytes,
...
@@ -188,16 +189,18 @@ static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr)
...
@@ -188,16 +189,18 @@ static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr)
for
(
i
=
1
;
i
<=
3
;
i
++
)
{
for
(
i
=
1
;
i
<=
3
;
i
++
)
{
/*
/*
* Fill the buffer with the address byte value we want to
* Fill the buffer with the address byte value we want to
* hit 4 times.
* hit 4 times. No need to worry about endianness as the
* same byte is copied to all four bytes of addr_val at
* any time.
*/
*/
memset
(
addr_val
,
((
u8
*
)
&
addr
)[
i
],
4
);
memset
(
(
u8
*
)
&
addr_val
,
((
u8
*
)
&
addr
)[
i
],
4
);
/*
/*
* Hit each byte of the register address with a 4-byte
* Hit each byte of the register address with a 4-byte
* write operation to the same address, this is a harmless
* write operation to the same address, this is a harmless
* operation.
* operation.
*/
*/
status
=
hif_read_write_sync
(
ar
,
reg_addr
+
i
,
addr_val
,
status
=
hif_read_write_sync
(
ar
,
reg_addr
+
i
,
(
u8
*
)
&
addr_val
,
4
,
HIF_WR_SYNC_BYTE_FIX
);
4
,
HIF_WR_SYNC_BYTE_FIX
);
if
(
status
)
if
(
status
)
break
;
break
;
...
@@ -215,7 +218,9 @@ static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr)
...
@@ -215,7 +218,9 @@ static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr)
* cycle to start, the extra 3 byte write to bytes 1,2,3 has no
* cycle to start, the extra 3 byte write to bytes 1,2,3 has no
* effect since we are writing the same values again
* effect since we are writing the same values again
*/
*/
status
=
hif_read_write_sync
(
ar
,
reg_addr
,
(
u8
*
)(
&
addr
),
addr_val
=
cpu_to_le32
(
addr
);
status
=
hif_read_write_sync
(
ar
,
reg_addr
,
(
u8
*
)
&
(
addr_val
),
4
,
HIF_WR_SYNC_BYTE_INC
);
4
,
HIF_WR_SYNC_BYTE_INC
);
if
(
status
)
{
if
(
status
)
{
...
@@ -228,90 +233,193 @@ static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr)
...
@@ -228,90 +233,193 @@ static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr)
}
}
/*
/*
* Read from the
ATH6KL through its diagnostic window. No cooperation from
* Read from the
hardware through its diagnostic window. No cooperation
*
the Target
is required for this.
*
from the firmware
is required for this.
*/
*/
int
ath6kl_
read_reg_diag
(
struct
ath6kl
*
ar
,
u32
*
address
,
u32
*
data
)
int
ath6kl_
diag_read32
(
struct
ath6kl
*
ar
,
u32
address
,
u32
*
value
)
{
{
int
status
;
int
ret
;
/* set window register to start read cycle */
/* set window register to start read cycle */
status
=
ath6kl_set_addrwin_reg
(
ar
,
WINDOW_READ_ADDR_ADDRESS
,
ret
=
ath6kl_set_addrwin_reg
(
ar
,
WINDOW_READ_ADDR_ADDRESS
,
address
);
*
address
);
if
(
ret
)
return
ret
;
if
(
status
)
return
status
;
/* read the data */
/* read the data */
status
=
hif_read_write_sync
(
ar
,
WINDOW_DATA_ADDRESS
,
(
u8
*
)
data
,
ret
=
hif_read_write_sync
(
ar
,
WINDOW_DATA_ADDRESS
,
(
u8
*
)
value
,
sizeof
(
u32
),
HIF_RD_SYNC_BYTE_INC
);
sizeof
(
*
value
),
HIF_RD_SYNC_BYTE_INC
);
if
(
status
)
{
if
(
ret
)
{
ath6kl_err
(
"failed to read from window data addr
\n
"
);
ath6kl_warn
(
"failed to read32 through diagnose window: %d
\n
"
,
return
status
;
ret
);
return
ret
;
}
}
return
status
;
return
0
;
}
}
/*
/*
* Write to the ATH6KL through its diagnostic window. No cooperation from
* Write to the ATH6KL through its diagnostic window. No cooperation from
* the Target is required for this.
* the Target is required for this.
*/
*/
static
int
ath6kl_write_reg_diag
(
struct
ath6kl
*
ar
,
u32
*
address
,
u32
*
data
)
int
ath6kl_diag_write32
(
struct
ath6kl
*
ar
,
u32
address
,
__le32
value
)
{
{
int
status
;
int
ret
;
/* set write data */
/* set write data */
status
=
hif_read_write_sync
(
ar
,
WINDOW_DATA_ADDRESS
,
(
u8
*
)
data
,
ret
=
hif_read_write_sync
(
ar
,
WINDOW_DATA_ADDRESS
,
(
u8
*
)
&
value
,
sizeof
(
u32
),
HIF_WR_SYNC_BYTE_INC
);
sizeof
(
value
),
HIF_WR_SYNC_BYTE_INC
);
if
(
status
)
{
if
(
ret
)
{
ath6kl_err
(
"failed to write 0x%x to window data addr
\n
"
,
*
data
);
ath6kl_err
(
"failed to write 0x%x during diagnose window to 0x%d
\n
"
,
return
status
;
address
,
value
);
return
ret
;
}
}
/* set window register, which starts the write cycle */
/* set window register, which starts the write cycle */
return
ath6kl_set_addrwin_reg
(
ar
,
WINDOW_WRITE_ADDR_ADDRESS
,
return
ath6kl_set_addrwin_reg
(
ar
,
WINDOW_WRITE_ADDR_ADDRESS
,
*
address
);
address
);
}
}
int
ath6kl_access_datadiag
(
struct
ath6kl
*
ar
,
u32
address
,
int
ath6kl_diag_read
(
struct
ath6kl
*
ar
,
u32
address
,
void
*
data
,
u32
length
)
u8
*
data
,
u32
length
,
bool
read
)
{
u32
count
,
*
buf
=
data
;
int
ret
;
if
(
WARN_ON
(
length
%
4
))
return
-
EINVAL
;
for
(
count
=
0
;
count
<
length
/
4
;
count
++
,
address
+=
4
)
{
ret
=
ath6kl_diag_read32
(
ar
,
address
,
&
buf
[
count
]);
if
(
ret
)
return
ret
;
}
return
0
;
}
int
ath6kl_diag_write
(
struct
ath6kl
*
ar
,
u32
address
,
void
*
data
,
u32
length
)
{
{
u32
count
;
u32
count
;
int
status
=
0
;
__le32
*
buf
=
data
;
int
ret
;
for
(
count
=
0
;
count
<
length
;
count
+=
4
,
address
+=
4
)
{
if
(
WARN_ON
(
length
%
4
))
if
(
read
)
{
return
-
EINVAL
;
status
=
ath6kl_read_reg_diag
(
ar
,
&
address
,
(
u32
*
)
&
data
[
count
]);
for
(
count
=
0
;
count
<
length
/
4
;
count
++
,
address
+=
4
)
{
if
(
status
)
ret
=
ath6kl_diag_write32
(
ar
,
address
,
buf
[
count
]);
break
;
if
(
ret
)
}
else
{
return
ret
;
status
=
ath6kl_write_reg_diag
(
ar
,
&
address
,
}
(
u32
*
)
&
data
[
count
]);
if
(
status
)
return
0
;
break
;
}
}
int
ath6kl_read_fwlogs
(
struct
ath6kl
*
ar
)
{
struct
ath6kl_dbglog_hdr
debug_hdr
;
struct
ath6kl_dbglog_buf
debug_buf
;
u32
address
,
length
,
dropped
,
firstbuf
,
debug_hdr_addr
;
int
ret
=
0
,
loop
;
u8
*
buf
;
buf
=
kmalloc
(
ATH6KL_FWLOG_PAYLOAD_SIZE
,
GFP_KERNEL
);
if
(
!
buf
)
return
-
ENOMEM
;
address
=
TARG_VTOP
(
ar
->
target_type
,
ath6kl_get_hi_item_addr
(
ar
,
HI_ITEM
(
hi_dbglog_hdr
)));
ret
=
ath6kl_diag_read32
(
ar
,
address
,
&
debug_hdr_addr
);
if
(
ret
)
goto
out
;
/* Get the contents of the ring buffer */
if
(
debug_hdr_addr
==
0
)
{
ath6kl_warn
(
"Invalid address for debug_hdr_addr
\n
"
);
ret
=
-
EINVAL
;
goto
out
;
}
}
return
status
;
address
=
TARG_VTOP
(
ar
->
target_type
,
debug_hdr_addr
);
ath6kl_diag_read
(
ar
,
address
,
&
debug_hdr
,
sizeof
(
debug_hdr
));
address
=
TARG_VTOP
(
ar
->
target_type
,
le32_to_cpu
(
debug_hdr
.
dbuf_addr
));
firstbuf
=
address
;
dropped
=
le32_to_cpu
(
debug_hdr
.
dropped
);
ath6kl_diag_read
(
ar
,
address
,
&
debug_buf
,
sizeof
(
debug_buf
));
loop
=
100
;
do
{
address
=
TARG_VTOP
(
ar
->
target_type
,
le32_to_cpu
(
debug_buf
.
buffer_addr
));
length
=
le32_to_cpu
(
debug_buf
.
length
);
if
(
length
!=
0
&&
(
le32_to_cpu
(
debug_buf
.
length
)
<=
le32_to_cpu
(
debug_buf
.
bufsize
)))
{
length
=
ALIGN
(
length
,
4
);
ret
=
ath6kl_diag_read
(
ar
,
address
,
buf
,
length
);
if
(
ret
)
goto
out
;
ath6kl_debug_fwlog_event
(
ar
,
buf
,
length
);
}
address
=
TARG_VTOP
(
ar
->
target_type
,
le32_to_cpu
(
debug_buf
.
next
));
ath6kl_diag_read
(
ar
,
address
,
&
debug_buf
,
sizeof
(
debug_buf
));
if
(
ret
)
goto
out
;
loop
--
;
if
(
WARN_ON
(
loop
==
0
))
{
ret
=
-
ETIMEDOUT
;
goto
out
;
}
}
while
(
address
!=
firstbuf
);
out:
kfree
(
buf
);
return
ret
;
}
}
/* FIXME: move to a better place, target.h? */
#define AR6003_RESET_CONTROL_ADDRESS 0x00004000
#define AR6004_RESET_CONTROL_ADDRESS 0x00004000
static
void
ath6kl_reset_device
(
struct
ath6kl
*
ar
,
u32
target_type
,
static
void
ath6kl_reset_device
(
struct
ath6kl
*
ar
,
u32
target_type
,
bool
wait_fot_compltn
,
bool
cold_reset
)
bool
wait_fot_compltn
,
bool
cold_reset
)
{
{
int
status
=
0
;
int
status
=
0
;
u32
address
;
u32
address
;
u
32
data
;
__le
32
data
;
if
(
target_type
!=
TARGET_TYPE_AR6003
)
if
(
target_type
!=
TARGET_TYPE_AR6003
&&
target_type
!=
TARGET_TYPE_AR6004
)
return
;
return
;
data
=
cold_reset
?
RESET_CONTROL_COLD_RST
:
RESET_CONTROL_MBOX_RST
;
data
=
cold_reset
?
cpu_to_le32
(
RESET_CONTROL_COLD_RST
)
:
cpu_to_le32
(
RESET_CONTROL_MBOX_RST
);
address
=
RTC_BASE_ADDRESS
;
switch
(
target_type
)
{
status
=
ath6kl_write_reg_diag
(
ar
,
&
address
,
&
data
);
case
TARGET_TYPE_AR6003
:
address
=
AR6003_RESET_CONTROL_ADDRESS
;
break
;
case
TARGET_TYPE_AR6004
:
address
=
AR6004_RESET_CONTROL_ADDRESS
;
break
;
default:
address
=
AR6003_RESET_CONTROL_ADDRESS
;
break
;
}
status
=
ath6kl_diag_write32
(
ar
,
address
,
data
);
if
(
status
)
if
(
status
)
ath6kl_err
(
"failed to reset target
\n
"
);
ath6kl_err
(
"failed to reset target
\n
"
);
...
@@ -411,68 +519,107 @@ static void ath6kl_install_static_wep_keys(struct ath6kl *ar)
...
@@ -411,68 +519,107 @@ static void ath6kl_install_static_wep_keys(struct ath6kl *ar)
}
}
}
}
static
void
ath6kl_connect_ap_mode
(
struct
ath6kl
*
ar
,
u16
channel
,
u8
*
bssid
,
void
ath6kl_connect_ap_mode_bss
(
struct
ath6kl
*
ar
,
u16
channel
)
u16
listen_int
,
u16
beacon_int
,
u8
assoc_resp_len
,
u8
*
assoc_info
)
{
{
struct
net_device
*
dev
=
ar
->
net_dev
;
struct
station_info
sinfo
;
struct
ath6kl_req_key
*
ik
;
struct
ath6kl_req_key
*
ik
;
enum
crypto_type
keyType
=
NONE_CRYPT
;
int
res
;
u8
key_rsc
[
ATH6KL_KEY_SEQ_LEN
];
if
(
memcmp
(
dev
->
dev_addr
,
bssid
,
ETH_ALEN
)
==
0
)
{
ik
=
&
ar
->
ap_mode_bkey
;
ik
=
&
ar
->
ap_mode_bkey
;
switch
(
ar
->
auth_mode
)
{
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"AP mode started on %u MHz
\n
"
,
channel
);
case
NONE_AUTH
:
if
(
ar
->
prwise_crypto
==
WEP_CRYPT
)
switch
(
ar
->
auth_mode
)
{
ath6kl_install_static_wep_keys
(
ar
);
case
NONE_AUTH
:
break
;
if
(
ar
->
prwise_crypto
==
WEP_CRYPT
)
case
WPA_PSK_AUTH
:
ath6kl_install_static_wep_keys
(
ar
);
case
WPA2_PSK_AUTH
:
break
;
case
(
WPA_PSK_AUTH
|
WPA2_PSK_AUTH
):
case
WPA_PSK_AUTH
:
switch
(
ik
->
ik_type
)
{
case
WPA2_PSK_AUTH
:
case
ATH6KL_CIPHER_TKIP
:
case
(
WPA_PSK_AUTH
|
WPA2_PSK_AUTH
):
keyType
=
TKIP_CRYPT
;
if
(
!
ik
->
valid
)
break
;
case
ATH6KL_CIPHER_AES_CCM
:
keyType
=
AES_CRYPT
;
break
;
default:
goto
skip_key
;
}
ath6kl_wmi_addkey_cmd
(
ar
->
wmi
,
ik
->
ik_keyix
,
keyType
,
GROUP_USAGE
,
ik
->
ik_keylen
,
(
u8
*
)
&
ik
->
ik_keyrsc
,
ik
->
ik_keydata
,
KEY_OP_INIT_VAL
,
ik
->
ik_macaddr
,
SYNC_BOTH_WMIFLAG
);
break
;
break
;
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"Delayed addkey for "
"the initial group key for AP mode
\n
"
);
memset
(
key_rsc
,
0
,
sizeof
(
key_rsc
));
res
=
ath6kl_wmi_addkey_cmd
(
ar
->
wmi
,
ik
->
key_index
,
ik
->
key_type
,
GROUP_USAGE
,
ik
->
key_len
,
key_rsc
,
ik
->
key
,
KEY_OP_INIT_VAL
,
NULL
,
SYNC_BOTH_WMIFLAG
);
if
(
res
)
{
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"Delayed "
"addkey failed: %d
\n
"
,
res
);
}
}
skip_key:
break
;
set_bit
(
CONNECTED
,
&
ar
->
flag
);
return
;
}
}
ath6kl_dbg
(
ATH6KL_DBG_TRC
,
"new station %pM aid=%d
\n
"
,
ath6kl_wmi_bssfilter_cmd
(
ar
->
wmi
,
NONE_BSS_FILTER
,
0
);
bssid
,
channel
);
set_bit
(
CONNECTED
,
&
ar
->
flag
);
netif_carrier_on
(
ar
->
net_dev
);
}
void
ath6kl_connect_ap_mode_sta
(
struct
ath6kl
*
ar
,
u16
aid
,
u8
*
mac_addr
,
u8
keymgmt
,
u8
ucipher
,
u8
auth
,
u8
assoc_req_len
,
u8
*
assoc_info
)
{
u8
*
ies
=
NULL
,
*
wpa_ie
=
NULL
,
*
pos
;
size_t
ies_len
=
0
;
struct
station_info
sinfo
;
ath6kl_add_new_sta
(
ar
,
bssid
,
channel
,
assoc_info
,
assoc_resp_len
,
ath6kl_dbg
(
ATH6KL_DBG_TRC
,
"new station %pM aid=%d
\n
"
,
mac_addr
,
aid
);
listen_int
&
0xFF
,
beacon_int
,
(
listen_int
>>
8
)
&
0xFF
);
if
(
assoc_req_len
>
sizeof
(
struct
ieee80211_hdr_3addr
))
{
struct
ieee80211_mgmt
*
mgmt
=
(
struct
ieee80211_mgmt
*
)
assoc_info
;
if
(
ieee80211_is_assoc_req
(
mgmt
->
frame_control
)
&&
assoc_req_len
>=
sizeof
(
struct
ieee80211_hdr_3addr
)
+
sizeof
(
mgmt
->
u
.
assoc_req
))
{
ies
=
mgmt
->
u
.
assoc_req
.
variable
;
ies_len
=
assoc_info
+
assoc_req_len
-
ies
;
}
else
if
(
ieee80211_is_reassoc_req
(
mgmt
->
frame_control
)
&&
assoc_req_len
>=
sizeof
(
struct
ieee80211_hdr_3addr
)
+
sizeof
(
mgmt
->
u
.
reassoc_req
))
{
ies
=
mgmt
->
u
.
reassoc_req
.
variable
;
ies_len
=
assoc_info
+
assoc_req_len
-
ies
;
}
}
pos
=
ies
;
while
(
pos
&&
pos
+
1
<
ies
+
ies_len
)
{
if
(
pos
+
2
+
pos
[
1
]
>
ies
+
ies_len
)
break
;
if
(
pos
[
0
]
==
WLAN_EID_RSN
)
wpa_ie
=
pos
;
/* RSN IE */
else
if
(
pos
[
0
]
==
WLAN_EID_VENDOR_SPECIFIC
&&
pos
[
1
]
>=
4
&&
pos
[
2
]
==
0x00
&&
pos
[
3
]
==
0x50
&&
pos
[
4
]
==
0xf2
)
{
if
(
pos
[
5
]
==
0x01
)
wpa_ie
=
pos
;
/* WPA IE */
else
if
(
pos
[
5
]
==
0x04
)
{
wpa_ie
=
pos
;
/* WPS IE */
break
;
/* overrides WPA/RSN IE */
}
}
pos
+=
2
+
pos
[
1
];
}
ath6kl_add_new_sta
(
ar
,
mac_addr
,
aid
,
wpa_ie
,
wpa_ie
?
2
+
wpa_ie
[
1
]
:
0
,
keymgmt
,
ucipher
,
auth
);
/* send event to application */
/* send event to application */
memset
(
&
sinfo
,
0
,
sizeof
(
sinfo
));
memset
(
&
sinfo
,
0
,
sizeof
(
sinfo
));
/* TODO: sinfo.generation */
/* TODO: sinfo.generation */
/* TODO: need to deliver (Re)AssocReq IEs somehow.. change in
* cfg80211 needed, e.g., by adding those into sinfo
*/
cfg80211_new_sta
(
ar
->
net_dev
,
bssid
,
&
sinfo
,
GFP_KERNEL
);
netif_wake_queue
(
ar
->
net_dev
);
sinfo
.
assoc_req_ies
=
ies
;
sinfo
.
assoc_req_ies_len
=
ies_len
;
sinfo
.
filled
|=
STATION_INFO_ASSOC_REQ_IES
;
return
;
cfg80211_new_sta
(
ar
->
net_dev
,
mac_addr
,
&
sinfo
,
GFP_KERNEL
);
netif_wake_queue
(
ar
->
net_dev
);
}
}
/* Functions for Tx credit handling */
/* Functions for Tx credit handling */
...
@@ -779,6 +926,41 @@ void ath6kl_disconnect(struct ath6kl *ar)
...
@@ -779,6 +926,41 @@ void ath6kl_disconnect(struct ath6kl *ar)
}
}
}
}
void
ath6kl_deep_sleep_enable
(
struct
ath6kl
*
ar
)
{
switch
(
ar
->
sme_state
)
{
case
SME_CONNECTING
:
cfg80211_connect_result
(
ar
->
net_dev
,
ar
->
bssid
,
NULL
,
0
,
NULL
,
0
,
WLAN_STATUS_UNSPECIFIED_FAILURE
,
GFP_KERNEL
);
break
;
case
SME_CONNECTED
:
default:
/*
* FIXME: oddly enough smeState is in DISCONNECTED during
* suspend, why? Need to send disconnected event in that
* state.
*/
cfg80211_disconnected
(
ar
->
net_dev
,
0
,
NULL
,
0
,
GFP_KERNEL
);
break
;
}
if
(
test_bit
(
CONNECTED
,
&
ar
->
flag
)
||
test_bit
(
CONNECT_PEND
,
&
ar
->
flag
))
ath6kl_wmi_disconnect_cmd
(
ar
->
wmi
);
ar
->
sme_state
=
SME_DISCONNECTED
;
/* disable scanning */
if
(
ath6kl_wmi_scanparams_cmd
(
ar
->
wmi
,
0xFFFF
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
)
!=
0
)
printk
(
KERN_WARNING
"ath6kl: failed to disable scan "
"during suspend
\n
"
);
ath6kl_cfg80211_scan_complete_event
(
ar
,
-
ECANCELED
);
}
/* WMI Event handlers */
/* WMI Event handlers */
static
const
char
*
get_hw_id_string
(
u32
id
)
static
const
char
*
get_hw_id_string
(
u32
id
)
...
@@ -819,17 +1001,20 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver)
...
@@ -819,17 +1001,20 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver)
set_bit
(
WMI_READY
,
&
ar
->
flag
);
set_bit
(
WMI_READY
,
&
ar
->
flag
);
wake_up
(
&
ar
->
event_wq
);
wake_up
(
&
ar
->
event_wq
);
ath6kl_info
(
"hw %s fw %s
\n
"
,
ath6kl_info
(
"hw %s fw %s
%s
\n
"
,
get_hw_id_string
(
ar
->
wdev
->
wiphy
->
hw_version
),
get_hw_id_string
(
ar
->
wdev
->
wiphy
->
hw_version
),
ar
->
wdev
->
wiphy
->
fw_version
);
ar
->
wdev
->
wiphy
->
fw_version
,
test_bit
(
TESTMODE
,
&
ar
->
flag
)
?
" testmode"
:
""
);
}
}
void
ath6kl_scan_complete_evt
(
struct
ath6kl
*
ar
,
int
status
)
void
ath6kl_scan_complete_evt
(
struct
ath6kl
*
ar
,
int
status
)
{
{
ath6kl_cfg80211_scan_complete_event
(
ar
,
status
);
ath6kl_cfg80211_scan_complete_event
(
ar
,
status
);
if
(
!
ar
->
usr_bss_filter
)
if
(
!
ar
->
usr_bss_filter
)
{
clear_bit
(
CLEAR_BSSFILTER_ON_BEACON
,
&
ar
->
flag
);
ath6kl_wmi_bssfilter_cmd
(
ar
->
wmi
,
NONE_BSS_FILTER
,
0
);
ath6kl_wmi_bssfilter_cmd
(
ar
->
wmi
,
NONE_BSS_FILTER
,
0
);
}
ath6kl_dbg
(
ATH6KL_DBG_WLAN_SCAN
,
"scan complete: %d
\n
"
,
status
);
ath6kl_dbg
(
ATH6KL_DBG_WLAN_SCAN
,
"scan complete: %d
\n
"
,
status
);
}
}
...
@@ -842,13 +1027,6 @@ void ath6kl_connect_event(struct ath6kl *ar, u16 channel, u8 *bssid,
...
@@ -842,13 +1027,6 @@ void ath6kl_connect_event(struct ath6kl *ar, u16 channel, u8 *bssid,
{
{
unsigned
long
flags
;
unsigned
long
flags
;
if
(
ar
->
nw_type
==
AP_NETWORK
)
{
ath6kl_connect_ap_mode
(
ar
,
channel
,
bssid
,
listen_int
,
beacon_int
,
assoc_resp_len
,
assoc_info
);
return
;
}
ath6kl_cfg80211_connect_event
(
ar
,
channel
,
bssid
,
ath6kl_cfg80211_connect_event
(
ar
,
channel
,
bssid
,
listen_int
,
beacon_int
,
listen_int
,
beacon_int
,
net_type
,
beacon_ie_len
,
net_type
,
beacon_ie_len
,
...
@@ -880,8 +1058,10 @@ void ath6kl_connect_event(struct ath6kl *ar, u16 channel, u8 *bssid,
...
@@ -880,8 +1058,10 @@ void ath6kl_connect_event(struct ath6kl *ar, u16 channel, u8 *bssid,
ar
->
next_ep_id
=
ENDPOINT_2
;
ar
->
next_ep_id
=
ENDPOINT_2
;
}
}
if
(
!
ar
->
usr_bss_filter
)
if
(
!
ar
->
usr_bss_filter
)
{
ath6kl_wmi_bssfilter_cmd
(
ar
->
wmi
,
NONE_BSS_FILTER
,
0
);
set_bit
(
CLEAR_BSSFILTER_ON_BEACON
,
&
ar
->
flag
);
ath6kl_wmi_bssfilter_cmd
(
ar
->
wmi
,
CURRENT_BSS_FILTER
,
0
);
}
}
}
void
ath6kl_tkip_micerr_event
(
struct
ath6kl
*
ar
,
u8
keyid
,
bool
ismcast
)
void
ath6kl_tkip_micerr_event
(
struct
ath6kl
*
ar
,
u8
keyid
,
bool
ismcast
)
...
@@ -915,26 +1095,11 @@ static void ath6kl_update_target_stats(struct ath6kl *ar, u8 *ptr, u32 len)
...
@@ -915,26 +1095,11 @@ static void ath6kl_update_target_stats(struct ath6kl *ar, u8 *ptr, u32 len)
(
struct
wmi_target_stats
*
)
ptr
;
(
struct
wmi_target_stats
*
)
ptr
;
struct
target_stats
*
stats
=
&
ar
->
target_stats
;
struct
target_stats
*
stats
=
&
ar
->
target_stats
;
struct
tkip_ccmp_stats
*
ccmp_stats
;
struct
tkip_ccmp_stats
*
ccmp_stats
;
struct
bss
*
conn_bss
=
NULL
;
struct
cserv_stats
*
c_stats
;
u8
ac
;
u8
ac
;
if
(
len
<
sizeof
(
*
tgt_stats
))
if
(
len
<
sizeof
(
*
tgt_stats
))
return
;
return
;
/* update the RSSI of the connected bss */
if
(
test_bit
(
CONNECTED
,
&
ar
->
flag
))
{
conn_bss
=
ath6kl_wmi_find_node
(
ar
->
wmi
,
ar
->
bssid
);
if
(
conn_bss
)
{
c_stats
=
&
tgt_stats
->
cserv_stats
;
conn_bss
->
ni_rssi
=
a_sle16_to_cpu
(
c_stats
->
cs_ave_beacon_rssi
);
conn_bss
->
ni_snr
=
tgt_stats
->
cserv_stats
.
cs_ave_beacon_snr
;
ath6kl_wmi_node_return
(
ar
->
wmi
,
conn_bss
);
}
}
ath6kl_dbg
(
ATH6KL_DBG_TRC
,
"updating target stats
\n
"
);
ath6kl_dbg
(
ATH6KL_DBG_TRC
,
"updating target stats
\n
"
);
stats
->
tx_pkt
+=
le32_to_cpu
(
tgt_stats
->
stats
.
tx
.
pkt
);
stats
->
tx_pkt
+=
le32_to_cpu
(
tgt_stats
->
stats
.
tx
.
pkt
);
...
@@ -1165,7 +1330,6 @@ void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, u8 *bssid,
...
@@ -1165,7 +1330,6 @@ void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, u8 *bssid,
u8
assoc_resp_len
,
u8
*
assoc_info
,
u8
assoc_resp_len
,
u8
*
assoc_info
,
u16
prot_reason_status
)
u16
prot_reason_status
)
{
{
struct
bss
*
wmi_ssid_node
=
NULL
;
unsigned
long
flags
;
unsigned
long
flags
;
if
(
ar
->
nw_type
==
AP_NETWORK
)
{
if
(
ar
->
nw_type
==
AP_NETWORK
)
{
...
@@ -1188,7 +1352,10 @@ void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, u8 *bssid,
...
@@ -1188,7 +1352,10 @@ void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, u8 *bssid,
cfg80211_del_sta
(
ar
->
net_dev
,
bssid
,
GFP_KERNEL
);
cfg80211_del_sta
(
ar
->
net_dev
,
bssid
,
GFP_KERNEL
);
}
}
clear_bit
(
CONNECTED
,
&
ar
->
flag
);
if
(
memcmp
(
ar
->
net_dev
->
dev_addr
,
bssid
,
ETH_ALEN
)
==
0
)
{
memset
(
ar
->
wep_key_list
,
0
,
sizeof
(
ar
->
wep_key_list
));
clear_bit
(
CONNECTED
,
&
ar
->
flag
);
}
return
;
return
;
}
}
...
@@ -1222,33 +1389,6 @@ void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, u8 *bssid,
...
@@ -1222,33 +1389,6 @@ void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, u8 *bssid,
}
}
}
}
if
((
reason
==
NO_NETWORK_AVAIL
)
&&
test_bit
(
WMI_READY
,
&
ar
->
flag
))
{
ath6kl_wmi_node_free
(
ar
->
wmi
,
bssid
);
/*
* In case any other same SSID nodes are present remove it,
* since those nodes also not available now.
*/
do
{
/*
* Find the nodes based on SSID and remove it
*
* Note: This case will not work out for
* Hidden-SSID
*/
wmi_ssid_node
=
ath6kl_wmi_find_ssid_node
(
ar
->
wmi
,
ar
->
ssid
,
ar
->
ssid_len
,
false
,
true
);
if
(
wmi_ssid_node
)
ath6kl_wmi_node_free
(
ar
->
wmi
,
wmi_ssid_node
->
ni_macaddr
);
}
while
(
wmi_ssid_node
);
}
/* update connect & link status atomically */
/* update connect & link status atomically */
spin_lock_irqsave
(
&
ar
->
lock
,
flags
);
spin_lock_irqsave
(
&
ar
->
lock
,
flags
);
clear_bit
(
CONNECTED
,
&
ar
->
flag
);
clear_bit
(
CONNECTED
,
&
ar
->
flag
);
...
@@ -1331,7 +1471,7 @@ void init_netdev(struct net_device *dev)
...
@@ -1331,7 +1471,7 @@ void init_netdev(struct net_device *dev)
dev
->
needed_headroom
=
ETH_HLEN
;
dev
->
needed_headroom
=
ETH_HLEN
;
dev
->
needed_headroom
+=
sizeof
(
struct
ath6kl_llc_snap_hdr
)
+
dev
->
needed_headroom
+=
sizeof
(
struct
ath6kl_llc_snap_hdr
)
+
sizeof
(
struct
wmi_data_hdr
)
+
HTC_HDR_LENGTH
sizeof
(
struct
wmi_data_hdr
)
+
HTC_HDR_LENGTH
+
WMI_MAX_TX_META_SZ
;
+
WMI_MAX_TX_META_SZ
+
ATH6KL_HTC_ALIGN_BYTES
;
return
;
return
;
}
}
drivers/net/wireless/ath/ath6kl/node.c
deleted
100644 → 0
View file @
49a59543
/*
* Copyright (c) 2004-2011 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "htc.h"
#include "wmi.h"
#include "debug.h"
struct
bss
*
wlan_node_alloc
(
int
wh_size
)
{
struct
bss
*
ni
;
ni
=
kzalloc
(
sizeof
(
struct
bss
),
GFP_ATOMIC
);
if
((
ni
!=
NULL
)
&&
wh_size
)
{
ni
->
ni_buf
=
kmalloc
(
wh_size
,
GFP_ATOMIC
);
if
(
ni
->
ni_buf
==
NULL
)
{
kfree
(
ni
);
return
NULL
;
}
}
return
ni
;
}
void
wlan_node_free
(
struct
bss
*
ni
)
{
kfree
(
ni
->
ni_buf
);
kfree
(
ni
);
}
void
wlan_setup_node
(
struct
ath6kl_node_table
*
nt
,
struct
bss
*
ni
,
const
u8
*
mac_addr
)
{
int
hash
;
memcpy
(
ni
->
ni_macaddr
,
mac_addr
,
ETH_ALEN
);
hash
=
ATH6KL_NODE_HASH
(
mac_addr
);
ni
->
ni_refcnt
=
1
;
ni
->
ni_tstamp
=
jiffies_to_msecs
(
jiffies
);
ni
->
ni_actcnt
=
WLAN_NODE_INACT_CNT
;
spin_lock_bh
(
&
nt
->
nt_nodelock
);
/* insert at the end of the node list */
ni
->
ni_list_next
=
NULL
;
ni
->
ni_list_prev
=
nt
->
nt_node_last
;
if
(
nt
->
nt_node_last
!=
NULL
)
nt
->
nt_node_last
->
ni_list_next
=
ni
;
nt
->
nt_node_last
=
ni
;
if
(
nt
->
nt_node_first
==
NULL
)
nt
->
nt_node_first
=
ni
;
/* insert into the hash list */
ni
->
ni_hash_next
=
nt
->
nt_hash
[
hash
];
if
(
ni
->
ni_hash_next
!=
NULL
)
nt
->
nt_hash
[
hash
]
->
ni_hash_prev
=
ni
;
ni
->
ni_hash_prev
=
NULL
;
nt
->
nt_hash
[
hash
]
=
ni
;
spin_unlock_bh
(
&
nt
->
nt_nodelock
);
}
struct
bss
*
wlan_find_node
(
struct
ath6kl_node_table
*
nt
,
const
u8
*
mac_addr
)
{
struct
bss
*
ni
,
*
found_ni
=
NULL
;
int
hash
;
spin_lock_bh
(
&
nt
->
nt_nodelock
);
hash
=
ATH6KL_NODE_HASH
(
mac_addr
);
for
(
ni
=
nt
->
nt_hash
[
hash
];
ni
;
ni
=
ni
->
ni_hash_next
)
{
if
(
memcmp
(
ni
->
ni_macaddr
,
mac_addr
,
ETH_ALEN
)
==
0
)
{
ni
->
ni_refcnt
++
;
found_ni
=
ni
;
break
;
}
}
spin_unlock_bh
(
&
nt
->
nt_nodelock
);
return
found_ni
;
}
void
wlan_node_reclaim
(
struct
ath6kl_node_table
*
nt
,
struct
bss
*
ni
)
{
int
hash
;
spin_lock_bh
(
&
nt
->
nt_nodelock
);
if
(
ni
->
ni_list_prev
==
NULL
)
/* fix list head */
nt
->
nt_node_first
=
ni
->
ni_list_next
;
else
ni
->
ni_list_prev
->
ni_list_next
=
ni
->
ni_list_next
;
if
(
ni
->
ni_list_next
==
NULL
)
/* fix list tail */
nt
->
nt_node_last
=
ni
->
ni_list_prev
;
else
ni
->
ni_list_next
->
ni_list_prev
=
ni
->
ni_list_prev
;
if
(
ni
->
ni_hash_prev
==
NULL
)
{
/* first in list so fix the list head */
hash
=
ATH6KL_NODE_HASH
(
ni
->
ni_macaddr
);
nt
->
nt_hash
[
hash
]
=
ni
->
ni_hash_next
;
}
else
{
ni
->
ni_hash_prev
->
ni_hash_next
=
ni
->
ni_hash_next
;
}
if
(
ni
->
ni_hash_next
!=
NULL
)
ni
->
ni_hash_next
->
ni_hash_prev
=
ni
->
ni_hash_prev
;
wlan_node_free
(
ni
);
spin_unlock_bh
(
&
nt
->
nt_nodelock
);
}
static
void
wlan_node_dec_free
(
struct
bss
*
ni
)
{
if
((
ni
->
ni_refcnt
--
)
==
1
)
wlan_node_free
(
ni
);
}
void
wlan_free_allnodes
(
struct
ath6kl_node_table
*
nt
)
{
struct
bss
*
ni
;
while
((
ni
=
nt
->
nt_node_first
)
!=
NULL
)
wlan_node_reclaim
(
nt
,
ni
);
}
void
wlan_iterate_nodes
(
struct
ath6kl_node_table
*
nt
,
void
*
arg
)
{
struct
bss
*
ni
;
spin_lock_bh
(
&
nt
->
nt_nodelock
);
for
(
ni
=
nt
->
nt_node_first
;
ni
;
ni
=
ni
->
ni_list_next
)
{
ni
->
ni_refcnt
++
;
ath6kl_cfg80211_scan_node
(
arg
,
ni
);
wlan_node_dec_free
(
ni
);
}
spin_unlock_bh
(
&
nt
->
nt_nodelock
);
}
void
wlan_node_table_init
(
struct
ath6kl_node_table
*
nt
)
{
ath6kl_dbg
(
ATH6KL_DBG_WLAN_NODE
,
"node table = 0x%lx
\n
"
,
(
unsigned
long
)
nt
);
memset
(
nt
,
0
,
sizeof
(
struct
ath6kl_node_table
));
spin_lock_init
(
&
nt
->
nt_nodelock
);
nt
->
nt_node_age
=
WLAN_NODE_INACT_TIMEOUT_MSEC
;
}
void
wlan_refresh_inactive_nodes
(
struct
ath6kl
*
ar
)
{
struct
ath6kl_node_table
*
nt
=
&
ar
->
scan_table
;
struct
bss
*
bss
;
u32
now
;
now
=
jiffies_to_msecs
(
jiffies
);
bss
=
nt
->
nt_node_first
;
while
(
bss
!=
NULL
)
{
/* refresh all nodes except the current bss */
if
(
memcmp
(
ar
->
bssid
,
bss
->
ni_macaddr
,
ETH_ALEN
)
!=
0
)
{
if
(((
now
-
bss
->
ni_tstamp
)
>
nt
->
nt_node_age
)
||
--
bss
->
ni_actcnt
==
0
)
{
wlan_node_reclaim
(
nt
,
bss
);
}
}
bss
=
bss
->
ni_list_next
;
}
}
void
wlan_node_table_cleanup
(
struct
ath6kl_node_table
*
nt
)
{
wlan_free_allnodes
(
nt
);
}
struct
bss
*
wlan_find_ssid_node
(
struct
ath6kl_node_table
*
nt
,
u8
*
ssid
,
u32
ssid_len
,
bool
is_wpa2
,
bool
match_ssid
)
{
struct
bss
*
ni
,
*
found_ni
=
NULL
;
u8
*
ie_ssid
;
spin_lock_bh
(
&
nt
->
nt_nodelock
);
for
(
ni
=
nt
->
nt_node_first
;
ni
;
ni
=
ni
->
ni_list_next
)
{
ie_ssid
=
ni
->
ni_cie
.
ie_ssid
;
if
((
ie_ssid
[
1
]
<=
IEEE80211_MAX_SSID_LEN
)
&&
(
memcmp
(
ssid
,
&
ie_ssid
[
2
],
ssid_len
)
==
0
))
{
if
(
match_ssid
||
(
is_wpa2
&&
ni
->
ni_cie
.
ie_rsn
!=
NULL
)
||
(
!
is_wpa2
&&
ni
->
ni_cie
.
ie_wpa
!=
NULL
))
{
ni
->
ni_refcnt
++
;
found_ni
=
ni
;
break
;
}
}
}
spin_unlock_bh
(
&
nt
->
nt_nodelock
);
return
found_ni
;
}
void
wlan_node_return
(
struct
ath6kl_node_table
*
nt
,
struct
bss
*
ni
)
{
spin_lock_bh
(
&
nt
->
nt_nodelock
);
wlan_node_dec_free
(
ni
);
spin_unlock_bh
(
&
nt
->
nt_nodelock
);
}
drivers/net/wireless/ath/ath6kl/sdio.c
View file @
a5abbcb2
...
@@ -25,6 +25,7 @@
...
@@ -25,6 +25,7 @@
#include "hif-ops.h"
#include "hif-ops.h"
#include "target.h"
#include "target.h"
#include "debug.h"
#include "debug.h"
#include "cfg80211.h"
struct
ath6kl_sdio
{
struct
ath6kl_sdio
{
struct
sdio_func
*
func
;
struct
sdio_func
*
func
;
...
@@ -134,10 +135,12 @@ static int ath6kl_sdio_io(struct sdio_func *func, u32 request, u32 addr,
...
@@ -134,10 +135,12 @@ static int ath6kl_sdio_io(struct sdio_func *func, u32 request, u32 addr,
int
ret
=
0
;
int
ret
=
0
;
if
(
request
&
HIF_WRITE
)
{
if
(
request
&
HIF_WRITE
)
{
/* FIXME: looks like ugly workaround for something */
if
(
addr
>=
HIF_MBOX_BASE_ADDR
&&
if
(
addr
>=
HIF_MBOX_BASE_ADDR
&&
addr
<=
HIF_MBOX_END_ADDR
)
addr
<=
HIF_MBOX_END_ADDR
)
addr
+=
(
HIF_MBOX_WIDTH
-
len
);
addr
+=
(
HIF_MBOX_WIDTH
-
len
);
/* FIXME: this also looks like ugly workaround */
if
(
addr
==
HIF_MBOX0_EXT_BASE_ADDR
)
if
(
addr
==
HIF_MBOX0_EXT_BASE_ADDR
)
addr
+=
HIF_MBOX0_EXT_WIDTH
-
len
;
addr
+=
HIF_MBOX0_EXT_WIDTH
-
len
;
...
@@ -152,6 +155,11 @@ static int ath6kl_sdio_io(struct sdio_func *func, u32 request, u32 addr,
...
@@ -152,6 +155,11 @@ static int ath6kl_sdio_io(struct sdio_func *func, u32 request, u32 addr,
ret
=
sdio_memcpy_fromio
(
func
,
buf
,
addr
,
len
);
ret
=
sdio_memcpy_fromio
(
func
,
buf
,
addr
,
len
);
}
}
ath6kl_dbg
(
ATH6KL_DBG_SDIO
,
"%s addr 0x%x%s buf 0x%p len %d
\n
"
,
request
&
HIF_WRITE
?
"wr"
:
"rd"
,
addr
,
request
&
HIF_FIXED_ADDRESS
?
" (fixed)"
:
""
,
buf
,
len
);
ath6kl_dbg_dump
(
ATH6KL_DBG_SDIO_DUMP
,
NULL
,
"sdio "
,
buf
,
len
);
return
ret
;
return
ret
;
}
}
...
@@ -172,7 +180,8 @@ static struct bus_request *ath6kl_sdio_alloc_busreq(struct ath6kl_sdio *ar_sdio)
...
@@ -172,7 +180,8 @@ static struct bus_request *ath6kl_sdio_alloc_busreq(struct ath6kl_sdio *ar_sdio)
list_del
(
&
bus_req
->
list
);
list_del
(
&
bus_req
->
list
);
spin_unlock_irqrestore
(
&
ar_sdio
->
lock
,
flag
);
spin_unlock_irqrestore
(
&
ar_sdio
->
lock
,
flag
);
ath6kl_dbg
(
ATH6KL_DBG_TRC
,
"%s: bus request 0x%p
\n
"
,
__func__
,
bus_req
);
ath6kl_dbg
(
ATH6KL_DBG_SCATTER
,
"%s: bus request 0x%p
\n
"
,
__func__
,
bus_req
);
return
bus_req
;
return
bus_req
;
}
}
...
@@ -182,7 +191,8 @@ static void ath6kl_sdio_free_bus_req(struct ath6kl_sdio *ar_sdio,
...
@@ -182,7 +191,8 @@ static void ath6kl_sdio_free_bus_req(struct ath6kl_sdio *ar_sdio,
{
{
unsigned
long
flag
;
unsigned
long
flag
;
ath6kl_dbg
(
ATH6KL_DBG_TRC
,
"%s: bus request 0x%p
\n
"
,
__func__
,
bus_req
);
ath6kl_dbg
(
ATH6KL_DBG_SCATTER
,
"%s: bus request 0x%p
\n
"
,
__func__
,
bus_req
);
spin_lock_irqsave
(
&
ar_sdio
->
lock
,
flag
);
spin_lock_irqsave
(
&
ar_sdio
->
lock
,
flag
);
list_add_tail
(
&
bus_req
->
list
,
&
ar_sdio
->
bus_req_freeq
);
list_add_tail
(
&
bus_req
->
list
,
&
ar_sdio
->
bus_req_freeq
);
...
@@ -213,16 +223,6 @@ static void ath6kl_sdio_setup_scat_data(struct hif_scatter_req *scat_req,
...
@@ -213,16 +223,6 @@ static void ath6kl_sdio_setup_scat_data(struct hif_scatter_req *scat_req,
/* assemble SG list */
/* assemble SG list */
for
(
i
=
0
;
i
<
scat_req
->
scat_entries
;
i
++
,
sg
++
)
{
for
(
i
=
0
;
i
<
scat_req
->
scat_entries
;
i
++
,
sg
++
)
{
if
((
unsigned
long
)
scat_req
->
scat_list
[
i
].
buf
&
0x3
)
/*
* Some scatter engines can handle unaligned
* buffers, print this as informational only.
*/
ath6kl_dbg
(
ATH6KL_DBG_SCATTER
,
"(%s) scatter buffer is unaligned 0x%p
\n
"
,
scat_req
->
req
&
HIF_WRITE
?
"WR"
:
"RD"
,
scat_req
->
scat_list
[
i
].
buf
);
ath6kl_dbg
(
ATH6KL_DBG_SCATTER
,
"%d: addr:0x%p, len:%d
\n
"
,
ath6kl_dbg
(
ATH6KL_DBG_SCATTER
,
"%d: addr:0x%p, len:%d
\n
"
,
i
,
scat_req
->
scat_list
[
i
].
buf
,
i
,
scat_req
->
scat_list
[
i
].
buf
,
scat_req
->
scat_list
[
i
].
len
);
scat_req
->
scat_list
[
i
].
len
);
...
@@ -447,6 +447,8 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func)
...
@@ -447,6 +447,8 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func)
int
status
;
int
status
;
struct
ath6kl_sdio
*
ar_sdio
;
struct
ath6kl_sdio
*
ar_sdio
;
ath6kl_dbg
(
ATH6KL_DBG_SDIO
,
"irq
\n
"
);
ar_sdio
=
sdio_get_drvdata
(
func
);
ar_sdio
=
sdio_get_drvdata
(
func
);
atomic_set
(
&
ar_sdio
->
irq_handling
,
1
);
atomic_set
(
&
ar_sdio
->
irq_handling
,
1
);
...
@@ -684,7 +686,7 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar)
...
@@ -684,7 +686,7 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar)
MAX_SCATTER_REQUESTS
,
virt_scat
);
MAX_SCATTER_REQUESTS
,
virt_scat
);
if
(
!
ret
)
{
if
(
!
ret
)
{
ath6kl_dbg
(
ATH6KL_DBG_
ANY
,
ath6kl_dbg
(
ATH6KL_DBG_
SCATTER
,
"hif-scatter enabled: max scatter req : %d entries: %d
\n
"
,
"hif-scatter enabled: max scatter req : %d entries: %d
\n
"
,
MAX_SCATTER_REQUESTS
,
MAX_SCATTER_REQUESTS
,
MAX_SCATTER_ENTRIES_PER_REQ
);
MAX_SCATTER_ENTRIES_PER_REQ
);
...
@@ -709,7 +711,7 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar)
...
@@ -709,7 +711,7 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar)
return
ret
;
return
ret
;
}
}
ath6kl_dbg
(
ATH6KL_DBG_
ANY
,
ath6kl_dbg
(
ATH6KL_DBG_
SCATTER
,
"Vitual scatter enabled, max_scat_req:%d, entries:%d
\n
"
,
"Vitual scatter enabled, max_scat_req:%d, entries:%d
\n
"
,
ATH6KL_SCATTER_REQS
,
ATH6KL_SCATTER_ENTRIES_PER_REQ
);
ATH6KL_SCATTER_REQS
,
ATH6KL_SCATTER_ENTRIES_PER_REQ
);
...
@@ -721,6 +723,34 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar)
...
@@ -721,6 +723,34 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar)
return
0
;
return
0
;
}
}
static
int
ath6kl_sdio_suspend
(
struct
ath6kl
*
ar
)
{
struct
ath6kl_sdio
*
ar_sdio
=
ath6kl_sdio_priv
(
ar
);
struct
sdio_func
*
func
=
ar_sdio
->
func
;
mmc_pm_flag_t
flags
;
int
ret
;
flags
=
sdio_get_host_pm_caps
(
func
);
if
(
!
(
flags
&
MMC_PM_KEEP_POWER
))
/* as host doesn't support keep power we need to bail out */
ath6kl_dbg
(
ATH6KL_DBG_SDIO
,
"func %d doesn't support MMC_PM_KEEP_POWER
\n
"
,
func
->
num
);
return
-
EINVAL
;
ret
=
sdio_set_host_pm_flags
(
func
,
MMC_PM_KEEP_POWER
);
if
(
ret
)
{
printk
(
KERN_ERR
"ath6kl: set sdio pm flags failed: %d
\n
"
,
ret
);
return
ret
;
}
ath6kl_deep_sleep_enable
(
ar
);
return
0
;
}
static
const
struct
ath6kl_hif_ops
ath6kl_sdio_ops
=
{
static
const
struct
ath6kl_hif_ops
ath6kl_sdio_ops
=
{
.
read_write_sync
=
ath6kl_sdio_read_write_sync
,
.
read_write_sync
=
ath6kl_sdio_read_write_sync
,
.
write_async
=
ath6kl_sdio_write_async
,
.
write_async
=
ath6kl_sdio_write_async
,
...
@@ -731,6 +761,7 @@ static const struct ath6kl_hif_ops ath6kl_sdio_ops = {
...
@@ -731,6 +761,7 @@ static const struct ath6kl_hif_ops ath6kl_sdio_ops = {
.
enable_scatter
=
ath6kl_sdio_enable_scatter
,
.
enable_scatter
=
ath6kl_sdio_enable_scatter
,
.
scat_req_rw
=
ath6kl_sdio_async_rw_scatter
,
.
scat_req_rw
=
ath6kl_sdio_async_rw_scatter
,
.
cleanup_scatter
=
ath6kl_sdio_cleanup_scatter
,
.
cleanup_scatter
=
ath6kl_sdio_cleanup_scatter
,
.
suspend
=
ath6kl_sdio_suspend
,
};
};
static
int
ath6kl_sdio_probe
(
struct
sdio_func
*
func
,
static
int
ath6kl_sdio_probe
(
struct
sdio_func
*
func
,
...
@@ -741,10 +772,10 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
...
@@ -741,10 +772,10 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
struct
ath6kl
*
ar
;
struct
ath6kl
*
ar
;
int
count
;
int
count
;
ath6kl_dbg
(
ATH6KL_DBG_
TRC
,
ath6kl_dbg
(
ATH6KL_DBG_
SDIO
,
"
%s: func: 0x%X, vendor id: 0x%X, dev id: 0x%X, block size: 0x%X/0x%X
\n
"
,
"
new func %d vendor 0x%x device 0x%x block 0x%x/0x%x
\n
"
,
__func__
,
func
->
num
,
func
->
vendor
,
func
->
num
,
func
->
vendor
,
func
->
device
,
func
->
device
,
func
->
max_blksize
,
func
->
cur_blksize
);
func
->
max_blksize
,
func
->
cur_blksize
);
ar_sdio
=
kzalloc
(
sizeof
(
struct
ath6kl_sdio
),
GFP_KERNEL
);
ar_sdio
=
kzalloc
(
sizeof
(
struct
ath6kl_sdio
),
GFP_KERNEL
);
if
(
!
ar_sdio
)
if
(
!
ar_sdio
)
...
@@ -800,10 +831,10 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
...
@@ -800,10 +831,10 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
ath6kl_err
(
"Failed to enable 4-bit async irq mode %d
\n
"
,
ath6kl_err
(
"Failed to enable 4-bit async irq mode %d
\n
"
,
ret
);
ret
);
sdio_release_host
(
func
);
sdio_release_host
(
func
);
goto
err_
dma
;
goto
err_
cfg80211
;
}
}
ath6kl_dbg
(
ATH6KL_DBG_
TRC
,
"4-bit async irq mode enabled
\n
"
);
ath6kl_dbg
(
ATH6KL_DBG_
SDIO
,
"4-bit async irq mode enabled
\n
"
);
}
}
/* give us some time to enable, in ms */
/* give us some time to enable, in ms */
...
@@ -813,7 +844,7 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
...
@@ -813,7 +844,7 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
ret
=
ath6kl_sdio_power_on
(
ar_sdio
);
ret
=
ath6kl_sdio_power_on
(
ar_sdio
);
if
(
ret
)
if
(
ret
)
goto
err_
dma
;
goto
err_
cfg80211
;
sdio_claim_host
(
func
);
sdio_claim_host
(
func
);
...
@@ -837,6 +868,8 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
...
@@ -837,6 +868,8 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
err_off:
err_off:
ath6kl_sdio_power_off
(
ar_sdio
);
ath6kl_sdio_power_off
(
ar_sdio
);
err_cfg80211:
ath6kl_cfg80211_deinit
(
ar_sdio
->
ar
);
err_dma:
err_dma:
kfree
(
ar_sdio
->
dma_buffer
);
kfree
(
ar_sdio
->
dma_buffer
);
err_hif:
err_hif:
...
@@ -849,6 +882,10 @@ static void ath6kl_sdio_remove(struct sdio_func *func)
...
@@ -849,6 +882,10 @@ static void ath6kl_sdio_remove(struct sdio_func *func)
{
{
struct
ath6kl_sdio
*
ar_sdio
;
struct
ath6kl_sdio
*
ar_sdio
;
ath6kl_dbg
(
ATH6KL_DBG_SDIO
,
"removed func %d vendor 0x%x device 0x%x
\n
"
,
func
->
num
,
func
->
vendor
,
func
->
device
);
ar_sdio
=
sdio_get_drvdata
(
func
);
ar_sdio
=
sdio_get_drvdata
(
func
);
ath6kl_stop_txrx
(
ar_sdio
->
ar
);
ath6kl_stop_txrx
(
ar_sdio
->
ar
);
...
...
drivers/net/wireless/ath/ath6kl/target.h
View file @
a5abbcb2
...
@@ -20,6 +20,9 @@
...
@@ -20,6 +20,9 @@
#define AR6003_BOARD_DATA_SZ 1024
#define AR6003_BOARD_DATA_SZ 1024
#define AR6003_BOARD_EXT_DATA_SZ 768
#define AR6003_BOARD_EXT_DATA_SZ 768
#define AR6004_BOARD_DATA_SZ 7168
#define AR6004_BOARD_EXT_DATA_SZ 0
#define RESET_CONTROL_ADDRESS 0x00000000
#define RESET_CONTROL_ADDRESS 0x00000000
#define RESET_CONTROL_COLD_RST 0x00000100
#define RESET_CONTROL_COLD_RST 0x00000100
#define RESET_CONTROL_MBOX_RST 0x00000004
#define RESET_CONTROL_MBOX_RST 0x00000004
...
@@ -135,7 +138,8 @@
...
@@ -135,7 +138,8 @@
* between the two, and is intended to remain constant (with additions only
* between the two, and is intended to remain constant (with additions only
* at the end).
* at the end).
*/
*/
#define ATH6KL_HI_START_ADDR 0x00540600
#define ATH6KL_AR6003_HI_START_ADDR 0x00540600
#define ATH6KL_AR6004_HI_START_ADDR 0x00400800
/*
/*
* These are items that the Host may need to access
* These are items that the Host may need to access
...
@@ -300,6 +304,11 @@ struct host_interest {
...
@@ -300,6 +304,11 @@ struct host_interest {
#define HI_OPTION_FW_MODE_BSS_STA 0x1
#define HI_OPTION_FW_MODE_BSS_STA 0x1
#define HI_OPTION_FW_MODE_AP 0x2
#define HI_OPTION_FW_MODE_AP 0x2
#define HI_OPTION_FW_SUBMODE_NONE 0x0
#define HI_OPTION_FW_SUBMODE_P2PDEV 0x1
#define HI_OPTION_FW_SUBMODE_P2PCLIENT 0x2
#define HI_OPTION_FW_SUBMODE_P2PGO 0x3
#define HI_OPTION_NUM_DEV_SHIFT 0x9
#define HI_OPTION_NUM_DEV_SHIFT 0x9
#define HI_OPTION_FW_BRIDGE_SHIFT 0x04
#define HI_OPTION_FW_BRIDGE_SHIFT 0x04
...
@@ -312,20 +321,44 @@ struct host_interest {
...
@@ -312,20 +321,44 @@ struct host_interest {
|------------------------------------------------------------------------------|
|------------------------------------------------------------------------------|
*/
*/
#define HI_OPTION_FW_MODE_SHIFT 0xC
#define HI_OPTION_FW_MODE_SHIFT 0xC
#define HI_OPTION_FW_SUBMODE_SHIFT 0x14
/* Convert a Target virtual address into a Target physical address */
/* Convert a Target virtual address into a Target physical address */
#define TARG_VTOP(vaddr) (vaddr & 0x001fffff)
#define AR6003_VTOP(vaddr) ((vaddr) & 0x001fffff)
#define AR6004_VTOP(vaddr) (vaddr)
#define TARG_VTOP(target_type, vaddr) \
(((target_type) == TARGET_TYPE_AR6003) ? AR6003_VTOP(vaddr) : \
(((target_type) == TARGET_TYPE_AR6004) ? AR6004_VTOP(vaddr) : 0))
#define AR6003_REV2_APP_START_OVERRIDE 0x944C00
#define AR6003_REV2_APP_LOAD_ADDRESS 0x543180
#define AR6003_REV2_APP_LOAD_ADDRESS 0x543180
#define AR6003_REV2_BOARD_EXT_DATA_ADDRESS 0x57E500
#define AR6003_REV2_BOARD_EXT_DATA_ADDRESS 0x57E500
#define AR6003_REV2_DATASET_PATCH_ADDRESS 0x57e884
#define AR6003_REV2_DATASET_PATCH_ADDRESS 0x57e884
#define AR6003_REV2_RAM_RESERVE_SIZE 6912
#define AR6003_REV2_RAM_RESERVE_SIZE 6912
#define AR6003_REV3_APP_START_OVERRIDE 0x945d00
#define AR6003_REV3_APP_LOAD_ADDRESS 0x545000
#define AR6003_REV3_APP_LOAD_ADDRESS 0x545000
#define AR6003_REV3_BOARD_EXT_DATA_ADDRESS 0x542330
#define AR6003_REV3_BOARD_EXT_DATA_ADDRESS 0x542330
#define AR6003_REV3_DATASET_PATCH_ADDRESS 0x57FF74
#define AR6003_REV3_DATASET_PATCH_ADDRESS 0x57FF74
#define AR6003_REV3_RAM_RESERVE_SIZE 512
#define AR6003_REV3_RAM_RESERVE_SIZE 512
#define AR6004_REV1_BOARD_DATA_ADDRESS 0x435400
#define AR6004_REV1_BOARD_EXT_DATA_ADDRESS 0x437000
#define AR6004_REV1_RAM_RESERVE_SIZE 11264
#define ATH6KL_FWLOG_PAYLOAD_SIZE 1500
struct
ath6kl_dbglog_buf
{
__le32
next
;
__le32
buffer_addr
;
__le32
bufsize
;
__le32
length
;
__le32
count
;
__le32
free
;
}
__packed
;
struct
ath6kl_dbglog_hdr
{
__le32
dbuf_addr
;
__le32
dropped
;
}
__packed
;
#endif
#endif
drivers/net/wireless/ath/ath6kl/testmode.c
0 → 100644
View file @
a5abbcb2
/*
* Copyright (c) 2010-2011 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "testmode.h"
#include <net/netlink.h>
enum
ath6kl_tm_attr
{
__ATH6KL_TM_ATTR_INVALID
=
0
,
ATH6KL_TM_ATTR_CMD
=
1
,
ATH6KL_TM_ATTR_DATA
=
2
,
/* keep last */
__ATH6KL_TM_ATTR_AFTER_LAST
,
ATH6KL_TM_ATTR_MAX
=
__ATH6KL_TM_ATTR_AFTER_LAST
-
1
,
};
enum
ath6kl_tm_cmd
{
ATH6KL_TM_CMD_TCMD
=
0
,
ATH6KL_TM_CMD_RX_REPORT
=
1
,
};
#define ATH6KL_TM_DATA_MAX_LEN 5000
static
const
struct
nla_policy
ath6kl_tm_policy
[
ATH6KL_TM_ATTR_MAX
+
1
]
=
{
[
ATH6KL_TM_ATTR_CMD
]
=
{
.
type
=
NLA_U32
},
[
ATH6KL_TM_ATTR_DATA
]
=
{
.
type
=
NLA_BINARY
,
.
len
=
ATH6KL_TM_DATA_MAX_LEN
},
};
void
ath6kl_tm_rx_report_event
(
struct
ath6kl
*
ar
,
void
*
buf
,
size_t
buf_len
)
{
if
(
down_interruptible
(
&
ar
->
sem
))
return
;
kfree
(
ar
->
tm
.
rx_report
);
ar
->
tm
.
rx_report
=
kmemdup
(
buf
,
buf_len
,
GFP_KERNEL
);
ar
->
tm
.
rx_report_len
=
buf_len
;
up
(
&
ar
->
sem
);
wake_up
(
&
ar
->
event_wq
);
}
static
int
ath6kl_tm_rx_report
(
struct
ath6kl
*
ar
,
void
*
buf
,
size_t
buf_len
,
struct
sk_buff
*
skb
)
{
int
ret
=
0
;
long
left
;
if
(
down_interruptible
(
&
ar
->
sem
))
return
-
ERESTARTSYS
;
if
(
!
test_bit
(
WMI_READY
,
&
ar
->
flag
))
{
ret
=
-
EIO
;
goto
out
;
}
if
(
test_bit
(
DESTROY_IN_PROGRESS
,
&
ar
->
flag
))
{
ret
=
-
EBUSY
;
goto
out
;
}
if
(
ath6kl_wmi_test_cmd
(
ar
->
wmi
,
buf
,
buf_len
)
<
0
)
{
up
(
&
ar
->
sem
);
return
-
EIO
;
}
left
=
wait_event_interruptible_timeout
(
ar
->
event_wq
,
ar
->
tm
.
rx_report
!=
NULL
,
WMI_TIMEOUT
);
if
(
left
==
0
)
{
ret
=
-
ETIMEDOUT
;
goto
out
;
}
else
if
(
left
<
0
)
{
ret
=
left
;
goto
out
;
}
if
(
ar
->
tm
.
rx_report
==
NULL
||
ar
->
tm
.
rx_report_len
==
0
)
{
ret
=
-
EINVAL
;
goto
out
;
}
NLA_PUT
(
skb
,
ATH6KL_TM_ATTR_DATA
,
ar
->
tm
.
rx_report_len
,
ar
->
tm
.
rx_report
);
kfree
(
ar
->
tm
.
rx_report
);
ar
->
tm
.
rx_report
=
NULL
;
out:
up
(
&
ar
->
sem
);
return
ret
;
nla_put_failure:
ret
=
-
ENOBUFS
;
goto
out
;
}
int
ath6kl_tm_cmd
(
struct
wiphy
*
wiphy
,
void
*
data
,
int
len
)
{
struct
ath6kl
*
ar
=
wiphy_priv
(
wiphy
);
struct
nlattr
*
tb
[
ATH6KL_TM_ATTR_MAX
+
1
];
int
err
,
buf_len
,
reply_len
;
struct
sk_buff
*
skb
;
void
*
buf
;
err
=
nla_parse
(
tb
,
ATH6KL_TM_ATTR_MAX
,
data
,
len
,
ath6kl_tm_policy
);
if
(
err
)
return
err
;
if
(
!
tb
[
ATH6KL_TM_ATTR_CMD
])
return
-
EINVAL
;
switch
(
nla_get_u32
(
tb
[
ATH6KL_TM_ATTR_CMD
]))
{
case
ATH6KL_TM_CMD_TCMD
:
if
(
!
tb
[
ATH6KL_TM_ATTR_DATA
])
return
-
EINVAL
;
buf
=
nla_data
(
tb
[
ATH6KL_TM_ATTR_DATA
]);
buf_len
=
nla_len
(
tb
[
ATH6KL_TM_ATTR_DATA
]);
ath6kl_wmi_test_cmd
(
ar
->
wmi
,
buf
,
buf_len
);
return
0
;
break
;
case
ATH6KL_TM_CMD_RX_REPORT
:
if
(
!
tb
[
ATH6KL_TM_ATTR_DATA
])
return
-
EINVAL
;
buf
=
nla_data
(
tb
[
ATH6KL_TM_ATTR_DATA
]);
buf_len
=
nla_len
(
tb
[
ATH6KL_TM_ATTR_DATA
]);
reply_len
=
nla_total_size
(
ATH6KL_TM_DATA_MAX_LEN
);
skb
=
cfg80211_testmode_alloc_reply_skb
(
wiphy
,
reply_len
);
if
(
!
skb
)
return
-
ENOMEM
;
err
=
ath6kl_tm_rx_report
(
ar
,
buf
,
buf_len
,
skb
);
if
(
err
<
0
)
{
kfree_skb
(
skb
);
return
err
;
}
return
cfg80211_testmode_reply
(
skb
);
default:
return
-
EOPNOTSUPP
;
}
}
drivers/net/wireless/ath/ath6kl/testmode.h
0 → 100644
View file @
a5abbcb2
/*
* Copyright (c) 2010-2011 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "core.h"
#ifdef CONFIG_NL80211_TESTMODE
void
ath6kl_tm_rx_report_event
(
struct
ath6kl
*
ar
,
void
*
buf
,
size_t
buf_len
);
int
ath6kl_tm_cmd
(
struct
wiphy
*
wiphy
,
void
*
data
,
int
len
);
#else
static
inline
void
ath6kl_tm_rx_report_event
(
struct
ath6kl
*
ar
,
void
*
buf
,
size_t
buf_len
)
{
}
static
inline
int
ath6kl_tm_cmd
(
struct
wiphy
*
wiphy
,
void
*
data
,
int
len
)
{
return
0
;
}
#endif
drivers/net/wireless/ath/ath6kl/txrx.c
View file @
a5abbcb2
...
@@ -239,7 +239,6 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
...
@@ -239,7 +239,6 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
u16
htc_tag
=
ATH6KL_DATA_PKT_TAG
;
u16
htc_tag
=
ATH6KL_DATA_PKT_TAG
;
u8
ac
=
99
;
/* initialize to unmapped ac */
u8
ac
=
99
;
/* initialize to unmapped ac */
bool
chk_adhoc_ps_mapping
=
false
,
more_data
=
false
;
bool
chk_adhoc_ps_mapping
=
false
,
more_data
=
false
;
struct
wmi_tx_meta_v2
meta_v2
;
int
ret
;
int
ret
;
ath6kl_dbg
(
ATH6KL_DBG_WLAN_TX
,
ath6kl_dbg
(
ATH6KL_DBG_WLAN_TX
,
...
@@ -262,8 +261,6 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
...
@@ -262,8 +261,6 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
}
}
if
(
test_bit
(
WMI_ENABLED
,
&
ar
->
flag
))
{
if
(
test_bit
(
WMI_ENABLED
,
&
ar
->
flag
))
{
memset
(
&
meta_v2
,
0
,
sizeof
(
meta_v2
));
if
(
skb_headroom
(
skb
)
<
dev
->
needed_headroom
)
{
if
(
skb_headroom
(
skb
)
<
dev
->
needed_headroom
)
{
WARN_ON
(
1
);
WARN_ON
(
1
);
goto
fail_tx
;
goto
fail_tx
;
...
@@ -320,12 +317,31 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
...
@@ -320,12 +317,31 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
spin_unlock_bh
(
&
ar
->
lock
);
spin_unlock_bh
(
&
ar
->
lock
);
if
(
!
IS_ALIGNED
((
unsigned
long
)
skb
->
data
-
HTC_HDR_LENGTH
,
4
)
&&
skb_cloned
(
skb
))
{
/*
* We will touch (move the buffer data to align it. Since the
* skb buffer is cloned and not only the header is changed, we
* have to copy it to allow the changes. Since we are copying
* the data here, we may as well align it by reserving suitable
* headroom to avoid the memmove in ath6kl_htc_tx_buf_align().
*/
struct
sk_buff
*
nskb
;
nskb
=
skb_copy_expand
(
skb
,
HTC_HDR_LENGTH
,
0
,
GFP_ATOMIC
);
if
(
nskb
==
NULL
)
goto
fail_tx
;
kfree_skb
(
skb
);
skb
=
nskb
;
}
cookie
->
skb
=
skb
;
cookie
->
skb
=
skb
;
cookie
->
map_no
=
map_no
;
cookie
->
map_no
=
map_no
;
set_htc_pkt_info
(
&
cookie
->
htc_pkt
,
cookie
,
skb
->
data
,
skb
->
len
,
set_htc_pkt_info
(
&
cookie
->
htc_pkt
,
cookie
,
skb
->
data
,
skb
->
len
,
eid
,
htc_tag
);
eid
,
htc_tag
);
ath6kl_dbg_dump
(
ATH6KL_DBG_RAW_BYTES
,
__func__
,
skb
->
data
,
skb
->
len
);
ath6kl_dbg_dump
(
ATH6KL_DBG_RAW_BYTES
,
__func__
,
"tx "
,
skb
->
data
,
skb
->
len
);
/*
/*
* HTC interface is asynchronous, if this fails, cleanup will
* HTC interface is asynchronous, if this fails, cleanup will
...
@@ -689,6 +705,8 @@ void ath6kl_rx_refill(struct htc_target *target, enum htc_endpoint_id endpoint)
...
@@ -689,6 +705,8 @@ void ath6kl_rx_refill(struct htc_target *target, enum htc_endpoint_id endpoint)
break
;
break
;
packet
=
(
struct
htc_packet
*
)
skb
->
head
;
packet
=
(
struct
htc_packet
*
)
skb
->
head
;
if
(
!
IS_ALIGNED
((
unsigned
long
)
skb
->
data
,
4
))
skb
->
data
=
PTR_ALIGN
(
skb
->
data
-
4
,
4
);
set_htc_rxpkt_info
(
packet
,
skb
,
skb
->
data
,
set_htc_rxpkt_info
(
packet
,
skb
,
skb
->
data
,
ATH6KL_BUFFER_SIZE
,
endpoint
);
ATH6KL_BUFFER_SIZE
,
endpoint
);
list_add_tail
(
&
packet
->
list
,
&
queue
);
list_add_tail
(
&
packet
->
list
,
&
queue
);
...
@@ -709,6 +727,8 @@ void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count)
...
@@ -709,6 +727,8 @@ void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count)
return
;
return
;
packet
=
(
struct
htc_packet
*
)
skb
->
head
;
packet
=
(
struct
htc_packet
*
)
skb
->
head
;
if
(
!
IS_ALIGNED
((
unsigned
long
)
skb
->
data
,
4
))
skb
->
data
=
PTR_ALIGN
(
skb
->
data
-
4
,
4
);
set_htc_rxpkt_info
(
packet
,
skb
,
skb
->
data
,
set_htc_rxpkt_info
(
packet
,
skb
,
skb
->
data
,
ATH6KL_AMSDU_BUFFER_SIZE
,
0
);
ATH6KL_AMSDU_BUFFER_SIZE
,
0
);
spin_lock_bh
(
&
ar
->
lock
);
spin_lock_bh
(
&
ar
->
lock
);
...
@@ -812,7 +832,7 @@ static void aggr_slice_amsdu(struct aggr_info *p_aggr,
...
@@ -812,7 +832,7 @@ static void aggr_slice_amsdu(struct aggr_info *p_aggr,
/* Add the length of A-MSDU subframe padding bytes -
/* Add the length of A-MSDU subframe padding bytes -
* Round to nearest word.
* Round to nearest word.
*/
*/
frame_8023_len
=
ALIGN
(
frame_8023_len
+
3
,
3
);
frame_8023_len
=
ALIGN
(
frame_8023_len
,
4
);
framep
+=
frame_8023_len
;
framep
+=
frame_8023_len
;
amsdu_len
-=
frame_8023_len
;
amsdu_len
-=
frame_8023_len
;
...
@@ -1044,12 +1064,13 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
...
@@ -1044,12 +1064,13 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
ar
->
net_stats
.
rx_packets
++
;
ar
->
net_stats
.
rx_packets
++
;
ar
->
net_stats
.
rx_bytes
+=
packet
->
act_len
;
ar
->
net_stats
.
rx_bytes
+=
packet
->
act_len
;
spin_unlock_bh
(
&
ar
->
lock
);
skb_put
(
skb
,
packet
->
act_len
+
HTC_HDR_LENGTH
);
skb_put
(
skb
,
packet
->
act_len
+
HTC_HDR_LENGTH
);
skb_pull
(
skb
,
HTC_HDR_LENGTH
);
skb_pull
(
skb
,
HTC_HDR_LENGTH
);
ath6kl_dbg_dump
(
ATH6KL_DBG_RAW_BYTES
,
__func__
,
skb
->
data
,
skb
->
len
);
ath6kl_dbg_dump
(
ATH6KL_DBG_RAW_BYTES
,
__func__
,
"rx "
,
skb
->
data
,
skb
->
len
);
spin_unlock_bh
(
&
ar
->
lock
);
skb
->
dev
=
ar
->
net_dev
;
skb
->
dev
=
ar
->
net_dev
;
...
@@ -1065,9 +1086,8 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
...
@@ -1065,9 +1086,8 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
return
;
return
;
}
}
min_hdr_len
=
sizeof
(
struct
ethhdr
);
min_hdr_len
=
sizeof
(
struct
ethhdr
)
+
sizeof
(
struct
wmi_data_hdr
)
+
min_hdr_len
+=
sizeof
(
struct
wmi_data_hdr
)
+
sizeof
(
struct
ath6kl_llc_snap_hdr
);
sizeof
(
struct
ath6kl_llc_snap_hdr
);
dhdr
=
(
struct
wmi_data_hdr
*
)
skb
->
data
;
dhdr
=
(
struct
wmi_data_hdr
*
)
skb
->
data
;
...
@@ -1163,8 +1183,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
...
@@ -1163,8 +1183,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
seq_no
=
wmi_data_hdr_get_seqno
(
dhdr
);
seq_no
=
wmi_data_hdr_get_seqno
(
dhdr
);
meta_type
=
wmi_data_hdr_get_meta
(
dhdr
);
meta_type
=
wmi_data_hdr_get_meta
(
dhdr
);
dot11_hdr
=
wmi_data_hdr_get_dot11
(
dhdr
);
dot11_hdr
=
wmi_data_hdr_get_dot11
(
dhdr
);
skb_pull
(
skb
,
sizeof
(
struct
wmi_data_hdr
));
ath6kl_wmi_data_hdr_remove
(
ar
->
wmi
,
skb
);
switch
(
meta_type
)
{
switch
(
meta_type
)
{
case
WMI_META_VERSION_1
:
case
WMI_META_VERSION_1
:
...
@@ -1231,9 +1250,15 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
...
@@ -1231,9 +1250,15 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
ath6kl_data_tx
(
skb1
,
ar
->
net_dev
);
ath6kl_data_tx
(
skb1
,
ar
->
net_dev
);
}
}
if
(
!
aggr_process_recv_frm
(
ar
->
aggr_cntxt
,
tid
,
seq_no
,
datap
=
(
struct
ethhdr
*
)
skb
->
data
;
is_amsdu
,
skb
))
ath6kl_deliver_frames_to_nw_stack
(
ar
->
net_dev
,
skb
);
if
(
is_unicast_ether_addr
(
datap
->
h_dest
)
&&
aggr_process_recv_frm
(
ar
->
aggr_cntxt
,
tid
,
seq_no
,
is_amsdu
,
skb
))
/* aggregation code will handle the skb */
return
;
ath6kl_deliver_frames_to_nw_stack
(
ar
->
net_dev
,
skb
);
}
}
static
void
aggr_timeout
(
unsigned
long
arg
)
static
void
aggr_timeout
(
unsigned
long
arg
)
...
@@ -1250,10 +1275,6 @@ static void aggr_timeout(unsigned long arg)
...
@@ -1250,10 +1275,6 @@ static void aggr_timeout(unsigned long arg)
if
(
!
rxtid
->
aggr
||
!
rxtid
->
timer_mon
||
rxtid
->
progress
)
if
(
!
rxtid
->
aggr
||
!
rxtid
->
timer_mon
||
rxtid
->
progress
)
continue
;
continue
;
/*
* FIXME: these timeouts happen quite fruently, something
* line once within 60 seconds. Investigate why.
*/
stats
->
num_timeouts
++
;
stats
->
num_timeouts
++
;
ath6kl_dbg
(
ATH6KL_DBG_AGGR
,
ath6kl_dbg
(
ATH6KL_DBG_AGGR
,
"aggr timeout (st %d end %d)
\n
"
,
"aggr timeout (st %d end %d)
\n
"
,
...
...
drivers/net/wireless/ath/ath6kl/wmi.c
View file @
a5abbcb2
...
@@ -17,6 +17,9 @@
...
@@ -17,6 +17,9 @@
#include <linux/ip.h>
#include <linux/ip.h>
#include "core.h"
#include "core.h"
#include "debug.h"
#include "debug.h"
#include "testmode.h"
#include "../regd.h"
#include "../regd_common.h"
static
int
ath6kl_wmi_sync_point
(
struct
wmi
*
wmi
);
static
int
ath6kl_wmi_sync_point
(
struct
wmi
*
wmi
);
...
@@ -167,9 +170,11 @@ int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb,
...
@@ -167,9 +170,11 @@ int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb,
if
(
WARN_ON
(
skb
==
NULL
))
if
(
WARN_ON
(
skb
==
NULL
))
return
-
EINVAL
;
return
-
EINVAL
;
ret
=
ath6kl_wmi_meta_add
(
wmi
,
skb
,
&
meta_ver
,
tx_meta_info
);
if
(
tx_meta_info
)
{
if
(
ret
)
ret
=
ath6kl_wmi_meta_add
(
wmi
,
skb
,
&
meta_ver
,
tx_meta_info
);
return
ret
;
if
(
ret
)
return
ret
;
}
skb_push
(
skb
,
sizeof
(
struct
wmi_data_hdr
));
skb_push
(
skb
,
sizeof
(
struct
wmi_data_hdr
));
...
@@ -376,35 +381,6 @@ int ath6kl_wmi_dot3_2_dix(struct sk_buff *skb)
...
@@ -376,35 +381,6 @@ int ath6kl_wmi_dot3_2_dix(struct sk_buff *skb)
return
0
;
return
0
;
}
}
int
ath6kl_wmi_data_hdr_remove
(
struct
wmi
*
wmi
,
struct
sk_buff
*
skb
)
{
if
(
WARN_ON
(
skb
==
NULL
))
return
-
EINVAL
;
skb_pull
(
skb
,
sizeof
(
struct
wmi_data_hdr
));
return
0
;
}
static
void
ath6kl_wmi_convert_bssinfo_hdr2_to_hdr
(
struct
sk_buff
*
skb
,
u8
*
datap
)
{
struct
wmi_bss_info_hdr2
bih2
;
struct
wmi_bss_info_hdr
*
bih
;
memcpy
(
&
bih2
,
datap
,
sizeof
(
struct
wmi_bss_info_hdr2
));
skb_push
(
skb
,
4
);
bih
=
(
struct
wmi_bss_info_hdr
*
)
skb
->
data
;
bih
->
ch
=
bih2
.
ch
;
bih
->
frame_type
=
bih2
.
frame_type
;
bih
->
snr
=
bih2
.
snr
;
bih
->
rssi
=
a_cpu_to_sle16
(
bih2
.
snr
-
95
);
bih
->
ie_mask
=
cpu_to_le32
(
le16_to_cpu
(
bih2
.
ie_mask
));
memcpy
(
bih
->
bssid
,
bih2
.
bssid
,
ETH_ALEN
);
}
static
int
ath6kl_wmi_tx_complete_event_rx
(
u8
*
datap
,
int
len
)
static
int
ath6kl_wmi_tx_complete_event_rx
(
u8
*
datap
,
int
len
)
{
{
struct
tx_complete_msg_v1
*
msg_v1
;
struct
tx_complete_msg_v1
*
msg_v1
;
...
@@ -433,6 +409,201 @@ static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len)
...
@@ -433,6 +409,201 @@ static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len)
return
0
;
return
0
;
}
}
static
int
ath6kl_wmi_remain_on_chnl_event_rx
(
struct
wmi
*
wmi
,
u8
*
datap
,
int
len
)
{
struct
wmi_remain_on_chnl_event
*
ev
;
u32
freq
;
u32
dur
;
struct
ieee80211_channel
*
chan
;
struct
ath6kl
*
ar
=
wmi
->
parent_dev
;
if
(
len
<
sizeof
(
*
ev
))
return
-
EINVAL
;
ev
=
(
struct
wmi_remain_on_chnl_event
*
)
datap
;
freq
=
le32_to_cpu
(
ev
->
freq
);
dur
=
le32_to_cpu
(
ev
->
duration
);
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"remain_on_chnl: freq=%u dur=%u
\n
"
,
freq
,
dur
);
chan
=
ieee80211_get_channel
(
ar
->
wdev
->
wiphy
,
freq
);
if
(
!
chan
)
{
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"remain_on_chnl: Unknown channel "
"(freq=%u)
\n
"
,
freq
);
return
-
EINVAL
;
}
cfg80211_ready_on_channel
(
ar
->
net_dev
,
1
,
chan
,
NL80211_CHAN_NO_HT
,
dur
,
GFP_ATOMIC
);
return
0
;
}
static
int
ath6kl_wmi_cancel_remain_on_chnl_event_rx
(
struct
wmi
*
wmi
,
u8
*
datap
,
int
len
)
{
struct
wmi_cancel_remain_on_chnl_event
*
ev
;
u32
freq
;
u32
dur
;
struct
ieee80211_channel
*
chan
;
struct
ath6kl
*
ar
=
wmi
->
parent_dev
;
if
(
len
<
sizeof
(
*
ev
))
return
-
EINVAL
;
ev
=
(
struct
wmi_cancel_remain_on_chnl_event
*
)
datap
;
freq
=
le32_to_cpu
(
ev
->
freq
);
dur
=
le32_to_cpu
(
ev
->
duration
);
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"cancel_remain_on_chnl: freq=%u dur=%u "
"status=%u
\n
"
,
freq
,
dur
,
ev
->
status
);
chan
=
ieee80211_get_channel
(
ar
->
wdev
->
wiphy
,
freq
);
if
(
!
chan
)
{
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"cancel_remain_on_chnl: Unknown "
"channel (freq=%u)
\n
"
,
freq
);
return
-
EINVAL
;
}
cfg80211_remain_on_channel_expired
(
ar
->
net_dev
,
1
,
chan
,
NL80211_CHAN_NO_HT
,
GFP_ATOMIC
);
return
0
;
}
static
int
ath6kl_wmi_tx_status_event_rx
(
struct
wmi
*
wmi
,
u8
*
datap
,
int
len
)
{
struct
wmi_tx_status_event
*
ev
;
u32
id
;
struct
ath6kl
*
ar
=
wmi
->
parent_dev
;
if
(
len
<
sizeof
(
*
ev
))
return
-
EINVAL
;
ev
=
(
struct
wmi_tx_status_event
*
)
datap
;
id
=
le32_to_cpu
(
ev
->
id
);
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"tx_status: id=%x ack_status=%u
\n
"
,
id
,
ev
->
ack_status
);
if
(
wmi
->
last_mgmt_tx_frame
)
{
cfg80211_mgmt_tx_status
(
ar
->
net_dev
,
id
,
wmi
->
last_mgmt_tx_frame
,
wmi
->
last_mgmt_tx_frame_len
,
!!
ev
->
ack_status
,
GFP_ATOMIC
);
kfree
(
wmi
->
last_mgmt_tx_frame
);
wmi
->
last_mgmt_tx_frame
=
NULL
;
wmi
->
last_mgmt_tx_frame_len
=
0
;
}
return
0
;
}
static
int
ath6kl_wmi_rx_probe_req_event_rx
(
struct
wmi
*
wmi
,
u8
*
datap
,
int
len
)
{
struct
wmi_p2p_rx_probe_req_event
*
ev
;
u32
freq
;
u16
dlen
;
struct
ath6kl
*
ar
=
wmi
->
parent_dev
;
if
(
len
<
sizeof
(
*
ev
))
return
-
EINVAL
;
ev
=
(
struct
wmi_p2p_rx_probe_req_event
*
)
datap
;
freq
=
le32_to_cpu
(
ev
->
freq
);
dlen
=
le16_to_cpu
(
ev
->
len
);
if
(
datap
+
len
<
ev
->
data
+
dlen
)
{
ath6kl_err
(
"invalid wmi_p2p_rx_probe_req_event: "
"len=%d dlen=%u
\n
"
,
len
,
dlen
);
return
-
EINVAL
;
}
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"rx_probe_req: len=%u freq=%u "
"probe_req_report=%d
\n
"
,
dlen
,
freq
,
ar
->
probe_req_report
);
if
(
ar
->
probe_req_report
||
ar
->
nw_type
==
AP_NETWORK
)
cfg80211_rx_mgmt
(
ar
->
net_dev
,
freq
,
ev
->
data
,
dlen
,
GFP_ATOMIC
);
return
0
;
}
static
int
ath6kl_wmi_p2p_capabilities_event_rx
(
u8
*
datap
,
int
len
)
{
struct
wmi_p2p_capabilities_event
*
ev
;
u16
dlen
;
if
(
len
<
sizeof
(
*
ev
))
return
-
EINVAL
;
ev
=
(
struct
wmi_p2p_capabilities_event
*
)
datap
;
dlen
=
le16_to_cpu
(
ev
->
len
);
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"p2p_capab: len=%u
\n
"
,
dlen
);
return
0
;
}
static
int
ath6kl_wmi_rx_action_event_rx
(
struct
wmi
*
wmi
,
u8
*
datap
,
int
len
)
{
struct
wmi_rx_action_event
*
ev
;
u32
freq
;
u16
dlen
;
struct
ath6kl
*
ar
=
wmi
->
parent_dev
;
if
(
len
<
sizeof
(
*
ev
))
return
-
EINVAL
;
ev
=
(
struct
wmi_rx_action_event
*
)
datap
;
freq
=
le32_to_cpu
(
ev
->
freq
);
dlen
=
le16_to_cpu
(
ev
->
len
);
if
(
datap
+
len
<
ev
->
data
+
dlen
)
{
ath6kl_err
(
"invalid wmi_rx_action_event: "
"len=%d dlen=%u
\n
"
,
len
,
dlen
);
return
-
EINVAL
;
}
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"rx_action: len=%u freq=%u
\n
"
,
dlen
,
freq
);
cfg80211_rx_mgmt
(
ar
->
net_dev
,
freq
,
ev
->
data
,
dlen
,
GFP_ATOMIC
);
return
0
;
}
static
int
ath6kl_wmi_p2p_info_event_rx
(
u8
*
datap
,
int
len
)
{
struct
wmi_p2p_info_event
*
ev
;
u32
flags
;
u16
dlen
;
if
(
len
<
sizeof
(
*
ev
))
return
-
EINVAL
;
ev
=
(
struct
wmi_p2p_info_event
*
)
datap
;
flags
=
le32_to_cpu
(
ev
->
info_req_flags
);
dlen
=
le16_to_cpu
(
ev
->
len
);
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"p2p_info: flags=%x len=%d
\n
"
,
flags
,
dlen
);
if
(
flags
&
P2P_FLAG_CAPABILITIES_REQ
)
{
struct
wmi_p2p_capabilities
*
cap
;
if
(
dlen
<
sizeof
(
*
cap
))
return
-
EINVAL
;
cap
=
(
struct
wmi_p2p_capabilities
*
)
ev
->
data
;
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"p2p_info: GO Power Save = %d
\n
"
,
cap
->
go_power_save
);
}
if
(
flags
&
P2P_FLAG_MACADDR_REQ
)
{
struct
wmi_p2p_macaddr
*
mac
;
if
(
dlen
<
sizeof
(
*
mac
))
return
-
EINVAL
;
mac
=
(
struct
wmi_p2p_macaddr
*
)
ev
->
data
;
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"p2p_info: MAC Address = %pM
\n
"
,
mac
->
mac_addr
);
}
if
(
flags
&
P2P_FLAG_HMODEL_REQ
)
{
struct
wmi_p2p_hmodel
*
mod
;
if
(
dlen
<
sizeof
(
*
mod
))
return
-
EINVAL
;
mod
=
(
struct
wmi_p2p_hmodel
*
)
ev
->
data
;
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"p2p_info: P2P Model = %d (%s)
\n
"
,
mod
->
p2p_model
,
mod
->
p2p_model
?
"host"
:
"firmware"
);
}
return
0
;
}
static
inline
struct
sk_buff
*
ath6kl_wmi_get_new_buf
(
u32
size
)
static
inline
struct
sk_buff
*
ath6kl_wmi_get_new_buf
(
u32
size
)
{
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
...
@@ -478,18 +649,84 @@ static int ath6kl_wmi_ready_event_rx(struct wmi *wmi, u8 *datap, int len)
...
@@ -478,18 +649,84 @@ static int ath6kl_wmi_ready_event_rx(struct wmi *wmi, u8 *datap, int len)
return
0
;
return
0
;
}
}
/*
* Mechanism to modify the roaming behavior in the firmware. The lower rssi
* at which the station has to roam can be passed with
* WMI_SET_LRSSI_SCAN_PARAMS. Subtract 96 from RSSI to get the signal level
* in dBm.
*/
int
ath6kl_wmi_set_roam_lrssi_cmd
(
struct
wmi
*
wmi
,
u8
lrssi
)
{
struct
sk_buff
*
skb
;
struct
roam_ctrl_cmd
*
cmd
;
skb
=
ath6kl_wmi_get_new_buf
(
sizeof
(
*
cmd
));
if
(
!
skb
)
return
-
ENOMEM
;
cmd
=
(
struct
roam_ctrl_cmd
*
)
skb
->
data
;
cmd
->
info
.
params
.
lrssi_scan_period
=
cpu_to_le16
(
DEF_LRSSI_SCAN_PERIOD
);
cmd
->
info
.
params
.
lrssi_scan_threshold
=
a_cpu_to_sle16
(
lrssi
+
DEF_SCAN_FOR_ROAM_INTVL
);
cmd
->
info
.
params
.
lrssi_roam_threshold
=
a_cpu_to_sle16
(
lrssi
);
cmd
->
info
.
params
.
roam_rssi_floor
=
DEF_LRSSI_ROAM_FLOOR
;
cmd
->
roam_ctrl
=
WMI_SET_LRSSI_SCAN_PARAMS
;
ath6kl_wmi_cmd_send
(
wmi
,
skb
,
WMI_SET_ROAM_CTRL_CMDID
,
NO_SYNC_WMIFLAG
);
return
0
;
}
static
int
ath6kl_wmi_connect_event_rx
(
struct
wmi
*
wmi
,
u8
*
datap
,
int
len
)
static
int
ath6kl_wmi_connect_event_rx
(
struct
wmi
*
wmi
,
u8
*
datap
,
int
len
)
{
{
struct
wmi_connect_event
*
ev
;
struct
wmi_connect_event
*
ev
;
u8
*
pie
,
*
peie
;
u8
*
pie
,
*
peie
;
struct
ath6kl
*
ar
=
wmi
->
parent_dev
;
if
(
len
<
sizeof
(
struct
wmi_connect_event
))
if
(
len
<
sizeof
(
struct
wmi_connect_event
))
return
-
EINVAL
;
return
-
EINVAL
;
ev
=
(
struct
wmi_connect_event
*
)
datap
;
ev
=
(
struct
wmi_connect_event
*
)
datap
;
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"%s: freq %d bssid %pM
\n
"
,
if
(
ar
->
nw_type
==
AP_NETWORK
)
{
__func__
,
ev
->
ch
,
ev
->
bssid
);
/* AP mode start/STA connected event */
struct
net_device
*
dev
=
ar
->
net_dev
;
if
(
memcmp
(
dev
->
dev_addr
,
ev
->
u
.
ap_bss
.
bssid
,
ETH_ALEN
)
==
0
)
{
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"%s: freq %d bssid %pM "
"(AP started)
\n
"
,
__func__
,
le16_to_cpu
(
ev
->
u
.
ap_bss
.
ch
),
ev
->
u
.
ap_bss
.
bssid
);
ath6kl_connect_ap_mode_bss
(
ar
,
le16_to_cpu
(
ev
->
u
.
ap_bss
.
ch
));
}
else
{
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"%s: aid %u mac_addr %pM "
"auth=%u keymgmt=%u cipher=%u apsd_info=%u "
"(STA connected)
\n
"
,
__func__
,
ev
->
u
.
ap_sta
.
aid
,
ev
->
u
.
ap_sta
.
mac_addr
,
ev
->
u
.
ap_sta
.
auth
,
ev
->
u
.
ap_sta
.
keymgmt
,
le16_to_cpu
(
ev
->
u
.
ap_sta
.
cipher
),
ev
->
u
.
ap_sta
.
apsd_info
);
ath6kl_connect_ap_mode_sta
(
ar
,
ev
->
u
.
ap_sta
.
aid
,
ev
->
u
.
ap_sta
.
mac_addr
,
ev
->
u
.
ap_sta
.
keymgmt
,
le16_to_cpu
(
ev
->
u
.
ap_sta
.
cipher
),
ev
->
u
.
ap_sta
.
auth
,
ev
->
assoc_req_len
,
ev
->
assoc_info
+
ev
->
beacon_ie_len
);
}
return
0
;
}
/* STA/IBSS mode connection event */
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"wmi event connect freq %d bssid %pM listen_intvl %d beacon_intvl %d type %d
\n
"
,
le16_to_cpu
(
ev
->
u
.
sta
.
ch
),
ev
->
u
.
sta
.
bssid
,
le16_to_cpu
(
ev
->
u
.
sta
.
listen_intvl
),
le16_to_cpu
(
ev
->
u
.
sta
.
beacon_intvl
),
le32_to_cpu
(
ev
->
u
.
sta
.
nw_type
));
/* Start of assoc rsp IEs */
/* Start of assoc rsp IEs */
pie
=
ev
->
assoc_info
+
ev
->
beacon_ie_len
+
pie
=
ev
->
assoc_info
+
ev
->
beacon_ie_len
+
...
@@ -518,16 +755,92 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len)
...
@@ -518,16 +755,92 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len)
pie
+=
pie
[
1
]
+
2
;
pie
+=
pie
[
1
]
+
2
;
}
}
ath6kl_connect_event
(
wmi
->
parent_dev
,
le16_to_cpu
(
ev
->
ch
),
ev
->
bssid
,
ath6kl_connect_event
(
wmi
->
parent_dev
,
le16_to_cpu
(
ev
->
u
.
sta
.
ch
),
le16_to_cpu
(
ev
->
listen_intvl
),
ev
->
u
.
sta
.
bssid
,
le16_to_cpu
(
ev
->
beacon_intvl
),
le16_to_cpu
(
ev
->
u
.
sta
.
listen_intvl
),
le32_to_cpu
(
ev
->
nw_type
),
le16_to_cpu
(
ev
->
u
.
sta
.
beacon_intvl
),
le32_to_cpu
(
ev
->
u
.
sta
.
nw_type
),
ev
->
beacon_ie_len
,
ev
->
assoc_req_len
,
ev
->
beacon_ie_len
,
ev
->
assoc_req_len
,
ev
->
assoc_resp_len
,
ev
->
assoc_info
);
ev
->
assoc_resp_len
,
ev
->
assoc_info
);
return
0
;
return
0
;
}
}
static
struct
country_code_to_enum_rd
*
ath6kl_regd_find_country
(
u16
countryCode
)
{
int
i
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
allCountries
);
i
++
)
{
if
(
allCountries
[
i
].
countryCode
==
countryCode
)
return
&
allCountries
[
i
];
}
return
NULL
;
}
static
struct
reg_dmn_pair_mapping
*
ath6kl_get_regpair
(
u16
regdmn
)
{
int
i
;
if
(
regdmn
==
NO_ENUMRD
)
return
NULL
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
regDomainPairs
);
i
++
)
{
if
(
regDomainPairs
[
i
].
regDmnEnum
==
regdmn
)
return
&
regDomainPairs
[
i
];
}
return
NULL
;
}
static
struct
country_code_to_enum_rd
*
ath6kl_regd_find_country_by_rd
(
u16
regdmn
)
{
int
i
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
allCountries
);
i
++
)
{
if
(
allCountries
[
i
].
regDmnEnum
==
regdmn
)
return
&
allCountries
[
i
];
}
return
NULL
;
}
static
void
ath6kl_wmi_regdomain_event
(
struct
wmi
*
wmi
,
u8
*
datap
,
int
len
)
{
struct
ath6kl_wmi_regdomain
*
ev
;
struct
country_code_to_enum_rd
*
country
=
NULL
;
struct
reg_dmn_pair_mapping
*
regpair
=
NULL
;
char
alpha2
[
2
];
u32
reg_code
;
ev
=
(
struct
ath6kl_wmi_regdomain
*
)
datap
;
reg_code
=
le32_to_cpu
(
ev
->
reg_code
);
if
((
reg_code
>>
ATH6KL_COUNTRY_RD_SHIFT
)
&
COUNTRY_ERD_FLAG
)
country
=
ath6kl_regd_find_country
((
u16
)
reg_code
);
else
if
(
!
(((
u16
)
reg_code
&
WORLD_SKU_MASK
)
==
WORLD_SKU_PREFIX
))
{
regpair
=
ath6kl_get_regpair
((
u16
)
reg_code
);
country
=
ath6kl_regd_find_country_by_rd
((
u16
)
reg_code
);
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"Regpair used: 0x%0x
\n
"
,
regpair
->
regDmnEnum
);
}
if
(
country
)
{
alpha2
[
0
]
=
country
->
isoName
[
0
];
alpha2
[
1
]
=
country
->
isoName
[
1
];
regulatory_hint
(
wmi
->
parent_dev
->
wdev
->
wiphy
,
alpha2
);
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"Country alpha2 being used: %c%c
\n
"
,
alpha2
[
0
],
alpha2
[
1
]);
}
}
static
int
ath6kl_wmi_disconnect_event_rx
(
struct
wmi
*
wmi
,
u8
*
datap
,
int
len
)
static
int
ath6kl_wmi_disconnect_event_rx
(
struct
wmi
*
wmi
,
u8
*
datap
,
int
len
)
{
{
struct
wmi_disconnect_event
*
ev
;
struct
wmi_disconnect_event
*
ev
;
...
@@ -538,6 +851,11 @@ static int ath6kl_wmi_disconnect_event_rx(struct wmi *wmi, u8 *datap, int len)
...
@@ -538,6 +851,11 @@ static int ath6kl_wmi_disconnect_event_rx(struct wmi *wmi, u8 *datap, int len)
ev
=
(
struct
wmi_disconnect_event
*
)
datap
;
ev
=
(
struct
wmi_disconnect_event
*
)
datap
;
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"wmi event disconnect proto_reason %d bssid %pM wmi_reason %d assoc_resp_len %d
\n
"
,
le16_to_cpu
(
ev
->
proto_reason_status
),
ev
->
bssid
,
ev
->
disconn_reason
,
ev
->
assoc_resp_len
);
wmi
->
is_wmm_enabled
=
false
;
wmi
->
is_wmm_enabled
=
false
;
wmi
->
pair_crypto_type
=
NONE_CRYPT
;
wmi
->
pair_crypto_type
=
NONE_CRYPT
;
wmi
->
grp_crypto_type
=
NONE_CRYPT
;
wmi
->
grp_crypto_type
=
NONE_CRYPT
;
...
@@ -582,315 +900,92 @@ static int ath6kl_wmi_tkip_micerr_event_rx(struct wmi *wmi, u8 *datap, int len)
...
@@ -582,315 +900,92 @@ static int ath6kl_wmi_tkip_micerr_event_rx(struct wmi *wmi, u8 *datap, int len)
return
0
;
return
0
;
}
}
static
int
ath6kl_wlan_parse_beacon
(
u8
*
buf
,
int
frame_len
,
struct
ath6kl_common_ie
*
cie
)
{
u8
*
frm
,
*
efrm
;
u8
elemid_ssid
=
false
;
frm
=
buf
;
efrm
=
(
u8
*
)
(
frm
+
frame_len
);
/*
* beacon/probe response frame format
* [8] time stamp
* [2] beacon interval
* [2] capability information
* [tlv] ssid
* [tlv] supported rates
* [tlv] country information
* [tlv] parameter set (FH/DS)
* [tlv] erp information
* [tlv] extended supported rates
* [tlv] WMM
* [tlv] WPA or RSN
* [tlv] Atheros Advanced Capabilities
*/
if
((
efrm
-
frm
)
<
12
)
return
-
EINVAL
;
memset
(
cie
,
0
,
sizeof
(
*
cie
));
cie
->
ie_tstamp
=
frm
;
frm
+=
8
;
cie
->
ie_beaconInt
=
*
(
u16
*
)
frm
;
frm
+=
2
;
cie
->
ie_capInfo
=
*
(
u16
*
)
frm
;
frm
+=
2
;
cie
->
ie_chan
=
0
;
while
(
frm
<
efrm
)
{
switch
(
*
frm
)
{
case
WLAN_EID_SSID
:
if
(
!
elemid_ssid
)
{
cie
->
ie_ssid
=
frm
;
elemid_ssid
=
true
;
}
break
;
case
WLAN_EID_SUPP_RATES
:
cie
->
ie_rates
=
frm
;
break
;
case
WLAN_EID_COUNTRY
:
cie
->
ie_country
=
frm
;
break
;
case
WLAN_EID_FH_PARAMS
:
break
;
case
WLAN_EID_DS_PARAMS
:
cie
->
ie_chan
=
frm
[
2
];
break
;
case
WLAN_EID_TIM
:
cie
->
ie_tim
=
frm
;
break
;
case
WLAN_EID_IBSS_PARAMS
:
break
;
case
WLAN_EID_EXT_SUPP_RATES
:
cie
->
ie_xrates
=
frm
;
break
;
case
WLAN_EID_ERP_INFO
:
if
(
frm
[
1
]
!=
1
)
return
-
EINVAL
;
cie
->
ie_erp
=
frm
[
2
];
break
;
case
WLAN_EID_RSN
:
cie
->
ie_rsn
=
frm
;
break
;
case
WLAN_EID_HT_CAPABILITY
:
cie
->
ie_htcap
=
frm
;
break
;
case
WLAN_EID_HT_INFORMATION
:
cie
->
ie_htop
=
frm
;
break
;
case
WLAN_EID_VENDOR_SPECIFIC
:
if
(
frm
[
1
]
>
3
&&
frm
[
2
]
==
0x00
&&
frm
[
3
]
==
0x50
&&
frm
[
4
]
==
0xf2
)
{
/* OUT Type (00:50:F2) */
if
(
frm
[
5
]
==
WPA_OUI_TYPE
)
{
/* WPA OUT */
cie
->
ie_wpa
=
frm
;
}
else
if
(
frm
[
5
]
==
WMM_OUI_TYPE
)
{
/* WMM OUT */
cie
->
ie_wmm
=
frm
;
}
else
if
(
frm
[
5
]
==
WSC_OUT_TYPE
)
{
/* WSC OUT */
cie
->
ie_wsc
=
frm
;
}
}
else
if
(
frm
[
1
]
>
3
&&
frm
[
2
]
==
0x00
&&
frm
[
3
]
==
0x03
&&
frm
[
4
]
==
0x7f
&&
frm
[
5
]
==
ATH_OUI_TYPE
)
{
/* Atheros OUI (00:03:7f) */
cie
->
ie_ath
=
frm
;
}
break
;
default:
break
;
}
frm
+=
frm
[
1
]
+
2
;
}
if
((
cie
->
ie_rates
==
NULL
)
||
(
cie
->
ie_rates
[
1
]
>
ATH6KL_RATE_MAXSIZE
))
return
-
EINVAL
;
if
((
cie
->
ie_ssid
==
NULL
)
||
(
cie
->
ie_ssid
[
1
]
>
IEEE80211_MAX_SSID_LEN
))
return
-
EINVAL
;
return
0
;
}
static
int
ath6kl_wmi_bssinfo_event_rx
(
struct
wmi
*
wmi
,
u8
*
datap
,
int
len
)
static
int
ath6kl_wmi_bssinfo_event_rx
(
struct
wmi
*
wmi
,
u8
*
datap
,
int
len
)
{
{
struct
bss
*
bss
=
NULL
;
struct
wmi_bss_info_hdr2
*
bih
;
struct
wmi_bss_info_hdr
*
bih
;
u8
*
buf
;
u8
cached_ssid_len
=
0
;
struct
ieee80211_channel
*
channel
;
u8
cached_ssid
[
IEEE80211_MAX_SSID_LEN
]
=
{
0
};
struct
ath6kl
*
ar
=
wmi
->
parent_dev
;
u8
beacon_ssid_len
=
0
;
struct
ieee80211_mgmt
*
mgmt
;
u8
*
buf
,
*
ie_ssid
;
struct
cfg80211_bss
*
bss
;
u8
*
ni_buf
;
int
buf_len
;
int
ret
;
if
(
len
<=
sizeof
(
struct
wmi_bss_info_hdr
))
if
(
len
<=
sizeof
(
struct
wmi_bss_info_hdr
2
))
return
-
EINVAL
;
return
-
EINVAL
;
bih
=
(
struct
wmi_bss_info_hdr
*
)
datap
;
bih
=
(
struct
wmi_bss_info_hdr2
*
)
datap
;
bss
=
wlan_find_node
(
&
wmi
->
parent_dev
->
scan_table
,
bih
->
bssid
);
buf
=
datap
+
sizeof
(
struct
wmi_bss_info_hdr2
);
len
-=
sizeof
(
struct
wmi_bss_info_hdr2
);
if
(
a_sle16_to_cpu
(
bih
->
rssi
)
>
0
)
{
if
(
bss
==
NULL
)
return
0
;
else
bih
->
rssi
=
a_cpu_to_sle16
(
bss
->
ni_rssi
);
}
buf
=
datap
+
sizeof
(
struct
wmi_bss_info_hdr
);
len
-=
sizeof
(
struct
wmi_bss_info_hdr
);
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"bss info evt - ch %u, rssi %02x, bssid
\"
%pM
\"\n
"
,
"bss info evt - ch %u, snr %d, rssi %d, bssid
\"
%pM
\"
"
bih
->
ch
,
a_sle16_to_cpu
(
bih
->
rssi
),
bih
->
bssid
);
"frame_type=%d
\n
"
,
bih
->
ch
,
bih
->
snr
,
bih
->
snr
-
95
,
bih
->
bssid
,
if
(
bss
!=
NULL
)
{
bih
->
frame_type
);
/*
* Free up the node. We are about to allocate a new node.
if
(
bih
->
frame_type
!=
BEACON_FTYPE
&&
* In case of hidden AP, beacon will not have ssid,
bih
->
frame_type
!=
PROBERESP_FTYPE
)
* but a directed probe response will have it,
return
0
;
/* Only update BSS table for now */
* so cache the probe-resp-ssid if already present.
*/
if
(
bih
->
frame_type
==
BEACON_FTYPE
&&
if
(
wmi
->
is_probe_ssid
&&
(
bih
->
frame_type
==
BEACON_FTYPE
))
{
test_bit
(
CLEAR_BSSFILTER_ON_BEACON
,
&
ar
->
flag
))
{
ie_ssid
=
bss
->
ni_cie
.
ie_ssid
;
clear_bit
(
CLEAR_BSSFILTER_ON_BEACON
,
&
ar
->
flag
);
if
(
ie_ssid
&&
(
ie_ssid
[
1
]
<=
IEEE80211_MAX_SSID_LEN
)
&&
ath6kl_wmi_bssfilter_cmd
(
ar
->
wmi
,
NONE_BSS_FILTER
,
0
);
(
ie_ssid
[
2
]
!=
0
))
{
cached_ssid_len
=
ie_ssid
[
1
];
memcpy
(
cached_ssid
,
ie_ssid
+
2
,
cached_ssid_len
);
}
}
/*
* Use the current average rssi of associated AP base on
* assumption
* 1. Most os with GUI will update RSSI by
* ath6kl_wmi_get_stats_cmd() periodically.
* 2. ath6kl_wmi_get_stats_cmd(..) will be called when calling
* ath6kl_wmi_startscan_cmd(...)
* The average value of RSSI give end-user better feeling for
* instance value of scan result. It also sync up RSSI info
* in GUI between scan result and RSSI signal icon.
*/
if
(
memcmp
(
wmi
->
parent_dev
->
bssid
,
bih
->
bssid
,
ETH_ALEN
)
==
0
)
{
bih
->
rssi
=
a_cpu_to_sle16
(
bss
->
ni_rssi
);
bih
->
snr
=
bss
->
ni_snr
;
}
wlan_node_reclaim
(
&
wmi
->
parent_dev
->
scan_table
,
bss
);
}
}
/*
channel
=
ieee80211_get_channel
(
ar
->
wdev
->
wiphy
,
le16_to_cpu
(
bih
->
ch
));
* beacon/probe response frame format
if
(
channel
==
NULL
)
* [8] time stamp
* [2] beacon interval
* [2] capability information
* [tlv] ssid
*/
beacon_ssid_len
=
buf
[
SSID_IE_LEN_INDEX
];
/*
* If ssid is cached for this hidden AP, then change
* buffer len accordingly.
*/
if
(
wmi
->
is_probe_ssid
&&
(
bih
->
frame_type
==
BEACON_FTYPE
)
&&
(
cached_ssid_len
!=
0
)
&&
(
beacon_ssid_len
==
0
||
(
cached_ssid_len
>
beacon_ssid_len
&&
buf
[
SSID_IE_LEN_INDEX
+
1
]
==
0
)))
{
len
+=
(
cached_ssid_len
-
beacon_ssid_len
);
}
bss
=
wlan_node_alloc
(
len
);
if
(
!
bss
)
return
-
ENOMEM
;
bss
->
ni_snr
=
bih
->
snr
;
bss
->
ni_rssi
=
a_sle16_to_cpu
(
bih
->
rssi
);
if
(
WARN_ON
(
!
bss
->
ni_buf
))
return
-
EINVAL
;
return
-
EINVAL
;
/*
if
(
len
<
8
+
2
+
2
)
* In case of hidden AP, beacon will not have ssid,
* but a directed probe response will have it,
* so place the cached-ssid(probe-resp) in the bss info.
*/
if
(
wmi
->
is_probe_ssid
&&
(
bih
->
frame_type
==
BEACON_FTYPE
)
&&
(
cached_ssid_len
!=
0
)
&&
(
beacon_ssid_len
==
0
||
(
beacon_ssid_len
&&
buf
[
SSID_IE_LEN_INDEX
+
1
]
==
0
)))
{
ni_buf
=
bss
->
ni_buf
;
buf_len
=
len
;
/*
* Copy the first 14 bytes:
* time-stamp(8), beacon-interval(2),
* cap-info(2), ssid-id(1), ssid-len(1).
*/
memcpy
(
ni_buf
,
buf
,
SSID_IE_LEN_INDEX
+
1
);
ni_buf
[
SSID_IE_LEN_INDEX
]
=
cached_ssid_len
;
ni_buf
+=
(
SSID_IE_LEN_INDEX
+
1
);
buf
+=
(
SSID_IE_LEN_INDEX
+
1
);
buf_len
-=
(
SSID_IE_LEN_INDEX
+
1
);
memcpy
(
ni_buf
,
cached_ssid
,
cached_ssid_len
);
ni_buf
+=
cached_ssid_len
;
buf
+=
beacon_ssid_len
;
buf_len
-=
beacon_ssid_len
;
if
(
cached_ssid_len
>
beacon_ssid_len
)
buf_len
-=
(
cached_ssid_len
-
beacon_ssid_len
);
memcpy
(
ni_buf
,
buf
,
buf_len
);
}
else
memcpy
(
bss
->
ni_buf
,
buf
,
len
);
bss
->
ni_framelen
=
len
;
ret
=
ath6kl_wlan_parse_beacon
(
bss
->
ni_buf
,
len
,
&
bss
->
ni_cie
);
if
(
ret
)
{
wlan_node_free
(
bss
);
return
-
EINVAL
;
return
-
EINVAL
;
if
(
bih
->
frame_type
==
BEACON_FTYPE
&&
test_bit
(
CONNECTED
,
&
ar
->
flag
)
&&
memcmp
(
bih
->
bssid
,
ar
->
bssid
,
ETH_ALEN
)
==
0
)
{
const
u8
*
tim
;
tim
=
cfg80211_find_ie
(
WLAN_EID_TIM
,
buf
+
8
+
2
+
2
,
len
-
8
-
2
-
2
);
if
(
tim
&&
tim
[
1
]
>=
2
)
{
ar
->
assoc_bss_dtim_period
=
tim
[
3
];
set_bit
(
DTIM_PERIOD_AVAIL
,
&
ar
->
flag
);
}
}
}
/*
/*
* Update the frequency in ie_chan, overwriting of channel number
* In theory, use of cfg80211_inform_bss() would be more natural here
* which is done in ath6kl_wlan_parse_beacon
* since we do not have the full frame. However, at least for now,
* cfg80211 can only distinguish Beacon and Probe Response frames from
* each other when using cfg80211_inform_bss_frame(), so let's build a
* fake IEEE 802.11 header to be able to take benefit of this.
*/
*/
bss
->
ni_cie
.
ie_chan
=
le16_to_cpu
(
bih
->
ch
);
mgmt
=
kmalloc
(
24
+
len
,
GFP_ATOMIC
);
wlan_setup_node
(
&
wmi
->
parent_dev
->
scan_table
,
bss
,
bih
->
bssid
);
if
(
mgmt
==
NULL
)
return
0
;
}
static
int
ath6kl_wmi_opt_frame_event_rx
(
struct
wmi
*
wmi
,
u8
*
datap
,
int
len
)
{
struct
bss
*
bss
;
struct
wmi_opt_rx_info_hdr
*
bih
;
u8
*
buf
;
if
(
len
<=
sizeof
(
struct
wmi_opt_rx_info_hdr
))
return
-
EINVAL
;
return
-
EINVAL
;
bih
=
(
struct
wmi_opt_rx_info_hdr
*
)
datap
;
if
(
bih
->
frame_type
==
BEACON_FTYPE
)
{
buf
=
datap
+
sizeof
(
struct
wmi_opt_rx_info_hdr
);
mgmt
->
frame_control
=
cpu_to_le16
(
IEEE80211_FTYPE_MGMT
|
len
-=
sizeof
(
struct
wmi_opt_rx_info_hdr
);
IEEE80211_STYPE_BEACON
);
memset
(
mgmt
->
da
,
0xff
,
ETH_ALEN
);
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"opt frame event %2.2x:%2.2x
\n
"
,
}
else
{
bih
->
bssid
[
4
],
bih
->
bssid
[
5
])
;
struct
net_device
*
dev
=
ar
->
net_dev
;
bss
=
wlan_find_node
(
&
wmi
->
parent_dev
->
scan_table
,
bih
->
bssid
);
mgmt
->
frame_control
=
cpu_to_le16
(
IEEE80211_FTYPE_MGMT
|
if
(
bss
!=
NULL
)
{
IEEE80211_STYPE_PROBE_RESP
);
/* Free up the node. We are about to allocate a new node. */
memcpy
(
mgmt
->
da
,
dev
->
dev_addr
,
ETH_ALEN
);
wlan_node_reclaim
(
&
wmi
->
parent_dev
->
scan_table
,
bss
);
}
}
mgmt
->
duration
=
cpu_to_le16
(
0
);
bss
=
wlan_node_alloc
(
len
);
memcpy
(
mgmt
->
sa
,
bih
->
bssid
,
ETH_ALEN
);
if
(
!
bss
)
memcpy
(
mgmt
->
bssid
,
bih
->
bssid
,
ETH_ALEN
);
mgmt
->
seq_ctrl
=
cpu_to_le16
(
0
);
memcpy
(
&
mgmt
->
u
.
beacon
,
buf
,
len
);
bss
=
cfg80211_inform_bss_frame
(
ar
->
wdev
->
wiphy
,
channel
,
mgmt
,
24
+
len
,
(
bih
->
snr
-
95
)
*
100
,
GFP_ATOMIC
);
kfree
(
mgmt
);
if
(
bss
==
NULL
)
return
-
ENOMEM
;
return
-
ENOMEM
;
cfg80211_put_bss
(
bss
);
bss
->
ni_snr
=
bih
->
snr
;
bss
->
ni_cie
.
ie_chan
=
le16_to_cpu
(
bih
->
ch
);
if
(
WARN_ON
(
!
bss
->
ni_buf
))
return
-
EINVAL
;
memcpy
(
bss
->
ni_buf
,
buf
,
len
);
wlan_setup_node
(
&
wmi
->
parent_dev
->
scan_table
,
bss
,
bih
->
bssid
);
return
0
;
return
0
;
}
}
...
@@ -949,6 +1044,13 @@ static int ath6kl_wmi_bitrate_reply_rx(struct wmi *wmi, u8 *datap, int len)
...
@@ -949,6 +1044,13 @@ static int ath6kl_wmi_bitrate_reply_rx(struct wmi *wmi, u8 *datap, int len)
return
0
;
return
0
;
}
}
static
int
ath6kl_wmi_tcmd_test_report_rx
(
struct
wmi
*
wmi
,
u8
*
datap
,
int
len
)
{
ath6kl_tm_rx_report_event
(
wmi
->
parent_dev
,
datap
,
len
);
return
0
;
}
static
int
ath6kl_wmi_ratemask_reply_rx
(
struct
wmi
*
wmi
,
u8
*
datap
,
int
len
)
static
int
ath6kl_wmi_ratemask_reply_rx
(
struct
wmi
*
wmi
,
u8
*
datap
,
int
len
)
{
{
if
(
len
<
sizeof
(
struct
wmi_fix_rates_reply
))
if
(
len
<
sizeof
(
struct
wmi_fix_rates_reply
))
...
@@ -998,15 +1100,41 @@ static int ath6kl_wmi_scan_complete_rx(struct wmi *wmi, u8 *datap, int len)
...
@@ -998,15 +1100,41 @@ static int ath6kl_wmi_scan_complete_rx(struct wmi *wmi, u8 *datap, int len)
ev
=
(
struct
wmi_scan_complete_event
*
)
datap
;
ev
=
(
struct
wmi_scan_complete_event
*
)
datap
;
if
(
a_sle32_to_cpu
(
ev
->
status
)
==
0
)
wlan_refresh_inactive_nodes
(
wmi
->
parent_dev
);
ath6kl_scan_complete_evt
(
wmi
->
parent_dev
,
a_sle32_to_cpu
(
ev
->
status
));
ath6kl_scan_complete_evt
(
wmi
->
parent_dev
,
a_sle32_to_cpu
(
ev
->
status
));
wmi
->
is_probe_ssid
=
false
;
wmi
->
is_probe_ssid
=
false
;
return
0
;
return
0
;
}
}
static
int
ath6kl_wmi_neighbor_report_event_rx
(
struct
wmi
*
wmi
,
u8
*
datap
,
int
len
)
{
struct
wmi_neighbor_report_event
*
ev
;
u8
i
;
if
(
len
<
sizeof
(
*
ev
))
return
-
EINVAL
;
ev
=
(
struct
wmi_neighbor_report_event
*
)
datap
;
if
(
sizeof
(
*
ev
)
+
ev
->
num_neighbors
*
sizeof
(
struct
wmi_neighbor_info
)
>
len
)
{
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"truncated neighbor event "
"(num=%d len=%d)
\n
"
,
ev
->
num_neighbors
,
len
);
return
-
EINVAL
;
}
for
(
i
=
0
;
i
<
ev
->
num_neighbors
;
i
++
)
{
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"neighbor %d/%d - %pM 0x%x
\n
"
,
i
+
1
,
ev
->
num_neighbors
,
ev
->
neighbor
[
i
].
bssid
,
ev
->
neighbor
[
i
].
bss_flags
);
cfg80211_pmksa_candidate_notify
(
wmi
->
parent_dev
->
net_dev
,
i
,
ev
->
neighbor
[
i
].
bssid
,
!!
(
ev
->
neighbor
[
i
].
bss_flags
&
WMI_PREAUTH_CAPABLE_BSS
),
GFP_ATOMIC
);
}
return
0
;
}
/*
/*
* Target is reporting a programming error. This is for
* Target is reporting a programming error. This is for
* developer aid only. Target only checks a few common violations
* developer aid only. Target only checks a few common violations
...
@@ -1410,6 +1538,11 @@ int ath6kl_wmi_cmd_send(struct wmi *wmi, struct sk_buff *skb,
...
@@ -1410,6 +1538,11 @@ int ath6kl_wmi_cmd_send(struct wmi *wmi, struct sk_buff *skb,
if
(
WARN_ON
(
skb
==
NULL
))
if
(
WARN_ON
(
skb
==
NULL
))
return
-
EINVAL
;
return
-
EINVAL
;
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"wmi tx id %d len %d flag %d
\n
"
,
cmd_id
,
skb
->
len
,
sync_flag
);
ath6kl_dbg_dump
(
ATH6KL_DBG_WMI_DUMP
,
NULL
,
"wmi tx "
,
skb
->
data
,
skb
->
len
);
if
(
sync_flag
>=
END_WMIFLAG
)
{
if
(
sync_flag
>=
END_WMIFLAG
)
{
dev_kfree_skb
(
skb
);
dev_kfree_skb
(
skb
);
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -1468,6 +1601,13 @@ int ath6kl_wmi_connect_cmd(struct wmi *wmi, enum network_type nw_type,
...
@@ -1468,6 +1601,13 @@ int ath6kl_wmi_connect_cmd(struct wmi *wmi, enum network_type nw_type,
struct
wmi_connect_cmd
*
cc
;
struct
wmi_connect_cmd
*
cc
;
int
ret
;
int
ret
;
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"wmi connect bssid %pM freq %d flags 0x%x ssid_len %d "
"type %d dot11_auth %d auth %d pairwise %d group %d
\n
"
,
bssid
,
channel
,
ctrl_flags
,
ssid_len
,
nw_type
,
dot11_auth_mode
,
auth_mode
,
pairwise_crypto
,
group_crypto
);
ath6kl_dbg_dump
(
ATH6KL_DBG_WMI
,
NULL
,
"ssid "
,
ssid
,
ssid_len
);
wmi
->
traffic_class
=
100
;
wmi
->
traffic_class
=
100
;
if
((
pairwise_crypto
==
NONE_CRYPT
)
&&
(
group_crypto
!=
NONE_CRYPT
))
if
((
pairwise_crypto
==
NONE_CRYPT
)
&&
(
group_crypto
!=
NONE_CRYPT
))
...
@@ -1513,6 +1653,9 @@ int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 *bssid, u16 channel)
...
@@ -1513,6 +1653,9 @@ int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 *bssid, u16 channel)
struct
wmi_reconnect_cmd
*
cc
;
struct
wmi_reconnect_cmd
*
cc
;
int
ret
;
int
ret
;
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"wmi reconnect bssid %pM freq %d
\n
"
,
bssid
,
channel
);
wmi
->
traffic_class
=
100
;
wmi
->
traffic_class
=
100
;
skb
=
ath6kl_wmi_get_new_buf
(
sizeof
(
struct
wmi_reconnect_cmd
));
skb
=
ath6kl_wmi_get_new_buf
(
sizeof
(
struct
wmi_reconnect_cmd
));
...
@@ -1535,6 +1678,8 @@ int ath6kl_wmi_disconnect_cmd(struct wmi *wmi)
...
@@ -1535,6 +1678,8 @@ int ath6kl_wmi_disconnect_cmd(struct wmi *wmi)
{
{
int
ret
;
int
ret
;
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"wmi disconnect
\n
"
);
wmi
->
traffic_class
=
100
;
wmi
->
traffic_class
=
100
;
/* Disconnect command does not need to do a SYNC before. */
/* Disconnect command does not need to do a SYNC before. */
...
@@ -1551,7 +1696,7 @@ int ath6kl_wmi_startscan_cmd(struct wmi *wmi, enum wmi_scan_type scan_type,
...
@@ -1551,7 +1696,7 @@ int ath6kl_wmi_startscan_cmd(struct wmi *wmi, enum wmi_scan_type scan_type,
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
struct
wmi_start_scan_cmd
*
sc
;
struct
wmi_start_scan_cmd
*
sc
;
s8
size
;
s8
size
;
int
ret
;
int
i
,
ret
;
size
=
sizeof
(
struct
wmi_start_scan_cmd
);
size
=
sizeof
(
struct
wmi_start_scan_cmd
);
...
@@ -1576,8 +1721,8 @@ int ath6kl_wmi_startscan_cmd(struct wmi *wmi, enum wmi_scan_type scan_type,
...
@@ -1576,8 +1721,8 @@ int ath6kl_wmi_startscan_cmd(struct wmi *wmi, enum wmi_scan_type scan_type,
sc
->
force_scan_intvl
=
cpu_to_le32
(
force_scan_interval
);
sc
->
force_scan_intvl
=
cpu_to_le32
(
force_scan_interval
);
sc
->
num_ch
=
num_chan
;
sc
->
num_ch
=
num_chan
;
if
(
num_chan
)
for
(
i
=
0
;
i
<
num_chan
;
i
++
)
memcpy
(
sc
->
ch_list
,
ch_list
,
num_chan
*
sizeof
(
u16
)
);
sc
->
ch_list
[
i
]
=
cpu_to_le16
(
ch_list
[
i
]
);
ret
=
ath6kl_wmi_cmd_send
(
wmi
,
skb
,
WMI_START_SCAN_CMDID
,
ret
=
ath6kl_wmi_cmd_send
(
wmi
,
skb
,
WMI_START_SCAN_CMDID
,
NO_SYNC_WMIFLAG
);
NO_SYNC_WMIFLAG
);
...
@@ -1770,6 +1915,10 @@ int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 key_index,
...
@@ -1770,6 +1915,10 @@ int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 key_index,
struct
wmi_add_cipher_key_cmd
*
cmd
;
struct
wmi_add_cipher_key_cmd
*
cmd
;
int
ret
;
int
ret
;
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"addkey cmd: key_index=%u key_type=%d "
"key_usage=%d key_len=%d key_op_ctrl=%d
\n
"
,
key_index
,
key_type
,
key_usage
,
key_len
,
key_op_ctrl
);
if
((
key_index
>
WMI_MAX_KEY_INDEX
)
||
(
key_len
>
WMI_MAX_KEY_LEN
)
||
if
((
key_index
>
WMI_MAX_KEY_INDEX
)
||
(
key_len
>
WMI_MAX_KEY_LEN
)
||
(
key_material
==
NULL
))
(
key_material
==
NULL
))
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -2211,6 +2360,25 @@ int ath6kl_wmi_get_challenge_resp_cmd(struct wmi *wmi, u32 cookie, u32 source)
...
@@ -2211,6 +2360,25 @@ int ath6kl_wmi_get_challenge_resp_cmd(struct wmi *wmi, u32 cookie, u32 source)
return
ret
;
return
ret
;
}
}
int
ath6kl_wmi_config_debug_module_cmd
(
struct
wmi
*
wmi
,
u32
valid
,
u32
config
)
{
struct
ath6kl_wmix_dbglog_cfg_module_cmd
*
cmd
;
struct
sk_buff
*
skb
;
int
ret
;
skb
=
ath6kl_wmi_get_new_buf
(
sizeof
(
*
cmd
));
if
(
!
skb
)
return
-
ENOMEM
;
cmd
=
(
struct
ath6kl_wmix_dbglog_cfg_module_cmd
*
)
skb
->
data
;
cmd
->
valid
=
cpu_to_le32
(
valid
);
cmd
->
config
=
cpu_to_le32
(
config
);
ret
=
ath6kl_wmi_cmd_send_xtnd
(
wmi
,
skb
,
WMIX_DBGLOG_CFG_MODULE_CMDID
,
NO_SYNC_WMIFLAG
);
return
ret
;
}
int
ath6kl_wmi_get_stats_cmd
(
struct
wmi
*
wmi
)
int
ath6kl_wmi_get_stats_cmd
(
struct
wmi
*
wmi
)
{
{
return
ath6kl_wmi_simple_cmd
(
wmi
,
WMI_GET_STATISTICS_CMDID
);
return
ath6kl_wmi_simple_cmd
(
wmi
,
WMI_GET_STATISTICS_CMDID
);
...
@@ -2316,49 +2484,29 @@ int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 keep_alive_intvl)
...
@@ -2316,49 +2484,29 @@ int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 keep_alive_intvl)
return
ret
;
return
ret
;
}
}
s32
ath6kl_wmi_get_rate
(
s8
rate_index
)
int
ath6kl_wmi_test_cmd
(
struct
wmi
*
wmi
,
void
*
buf
,
size_t
len
)
{
{
if
(
rate_index
==
RATE_AUTO
)
struct
sk_buff
*
skb
;
return
0
;
int
ret
;
return
wmi_rate_tbl
[(
u32
)
rate_index
][
0
];
skb
=
ath6kl_wmi_get_new_buf
(
len
);
}
if
(
!
skb
)
return
-
ENOMEM
;
void
ath6kl_wmi_node_return
(
struct
wmi
*
wmi
,
struct
bss
*
bss
)
memcpy
(
skb
->
data
,
buf
,
len
);
{
if
(
bss
)
wlan_node_return
(
&
wmi
->
parent_dev
->
scan_table
,
bss
);
}
struct
bss
*
ath6kl_wmi_find_ssid_node
(
struct
wmi
*
wmi
,
u8
*
ssid
,
ret
=
ath6kl_wmi_cmd_send
(
wmi
,
skb
,
WMI_TEST_CMDID
,
NO_SYNC_WMIFLAG
);
u32
ssid_len
,
bool
is_wpa2
,
bool
match_ssid
)
{
struct
bss
*
node
=
NULL
;
node
=
wlan_find_ssid_node
(
&
wmi
->
parent_dev
->
scan_table
,
ssid
,
return
ret
;
ssid_len
,
is_wpa2
,
match_ssid
);
return
node
;
}
}
struct
bss
*
ath6kl_wmi_find_node
(
struct
wmi
*
wmi
,
const
u8
*
mac_addr
)
{
struct
bss
*
ni
=
NULL
;
ni
=
wlan_find_node
(
&
wmi
->
parent_dev
->
scan_table
,
mac_addr
);
return
ni
;
}
void
ath6kl_wmi_node_free
(
struct
wmi
*
wmi
,
const
u8
*
mac_addr
)
s32
ath6kl_wmi_get_rate
(
s8
rate_index
)
{
{
struct
bss
*
ni
=
NULL
;
if
(
rate_index
==
RATE_AUTO
)
return
0
;
ni
=
wlan_find_node
(
&
wmi
->
parent_dev
->
scan_table
,
mac_addr
);
if
(
ni
!=
NULL
)
wlan_node_reclaim
(
&
wmi
->
parent_dev
->
scan_table
,
ni
);
return
;
return
wmi_rate_tbl
[(
u32
)
rate_index
][
0
]
;
}
}
static
int
ath6kl_wmi_get_pmkid_list_event_rx
(
struct
wmi
*
wmi
,
u8
*
datap
,
static
int
ath6kl_wmi_get_pmkid_list_event_rx
(
struct
wmi
*
wmi
,
u8
*
datap
,
...
@@ -2400,6 +2548,47 @@ static int ath6kl_wmi_delba_req_event_rx(struct wmi *wmi, u8 *datap, int len)
...
@@ -2400,6 +2548,47 @@ static int ath6kl_wmi_delba_req_event_rx(struct wmi *wmi, u8 *datap, int len)
}
}
/* AP mode functions */
/* AP mode functions */
int
ath6kl_wmi_ap_profile_commit
(
struct
wmi
*
wmip
,
struct
wmi_connect_cmd
*
p
)
{
struct
sk_buff
*
skb
;
struct
wmi_connect_cmd
*
cm
;
int
res
;
skb
=
ath6kl_wmi_get_new_buf
(
sizeof
(
*
cm
));
if
(
!
skb
)
return
-
ENOMEM
;
cm
=
(
struct
wmi_connect_cmd
*
)
skb
->
data
;
memcpy
(
cm
,
p
,
sizeof
(
*
cm
));
res
=
ath6kl_wmi_cmd_send
(
wmip
,
skb
,
WMI_AP_CONFIG_COMMIT_CMDID
,
NO_SYNC_WMIFLAG
);
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"%s: nw_type=%u auth_mode=%u ch=%u "
"ctrl_flags=0x%x-> res=%d
\n
"
,
__func__
,
p
->
nw_type
,
p
->
auth_mode
,
le16_to_cpu
(
p
->
ch
),
le32_to_cpu
(
p
->
ctrl_flags
),
res
);
return
res
;
}
int
ath6kl_wmi_ap_set_mlme
(
struct
wmi
*
wmip
,
u8
cmd
,
const
u8
*
mac
,
u16
reason
)
{
struct
sk_buff
*
skb
;
struct
wmi_ap_set_mlme_cmd
*
cm
;
skb
=
ath6kl_wmi_get_new_buf
(
sizeof
(
*
cm
));
if
(
!
skb
)
return
-
ENOMEM
;
cm
=
(
struct
wmi_ap_set_mlme_cmd
*
)
skb
->
data
;
memcpy
(
cm
->
mac
,
mac
,
ETH_ALEN
);
cm
->
reason
=
cpu_to_le16
(
reason
);
cm
->
cmd
=
cmd
;
return
ath6kl_wmi_cmd_send
(
wmip
,
skb
,
WMI_AP_SET_MLME_CMDID
,
NO_SYNC_WMIFLAG
);
}
static
int
ath6kl_wmi_pspoll_event_rx
(
struct
wmi
*
wmi
,
u8
*
datap
,
int
len
)
static
int
ath6kl_wmi_pspoll_event_rx
(
struct
wmi
*
wmi
,
u8
*
datap
,
int
len
)
{
{
struct
wmi_pspoll_event
*
ev
;
struct
wmi_pspoll_event
*
ev
;
...
@@ -2433,6 +2622,7 @@ int ath6kl_wmi_set_pvb_cmd(struct wmi *wmi, u16 aid, bool flag)
...
@@ -2433,6 +2622,7 @@ int ath6kl_wmi_set_pvb_cmd(struct wmi *wmi, u16 aid, bool flag)
cmd
=
(
struct
wmi_ap_set_pvb_cmd
*
)
skb
->
data
;
cmd
=
(
struct
wmi_ap_set_pvb_cmd
*
)
skb
->
data
;
cmd
->
aid
=
cpu_to_le16
(
aid
);
cmd
->
aid
=
cpu_to_le16
(
aid
);
cmd
->
rsvd
=
cpu_to_le16
(
0
);
cmd
->
flag
=
cpu_to_le32
(
flag
);
cmd
->
flag
=
cpu_to_le32
(
flag
);
ret
=
ath6kl_wmi_cmd_send
(
wmi
,
skb
,
WMI_AP_SET_PVB_CMDID
,
ret
=
ath6kl_wmi_cmd_send
(
wmi
,
skb
,
WMI_AP_SET_PVB_CMDID
,
...
@@ -2464,6 +2654,160 @@ int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 rx_meta_ver,
...
@@ -2464,6 +2654,160 @@ int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 rx_meta_ver,
return
ret
;
return
ret
;
}
}
int
ath6kl_wmi_set_appie_cmd
(
struct
wmi
*
wmi
,
u8
mgmt_frm_type
,
const
u8
*
ie
,
u8
ie_len
)
{
struct
sk_buff
*
skb
;
struct
wmi_set_appie_cmd
*
p
;
skb
=
ath6kl_wmi_get_new_buf
(
sizeof
(
*
p
)
+
ie_len
);
if
(
!
skb
)
return
-
ENOMEM
;
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"set_appie_cmd: mgmt_frm_type=%u "
"ie_len=%u
\n
"
,
mgmt_frm_type
,
ie_len
);
p
=
(
struct
wmi_set_appie_cmd
*
)
skb
->
data
;
p
->
mgmt_frm_type
=
mgmt_frm_type
;
p
->
ie_len
=
ie_len
;
memcpy
(
p
->
ie_info
,
ie
,
ie_len
);
return
ath6kl_wmi_cmd_send
(
wmi
,
skb
,
WMI_SET_APPIE_CMDID
,
NO_SYNC_WMIFLAG
);
}
int
ath6kl_wmi_disable_11b_rates_cmd
(
struct
wmi
*
wmi
,
bool
disable
)
{
struct
sk_buff
*
skb
;
struct
wmi_disable_11b_rates_cmd
*
cmd
;
skb
=
ath6kl_wmi_get_new_buf
(
sizeof
(
*
cmd
));
if
(
!
skb
)
return
-
ENOMEM
;
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"disable_11b_rates_cmd: disable=%u
\n
"
,
disable
);
cmd
=
(
struct
wmi_disable_11b_rates_cmd
*
)
skb
->
data
;
cmd
->
disable
=
disable
?
1
:
0
;
return
ath6kl_wmi_cmd_send
(
wmi
,
skb
,
WMI_DISABLE_11B_RATES_CMDID
,
NO_SYNC_WMIFLAG
);
}
int
ath6kl_wmi_remain_on_chnl_cmd
(
struct
wmi
*
wmi
,
u32
freq
,
u32
dur
)
{
struct
sk_buff
*
skb
;
struct
wmi_remain_on_chnl_cmd
*
p
;
skb
=
ath6kl_wmi_get_new_buf
(
sizeof
(
*
p
));
if
(
!
skb
)
return
-
ENOMEM
;
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"remain_on_chnl_cmd: freq=%u dur=%u
\n
"
,
freq
,
dur
);
p
=
(
struct
wmi_remain_on_chnl_cmd
*
)
skb
->
data
;
p
->
freq
=
cpu_to_le32
(
freq
);
p
->
duration
=
cpu_to_le32
(
dur
);
return
ath6kl_wmi_cmd_send
(
wmi
,
skb
,
WMI_REMAIN_ON_CHNL_CMDID
,
NO_SYNC_WMIFLAG
);
}
int
ath6kl_wmi_send_action_cmd
(
struct
wmi
*
wmi
,
u32
id
,
u32
freq
,
u32
wait
,
const
u8
*
data
,
u16
data_len
)
{
struct
sk_buff
*
skb
;
struct
wmi_send_action_cmd
*
p
;
u8
*
buf
;
if
(
wait
)
return
-
EINVAL
;
/* Offload for wait not supported */
buf
=
kmalloc
(
data_len
,
GFP_KERNEL
);
if
(
!
buf
)
return
-
ENOMEM
;
skb
=
ath6kl_wmi_get_new_buf
(
sizeof
(
*
p
)
+
data_len
);
if
(
!
skb
)
{
kfree
(
buf
);
return
-
ENOMEM
;
}
kfree
(
wmi
->
last_mgmt_tx_frame
);
wmi
->
last_mgmt_tx_frame
=
buf
;
wmi
->
last_mgmt_tx_frame_len
=
data_len
;
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"send_action_cmd: id=%u freq=%u wait=%u "
"len=%u
\n
"
,
id
,
freq
,
wait
,
data_len
);
p
=
(
struct
wmi_send_action_cmd
*
)
skb
->
data
;
p
->
id
=
cpu_to_le32
(
id
);
p
->
freq
=
cpu_to_le32
(
freq
);
p
->
wait
=
cpu_to_le32
(
wait
);
p
->
len
=
cpu_to_le16
(
data_len
);
memcpy
(
p
->
data
,
data
,
data_len
);
return
ath6kl_wmi_cmd_send
(
wmi
,
skb
,
WMI_SEND_ACTION_CMDID
,
NO_SYNC_WMIFLAG
);
}
int
ath6kl_wmi_send_probe_response_cmd
(
struct
wmi
*
wmi
,
u32
freq
,
const
u8
*
dst
,
const
u8
*
data
,
u16
data_len
)
{
struct
sk_buff
*
skb
;
struct
wmi_p2p_probe_response_cmd
*
p
;
skb
=
ath6kl_wmi_get_new_buf
(
sizeof
(
*
p
)
+
data_len
);
if
(
!
skb
)
return
-
ENOMEM
;
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"send_probe_response_cmd: freq=%u dst=%pM "
"len=%u
\n
"
,
freq
,
dst
,
data_len
);
p
=
(
struct
wmi_p2p_probe_response_cmd
*
)
skb
->
data
;
p
->
freq
=
cpu_to_le32
(
freq
);
memcpy
(
p
->
destination_addr
,
dst
,
ETH_ALEN
);
p
->
len
=
cpu_to_le16
(
data_len
);
memcpy
(
p
->
data
,
data
,
data_len
);
return
ath6kl_wmi_cmd_send
(
wmi
,
skb
,
WMI_SEND_PROBE_RESPONSE_CMDID
,
NO_SYNC_WMIFLAG
);
}
int
ath6kl_wmi_probe_report_req_cmd
(
struct
wmi
*
wmi
,
bool
enable
)
{
struct
sk_buff
*
skb
;
struct
wmi_probe_req_report_cmd
*
p
;
skb
=
ath6kl_wmi_get_new_buf
(
sizeof
(
*
p
));
if
(
!
skb
)
return
-
ENOMEM
;
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"probe_report_req_cmd: enable=%u
\n
"
,
enable
);
p
=
(
struct
wmi_probe_req_report_cmd
*
)
skb
->
data
;
p
->
enable
=
enable
?
1
:
0
;
return
ath6kl_wmi_cmd_send
(
wmi
,
skb
,
WMI_PROBE_REQ_REPORT_CMDID
,
NO_SYNC_WMIFLAG
);
}
int
ath6kl_wmi_info_req_cmd
(
struct
wmi
*
wmi
,
u32
info_req_flags
)
{
struct
sk_buff
*
skb
;
struct
wmi_get_p2p_info
*
p
;
skb
=
ath6kl_wmi_get_new_buf
(
sizeof
(
*
p
));
if
(
!
skb
)
return
-
ENOMEM
;
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"info_req_cmd: flags=%x
\n
"
,
info_req_flags
);
p
=
(
struct
wmi_get_p2p_info
*
)
skb
->
data
;
p
->
info_req_flags
=
cpu_to_le32
(
info_req_flags
);
return
ath6kl_wmi_cmd_send
(
wmi
,
skb
,
WMI_GET_P2P_INFO_CMDID
,
NO_SYNC_WMIFLAG
);
}
int
ath6kl_wmi_cancel_remain_on_chnl_cmd
(
struct
wmi
*
wmi
)
{
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"cancel_remain_on_chnl_cmd
\n
"
);
return
ath6kl_wmi_simple_cmd
(
wmi
,
WMI_CANCEL_REMAIN_ON_CHNL_CMDID
);
}
static
int
ath6kl_wmi_control_rx_xtnd
(
struct
wmi
*
wmi
,
struct
sk_buff
*
skb
)
static
int
ath6kl_wmi_control_rx_xtnd
(
struct
wmi
*
wmi
,
struct
sk_buff
*
skb
)
{
{
struct
wmix_cmd_hdr
*
cmd
;
struct
wmix_cmd_hdr
*
cmd
;
...
@@ -2488,11 +2832,14 @@ static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb)
...
@@ -2488,11 +2832,14 @@ static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb)
switch
(
id
)
{
switch
(
id
)
{
case
WMIX_HB_CHALLENGE_RESP_EVENTID
:
case
WMIX_HB_CHALLENGE_RESP_EVENTID
:
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"wmi event hb challenge resp
\n
"
);
break
;
break
;
case
WMIX_DBGLOG_EVENTID
:
case
WMIX_DBGLOG_EVENTID
:
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"wmi event dbglog len %d
\n
"
,
len
);
ath6kl_debug_fwlog_event
(
wmi
->
parent_dev
,
datap
,
len
);
break
;
break
;
default:
default:
ath6kl_
err
(
"unknown cmd id 0x%x
\n
"
,
id
);
ath6kl_
warn
(
"unknown cmd id 0x%x
\n
"
,
id
);
wmi
->
stat
.
cmd_id_err
++
;
wmi
->
stat
.
cmd_id_err
++
;
ret
=
-
EINVAL
;
ret
=
-
EINVAL
;
break
;
break
;
...
@@ -2528,8 +2875,9 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
...
@@ -2528,8 +2875,9 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
datap
=
skb
->
data
;
datap
=
skb
->
data
;
len
=
skb
->
len
;
len
=
skb
->
len
;
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"%s: wmi id: %d
\n
"
,
__func__
,
id
);
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"wmi rx id %d len %d
\n
"
,
id
,
len
);
ath6kl_dbg_dump
(
ATH6KL_DBG_RAW_BYTES
,
"msg payload "
,
datap
,
len
);
ath6kl_dbg_dump
(
ATH6KL_DBG_WMI_DUMP
,
NULL
,
"wmi rx "
,
datap
,
len
);
switch
(
id
)
{
switch
(
id
)
{
case
WMI_GET_BITRATE_CMDID
:
case
WMI_GET_BITRATE_CMDID
:
...
@@ -2566,11 +2914,11 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
...
@@ -2566,11 +2914,11 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
break
;
break
;
case
WMI_BSSINFO_EVENTID
:
case
WMI_BSSINFO_EVENTID
:
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_BSSINFO_EVENTID
\n
"
);
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_BSSINFO_EVENTID
\n
"
);
ath6kl_wmi_convert_bssinfo_hdr2_to_hdr
(
skb
,
datap
);
ret
=
ath6kl_wmi_bssinfo_event_rx
(
wmi
,
datap
,
len
);
ret
=
ath6kl_wmi_bssinfo_event_rx
(
wmi
,
skb
->
data
,
skb
->
len
);
break
;
break
;
case
WMI_REGDOMAIN_EVENTID
:
case
WMI_REGDOMAIN_EVENTID
:
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_REGDOMAIN_EVENTID
\n
"
);
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_REGDOMAIN_EVENTID
\n
"
);
ath6kl_wmi_regdomain_event
(
wmi
,
datap
,
len
);
break
;
break
;
case
WMI_PSTREAM_TIMEOUT_EVENTID
:
case
WMI_PSTREAM_TIMEOUT_EVENTID
:
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_PSTREAM_TIMEOUT_EVENTID
\n
"
);
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_PSTREAM_TIMEOUT_EVENTID
\n
"
);
...
@@ -2578,6 +2926,7 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
...
@@ -2578,6 +2926,7 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
break
;
break
;
case
WMI_NEIGHBOR_REPORT_EVENTID
:
case
WMI_NEIGHBOR_REPORT_EVENTID
:
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_NEIGHBOR_REPORT_EVENTID
\n
"
);
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_NEIGHBOR_REPORT_EVENTID
\n
"
);
ret
=
ath6kl_wmi_neighbor_report_event_rx
(
wmi
,
datap
,
len
);
break
;
break
;
case
WMI_SCAN_COMPLETE_EVENTID
:
case
WMI_SCAN_COMPLETE_EVENTID
:
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_SCAN_COMPLETE_EVENTID
\n
"
);
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_SCAN_COMPLETE_EVENTID
\n
"
);
...
@@ -2600,7 +2949,7 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
...
@@ -2600,7 +2949,7 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
break
;
break
;
case
WMI_OPT_RX_FRAME_EVENTID
:
case
WMI_OPT_RX_FRAME_EVENTID
:
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_OPT_RX_FRAME_EVENTID
\n
"
);
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_OPT_RX_FRAME_EVENTID
\n
"
);
ret
=
ath6kl_wmi_opt_frame_event_rx
(
wmi
,
datap
,
len
);
/* this event has been deprecated */
break
;
break
;
case
WMI_REPORT_ROAM_TBL_EVENTID
:
case
WMI_REPORT_ROAM_TBL_EVENTID
:
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_REPORT_ROAM_TBL_EVENTID
\n
"
);
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_REPORT_ROAM_TBL_EVENTID
\n
"
);
...
@@ -2619,6 +2968,10 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
...
@@ -2619,6 +2968,10 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
case
WMI_REPORT_ROAM_DATA_EVENTID
:
case
WMI_REPORT_ROAM_DATA_EVENTID
:
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_REPORT_ROAM_DATA_EVENTID
\n
"
);
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_REPORT_ROAM_DATA_EVENTID
\n
"
);
break
;
break
;
case
WMI_TEST_EVENTID
:
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_TEST_EVENTID
\n
"
);
ret
=
ath6kl_wmi_tcmd_test_report_rx
(
wmi
,
datap
,
len
);
break
;
case
WMI_GET_FIXRATES_CMDID
:
case
WMI_GET_FIXRATES_CMDID
:
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_GET_FIXRATES_CMDID
\n
"
);
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_GET_FIXRATES_CMDID
\n
"
);
ret
=
ath6kl_wmi_ratemask_reply_rx
(
wmi
,
datap
,
len
);
ret
=
ath6kl_wmi_ratemask_reply_rx
(
wmi
,
datap
,
len
);
...
@@ -2683,6 +3036,36 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
...
@@ -2683,6 +3036,36 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_TX_COMPLETE_EVENTID
\n
"
);
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_TX_COMPLETE_EVENTID
\n
"
);
ret
=
ath6kl_wmi_tx_complete_event_rx
(
datap
,
len
);
ret
=
ath6kl_wmi_tx_complete_event_rx
(
datap
,
len
);
break
;
break
;
case
WMI_REMAIN_ON_CHNL_EVENTID
:
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_REMAIN_ON_CHNL_EVENTID
\n
"
);
ret
=
ath6kl_wmi_remain_on_chnl_event_rx
(
wmi
,
datap
,
len
);
break
;
case
WMI_CANCEL_REMAIN_ON_CHNL_EVENTID
:
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_CANCEL_REMAIN_ON_CHNL_EVENTID
\n
"
);
ret
=
ath6kl_wmi_cancel_remain_on_chnl_event_rx
(
wmi
,
datap
,
len
);
break
;
case
WMI_TX_STATUS_EVENTID
:
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_TX_STATUS_EVENTID
\n
"
);
ret
=
ath6kl_wmi_tx_status_event_rx
(
wmi
,
datap
,
len
);
break
;
case
WMI_RX_PROBE_REQ_EVENTID
:
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_RX_PROBE_REQ_EVENTID
\n
"
);
ret
=
ath6kl_wmi_rx_probe_req_event_rx
(
wmi
,
datap
,
len
);
break
;
case
WMI_P2P_CAPABILITIES_EVENTID
:
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_P2P_CAPABILITIES_EVENTID
\n
"
);
ret
=
ath6kl_wmi_p2p_capabilities_event_rx
(
datap
,
len
);
break
;
case
WMI_RX_ACTION_EVENTID
:
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_RX_ACTION_EVENTID
\n
"
);
ret
=
ath6kl_wmi_rx_action_event_rx
(
wmi
,
datap
,
len
);
break
;
case
WMI_P2P_INFO_EVENTID
:
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_P2P_INFO_EVENTID
\n
"
);
ret
=
ath6kl_wmi_p2p_info_event_rx
(
datap
,
len
);
break
;
default:
default:
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"unknown cmd id 0x%x
\n
"
,
id
);
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"unknown cmd id 0x%x
\n
"
,
id
);
wmi
->
stat
.
cmd_id_err
++
;
wmi
->
stat
.
cmd_id_err
++
;
...
@@ -2739,5 +3122,6 @@ void ath6kl_wmi_shutdown(struct wmi *wmi)
...
@@ -2739,5 +3122,6 @@ void ath6kl_wmi_shutdown(struct wmi *wmi)
if
(
!
wmi
)
if
(
!
wmi
)
return
;
return
;
kfree
(
wmi
->
last_mgmt_tx_frame
);
kfree
(
wmi
);
kfree
(
wmi
);
}
}
drivers/net/wireless/ath/ath6kl/wmi.h
View file @
a5abbcb2
...
@@ -129,6 +129,9 @@ struct wmi {
...
@@ -129,6 +129,9 @@ struct wmi {
u8
ht_allowed
[
A_NUM_BANDS
];
u8
ht_allowed
[
A_NUM_BANDS
];
u8
traffic_class
;
u8
traffic_class
;
bool
is_probe_ssid
;
bool
is_probe_ssid
;
u8
*
last_mgmt_tx_frame
;
size_t
last_mgmt_tx_frame_len
;
};
};
struct
host_app_area
{
struct
host_app_area
{
...
@@ -490,17 +493,61 @@ enum wmi_cmd_id {
...
@@ -490,17 +493,61 @@ enum wmi_cmd_id {
WMI_SET_PASSPHRASE_CMDID
,
WMI_SET_PASSPHRASE_CMDID
,
WMI_SEND_ASSOC_RES_CMDID
,
WMI_SEND_ASSOC_RES_CMDID
,
WMI_SET_ASSOC_REQ_RELAY_CMDID
,
WMI_SET_ASSOC_REQ_RELAY_CMDID
,
WMI_GET_RFKILL_MODE_CMDID
,
/* ACS command, consists of sub-commands */
/* ACS command, consists of sub-commands */
WMI_ACS_CTRL_CMDID
,
WMI_ACS_CTRL_CMDID
,
WMI_SET_EXCESS_TX_RETRY_THRES_CMDID
,
WMI_SET_TBD_TIME_CMDID
,
/*added for wmiconfig command for TBD */
/* Pktlog cmds */
WMI_PKTLOG_ENABLE_CMDID
,
WMI_PKTLOG_DISABLE_CMDID
,
/* More P2P Cmds */
WMI_P2P_GO_NEG_REQ_RSP_CMDID
,
WMI_P2P_GRP_INIT_CMDID
,
WMI_P2P_GRP_FORMATION_DONE_CMDID
,
WMI_P2P_INVITE_CMDID
,
WMI_P2P_INVITE_REQ_RSP_CMDID
,
WMI_P2P_PROV_DISC_REQ_CMDID
,
WMI_P2P_SET_CMDID
,
WMI_GET_RFKILL_MODE_CMDID
,
WMI_SET_RFKILL_MODE_CMDID
,
WMI_AP_SET_APSD_CMDID
,
WMI_AP_APSD_BUFFERED_TRAFFIC_CMDID
,
WMI_P2P_SDPD_TX_CMDID
,
/* F05C */
WMI_P2P_STOP_SDPD_CMDID
,
WMI_P2P_CANCEL_CMDID
,
/* Ultra low power store / recall commands */
/* Ultra low power store / recall commands */
WMI_STORERECALL_CONFIGURE_CMDID
,
WMI_STORERECALL_CONFIGURE_CMDID
,
WMI_STORERECALL_RECALL_CMDID
,
WMI_STORERECALL_RECALL_CMDID
,
WMI_STORERECALL_HOST_READY_CMDID
,
WMI_STORERECALL_HOST_READY_CMDID
,
WMI_FORCE_TARGET_ASSERT_CMDID
,
WMI_FORCE_TARGET_ASSERT_CMDID
,
WMI_SET_EXCESS_TX_RETRY_THRES_CMDID
,
WMI_SET_PROBED_SSID_EX_CMDID
,
WMI_SET_NETWORK_LIST_OFFLOAD_CMDID
,
WMI_SET_ARP_NS_OFFLOAD_CMDID
,
WMI_ADD_WOW_EXT_PATTERN_CMDID
,
WMI_GTK_OFFLOAD_OP_CMDID
,
WMI_REMAIN_ON_CHNL_CMDID
,
WMI_CANCEL_REMAIN_ON_CHNL_CMDID
,
WMI_SEND_ACTION_CMDID
,
WMI_PROBE_REQ_REPORT_CMDID
,
WMI_DISABLE_11B_RATES_CMDID
,
WMI_SEND_PROBE_RESPONSE_CMDID
,
WMI_GET_P2P_INFO_CMDID
,
WMI_AP_JOIN_BSS_CMDID
,
};
enum
wmi_mgmt_frame_type
{
WMI_FRAME_BEACON
=
0
,
WMI_FRAME_PROBE_REQ
,
WMI_FRAME_PROBE_RESP
,
WMI_FRAME_ASSOC_REQ
,
WMI_FRAME_ASSOC_RESP
,
WMI_NUM_MGMT_FRAME
};
};
/* WMI_CONNECT_CMDID */
/* WMI_CONNECT_CMDID */
...
@@ -519,11 +566,6 @@ enum dot11_auth_mode {
...
@@ -519,11 +566,6 @@ enum dot11_auth_mode {
LEAP_AUTH
=
0x04
,
LEAP_AUTH
=
0x04
,
};
};
enum
{
AUTH_IDLE
,
AUTH_OPEN_IN_PROGRESS
,
};
enum
auth_mode
{
enum
auth_mode
{
NONE_AUTH
=
0x01
,
NONE_AUTH
=
0x01
,
WPA_AUTH
=
0x02
,
WPA_AUTH
=
0x02
,
...
@@ -1179,15 +1221,26 @@ enum wmi_event_id {
...
@@ -1179,15 +1221,26 @@ enum wmi_event_id {
WMI_WAC_START_WPS_EVENTID
,
WMI_WAC_START_WPS_EVENTID
,
WMI_WAC_CTRL_REQ_REPLY_EVENTID
,
WMI_WAC_CTRL_REQ_REPLY_EVENTID
,
WMI_REPORT_WMM_PARAMS_EVENTID
,
WMI_WAC_REJECT_WPS_EVENTID
,
/* More P2P Events */
WMI_P2P_GO_NEG_REQ_EVENTID
,
WMI_P2P_INVITE_REQ_EVENTID
,
WMI_P2P_INVITE_RCVD_RESULT_EVENTID
,
WMI_P2P_INVITE_SENT_RESULT_EVENTID
,
WMI_P2P_PROV_DISC_RESP_EVENTID
,
WMI_P2P_PROV_DISC_REQ_EVENTID
,
/* RFKILL Events */
/* RFKILL Events */
WMI_RFKILL_STATE_CHANGE_EVENTID
,
WMI_RFKILL_STATE_CHANGE_EVENTID
,
WMI_RFKILL_GET_MODE_CMD_EVENTID
,
WMI_RFKILL_GET_MODE_CMD_EVENTID
,
WMI_THIN_RESERVED_START_EVENTID
=
0x8000
,
/*
WMI_P2P_START_SDPD_EVENTID
,
* Events in this range are reserved for thinmode
WMI_P2P_SDPD_RX_EVENTID
,
* See wmi_thin.h for actual definitions
*/
WMI_THIN_RESERVED_START_EVENTID
=
0x8000
,
/* Events in this range are reserved for thinmode */
WMI_THIN_RESERVED_END_EVENTID
=
0x8fff
,
WMI_THIN_RESERVED_END_EVENTID
=
0x8fff
,
WMI_SET_CHANNEL_EVENTID
,
WMI_SET_CHANNEL_EVENTID
,
...
@@ -1195,7 +1248,17 @@ enum wmi_event_id {
...
@@ -1195,7 +1248,17 @@ enum wmi_event_id {
/* Generic ACS event */
/* Generic ACS event */
WMI_ACS_EVENTID
,
WMI_ACS_EVENTID
,
WMI_REPORT_WMM_PARAMS_EVENTID
WMI_STORERECALL_STORE_EVENTID
,
WMI_WOW_EXT_WAKE_EVENTID
,
WMI_GTK_OFFLOAD_STATUS_EVENTID
,
WMI_NETWORK_LIST_OFFLOAD_EVENTID
,
WMI_REMAIN_ON_CHNL_EVENTID
,
WMI_CANCEL_REMAIN_ON_CHNL_EVENTID
,
WMI_TX_STATUS_EVENTID
,
WMI_RX_PROBE_REQ_EVENTID
,
WMI_P2P_CAPABILITIES_EVENTID
,
WMI_RX_ACTION_EVENTID
,
WMI_P2P_INFO_EVENTID
,
};
};
struct
wmi_ready_event_2
{
struct
wmi_ready_event_2
{
...
@@ -1207,11 +1270,30 @@ struct wmi_ready_event_2 {
...
@@ -1207,11 +1270,30 @@ struct wmi_ready_event_2 {
/* Connect Event */
/* Connect Event */
struct
wmi_connect_event
{
struct
wmi_connect_event
{
__le16
ch
;
union
{
u8
bssid
[
ETH_ALEN
];
struct
{
__le16
listen_intvl
;
__le16
ch
;
__le16
beacon_intvl
;
u8
bssid
[
ETH_ALEN
];
__le32
nw_type
;
__le16
listen_intvl
;
__le16
beacon_intvl
;
__le32
nw_type
;
}
sta
;
struct
{
u8
phymode
;
u8
aid
;
u8
mac_addr
[
ETH_ALEN
];
u8
auth
;
u8
keymgmt
;
__le16
cipher
;
u8
apsd_info
;
u8
unused
[
3
];
}
ap_sta
;
struct
{
__le16
ch
;
u8
bssid
[
ETH_ALEN
];
u8
unused
[
8
];
}
ap_bss
;
}
u
;
u8
beacon_ie_len
;
u8
beacon_ie_len
;
u8
assoc_req_len
;
u8
assoc_req_len
;
u8
assoc_resp_len
;
u8
assoc_resp_len
;
...
@@ -1238,6 +1320,12 @@ enum wmi_disconnect_reason {
...
@@ -1238,6 +1320,12 @@ enum wmi_disconnect_reason {
IBSS_MERGE
=
0xe
,
IBSS_MERGE
=
0xe
,
};
};
#define ATH6KL_COUNTRY_RD_SHIFT 16
struct
ath6kl_wmi_regdomain
{
__le32
reg_code
;
};
struct
wmi_disconnect_event
{
struct
wmi_disconnect_event
{
/* reason code, see 802.11 spec. */
/* reason code, see 802.11 spec. */
__le16
proto_reason_status
;
__le16
proto_reason_status
;
...
@@ -1265,33 +1353,54 @@ enum wmi_bi_ftype {
...
@@ -1265,33 +1353,54 @@ enum wmi_bi_ftype {
PROBEREQ_FTYPE
,
PROBEREQ_FTYPE
,
};
};
struct
wmi_bss_info_hdr
{
#define DEF_LRSSI_SCAN_PERIOD 5
__le16
ch
;
#define DEF_LRSSI_ROAM_THRESHOLD 20
#define DEF_LRSSI_ROAM_FLOOR 60
#define DEF_SCAN_FOR_ROAM_INTVL 2
/* see, enum wmi_bi_ftype */
enum
wmi_roam_ctrl
{
u8
frame_type
;
WMI_FORCE_ROAM
=
1
,
WMI_SET_ROAM_MODE
,
WMI_SET_HOST_BIAS
,
WMI_SET_LRSSI_SCAN_PARAMS
,
};
u8
snr
;
struct
bss_bias
{
a_sle16
rssi
;
u8
bssid
[
ETH_ALEN
];
u8
bssid
[
ETH_ALEN
];
__le32
ie_mask
;
u8
bias
;
}
__packed
;
}
__packed
;
/*
struct
bss_bias_info
{
* BSS INFO HDR version 2.0
u8
num_bss
;
* With 6 bytes HTC header and 6 bytes of WMI header
struct
bss_bias
bss_bias
[
1
];
* WMI_BSS_INFO_HDR cannot be accommodated in the removed 802.11 management
}
__packed
;
* header space.
* - Reduce the ie_mask to 2 bytes as only two bit flags are used
struct
low_rssi_scan_params
{
* - Remove rssi and compute it on the host. rssi = snr - 95
__le16
lrssi_scan_period
;
*/
a_sle16
lrssi_scan_threshold
;
a_sle16
lrssi_roam_threshold
;
u8
roam_rssi_floor
;
u8
reserved
[
1
];
}
__packed
;
struct
roam_ctrl_cmd
{
union
{
u8
bssid
[
ETH_ALEN
];
u8
roam_mode
;
struct
bss_bias_info
bss
;
struct
low_rssi_scan_params
params
;
}
__packed
info
;
u8
roam_ctrl
;
}
__packed
;
/* BSS INFO HDR version 2.0 */
struct
wmi_bss_info_hdr2
{
struct
wmi_bss_info_hdr2
{
__le16
ch
;
__le16
ch
;
/* frequency in MHz */
/* see, enum wmi_bi_ftype */
/* see, enum wmi_bi_ftype */
u8
frame_type
;
u8
frame_type
;
u8
snr
;
u8
snr
;
/* note: rssi = snr - 95 dBm */
u8
bssid
[
ETH_ALEN
];
u8
bssid
[
ETH_ALEN
];
__le16
ie_mask
;
__le16
ie_mask
;
}
__packed
;
}
__packed
;
...
@@ -1330,6 +1439,16 @@ enum wmi_bss_flags {
...
@@ -1330,6 +1439,16 @@ enum wmi_bss_flags {
WMI_PMKID_VALID_BSS
=
0x02
,
WMI_PMKID_VALID_BSS
=
0x02
,
};
};
struct
wmi_neighbor_info
{
u8
bssid
[
ETH_ALEN
];
u8
bss_flags
;
/* enum wmi_bss_flags */
}
__packed
;
struct
wmi_neighbor_report_event
{
u8
num_neighbors
;
struct
wmi_neighbor_info
neighbor
[
0
];
}
__packed
;
/* TKIP MIC Error Event */
/* TKIP MIC Error Event */
struct
wmi_tkip_micerr_event
{
struct
wmi_tkip_micerr_event
{
u8
key_id
;
u8
key_id
;
...
@@ -1642,6 +1761,12 @@ struct wmi_get_keepalive_cmd {
...
@@ -1642,6 +1761,12 @@ struct wmi_get_keepalive_cmd {
u8
keep_alive_intvl
;
u8
keep_alive_intvl
;
}
__packed
;
}
__packed
;
struct
wmi_set_appie_cmd
{
u8
mgmt_frm_type
;
/* enum wmi_mgmt_frame_type */
u8
ie_len
;
u8
ie_info
[
0
];
}
__packed
;
/* Notify the WSC registration status to the target */
/* Notify the WSC registration status to the target */
#define WSC_REG_ACTIVE 1
#define WSC_REG_ACTIVE 1
#define WSC_REG_INACTIVE 0
#define WSC_REG_INACTIVE 0
...
@@ -1789,8 +1914,26 @@ struct wmi_tx_complete_event {
...
@@ -1789,8 +1914,26 @@ struct wmi_tx_complete_event {
/* Used with WMI_AP_SET_NUM_STA_CMDID */
/* Used with WMI_AP_SET_NUM_STA_CMDID */
/*
* Used with WMI_AP_SET_MLME_CMDID
*/
/* MLME Commands */
#define WMI_AP_MLME_ASSOC 1
/* associate station */
#define WMI_AP_DISASSOC 2
/* disassociate station */
#define WMI_AP_DEAUTH 3
/* deauthenticate station */
#define WMI_AP_MLME_AUTHORIZE 4
/* authorize station */
#define WMI_AP_MLME_UNAUTHORIZE 5
/* unauthorize station */
struct
wmi_ap_set_mlme_cmd
{
u8
mac
[
ETH_ALEN
];
__le16
reason
;
/* 802.11 reason code */
u8
cmd
;
/* operation to perform (WMI_AP_*) */
}
__packed
;
struct
wmi_ap_set_pvb_cmd
{
struct
wmi_ap_set_pvb_cmd
{
__le32
flag
;
__le32
flag
;
__le16
rsvd
;
__le16
aid
;
__le16
aid
;
}
__packed
;
}
__packed
;
...
@@ -1840,6 +1983,100 @@ struct wmi_ap_mode_stat {
...
@@ -1840,6 +1983,100 @@ struct wmi_ap_mode_stat {
/* End of AP mode definitions */
/* End of AP mode definitions */
struct
wmi_remain_on_chnl_cmd
{
__le32
freq
;
__le32
duration
;
}
__packed
;
struct
wmi_send_action_cmd
{
__le32
id
;
__le32
freq
;
__le32
wait
;
__le16
len
;
u8
data
[
0
];
}
__packed
;
struct
wmi_tx_status_event
{
__le32
id
;
u8
ack_status
;
}
__packed
;
struct
wmi_probe_req_report_cmd
{
u8
enable
;
}
__packed
;
struct
wmi_disable_11b_rates_cmd
{
u8
disable
;
}
__packed
;
struct
wmi_set_appie_extended_cmd
{
u8
role_id
;
u8
mgmt_frm_type
;
u8
ie_len
;
u8
ie_info
[
0
];
}
__packed
;
struct
wmi_remain_on_chnl_event
{
__le32
freq
;
__le32
duration
;
}
__packed
;
struct
wmi_cancel_remain_on_chnl_event
{
__le32
freq
;
__le32
duration
;
u8
status
;
}
__packed
;
struct
wmi_rx_action_event
{
__le32
freq
;
__le16
len
;
u8
data
[
0
];
}
__packed
;
struct
wmi_p2p_capabilities_event
{
__le16
len
;
u8
data
[
0
];
}
__packed
;
struct
wmi_p2p_rx_probe_req_event
{
__le32
freq
;
__le16
len
;
u8
data
[
0
];
}
__packed
;
#define P2P_FLAG_CAPABILITIES_REQ (0x00000001)
#define P2P_FLAG_MACADDR_REQ (0x00000002)
#define P2P_FLAG_HMODEL_REQ (0x00000002)
struct
wmi_get_p2p_info
{
__le32
info_req_flags
;
}
__packed
;
struct
wmi_p2p_info_event
{
__le32
info_req_flags
;
__le16
len
;
u8
data
[
0
];
}
__packed
;
struct
wmi_p2p_capabilities
{
u8
go_power_save
;
}
__packed
;
struct
wmi_p2p_macaddr
{
u8
mac_addr
[
ETH_ALEN
];
}
__packed
;
struct
wmi_p2p_hmodel
{
u8
p2p_model
;
}
__packed
;
struct
wmi_p2p_probe_response_cmd
{
__le32
freq
;
u8
destination_addr
[
ETH_ALEN
];
__le16
len
;
u8
data
[
0
];
}
__packed
;
/* Extended WMI (WMIX)
/* Extended WMI (WMIX)
*
*
* Extended WMIX commands are encapsulated in a WMI message with
* Extended WMIX commands are encapsulated in a WMI message with
...
@@ -1898,6 +2135,11 @@ struct wmix_hb_challenge_resp_cmd {
...
@@ -1898,6 +2135,11 @@ struct wmix_hb_challenge_resp_cmd {
__le32
source
;
__le32
source
;
}
__packed
;
}
__packed
;
struct
ath6kl_wmix_dbglog_cfg_module_cmd
{
__le32
valid
;
__le32
config
;
}
__packed
;
/* End of Extended WMI (WMIX) */
/* End of Extended WMI (WMIX) */
enum
wmi_sync_flag
{
enum
wmi_sync_flag
{
...
@@ -1925,14 +2167,11 @@ int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb,
...
@@ -1925,14 +2167,11 @@ int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb,
int
ath6kl_wmi_dot11_hdr_remove
(
struct
wmi
*
wmi
,
struct
sk_buff
*
skb
);
int
ath6kl_wmi_dot11_hdr_remove
(
struct
wmi
*
wmi
,
struct
sk_buff
*
skb
);
int
ath6kl_wmi_dot3_2_dix
(
struct
sk_buff
*
skb
);
int
ath6kl_wmi_dot3_2_dix
(
struct
sk_buff
*
skb
);
int
ath6kl_wmi_data_hdr_remove
(
struct
wmi
*
wmi
,
struct
sk_buff
*
skb
);
int
ath6kl_wmi_implicit_create_pstream
(
struct
wmi
*
wmi
,
struct
sk_buff
*
skb
,
int
ath6kl_wmi_implicit_create_pstream
(
struct
wmi
*
wmi
,
struct
sk_buff
*
skb
,
u32
layer2_priority
,
bool
wmm_enabled
,
u32
layer2_priority
,
bool
wmm_enabled
,
u8
*
ac
);
u8
*
ac
);
int
ath6kl_wmi_control_rx
(
struct
wmi
*
wmi
,
struct
sk_buff
*
skb
);
int
ath6kl_wmi_control_rx
(
struct
wmi
*
wmi
,
struct
sk_buff
*
skb
);
struct
bss
*
ath6kl_wmi_find_node
(
struct
wmi
*
wmi
,
const
u8
*
mac_addr
);
void
ath6kl_wmi_node_free
(
struct
wmi
*
wmi
,
const
u8
*
mac_addr
);
int
ath6kl_wmi_cmd_send
(
struct
wmi
*
wmi
,
struct
sk_buff
*
skb
,
int
ath6kl_wmi_cmd_send
(
struct
wmi
*
wmi
,
struct
sk_buff
*
skb
,
enum
wmi_cmd_id
cmd_id
,
enum
wmi_sync_flag
sync_flag
);
enum
wmi_cmd_id
cmd_id
,
enum
wmi_sync_flag
sync_flag
);
...
@@ -1978,6 +2217,7 @@ int ath6kl_wmi_set_lpreamble_cmd(struct wmi *wmi, u8 status,
...
@@ -1978,6 +2217,7 @@ int ath6kl_wmi_set_lpreamble_cmd(struct wmi *wmi, u8 status,
u8
preamble_policy
);
u8
preamble_policy
);
int
ath6kl_wmi_get_challenge_resp_cmd
(
struct
wmi
*
wmi
,
u32
cookie
,
u32
source
);
int
ath6kl_wmi_get_challenge_resp_cmd
(
struct
wmi
*
wmi
,
u32
cookie
,
u32
source
);
int
ath6kl_wmi_config_debug_module_cmd
(
struct
wmi
*
wmi
,
u32
valid
,
u32
config
);
int
ath6kl_wmi_get_stats_cmd
(
struct
wmi
*
wmi
);
int
ath6kl_wmi_get_stats_cmd
(
struct
wmi
*
wmi
);
int
ath6kl_wmi_addkey_cmd
(
struct
wmi
*
wmi
,
u8
key_index
,
int
ath6kl_wmi_addkey_cmd
(
struct
wmi
*
wmi
,
u8
key_index
,
...
@@ -1995,23 +2235,47 @@ int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi);
...
@@ -1995,23 +2235,47 @@ int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi);
int
ath6kl_wmi_set_wmm_txop
(
struct
wmi
*
wmi
,
enum
wmi_txop_cfg
cfg
);
int
ath6kl_wmi_set_wmm_txop
(
struct
wmi
*
wmi
,
enum
wmi_txop_cfg
cfg
);
int
ath6kl_wmi_set_keepalive_cmd
(
struct
wmi
*
wmi
,
u8
keep_alive_intvl
);
int
ath6kl_wmi_set_keepalive_cmd
(
struct
wmi
*
wmi
,
u8
keep_alive_intvl
);
int
ath6kl_wmi_test_cmd
(
struct
wmi
*
wmi
,
void
*
buf
,
size_t
len
);
s32
ath6kl_wmi_get_rate
(
s8
rate_index
);
s32
ath6kl_wmi_get_rate
(
s8
rate_index
);
int
ath6kl_wmi_set_ip_cmd
(
struct
wmi
*
wmi
,
struct
wmi_set_ip_cmd
*
ip_cmd
);
int
ath6kl_wmi_set_ip_cmd
(
struct
wmi
*
wmi
,
struct
wmi_set_ip_cmd
*
ip_cmd
);
int
ath6kl_wmi_set_roam_lrssi_cmd
(
struct
wmi
*
wmi
,
u8
lrssi
);
struct
bss
*
ath6kl_wmi_find_ssid_node
(
struct
wmi
*
wmi
,
u8
*
ssid
,
/* AP mode */
u32
ssid_len
,
bool
is_wpa2
,
int
ath6kl_wmi_ap_profile_commit
(
struct
wmi
*
wmip
,
struct
wmi_connect_cmd
*
p
);
bool
match_ssid
);
void
ath6kl_wmi_node_return
(
struct
wmi
*
wmi
,
struct
bss
*
bss
);
int
ath6kl_wmi_ap_set_mlme
(
struct
wmi
*
wmip
,
u8
cmd
,
const
u8
*
mac
,
u16
reason
);
/* AP mode */
int
ath6kl_wmi_set_pvb_cmd
(
struct
wmi
*
wmi
,
u16
aid
,
bool
flag
);
int
ath6kl_wmi_set_pvb_cmd
(
struct
wmi
*
wmi
,
u16
aid
,
bool
flag
);
int
ath6kl_wmi_set_rx_frame_format_cmd
(
struct
wmi
*
wmi
,
u8
rx_meta_version
,
int
ath6kl_wmi_set_rx_frame_format_cmd
(
struct
wmi
*
wmi
,
u8
rx_meta_version
,
bool
rx_dot11_hdr
,
bool
defrag_on_host
);
bool
rx_dot11_hdr
,
bool
defrag_on_host
);
int
ath6kl_wmi_set_appie_cmd
(
struct
wmi
*
wmi
,
u8
mgmt_frm_type
,
const
u8
*
ie
,
u8
ie_len
);
/* P2P */
int
ath6kl_wmi_disable_11b_rates_cmd
(
struct
wmi
*
wmi
,
bool
disable
);
int
ath6kl_wmi_remain_on_chnl_cmd
(
struct
wmi
*
wmi
,
u32
freq
,
u32
dur
);
int
ath6kl_wmi_send_action_cmd
(
struct
wmi
*
wmi
,
u32
id
,
u32
freq
,
u32
wait
,
const
u8
*
data
,
u16
data_len
);
int
ath6kl_wmi_send_probe_response_cmd
(
struct
wmi
*
wmi
,
u32
freq
,
const
u8
*
dst
,
const
u8
*
data
,
u16
data_len
);
int
ath6kl_wmi_probe_report_req_cmd
(
struct
wmi
*
wmi
,
bool
enable
);
int
ath6kl_wmi_info_req_cmd
(
struct
wmi
*
wmi
,
u32
info_req_flags
);
int
ath6kl_wmi_cancel_remain_on_chnl_cmd
(
struct
wmi
*
wmi
);
int
ath6kl_wmi_set_appie_cmd
(
struct
wmi
*
wmi
,
u8
mgmt_frm_type
,
const
u8
*
ie
,
u8
ie_len
);
void
*
ath6kl_wmi_init
(
struct
ath6kl
*
devt
);
void
*
ath6kl_wmi_init
(
struct
ath6kl
*
devt
);
void
ath6kl_wmi_shutdown
(
struct
wmi
*
wmi
);
void
ath6kl_wmi_shutdown
(
struct
wmi
*
wmi
);
...
...
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