Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
1e5023c7
Commit
1e5023c7
authored
Nov 16, 2012
by
John W. Linville
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-linville' of
git://github.com/kvalo/ath6kl
parents
dfbebe14
ff7e6867
Changes
18
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
990 additions
and
285 deletions
+990
-285
drivers/net/wireless/ath/ath6kl/Kconfig
drivers/net/wireless/ath/ath6kl/Kconfig
+9
-0
drivers/net/wireless/ath/ath6kl/Makefile
drivers/net/wireless/ath/ath6kl/Makefile
+1
-0
drivers/net/wireless/ath/ath6kl/cfg80211.c
drivers/net/wireless/ath/ath6kl/cfg80211.c
+244
-126
drivers/net/wireless/ath/ath6kl/cfg80211.h
drivers/net/wireless/ath/ath6kl/cfg80211.h
+0
-1
drivers/net/wireless/ath/ath6kl/core.c
drivers/net/wireless/ath/ath6kl/core.c
+21
-0
drivers/net/wireless/ath/ath6kl/core.h
drivers/net/wireless/ath/ath6kl/core.h
+67
-2
drivers/net/wireless/ath/ath6kl/debug.h
drivers/net/wireless/ath/ath6kl/debug.h
+1
-0
drivers/net/wireless/ath/ath6kl/hif.c
drivers/net/wireless/ath/ath6kl/hif.c
+1
-5
drivers/net/wireless/ath/ath6kl/htc_mbox.c
drivers/net/wireless/ath/ath6kl/htc_mbox.c
+3
-10
drivers/net/wireless/ath/ath6kl/htc_pipe.c
drivers/net/wireless/ath/ath6kl/htc_pipe.c
+6
-8
drivers/net/wireless/ath/ath6kl/init.c
drivers/net/wireless/ath/ath6kl/init.c
+78
-14
drivers/net/wireless/ath/ath6kl/main.c
drivers/net/wireless/ath/ath6kl/main.c
+46
-9
drivers/net/wireless/ath/ath6kl/recovery.c
drivers/net/wireless/ath/ath6kl/recovery.c
+160
-0
drivers/net/wireless/ath/ath6kl/sdio.c
drivers/net/wireless/ath/ath6kl/sdio.c
+7
-20
drivers/net/wireless/ath/ath6kl/txrx.c
drivers/net/wireless/ath/ath6kl/txrx.c
+33
-14
drivers/net/wireless/ath/ath6kl/usb.c
drivers/net/wireless/ath/ath6kl/usb.c
+26
-6
drivers/net/wireless/ath/ath6kl/wmi.c
drivers/net/wireless/ath/ath6kl/wmi.c
+218
-61
drivers/net/wireless/ath/ath6kl/wmi.h
drivers/net/wireless/ath/ath6kl/wmi.h
+69
-9
No files found.
drivers/net/wireless/ath/ath6kl/Kconfig
View file @
1e5023c7
...
...
@@ -30,3 +30,12 @@ config ATH6KL_DEBUG
depends on ATH6KL
---help---
Enables debug support
config ATH6KL_REGDOMAIN
bool "Atheros ath6kl regdomain support"
depends on ATH6KL
depends on CFG80211_CERTIFICATION_ONUS
---help---
Enabling this makes it possible to change the regdomain in
the firmware. This can be only enabled if regulatory requirements
are taken into account.
drivers/net/wireless/ath/ath6kl/Makefile
View file @
1e5023c7
...
...
@@ -34,6 +34,7 @@ ath6kl_core-y += main.o
ath6kl_core-y
+=
txrx.o
ath6kl_core-y
+=
wmi.o
ath6kl_core-y
+=
core.o
ath6kl_core-y
+=
recovery.o
ath6kl_core-$(CONFIG_NL80211_TESTMODE)
+=
testmode.o
obj-$(CONFIG_ATH6KL_SDIO)
+=
ath6kl_sdio.o
...
...
drivers/net/wireless/ath/ath6kl/cfg80211.c
View file @
1e5023c7
...
...
@@ -147,15 +147,15 @@ static bool __ath6kl_cfg80211_sscan_stop(struct ath6kl_vif *vif)
{
struct
ath6kl
*
ar
=
vif
->
ar
;
if
(
ar
->
state
!=
ATH6KL_STATE_SCHED_SCAN
)
if
(
!
test_and_clear_bit
(
SCHED_SCANNING
,
&
vif
->
flags
)
)
return
false
;
del_timer_sync
(
&
vif
->
sched_scan_timer
);
ath6kl_wmi_set_host_sleep_mode_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
ATH6KL_HOST_MODE_AWAKE
)
;
if
(
ar
->
state
==
ATH6KL_STATE_RECOVERY
)
return
true
;
a
r
->
state
=
ATH6KL_STATE_ON
;
a
th6kl_wmi_enable_sched_scan_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
false
)
;
return
true
;
}
...
...
@@ -369,17 +369,13 @@ static int ath6kl_nliftype_to_drv_iftype(enum nl80211_iftype type, u8 *nw_type)
{
switch
(
type
)
{
case
NL80211_IFTYPE_STATION
:
case
NL80211_IFTYPE_P2P_CLIENT
:
*
nw_type
=
INFRA_NETWORK
;
break
;
case
NL80211_IFTYPE_ADHOC
:
*
nw_type
=
ADHOC_NETWORK
;
break
;
case
NL80211_IFTYPE_AP
:
*
nw_type
=
AP_NETWORK
;
break
;
case
NL80211_IFTYPE_P2P_CLIENT
:
*
nw_type
=
INFRA_NETWORK
;
break
;
case
NL80211_IFTYPE_P2P_GO
:
*
nw_type
=
AP_NETWORK
;
break
;
...
...
@@ -1031,30 +1027,15 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy,
vif
->
scan_req
=
request
;
if
(
test_bit
(
ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX
,
ar
->
fw_capabilities
))
{
/*
* If capable of doing P2P mgmt operations using
* station interface, send additional information like
* supported rates to advertise and xmit rates for
* probe requests
*/
ret
=
ath6kl_wmi_beginscan_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
WMI_LONG_SCAN
,
force_fg_scan
,
false
,
0
,
ATH6KL_FG_SCAN_INTERVAL
,
n_channels
,
channels
,
request
->
no_cck
,
request
->
rates
);
}
else
{
ret
=
ath6kl_wmi_startscan_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
WMI_LONG_SCAN
,
force_fg_scan
,
false
,
0
,
ATH6KL_FG_SCAN_INTERVAL
,
n_channels
,
channels
);
}
ret
=
ath6kl_wmi_beginscan_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
WMI_LONG_SCAN
,
force_fg_scan
,
false
,
0
,
ATH6KL_FG_SCAN_INTERVAL
,
n_channels
,
channels
,
request
->
no_cck
,
request
->
rates
);
if
(
ret
)
{
ath6kl_err
(
"
wmi_startscan_cmd failed
\n
"
);
ath6kl_err
(
"
failed to start scan: %d
\n
"
,
ret
);
vif
->
scan_req
=
NULL
;
}
...
...
@@ -1888,7 +1869,7 @@ static int ath6kl_wow_usr(struct ath6kl *ar, struct ath6kl_vif *vif,
struct
cfg80211_wowlan
*
wow
,
u32
*
filter
)
{
int
ret
,
pos
;
u8
mask
[
WOW_
MASK
_SIZE
];
u8
mask
[
WOW_
PATTERN
_SIZE
];
u16
i
;
/* Configure the patterns that we received from the user. */
...
...
@@ -2106,33 +2087,16 @@ static int ath6kl_cfg80211_host_sleep(struct ath6kl *ar, struct ath6kl_vif *vif)
return
ret
;
}
static
int
ath6kl_wow_suspend
(
struct
ath6kl
*
ar
,
struct
cfg80211_wowlan
*
wow
)
static
int
ath6kl_wow_suspend_vif
(
struct
ath6kl_vif
*
vif
,
struct
cfg80211_wowlan
*
wow
,
u32
*
filter
)
{
struct
ath6kl
*
ar
=
vif
->
ar
;
struct
in_device
*
in_dev
;
struct
in_ifaddr
*
ifa
;
struct
ath6kl_vif
*
vif
;
int
ret
;
u32
filter
=
0
;
u16
i
,
bmiss_time
;
u8
index
=
0
;
__be32
ips
[
MAX_IP_ADDRS
];
/* The FW currently can't support multi-vif WoW properly. */
if
(
ar
->
num_vif
>
1
)
return
-
EIO
;
vif
=
ath6kl_vif_first
(
ar
);
if
(
!
vif
)
return
-
EIO
;
if
(
!
ath6kl_cfg80211_ready
(
vif
))
return
-
EIO
;
if
(
!
test_bit
(
CONNECTED
,
&
vif
->
flags
))
return
-
ENOTCONN
;
if
(
wow
&&
(
wow
->
n_patterns
>
WOW_MAX_FILTERS_PER_LIST
))
return
-
EINVAL
;
u8
index
=
0
;
if
(
!
test_bit
(
NETDEV_MCAST_ALL_ON
,
&
vif
->
flags
)
&&
test_bit
(
ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER
,
...
...
@@ -2154,7 +2118,7 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
* the user.
*/
if
(
wow
)
ret
=
ath6kl_wow_usr
(
ar
,
vif
,
wow
,
&
filter
);
ret
=
ath6kl_wow_usr
(
ar
,
vif
,
wow
,
filter
);
else
if
(
vif
->
nw_type
==
AP_NETWORK
)
ret
=
ath6kl_wow_ap
(
ar
,
vif
);
else
...
...
@@ -2189,12 +2153,10 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
return
ret
;
}
ar
->
state
=
ATH6KL_STATE_SUSPENDING
;
/* Setup own IP addr for ARP agent. */
in_dev
=
__in_dev_get_rtnl
(
vif
->
ndev
);
if
(
!
in_dev
)
goto
skip_arp
;
return
0
;
ifa
=
in_dev
->
ifa_list
;
memset
(
&
ips
,
0
,
sizeof
(
ips
));
...
...
@@ -2217,41 +2179,61 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
return
ret
;
}
skip_arp:
ret
=
ath6kl_wmi_set_wow_mode_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
return
ret
;
}
static
int
ath6kl_wow_suspend
(
struct
ath6kl
*
ar
,
struct
cfg80211_wowlan
*
wow
)
{
struct
ath6kl_vif
*
first_vif
,
*
vif
;
int
ret
=
0
;
u32
filter
=
0
;
bool
connected
=
false
;
/* enter / leave wow suspend on first vif always */
first_vif
=
ath6kl_vif_first
(
ar
);
if
(
WARN_ON
(
unlikely
(
!
first_vif
))
||
!
ath6kl_cfg80211_ready
(
first_vif
))
return
-
EIO
;
if
(
wow
&&
(
wow
->
n_patterns
>
WOW_MAX_FILTERS_PER_LIST
))
return
-
EINVAL
;
/* install filters for each connected vif */
spin_lock_bh
(
&
ar
->
list_lock
);
list_for_each_entry
(
vif
,
&
ar
->
vif_list
,
list
)
{
if
(
!
test_bit
(
CONNECTED
,
&
vif
->
flags
)
||
!
ath6kl_cfg80211_ready
(
vif
))
continue
;
connected
=
true
;
ret
=
ath6kl_wow_suspend_vif
(
vif
,
wow
,
&
filter
);
if
(
ret
)
break
;
}
spin_unlock_bh
(
&
ar
->
list_lock
);
if
(
!
connected
)
return
-
ENOTCONN
;
else
if
(
ret
)
return
ret
;
ar
->
state
=
ATH6KL_STATE_SUSPENDING
;
ret
=
ath6kl_wmi_set_wow_mode_cmd
(
ar
->
wmi
,
first_vif
->
fw_vif_idx
,
ATH6KL_WOW_MODE_ENABLE
,
filter
,
WOW_HOST_REQ_DELAY
);
if
(
ret
)
return
ret
;
ret
=
ath6kl_cfg80211_host_sleep
(
ar
,
vif
);
if
(
ret
)
return
ret
;
return
0
;
return
ath6kl_cfg80211_host_sleep
(
ar
,
first_vif
);
}
static
int
ath6kl_wow_resume
(
struct
ath6kl
*
ar
)
static
int
ath6kl_wow_resume
_vif
(
struct
ath6kl_vif
*
vif
)
{
struct
ath6kl
_vif
*
vif
;
struct
ath6kl
*
ar
=
vif
->
ar
;
int
ret
;
vif
=
ath6kl_vif_first
(
ar
);
if
(
!
vif
)
return
-
EIO
;
ar
->
state
=
ATH6KL_STATE_RESUMING
;
ret
=
ath6kl_wmi_set_host_sleep_mode_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
ATH6KL_HOST_MODE_AWAKE
);
if
(
ret
)
{
ath6kl_warn
(
"Failed to configure host sleep mode for wow resume: %d
\n
"
,
ret
);
ar
->
state
=
ATH6KL_STATE_WOW
;
return
ret
;
}
if
(
vif
->
nw_type
!=
AP_NETWORK
)
{
ret
=
ath6kl_wmi_scanparams_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
0
,
0
,
0
,
0
,
0
,
0
,
3
,
0
,
0
,
0
);
...
...
@@ -2269,13 +2251,11 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
return
ret
;
}
ar
->
state
=
ATH6KL_STATE_ON
;
if
(
!
test_bit
(
NETDEV_MCAST_ALL_OFF
,
&
vif
->
flags
)
&&
test_bit
(
ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER
,
ar
->
fw_capabilities
))
{
ret
=
ath6kl_wmi_mcast_filter_cmd
(
vif
->
ar
->
wmi
,
vif
->
fw_vif_idx
,
true
);
vif
->
fw_vif_idx
,
true
);
if
(
ret
)
return
ret
;
}
...
...
@@ -2285,6 +2265,48 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
return
0
;
}
static
int
ath6kl_wow_resume
(
struct
ath6kl
*
ar
)
{
struct
ath6kl_vif
*
vif
;
int
ret
;
vif
=
ath6kl_vif_first
(
ar
);
if
(
WARN_ON
(
unlikely
(
!
vif
))
||
!
ath6kl_cfg80211_ready
(
vif
))
return
-
EIO
;
ar
->
state
=
ATH6KL_STATE_RESUMING
;
ret
=
ath6kl_wmi_set_host_sleep_mode_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
ATH6KL_HOST_MODE_AWAKE
);
if
(
ret
)
{
ath6kl_warn
(
"Failed to configure host sleep mode for wow resume: %d
\n
"
,
ret
);
goto
cleanup
;
}
spin_lock_bh
(
&
ar
->
list_lock
);
list_for_each_entry
(
vif
,
&
ar
->
vif_list
,
list
)
{
if
(
!
test_bit
(
CONNECTED
,
&
vif
->
flags
)
||
!
ath6kl_cfg80211_ready
(
vif
))
continue
;
ret
=
ath6kl_wow_resume_vif
(
vif
);
if
(
ret
)
break
;
}
spin_unlock_bh
(
&
ar
->
list_lock
);
if
(
ret
)
goto
cleanup
;
ar
->
state
=
ATH6KL_STATE_ON
;
return
0
;
cleanup:
ar
->
state
=
ATH6KL_STATE_WOW
;
return
ret
;
}
static
int
ath6kl_cfg80211_deepsleep_suspend
(
struct
ath6kl
*
ar
)
{
struct
ath6kl_vif
*
vif
;
...
...
@@ -2421,13 +2443,6 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar,
break
;
case
ATH6KL_CFG_SUSPEND_SCHED_SCAN
:
/*
* Nothing needed for schedule scan, firmware is already in
* wow mode and sleeping most of the time.
*/
break
;
default:
break
;
}
...
...
@@ -2475,9 +2490,6 @@ int ath6kl_cfg80211_resume(struct ath6kl *ar)
}
break
;
case
ATH6KL_STATE_SCHED_SCAN
:
break
;
default:
break
;
}
...
...
@@ -2494,14 +2506,23 @@ static int __ath6kl_cfg80211_suspend(struct wiphy *wiphy,
{
struct
ath6kl
*
ar
=
wiphy_priv
(
wiphy
);
ath6kl_recovery_suspend
(
ar
);
return
ath6kl_hif_suspend
(
ar
,
wow
);
}
static
int
__ath6kl_cfg80211_resume
(
struct
wiphy
*
wiphy
)
{
struct
ath6kl
*
ar
=
wiphy_priv
(
wiphy
);
int
err
;
err
=
ath6kl_hif_resume
(
ar
);
if
(
err
)
return
err
;
ath6kl_recovery_resume
(
ar
);
return
ath6kl_hif_resume
(
ar
)
;
return
0
;
}
/*
...
...
@@ -2738,6 +2759,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
int
res
;
int
i
,
ret
;
u16
rsn_capab
=
0
;
int
inactivity_timeout
=
0
;
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"%s:
\n
"
,
__func__
);
...
...
@@ -2874,8 +2896,15 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
}
if
(
info
->
inactivity_timeout
)
{
inactivity_timeout
=
info
->
inactivity_timeout
;
if
(
ar
->
hw
.
flags
&
ATH6KL_HW_AP_INACTIVITY_MINS
)
inactivity_timeout
=
DIV_ROUND_UP
(
inactivity_timeout
,
60
);
res
=
ath6kl_wmi_set_inact_period
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
in
fo
->
in
activity_timeout
);
inactivity_timeout
);
if
(
res
<
0
)
return
res
;
}
...
...
@@ -2897,6 +2926,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
WLAN_EID_RSN
,
WMI_RSN_IE_CAPB
,
(
const
u8
*
)
&
rsn_capab
,
sizeof
(
rsn_capab
));
vif
->
rsn_capab
=
rsn_capab
;
if
(
res
<
0
)
return
res
;
}
...
...
@@ -3210,7 +3240,7 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
struct
ath6kl
*
ar
=
ath6kl_priv
(
dev
);
struct
ath6kl_vif
*
vif
=
netdev_priv
(
dev
);
u16
interval
;
int
ret
;
int
ret
,
rssi_thold
;
if
(
ar
->
state
!=
ATH6KL_STATE_ON
)
return
-
EIO
;
...
...
@@ -3218,10 +3248,6 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
if
(
vif
->
sme_state
!=
SME_DISCONNECTED
)
return
-
EBUSY
;
/* The FW currently can't support multi-vif WoW properly. */
if
(
ar
->
num_vif
>
1
)
return
-
EIO
;
ath6kl_cfg80211_scan_complete_event
(
vif
,
true
);
ret
=
ath6kl_set_probed_ssids
(
ar
,
vif
,
request
->
ssids
,
...
...
@@ -3243,6 +3269,23 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
return
ret
;
}
if
(
test_bit
(
ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD
,
ar
->
fw_capabilities
))
{
if
(
request
->
rssi_thold
<=
NL80211_SCAN_RSSI_THOLD_OFF
)
rssi_thold
=
0
;
else
if
(
request
->
rssi_thold
<
-
127
)
rssi_thold
=
-
127
;
else
rssi_thold
=
request
->
rssi_thold
;
ret
=
ath6kl_wmi_set_rssi_filter_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
rssi_thold
);
if
(
ret
)
{
ath6kl_err
(
"failed to set RSSI threshold for scan
\n
"
);
return
ret
;
}
}
/* fw uses seconds, also make sure that it's >0 */
interval
=
max_t
(
u16
,
1
,
request
->
interval
/
1000
);
...
...
@@ -3250,15 +3293,6 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
interval
,
interval
,
vif
->
bg_scan_period
,
0
,
0
,
0
,
3
,
0
,
0
,
0
);
ret
=
ath6kl_wmi_set_wow_mode_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
ATH6KL_WOW_MODE_ENABLE
,
WOW_FILTER_SSID
,
WOW_HOST_REQ_DELAY
);
if
(
ret
)
{
ath6kl_warn
(
"Failed to enable wow with ssid filter: %d
\n
"
,
ret
);
return
ret
;
}
/* this also clears IE in fw if it's not set */
ret
=
ath6kl_wmi_set_appie_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
WMI_FRAME_PROBE_REQ
,
...
...
@@ -3269,17 +3303,13 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
return
ret
;
}
ret
=
ath6kl_wmi_set_host_sleep_mode_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
ATH6KL_HOST_MODE_ASLEEP
);
if
(
ret
)
{
ath6kl_warn
(
"Failed to enable host sleep mode for sched scan: %d
\n
"
,
ret
);
ret
=
ath6kl_wmi_enable_sched_scan_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
true
);
if
(
ret
)
return
ret
;
}
ar
->
state
=
ATH6KL_STATE_SCHED_SCAN
;
set_bit
(
SCHED_SCANNING
,
&
vif
->
flags
)
;
return
ret
;
return
0
;
}
static
int
ath6kl_cfg80211_sscan_stop
(
struct
wiphy
*
wiphy
,
...
...
@@ -3308,6 +3338,27 @@ static int ath6kl_cfg80211_set_bitrate(struct wiphy *wiphy,
mask
);
}
static
int
ath6kl_cfg80211_set_txe_config
(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
,
u32
rate
,
u32
pkts
,
u32
intvl
)
{
struct
ath6kl
*
ar
=
ath6kl_priv
(
dev
);
struct
ath6kl_vif
*
vif
=
netdev_priv
(
dev
);
if
(
vif
->
nw_type
!=
INFRA_NETWORK
||
!
test_bit
(
ATH6KL_FW_CAPABILITY_TX_ERR_NOTIFY
,
ar
->
fw_capabilities
))
return
-
EOPNOTSUPP
;
if
(
vif
->
sme_state
!=
SME_CONNECTED
)
return
-
ENOTCONN
;
/* save this since the firmware won't report the interval */
vif
->
txe_intvl
=
intvl
;
return
ath6kl_wmi_set_txe_notify
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
rate
,
pkts
,
intvl
);
}
static
const
struct
ieee80211_txrx_stypes
ath6kl_mgmt_stypes
[
NUM_NL80211_IFTYPES
]
=
{
[
NL80211_IFTYPE_STATION
]
=
{
...
...
@@ -3374,6 +3425,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = {
.
sched_scan_start
=
ath6kl_cfg80211_sscan_start
,
.
sched_scan_stop
=
ath6kl_cfg80211_sscan_stop
,
.
set_bitrate_mask
=
ath6kl_cfg80211_set_bitrate
,
.
set_cqm_txe_config
=
ath6kl_cfg80211_set_txe_config
,
};
void
ath6kl_cfg80211_stop
(
struct
ath6kl_vif
*
vif
)
...
...
@@ -3394,16 +3446,22 @@ void ath6kl_cfg80211_stop(struct ath6kl_vif *vif)
break
;
}
if
(
test_bit
(
CONNECTED
,
&
vif
->
flags
)
||
test_bit
(
CONNECT_PEND
,
&
vif
->
flags
))
if
(
vif
->
ar
->
state
!=
ATH6KL_STATE_RECOVERY
&&
(
test_bit
(
CONNECTED
,
&
vif
->
flags
)
||
test_bit
(
CONNECT_PEND
,
&
vif
->
flags
)))
ath6kl_wmi_disconnect_cmd
(
vif
->
ar
->
wmi
,
vif
->
fw_vif_idx
);
vif
->
sme_state
=
SME_DISCONNECTED
;
clear_bit
(
CONNECTED
,
&
vif
->
flags
);
clear_bit
(
CONNECT_PEND
,
&
vif
->
flags
);
/* Stop netdev queues, needed during recovery */
netif_stop_queue
(
vif
->
ndev
);
netif_carrier_off
(
vif
->
ndev
);
/* disable scanning */
if
(
ath6kl_wmi_scanparams_cmd
(
vif
->
ar
->
wmi
,
vif
->
fw_vif_idx
,
0xFFFF
,
if
(
vif
->
ar
->
state
!=
ATH6KL_STATE_RECOVERY
&&
ath6kl_wmi_scanparams_cmd
(
vif
->
ar
->
wmi
,
vif
->
fw_vif_idx
,
0xFFFF
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
)
!=
0
)
ath6kl_warn
(
"failed to disable scan during stop
\n
"
);
...
...
@@ -3415,7 +3473,7 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar)
struct
ath6kl_vif
*
vif
;
vif
=
ath6kl_vif_first
(
ar
);
if
(
!
vif
)
{
if
(
!
vif
&&
ar
->
state
!=
ATH6KL_STATE_RECOVERY
)
{
/* save the current power mode before enabling power save */
ar
->
wmi
->
saved_pwr_mode
=
ar
->
wmi
->
pwr_mode
;
...
...
@@ -3433,6 +3491,56 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar)
ath6kl_cfg80211_stop
(
vif
);
}
static
int
ath6kl_cfg80211_reg_notify
(
struct
wiphy
*
wiphy
,
struct
regulatory_request
*
request
)
{
struct
ath6kl
*
ar
=
wiphy_priv
(
wiphy
);
u32
rates
[
IEEE80211_NUM_BANDS
];
int
ret
,
i
;
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"cfg reg_notify %c%c%s%s initiator %d hint_type %d
\n
"
,
request
->
alpha2
[
0
],
request
->
alpha2
[
1
],
request
->
intersect
?
" intersect"
:
""
,
request
->
processed
?
" processed"
:
""
,
request
->
initiator
,
request
->
user_reg_hint_type
);
/*
* As firmware is not able intersect regdoms, we can only listen to
* cellular hints.
*/
if
(
request
->
user_reg_hint_type
!=
NL80211_USER_REG_HINT_CELL_BASE
)
return
-
EOPNOTSUPP
;
ret
=
ath6kl_wmi_set_regdomain_cmd
(
ar
->
wmi
,
request
->
alpha2
);
if
(
ret
)
{
ath6kl_err
(
"failed to set regdomain: %d
\n
"
,
ret
);
return
ret
;
}
/*
* Firmware will apply the regdomain change only after a scan is
* issued and it will send a WMI_REGDOMAIN_EVENTID when it has been
* changed.
*/
for
(
i
=
0
;
i
<
IEEE80211_NUM_BANDS
;
i
++
)
if
(
wiphy
->
bands
[
i
])
rates
[
i
]
=
(
1
<<
wiphy
->
bands
[
i
]
->
n_bitrates
)
-
1
;
ret
=
ath6kl_wmi_beginscan_cmd
(
ar
->
wmi
,
0
,
WMI_LONG_SCAN
,
false
,
false
,
0
,
ATH6KL_FG_SCAN_INTERVAL
,
0
,
NULL
,
false
,
rates
);
if
(
ret
)
{
ath6kl_err
(
"failed to start scan for a regdomain change: %d
\n
"
,
ret
);
return
ret
;
}
return
0
;
}
static
int
ath6kl_cfg80211_vif_init
(
struct
ath6kl_vif
*
vif
)
{
vif
->
aggr_cntxt
=
aggr_init
(
vif
);
...
...
@@ -3505,9 +3613,13 @@ struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name,
vif
->
htcap
[
IEEE80211_BAND_5GHZ
].
ht_enable
=
true
;
memcpy
(
ndev
->
dev_addr
,
ar
->
mac_addr
,
ETH_ALEN
);
if
(
fw_vif_idx
!=
0
)
if
(
fw_vif_idx
!=
0
)
{
ndev
->
dev_addr
[
0
]
=
(
ndev
->
dev_addr
[
0
]
^
(
1
<<
fw_vif_idx
))
|
0x2
;
if
(
test_bit
(
ATH6KL_FW_CAPABILITY_CUSTOM_MAC_ADDR
,
ar
->
fw_capabilities
))
ndev
->
dev_addr
[
4
]
^=
0x80
;
}
init_netdev
(
ndev
);
...
...
@@ -3561,6 +3673,12 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
BIT
(
NL80211_IFTYPE_P2P_CLIENT
);
}
if
(
config_enabled
(
CONFIG_ATH6KL_REGDOMAIN
)
&&
test_bit
(
ATH6KL_FW_CAPABILITY_REGDOMAIN
,
ar
->
fw_capabilities
))
{
wiphy
->
reg_notifier
=
ath6kl_cfg80211_reg_notify
;
ar
->
wiphy
->
features
|=
NL80211_FEATURE_CELL_BASE_REG_HINTS
;
}
/* max num of ssids that can be probed during scanning */
wiphy
->
max_scan_ssids
=
MAX_PROBED_SSIDS
;
...
...
@@ -3606,7 +3724,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
ath6kl_band_5ghz
.
ht_cap
.
ht_supported
=
false
;
}
if
(
ar
->
hw
.
flags
&
ATH6KL_HW_
FLAG_
64BIT_RATES
)
{
if
(
ar
->
hw
.
flags
&
ATH6KL_HW_64BIT_RATES
)
{
ath6kl_band_2ghz
.
ht_cap
.
mcs
.
rx_mask
[
0
]
=
0xff
;
ath6kl_band_5ghz
.
ht_cap
.
mcs
.
rx_mask
[
0
]
=
0xff
;
ath6kl_band_2ghz
.
ht_cap
.
mcs
.
rx_mask
[
1
]
=
0xff
;
...
...
@@ -3645,7 +3763,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
|
WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
;
if
(
test_bit
(
ATH6KL_FW_CAPABILITY_SCHED_SCAN
,
ar
->
fw_capabilities
))
if
(
test_bit
(
ATH6KL_FW_CAPABILITY_SCHED_SCAN
_V2
,
ar
->
fw_capabilities
))
ar
->
wiphy
->
flags
|=
WIPHY_FLAG_SUPPORTS_SCHED_SCAN
;
if
(
test_bit
(
ATH6KL_FW_CAPABILITY_INACTIVITY_TIMEOUT
,
...
...
drivers/net/wireless/ath/ath6kl/cfg80211.h
View file @
1e5023c7
...
...
@@ -22,7 +22,6 @@ enum ath6kl_cfg_suspend_mode {
ATH6KL_CFG_SUSPEND_DEEPSLEEP
,
ATH6KL_CFG_SUSPEND_CUTPOWER
,
ATH6KL_CFG_SUSPEND_WOW
,
ATH6KL_CFG_SUSPEND_SCHED_SCAN
,
};
struct
wireless_dev
*
ath6kl_interface_add
(
struct
ath6kl
*
ar
,
const
char
*
name
,
...
...
drivers/net/wireless/ath/ath6kl/core.c
View file @
1e5023c7
...
...
@@ -33,6 +33,8 @@ static unsigned int wow_mode;
static
unsigned
int
uart_debug
;
static
unsigned
int
ath6kl_p2p
;
static
unsigned
int
testmode
;
static
unsigned
int
recovery_enable
;
static
unsigned
int
heart_beat_poll
;
module_param
(
debug_mask
,
uint
,
0644
);
module_param
(
suspend_mode
,
uint
,
0644
);
...
...
@@ -40,6 +42,12 @@ module_param(wow_mode, uint, 0644);
module_param
(
uart_debug
,
uint
,
0644
);
module_param
(
ath6kl_p2p
,
uint
,
0644
);
module_param
(
testmode
,
uint
,
0644
);
module_param
(
recovery_enable
,
uint
,
0644
);
module_param
(
heart_beat_poll
,
uint
,
0644
);
MODULE_PARM_DESC
(
recovery_enable
,
"Enable recovery from firmware error"
);
MODULE_PARM_DESC
(
heart_beat_poll
,
"Enable fw error detection periodic"
\
"polling. This also specifies the polling interval in"
\
"msecs. Set reocvery_enable for this to be effective"
);
void
ath6kl_core_tx_complete
(
struct
ath6kl
*
ar
,
struct
sk_buff
*
skb
)
{
...
...
@@ -202,6 +210,17 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type)
ath6kl_dbg
(
ATH6KL_DBG_TRC
,
"%s: name=%s dev=0x%p, ar=0x%p
\n
"
,
__func__
,
wdev
->
netdev
->
name
,
wdev
->
netdev
,
ar
);
ar
->
fw_recovery
.
enable
=
!!
recovery_enable
;
if
(
!
ar
->
fw_recovery
.
enable
)
return
ret
;
if
(
heart_beat_poll
&&
test_bit
(
ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL
,
ar
->
fw_capabilities
))
ar
->
fw_recovery
.
hb_poll
=
heart_beat_poll
;
ath6kl_recovery_init
(
ar
);
return
ret
;
err_rxbuf_cleanup:
...
...
@@ -291,6 +310,8 @@ void ath6kl_core_cleanup(struct ath6kl *ar)
{
ath6kl_hif_power_off
(
ar
);
ath6kl_recovery_cleanup
(
ar
);
destroy_workqueue
(
ar
->
ath6kl_wq
);
if
(
ar
->
htc_target
)
...
...
drivers/net/wireless/ath/ath6kl/core.h
View file @
1e5023c7
...
...
@@ -115,6 +115,27 @@ enum ath6kl_fw_capability {
*/
ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST
,
/* Firmware supports filtering BSS results by RSSI */
ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD
,
/* FW sets mac_addr[4] ^= 0x80 for newly created interfaces */
ATH6KL_FW_CAPABILITY_CUSTOM_MAC_ADDR
,
/* Firmware supports TX error rate notification */
ATH6KL_FW_CAPABILITY_TX_ERR_NOTIFY
,
/* supports WMI_SET_REGDOMAIN_CMDID command */
ATH6KL_FW_CAPABILITY_REGDOMAIN
,
/* Firmware supports sched scan decoupled from host sleep */
ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2
,
/*
* Firmware capability for hang detection through heart beat
* challenge messages.
*/
ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL
,
/* this needs to be last */
ATH6KL_FW_CAPABILITY_MAX
,
};
...
...
@@ -128,11 +149,15 @@ struct ath6kl_fw_ie {
};
enum
ath6kl_hw_flags
{
ATH6KL_HW_FLAG_64BIT_RATES
=
BIT
(
0
),
ATH6KL_HW_64BIT_RATES
=
BIT
(
0
),
ATH6KL_HW_AP_INACTIVITY_MINS
=
BIT
(
1
),
ATH6KL_HW_MAP_LP_ENDPOINT
=
BIT
(
2
),
ATH6KL_HW_SDIO_CRC_ERROR_WAR
=
BIT
(
3
),
};
#define ATH6KL_FW_API2_FILE "fw-2.bin"
#define ATH6KL_FW_API3_FILE "fw-3.bin"
#define ATH6KL_FW_API4_FILE "fw-4.bin"
/* AR6003 1.0 definitions */
#define AR6003_HW_1_0_VERSION 0x300002ba
...
...
@@ -186,6 +211,13 @@ enum ath6kl_hw_flags {
#define AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE \
AR6004_HW_1_2_FW_DIR "/bdata.bin"
/* AR6004 1.3 definitions */
#define AR6004_HW_1_3_VERSION 0x31c8088a
#define AR6004_HW_1_3_FW_DIR "ath6k/AR6004/hw1.3"
#define AR6004_HW_1_3_FIRMWARE_FILE "fw.ram.bin"
#define AR6004_HW_1_3_BOARD_DATA_FILE "ath6k/AR6004/hw1.3/bdata.bin"
#define AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE "ath6k/AR6004/hw1.3/bdata.bin"
/* Per STA data, used in AP mode */
#define STA_PS_AWAKE BIT(0)
#define STA_PS_SLEEP BIT(1)
...
...
@@ -536,6 +568,7 @@ enum ath6kl_vif_state {
HOST_SLEEP_MODE_CMD_PROCESSED
,
NETDEV_MCAST_ALL_ON
,
NETDEV_MCAST_ALL_OFF
,
SCHED_SCANNING
,
};
struct
ath6kl_vif
{
...
...
@@ -580,11 +613,13 @@ struct ath6kl_vif {
u16
assoc_bss_beacon_int
;
u16
listen_intvl_t
;
u16
bmiss_time_t
;
u32
txe_intvl
;
u16
bg_scan_period
;
u8
assoc_bss_dtim_period
;
struct
net_device_stats
net_stats
;
struct
target_stats
target_stats
;
struct
wmi_connect_cmd
profile
;
u16
rsn_capab
;
struct
list_head
mc_filter
;
};
...
...
@@ -609,6 +644,7 @@ enum ath6kl_dev_state {
SKIP_SCAN
,
ROAM_TBL_PEND
,
FIRST_BOOT
,
RECOVERY_CLEANUP
,
};
enum
ath6kl_state
{
...
...
@@ -619,7 +655,16 @@ enum ath6kl_state {
ATH6KL_STATE_DEEPSLEEP
,
ATH6KL_STATE_CUTPOWER
,
ATH6KL_STATE_WOW
,
ATH6KL_STATE_SCHED_SCAN
,
ATH6KL_STATE_RECOVERY
,
};
/* Fw error recovery */
#define ATH6KL_HB_RESP_MISS_THRES 5
enum
ath6kl_fw_err
{
ATH6KL_FW_ASSERT
,
ATH6KL_FW_HB_RESP_FAILURE
,
ATH6KL_FW_EP_FULL
,
};
struct
ath6kl
{
...
...
@@ -679,6 +724,7 @@ struct ath6kl {
struct
ath6kl_req_key
ap_mode_bkey
;
struct
sk_buff_head
mcastpsq
;
u32
want_ch_switch
;
u16
last_ch
;
/*
* FIXME: protects access to mcastpsq but is actually useless as
...
...
@@ -764,6 +810,17 @@ struct ath6kl {
bool
wiphy_registered
;
struct
ath6kl_fw_recovery
{
struct
work_struct
recovery_work
;
unsigned
long
err_reason
;
unsigned
long
hb_poll
;
struct
timer_list
hb_timer
;
u32
seq_num
;
bool
hb_pending
;
u8
hb_misscnt
;
bool
enable
;
}
fw_recovery
;
#ifdef CONFIG_ATH6KL_DEBUG
struct
{
struct
sk_buff_head
fwlog_queue
;
...
...
@@ -899,4 +956,12 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type);
void
ath6kl_core_cleanup
(
struct
ath6kl
*
ar
);
void
ath6kl_core_destroy
(
struct
ath6kl
*
ar
);
/* Fw error recovery */
void
ath6kl_init_hw_restart
(
struct
ath6kl
*
ar
);
void
ath6kl_recovery_err_notify
(
struct
ath6kl
*
ar
,
enum
ath6kl_fw_err
reason
);
void
ath6kl_recovery_hb_event
(
struct
ath6kl
*
ar
,
u32
cookie
);
void
ath6kl_recovery_init
(
struct
ath6kl
*
ar
);
void
ath6kl_recovery_cleanup
(
struct
ath6kl
*
ar
);
void
ath6kl_recovery_suspend
(
struct
ath6kl
*
ar
);
void
ath6kl_recovery_resume
(
struct
ath6kl
*
ar
);
#endif
/* CORE_H */
drivers/net/wireless/ath/ath6kl/debug.h
View file @
1e5023c7
...
...
@@ -44,6 +44,7 @@ enum ATH6K_DEBUG_MASK {
ATH6KL_DBG_SUSPEND
=
BIT
(
20
),
ATH6KL_DBG_USB
=
BIT
(
21
),
ATH6KL_DBG_USB_BULK
=
BIT
(
22
),
ATH6KL_DBG_RECOVERY
=
BIT
(
23
),
ATH6KL_DBG_ANY
=
0xffffffff
/* enable all logs */
};
...
...
drivers/net/wireless/ath/ath6kl/hif.c
View file @
1e5023c7
...
...
@@ -136,6 +136,7 @@ static int ath6kl_hif_proc_dbg_intr(struct ath6kl_device *dev)
ath6kl_hif_dump_fw_crash
(
dev
->
ar
);
ath6kl_read_fwlogs
(
dev
->
ar
);
ath6kl_recovery_err_notify
(
dev
->
ar
,
ATH6KL_FW_ASSERT
);
return
ret
;
}
...
...
@@ -693,11 +694,6 @@ int ath6kl_hif_setup(struct ath6kl_device *dev)
ath6kl_dbg
(
ATH6KL_DBG_HIF
,
"hif block size %d mbox addr 0x%x
\n
"
,
dev
->
htc_cnxt
->
block_sz
,
dev
->
ar
->
mbox_info
.
htc_addr
);
/* usb doesn't support enabling interrupts */
/* FIXME: remove check once USB support is implemented */
if
(
dev
->
ar
->
hif_type
==
ATH6KL_HIF_TYPE_USB
)
return
0
;
status
=
ath6kl_hif_disable_intrs
(
dev
);
fail_setup:
...
...
drivers/net/wireless/ath/ath6kl/htc_mbox.c
View file @
1e5023c7
...
...
@@ -2492,7 +2492,8 @@ static int ath6kl_htc_mbox_conn_service(struct htc_target *target,
max_msg_sz
=
le16_to_cpu
(
resp_msg
->
max_msg_sz
);
}
if
(
assigned_ep
>=
ENDPOINT_MAX
||
!
max_msg_sz
)
{
if
(
WARN_ON_ONCE
(
assigned_ep
==
ENDPOINT_UNUSED
||
assigned_ep
>=
ENDPOINT_MAX
||
!
max_msg_sz
))
{
status
=
-
ENOMEM
;
goto
fail_tx
;
}
...
...
@@ -2655,12 +2656,6 @@ static int ath6kl_htc_mbox_wait_target(struct htc_target *target)
struct
htc_service_connect_resp
resp
;
int
status
;
/* FIXME: remove once USB support is implemented */
if
(
target
->
dev
->
ar
->
hif_type
==
ATH6KL_HIF_TYPE_USB
)
{
ath6kl_err
(
"HTC doesn't support USB yet. Patience!
\n
"
);
return
-
EOPNOTSUPP
;
}
/* we should be getting 1 control message that the target is ready */
packet
=
htc_wait_for_ctrl_msg
(
target
);
...
...
@@ -2890,9 +2885,7 @@ static void ath6kl_htc_mbox_cleanup(struct htc_target *target)
{
struct
htc_packet
*
packet
,
*
tmp_packet
;
/* FIXME: remove check once USB support is implemented */
if
(
target
->
dev
->
ar
->
hif_type
!=
ATH6KL_HIF_TYPE_USB
)
ath6kl_hif_cleanup_scatter
(
target
->
dev
->
ar
);
ath6kl_hif_cleanup_scatter
(
target
->
dev
->
ar
);
list_for_each_entry_safe
(
packet
,
tmp_packet
,
&
target
->
free_ctrl_txbuf
,
list
)
{
...
...
drivers/net/wireless/ath/ath6kl/htc_pipe.c
View file @
1e5023c7
...
...
@@ -374,9 +374,8 @@ static enum htc_send_queue_result htc_try_send(struct htc_target *target,
packet
=
list_first_entry
(
txq
,
struct
htc_packet
,
list
);
list_del
(
&
packet
->
list
);
/* insert into local queue */
list_add_tail
(
&
packet
->
list
,
&
send_queue
);
/* move to local queue */
list_move_tail
(
&
packet
->
list
,
&
send_queue
);
}
/*
...
...
@@ -399,11 +398,10 @@ static enum htc_send_queue_result htc_try_send(struct htc_target *target,
* for cleanup */
}
else
{
/* callback wants to keep this packet,
* remove from caller's queue */
list_del
(
&
packet
->
list
);
/* put it in the send queue */
list_add_tail
(
&
packet
->
list
,
&
send_queue
);
* move from caller's queue to the send
* queue */
list_move_tail
(
&
packet
->
list
,
&
send_queue
);
}
}
...
...
drivers/net/wireless/ath/ath6kl/init.c
View file @
1e5023c7
...
...
@@ -42,7 +42,7 @@ static const struct ath6kl_hw hw_list[] = {
.
reserved_ram_size
=
6912
,
.
refclk_hz
=
26000000
,
.
uarttx_pin
=
8
,
.
flags
=
0
,
.
flags
=
ATH6KL_HW_SDIO_CRC_ERROR_WAR
,
/* hw2.0 needs override address hardcoded */
.
app_start_override_addr
=
0x944C00
,
...
...
@@ -68,7 +68,7 @@ static const struct ath6kl_hw hw_list[] = {
.
refclk_hz
=
26000000
,
.
uarttx_pin
=
8
,
.
testscript_addr
=
0x57ef74
,
.
flags
=
0
,
.
flags
=
ATH6KL_HW_SDIO_CRC_ERROR_WAR
,
.
fw
=
{
.
dir
=
AR6003_HW_2_1_1_FW_DIR
,
...
...
@@ -93,7 +93,8 @@ static const struct ath6kl_hw hw_list[] = {
.
board_addr
=
0x433900
,
.
refclk_hz
=
26000000
,
.
uarttx_pin
=
11
,
.
flags
=
ATH6KL_HW_FLAG_64BIT_RATES
,
.
flags
=
ATH6KL_HW_64BIT_RATES
|
ATH6KL_HW_AP_INACTIVITY_MINS
,
.
fw
=
{
.
dir
=
AR6004_HW_1_0_FW_DIR
,
...
...
@@ -113,8 +114,8 @@ static const struct ath6kl_hw hw_list[] = {
.
board_addr
=
0x43d400
,
.
refclk_hz
=
40000000
,
.
uarttx_pin
=
11
,
.
flags
=
ATH6KL_HW_
FLAG_64BIT_RATES
,
.
flags
=
ATH6KL_HW_
64BIT_RATES
|
ATH6KL_HW_AP_INACTIVITY_MINS
,
.
fw
=
{
.
dir
=
AR6004_HW_1_1_FW_DIR
,
.
fw
=
AR6004_HW_1_1_FIRMWARE_FILE
,
...
...
@@ -133,7 +134,8 @@ static const struct ath6kl_hw hw_list[] = {
.
board_addr
=
0x435c00
,
.
refclk_hz
=
40000000
,
.
uarttx_pin
=
11
,
.
flags
=
ATH6KL_HW_FLAG_64BIT_RATES
,
.
flags
=
ATH6KL_HW_64BIT_RATES
|
ATH6KL_HW_AP_INACTIVITY_MINS
,
.
fw
=
{
.
dir
=
AR6004_HW_1_2_FW_DIR
,
...
...
@@ -142,6 +144,28 @@ static const struct ath6kl_hw hw_list[] = {
.
fw_board
=
AR6004_HW_1_2_BOARD_DATA_FILE
,
.
fw_default_board
=
AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE
,
},
{
.
id
=
AR6004_HW_1_3_VERSION
,
.
name
=
"ar6004 hw 1.3"
,
.
dataset_patch_addr
=
0x437860
,
.
app_load_addr
=
0x1234
,
.
board_ext_data_addr
=
0x437000
,
.
reserved_ram_size
=
7168
,
.
board_addr
=
0x436400
,
.
refclk_hz
=
40000000
,
.
uarttx_pin
=
11
,
.
flags
=
ATH6KL_HW_64BIT_RATES
|
ATH6KL_HW_AP_INACTIVITY_MINS
|
ATH6KL_HW_MAP_LP_ENDPOINT
,
.
fw
=
{
.
dir
=
AR6004_HW_1_3_FW_DIR
,
.
fw
=
AR6004_HW_1_3_FIRMWARE_FILE
,
},
.
fw_board
=
AR6004_HW_1_3_BOARD_DATA_FILE
,
.
fw_default_board
=
AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE
,
},
};
/*
...
...
@@ -337,7 +361,7 @@ static int ath6kl_init_service_ep(struct ath6kl *ar)
if
(
ath6kl_connectservice
(
ar
,
&
connect
,
"WMI DATA BK"
))
return
-
EIO
;
/* connect to Video service, map this to
to
HI PRI */
/* connect to Video service, map this to HI PRI */
connect
.
svc_id
=
WMI_DATA_VI_SVC
;
if
(
ath6kl_connectservice
(
ar
,
&
connect
,
"WMI DATA VI"
))
return
-
EIO
;
...
...
@@ -1088,6 +1112,12 @@ int ath6kl_init_fetch_firmwares(struct ath6kl *ar)
if
(
ret
)
return
ret
;
ret
=
ath6kl_fetch_fw_apin
(
ar
,
ATH6KL_FW_API4_FILE
);
if
(
ret
==
0
)
{
ar
->
fw_api
=
4
;
goto
out
;
}
ret
=
ath6kl_fetch_fw_apin
(
ar
,
ATH6KL_FW_API3_FILE
);
if
(
ret
==
0
)
{
ar
->
fw_api
=
3
;
...
...
@@ -1401,8 +1431,7 @@ static int ath6kl_init_upload(struct ath6kl *ar)
return
status
;
/* WAR to avoid SDIO CRC err */
if
(
ar
->
version
.
target_ver
==
AR6003_HW_2_0_VERSION
||
ar
->
version
.
target_ver
==
AR6003_HW_2_1_1_VERSION
)
{
if
(
ar
->
hw
.
flags
&
ATH6KL_HW_SDIO_CRC_ERROR_WAR
)
{
ath6kl_err
(
"temporary war to avoid sdio crc error
\n
"
);
param
=
0x28
;
...
...
@@ -1520,7 +1549,7 @@ static const char *ath6kl_init_get_hif_name(enum ath6kl_hif_type type)
return
NULL
;
}
int
ath6kl_init_hw_start
(
struct
ath6kl
*
ar
)
static
int
__
ath6kl_init_hw_start
(
struct
ath6kl
*
ar
)
{
long
timeleft
;
int
ret
,
i
;
...
...
@@ -1616,8 +1645,6 @@ int ath6kl_init_hw_start(struct ath6kl *ar)
goto
err_htc_stop
;
}
ar
->
state
=
ATH6KL_STATE_ON
;
return
0
;
err_htc_stop:
...
...
@@ -1630,7 +1657,18 @@ int ath6kl_init_hw_start(struct ath6kl *ar)
return
ret
;
}
int
ath6kl_init_hw_stop
(
struct
ath6kl
*
ar
)
int
ath6kl_init_hw_start
(
struct
ath6kl
*
ar
)
{
int
err
;
err
=
__ath6kl_init_hw_start
(
ar
);
if
(
err
)
return
err
;
ar
->
state
=
ATH6KL_STATE_ON
;
return
0
;
}
static
int
__ath6kl_init_hw_stop
(
struct
ath6kl
*
ar
)
{
int
ret
;
...
...
@@ -1646,11 +1684,37 @@ int ath6kl_init_hw_stop(struct ath6kl *ar)
if
(
ret
)
ath6kl_warn
(
"failed to power off hif: %d
\n
"
,
ret
);
ar
->
state
=
ATH6KL_STATE_OFF
;
return
0
;
}
int
ath6kl_init_hw_stop
(
struct
ath6kl
*
ar
)
{
int
err
;
err
=
__ath6kl_init_hw_stop
(
ar
);
if
(
err
)
return
err
;
ar
->
state
=
ATH6KL_STATE_OFF
;
return
0
;
}
void
ath6kl_init_hw_restart
(
struct
ath6kl
*
ar
)
{
clear_bit
(
WMI_READY
,
&
ar
->
flag
);
ath6kl_cfg80211_stop_all
(
ar
);
if
(
__ath6kl_init_hw_stop
(
ar
))
{
ath6kl_dbg
(
ATH6KL_DBG_RECOVERY
,
"Failed to stop during fw error recovery
\n
"
);
return
;
}
if
(
__ath6kl_init_hw_start
(
ar
))
{
ath6kl_dbg
(
ATH6KL_DBG_RECOVERY
,
"Failed to restart during fw error recovery
\n
"
);
return
;
}
}
/* FIXME: move this to cfg80211.c and rename to ath6kl_cfg80211_vif_stop() */
void
ath6kl_cleanup_vif
(
struct
ath6kl_vif
*
vif
,
bool
wmi_ready
)
{
...
...
drivers/net/wireless/ath/ath6kl/main.c
View file @
1e5023c7
...
...
@@ -293,13 +293,17 @@ int ath6kl_read_fwlogs(struct ath6kl *ar)
}
address
=
TARG_VTOP
(
ar
->
target_type
,
debug_hdr_addr
);
ath6kl_diag_read
(
ar
,
address
,
&
debug_hdr
,
sizeof
(
debug_hdr
));
ret
=
ath6kl_diag_read
(
ar
,
address
,
&
debug_hdr
,
sizeof
(
debug_hdr
));
if
(
ret
)
goto
out
;
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
));
ret
=
ath6kl_diag_read
(
ar
,
address
,
&
debug_buf
,
sizeof
(
debug_buf
));
if
(
ret
)
goto
out
;
loop
=
100
;
...
...
@@ -322,7 +326,8 @@ int ath6kl_read_fwlogs(struct ath6kl *ar)
address
=
TARG_VTOP
(
ar
->
target_type
,
le32_to_cpu
(
debug_buf
.
next
));
ath6kl_diag_read
(
ar
,
address
,
&
debug_buf
,
sizeof
(
debug_buf
));
ret
=
ath6kl_diag_read
(
ar
,
address
,
&
debug_buf
,
sizeof
(
debug_buf
));
if
(
ret
)
goto
out
;
...
...
@@ -436,12 +441,9 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel)
break
;
}
if
(
ar
->
want_ch_switch
&
(
1
<<
vif
->
fw_vif_idx
))
{
ar
->
want_ch_switch
&=
~
(
1
<<
vif
->
fw_vif_idx
);
if
(
ar
->
last_ch
!=
channel
)
/* we actually don't know the phymode, default to HT20 */
ath6kl_cfg80211_ch_switch_notify
(
vif
,
channel
,
WMI_11G_HT20
);
}
ath6kl_cfg80211_ch_switch_notify
(
vif
,
channel
,
WMI_11G_HT20
);
ath6kl_wmi_bssfilter_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
NONE_BSS_FILTER
,
0
);
set_bit
(
CONNECTED
,
&
vif
->
flags
);
...
...
@@ -606,6 +608,18 @@ static int ath6kl_commit_ch_switch(struct ath6kl_vif *vif, u16 channel)
switch
(
vif
->
nw_type
)
{
case
AP_NETWORK
:
/*
* reconfigure any saved RSN IE capabilites in the beacon /
* probe response to stay in sync with the supplicant.
*/
if
(
vif
->
rsn_capab
&&
test_bit
(
ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE
,
ar
->
fw_capabilities
))
ath6kl_wmi_set_ie_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
WLAN_EID_RSN
,
WMI_RSN_IE_CAPB
,
(
const
u8
*
)
&
vif
->
rsn_capab
,
sizeof
(
vif
->
rsn_capab
));
return
ath6kl_wmi_ap_profile_commit
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
&
vif
->
profile
);
default:
...
...
@@ -628,6 +642,9 @@ static void ath6kl_check_ch_switch(struct ath6kl *ar, u16 channel)
if
(
ar
->
want_ch_switch
&
(
1
<<
vif
->
fw_vif_idx
))
res
=
ath6kl_commit_ch_switch
(
vif
,
channel
);
/* if channel switch failed, oh well we tried */
ar
->
want_ch_switch
&=
~
(
1
<<
vif
->
fw_vif_idx
);
if
(
res
)
ath6kl_err
(
"channel switch failed nw_type %d res %d
\n
"
,
vif
->
nw_type
,
res
);
...
...
@@ -981,8 +998,25 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid,
if
(
vif
->
nw_type
==
AP_NETWORK
)
{
/* disconnect due to other STA vif switching channels */
if
(
reason
==
BSS_DISCONNECTED
&&
prot_reason_status
==
WMI_AP_REASON_STA_ROAM
)
prot_reason_status
==
WMI_AP_REASON_STA_ROAM
)
{
ar
->
want_ch_switch
|=
1
<<
vif
->
fw_vif_idx
;
/* bail back to this channel if STA vif fails connect */
ar
->
last_ch
=
le16_to_cpu
(
vif
->
profile
.
ch
);
}
if
(
prot_reason_status
==
WMI_AP_REASON_MAX_STA
)
{
/* send max client reached notification to user space */
cfg80211_conn_failed
(
vif
->
ndev
,
bssid
,
NL80211_CONN_FAIL_MAX_CLIENTS
,
GFP_KERNEL
);
}
if
(
prot_reason_status
==
WMI_AP_REASON_ACL
)
{
/* send blocked client notification to user space */
cfg80211_conn_failed
(
vif
->
ndev
,
bssid
,
NL80211_CONN_FAIL_BLOCKED_CLIENT
,
GFP_KERNEL
);
}
if
(
!
ath6kl_remove_sta
(
ar
,
bssid
,
prot_reason_status
))
return
;
...
...
@@ -1041,6 +1075,9 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid,
}
}
/* restart disconnected concurrent vifs waiting for new channel */
ath6kl_check_ch_switch
(
ar
,
ar
->
last_ch
);
/* update connect & link status atomically */
spin_lock_bh
(
&
vif
->
if_lock
);
clear_bit
(
CONNECTED
,
&
vif
->
flags
);
...
...
drivers/net/wireless/ath/ath6kl/recovery.c
0 → 100644
View file @
1e5023c7
/*
* Copyright (c) 2012 Qualcomm Atheros, 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"
#include "cfg80211.h"
#include "debug.h"
static
void
ath6kl_recovery_work
(
struct
work_struct
*
work
)
{
struct
ath6kl
*
ar
=
container_of
(
work
,
struct
ath6kl
,
fw_recovery
.
recovery_work
);
ar
->
state
=
ATH6KL_STATE_RECOVERY
;
del_timer_sync
(
&
ar
->
fw_recovery
.
hb_timer
);
ath6kl_init_hw_restart
(
ar
);
ar
->
state
=
ATH6KL_STATE_ON
;
clear_bit
(
WMI_CTRL_EP_FULL
,
&
ar
->
flag
);
ar
->
fw_recovery
.
err_reason
=
0
;
if
(
ar
->
fw_recovery
.
hb_poll
)
mod_timer
(
&
ar
->
fw_recovery
.
hb_timer
,
jiffies
+
msecs_to_jiffies
(
ar
->
fw_recovery
.
hb_poll
));
}
void
ath6kl_recovery_err_notify
(
struct
ath6kl
*
ar
,
enum
ath6kl_fw_err
reason
)
{
if
(
!
ar
->
fw_recovery
.
enable
)
return
;
ath6kl_dbg
(
ATH6KL_DBG_RECOVERY
,
"Fw error detected, reason:%d
\n
"
,
reason
);
set_bit
(
reason
,
&
ar
->
fw_recovery
.
err_reason
);
if
(
!
test_bit
(
RECOVERY_CLEANUP
,
&
ar
->
flag
)
&&
ar
->
state
!=
ATH6KL_STATE_RECOVERY
)
queue_work
(
ar
->
ath6kl_wq
,
&
ar
->
fw_recovery
.
recovery_work
);
}
void
ath6kl_recovery_hb_event
(
struct
ath6kl
*
ar
,
u32
cookie
)
{
if
(
cookie
==
ar
->
fw_recovery
.
seq_num
)
ar
->
fw_recovery
.
hb_pending
=
false
;
}
static
void
ath6kl_recovery_hb_timer
(
unsigned
long
data
)
{
struct
ath6kl
*
ar
=
(
struct
ath6kl
*
)
data
;
int
err
;
if
(
test_bit
(
RECOVERY_CLEANUP
,
&
ar
->
flag
)
||
(
ar
->
state
==
ATH6KL_STATE_RECOVERY
))
return
;
if
(
ar
->
fw_recovery
.
hb_pending
)
ar
->
fw_recovery
.
hb_misscnt
++
;
else
ar
->
fw_recovery
.
hb_misscnt
=
0
;
if
(
ar
->
fw_recovery
.
hb_misscnt
>
ATH6KL_HB_RESP_MISS_THRES
)
{
ar
->
fw_recovery
.
hb_misscnt
=
0
;
ar
->
fw_recovery
.
seq_num
=
0
;
ar
->
fw_recovery
.
hb_pending
=
false
;
ath6kl_recovery_err_notify
(
ar
,
ATH6KL_FW_HB_RESP_FAILURE
);
return
;
}
ar
->
fw_recovery
.
seq_num
++
;
ar
->
fw_recovery
.
hb_pending
=
true
;
err
=
ath6kl_wmi_get_challenge_resp_cmd
(
ar
->
wmi
,
ar
->
fw_recovery
.
seq_num
,
0
);
if
(
err
)
ath6kl_warn
(
"Failed to send hb challenge request, err:%d
\n
"
,
err
);
mod_timer
(
&
ar
->
fw_recovery
.
hb_timer
,
jiffies
+
msecs_to_jiffies
(
ar
->
fw_recovery
.
hb_poll
));
}
void
ath6kl_recovery_init
(
struct
ath6kl
*
ar
)
{
struct
ath6kl_fw_recovery
*
recovery
=
&
ar
->
fw_recovery
;
clear_bit
(
RECOVERY_CLEANUP
,
&
ar
->
flag
);
INIT_WORK
(
&
recovery
->
recovery_work
,
ath6kl_recovery_work
);
recovery
->
seq_num
=
0
;
recovery
->
hb_misscnt
=
0
;
ar
->
fw_recovery
.
hb_pending
=
false
;
ar
->
fw_recovery
.
hb_timer
.
function
=
ath6kl_recovery_hb_timer
;
ar
->
fw_recovery
.
hb_timer
.
data
=
(
unsigned
long
)
ar
;
init_timer_deferrable
(
&
ar
->
fw_recovery
.
hb_timer
);
if
(
ar
->
fw_recovery
.
hb_poll
)
mod_timer
(
&
ar
->
fw_recovery
.
hb_timer
,
jiffies
+
msecs_to_jiffies
(
ar
->
fw_recovery
.
hb_poll
));
}
void
ath6kl_recovery_cleanup
(
struct
ath6kl
*
ar
)
{
if
(
!
ar
->
fw_recovery
.
enable
)
return
;
set_bit
(
RECOVERY_CLEANUP
,
&
ar
->
flag
);
del_timer_sync
(
&
ar
->
fw_recovery
.
hb_timer
);
cancel_work_sync
(
&
ar
->
fw_recovery
.
recovery_work
);
}
void
ath6kl_recovery_suspend
(
struct
ath6kl
*
ar
)
{
if
(
!
ar
->
fw_recovery
.
enable
)
return
;
ath6kl_recovery_cleanup
(
ar
);
if
(
!
ar
->
fw_recovery
.
err_reason
)
return
;
/* Process pending fw error detection */
ar
->
fw_recovery
.
err_reason
=
0
;
WARN_ON
(
ar
->
state
!=
ATH6KL_STATE_ON
);
ar
->
state
=
ATH6KL_STATE_RECOVERY
;
ath6kl_init_hw_restart
(
ar
);
ar
->
state
=
ATH6KL_STATE_ON
;
}
void
ath6kl_recovery_resume
(
struct
ath6kl
*
ar
)
{
if
(
!
ar
->
fw_recovery
.
enable
)
return
;
clear_bit
(
RECOVERY_CLEANUP
,
&
ar
->
flag
);
if
(
!
ar
->
fw_recovery
.
hb_poll
)
return
;
ar
->
fw_recovery
.
hb_pending
=
false
;
ar
->
fw_recovery
.
seq_num
=
0
;
ar
->
fw_recovery
.
hb_misscnt
=
0
;
mod_timer
(
&
ar
->
fw_recovery
.
hb_timer
,
jiffies
+
msecs_to_jiffies
(
ar
->
fw_recovery
.
hb_poll
));
}
drivers/net/wireless/ath/ath6kl/sdio.c
View file @
1e5023c7
...
...
@@ -709,7 +709,7 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar)
{
struct
ath6kl_sdio
*
ar_sdio
=
ath6kl_sdio_priv
(
ar
);
struct
htc_target
*
target
=
ar
->
htc_target
;
int
ret
;
int
ret
=
0
;
bool
virt_scat
=
false
;
if
(
ar_sdio
->
scatter_enabled
)
...
...
@@ -844,22 +844,6 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
bool
try_deepsleep
=
false
;
int
ret
;
if
(
ar
->
state
==
ATH6KL_STATE_SCHED_SCAN
)
{
ath6kl_dbg
(
ATH6KL_DBG_SUSPEND
,
"sched scan is in progress
\n
"
);
ret
=
ath6kl_set_sdio_pm_caps
(
ar
);
if
(
ret
)
goto
cut_pwr
;
ret
=
ath6kl_cfg80211_suspend
(
ar
,
ATH6KL_CFG_SUSPEND_SCHED_SCAN
,
NULL
);
if
(
ret
)
goto
cut_pwr
;
return
0
;
}
if
(
ar
->
suspend_mode
==
WLAN_POWER_STATE_WOW
||
(
!
ar
->
suspend_mode
&&
wow
))
{
...
...
@@ -942,14 +926,14 @@ static int ath6kl_sdio_resume(struct ath6kl *ar)
case
ATH6KL_STATE_WOW
:
break
;
case
ATH6KL_STATE_SCHED_SCAN
:
break
;
case
ATH6KL_STATE_SUSPENDING
:
break
;
case
ATH6KL_STATE_RESUMING
:
break
;
case
ATH6KL_STATE_RECOVERY
:
break
;
}
ath6kl_cfg80211_resume
(
ar
);
...
...
@@ -1462,3 +1446,6 @@ MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE);
MODULE_FIRMWARE
(
AR6004_HW_1_2_FW_DIR
"/"
AR6004_HW_1_2_FIRMWARE_FILE
);
MODULE_FIRMWARE
(
AR6004_HW_1_2_BOARD_DATA_FILE
);
MODULE_FIRMWARE
(
AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE
);
MODULE_FIRMWARE
(
AR6004_HW_1_3_FW_DIR
"/"
AR6004_HW_1_3_FIRMWARE_FILE
);
MODULE_FIRMWARE
(
AR6004_HW_1_3_BOARD_DATA_FILE
);
MODULE_FIRMWARE
(
AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE
);
drivers/net/wireless/ath/ath6kl/txrx.c
View file @
1e5023c7
...
...
@@ -288,8 +288,16 @@ int ath6kl_control_tx(void *devt, struct sk_buff *skb,
int
status
=
0
;
struct
ath6kl_cookie
*
cookie
=
NULL
;
if
(
WARN_ON_ONCE
(
ar
->
state
==
ATH6KL_STATE_WOW
))
if
(
WARN_ON_ONCE
(
ar
->
state
==
ATH6KL_STATE_WOW
))
{
dev_kfree_skb
(
skb
);
return
-
EACCES
;
}
if
(
WARN_ON_ONCE
(
eid
==
ENDPOINT_UNUSED
||
eid
>=
ENDPOINT_MAX
))
{
status
=
-
EINVAL
;
goto
fail_ctrl_tx
;
}
spin_lock_bh
(
&
ar
->
lock
);
...
...
@@ -591,6 +599,7 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
*/
set_bit
(
WMI_CTRL_EP_FULL
,
&
ar
->
flag
);
ath6kl_err
(
"wmi ctrl ep is full
\n
"
);
ath6kl_recovery_err_notify
(
ar
,
ATH6KL_FW_EP_FULL
);
return
action
;
}
...
...
@@ -695,22 +704,31 @@ void ath6kl_tx_complete(struct htc_target *target,
list
);
list_del
(
&
packet
->
list
);
if
(
WARN_ON_ONCE
(
packet
->
endpoint
==
ENDPOINT_UNUSED
||
packet
->
endpoint
>=
ENDPOINT_MAX
))
continue
;
ath6kl_cookie
=
(
struct
ath6kl_cookie
*
)
packet
->
pkt_cntxt
;
if
(
!
ath6kl_cookie
)
goto
fatal
;
if
(
WARN_ON_ONCE
(
!
ath6kl_cookie
)
)
continue
;
status
=
packet
->
status
;
skb
=
ath6kl_cookie
->
skb
;
eid
=
packet
->
endpoint
;
map_no
=
ath6kl_cookie
->
map_no
;
if
(
!
skb
||
!
skb
->
data
)
goto
fatal
;
if
(
WARN_ON_ONCE
(
!
skb
||
!
skb
->
data
))
{
dev_kfree_skb
(
skb
);
ath6kl_free_cookie
(
ar
,
ath6kl_cookie
);
continue
;
}
__skb_queue_tail
(
&
skb_queue
,
skb
);
if
(
!
status
&&
(
packet
->
act_len
!=
skb
->
len
))
goto
fatal
;
if
(
WARN_ON_ONCE
(
!
status
&&
(
packet
->
act_len
!=
skb
->
len
)))
{
ath6kl_free_cookie
(
ar
,
ath6kl_cookie
);
continue
;
}
ar
->
tx_pending
[
eid
]
--
;
...
...
@@ -792,11 +810,6 @@ void ath6kl_tx_complete(struct htc_target *target,
wake_up
(
&
ar
->
event_wq
);
return
;
fatal:
WARN_ON
(
1
);
spin_unlock_bh
(
&
ar
->
lock
);
return
;
}
void
ath6kl_tx_data_cleanup
(
struct
ath6kl
*
ar
)
...
...
@@ -885,8 +898,11 @@ void ath6kl_rx_refill(struct htc_target *target, enum htc_endpoint_id endpoint)
break
;
packet
=
(
struct
htc_packet
*
)
skb
->
head
;
if
(
!
IS_ALIGNED
((
unsigned
long
)
skb
->
data
,
4
))
if
(
!
IS_ALIGNED
((
unsigned
long
)
skb
->
data
,
4
))
{
size_t
len
=
skb_headlen
(
skb
);
skb
->
data
=
PTR_ALIGN
(
skb
->
data
-
4
,
4
);
skb_set_tail_pointer
(
skb
,
len
);
}
set_htc_rxpkt_info
(
packet
,
skb
,
skb
->
data
,
ATH6KL_BUFFER_SIZE
,
endpoint
);
packet
->
skb
=
skb
;
...
...
@@ -908,8 +924,11 @@ void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count)
return
;
packet
=
(
struct
htc_packet
*
)
skb
->
head
;
if
(
!
IS_ALIGNED
((
unsigned
long
)
skb
->
data
,
4
))
if
(
!
IS_ALIGNED
((
unsigned
long
)
skb
->
data
,
4
))
{
size_t
len
=
skb_headlen
(
skb
);
skb
->
data
=
PTR_ALIGN
(
skb
->
data
-
4
,
4
);
skb_set_tail_pointer
(
skb
,
len
);
}
set_htc_rxpkt_info
(
packet
,
skb
,
skb
->
data
,
ATH6KL_AMSDU_BUFFER_SIZE
,
0
);
packet
->
skb
=
skb
;
...
...
drivers/net/wireless/ath/ath6kl/usb.c
View file @
1e5023c7
...
...
@@ -185,9 +185,10 @@ static int ath6kl_usb_alloc_pipe_resources(struct ath6kl_usb_pipe *pipe,
for
(
i
=
0
;
i
<
urb_cnt
;
i
++
)
{
urb_context
=
kzalloc
(
sizeof
(
struct
ath6kl_urb_context
),
GFP_KERNEL
);
if
(
urb_context
==
NULL
)
/* FIXME: set status to -ENOMEM */
break
;
if
(
urb_context
==
NULL
)
{
status
=
-
ENOMEM
;
goto
fail_alloc_pipe_resources
;
}
urb_context
->
pipe
=
pipe
;
...
...
@@ -204,6 +205,7 @@ static int ath6kl_usb_alloc_pipe_resources(struct ath6kl_usb_pipe *pipe,
pipe
->
logical_pipe_num
,
pipe
->
usb_pipe_handle
,
pipe
->
urb_alloc
);
fail_alloc_pipe_resources:
return
status
;
}
...
...
@@ -803,7 +805,11 @@ static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id,
*
dl_pipe
=
ATH6KL_USB_PIPE_RX_DATA
;
break
;
case
WMI_DATA_VI_SVC
:
*
ul_pipe
=
ATH6KL_USB_PIPE_TX_DATA_MP
;
if
(
ar
->
hw
.
flags
&
ATH6KL_HW_MAP_LP_ENDPOINT
)
*
ul_pipe
=
ATH6KL_USB_PIPE_TX_DATA_LP
;
else
*
ul_pipe
=
ATH6KL_USB_PIPE_TX_DATA_MP
;
/*
* Disable rxdata2 directly, it will be enabled
* if FW enable rxdata2
...
...
@@ -811,7 +817,11 @@ static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id,
*
dl_pipe
=
ATH6KL_USB_PIPE_RX_DATA
;
break
;
case
WMI_DATA_VO_SVC
:
*
ul_pipe
=
ATH6KL_USB_PIPE_TX_DATA_HP
;
if
(
ar
->
hw
.
flags
&
ATH6KL_HW_MAP_LP_ENDPOINT
)
*
ul_pipe
=
ATH6KL_USB_PIPE_TX_DATA_LP
;
else
*
ul_pipe
=
ATH6KL_USB_PIPE_TX_DATA_MP
;
/*
* Disable rxdata2 directly, it will be enabled
* if FW enable rxdata2
...
...
@@ -1196,7 +1206,14 @@ static struct usb_driver ath6kl_usb_driver = {
static
int
ath6kl_usb_init
(
void
)
{
usb_register
(
&
ath6kl_usb_driver
);
int
ret
;
ret
=
usb_register
(
&
ath6kl_usb_driver
);
if
(
ret
)
{
ath6kl_err
(
"usb registration failed: %d
\n
"
,
ret
);
return
ret
;
}
return
0
;
}
...
...
@@ -1220,3 +1237,6 @@ MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE);
MODULE_FIRMWARE
(
AR6004_HW_1_2_FIRMWARE_FILE
);
MODULE_FIRMWARE
(
AR6004_HW_1_2_BOARD_DATA_FILE
);
MODULE_FIRMWARE
(
AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE
);
MODULE_FIRMWARE
(
AR6004_HW_1_3_FW_DIR
"/"
AR6004_HW_1_3_FIRMWARE_FILE
);
MODULE_FIRMWARE
(
AR6004_HW_1_3_BOARD_DATA_FILE
);
MODULE_FIRMWARE
(
AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE
);
drivers/net/wireless/ath/ath6kl/wmi.c
View file @
1e5023c7
...
...
@@ -936,8 +936,12 @@ static void ath6kl_wmi_regdomain_event(struct wmi *wmi, u8 *datap, int len)
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
(
regpair
)
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"Regpair used: 0x%0x
\n
"
,
regpair
->
regDmnEnum
);
else
ath6kl_warn
(
"Regpair not found reg_code 0x%0x
\n
"
,
reg_code
);
}
if
(
country
&&
wmi
->
parent_dev
->
wiphy_registered
)
{
...
...
@@ -1116,7 +1120,7 @@ static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len,
* the timer would not ever fire if the scan interval is short
* enough.
*/
if
(
ar
->
state
==
ATH6KL_STATE_SCHED_SCAN
&&
if
(
test_bit
(
SCHED_SCANNING
,
&
vif
->
flags
)
&&
!
timer_pending
(
&
vif
->
sched_scan_timer
))
{
mod_timer
(
&
vif
->
sched_scan_timer
,
jiffies
+
msecs_to_jiffies
(
ATH6KL_SCHED_SCAN_RESULT_DELAY
));
...
...
@@ -1170,6 +1174,9 @@ static int ath6kl_wmi_bitrate_reply_rx(struct wmi *wmi, u8 *datap, int len)
rate
=
RATE_AUTO
;
}
else
{
index
=
reply
->
rate_index
&
0x7f
;
if
(
WARN_ON_ONCE
(
index
>
(
RATE_MCS_7_40
+
1
)))
return
-
EINVAL
;
sgi
=
(
reply
->
rate_index
&
0x80
)
?
1
:
0
;
rate
=
wmi_rate_tbl
[
index
][
sgi
];
}
...
...
@@ -1531,6 +1538,68 @@ static int ath6kl_wmi_cac_event_rx(struct wmi *wmi, u8 *datap, int len,
return
0
;
}
static
int
ath6kl_wmi_txe_notify_event_rx
(
struct
wmi
*
wmi
,
u8
*
datap
,
int
len
,
struct
ath6kl_vif
*
vif
)
{
struct
wmi_txe_notify_event
*
ev
;
u32
rate
,
pkts
;
if
(
len
<
sizeof
(
*
ev
))
return
-
EINVAL
;
if
(
vif
->
sme_state
!=
SME_CONNECTED
)
return
-
ENOTCONN
;
ev
=
(
struct
wmi_txe_notify_event
*
)
datap
;
rate
=
le32_to_cpu
(
ev
->
rate
);
pkts
=
le32_to_cpu
(
ev
->
pkts
);
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"TXE notify event: peer %pM rate %d% pkts %d intvl %ds
\n
"
,
vif
->
bssid
,
rate
,
pkts
,
vif
->
txe_intvl
);
cfg80211_cqm_txe_notify
(
vif
->
ndev
,
vif
->
bssid
,
pkts
,
rate
,
vif
->
txe_intvl
,
GFP_KERNEL
);
return
0
;
}
int
ath6kl_wmi_set_txe_notify
(
struct
wmi
*
wmi
,
u8
idx
,
u32
rate
,
u32
pkts
,
u32
intvl
)
{
struct
sk_buff
*
skb
;
struct
wmi_txe_notify_cmd
*
cmd
;
skb
=
ath6kl_wmi_get_new_buf
(
sizeof
(
*
cmd
));
if
(
!
skb
)
return
-
ENOMEM
;
cmd
=
(
struct
wmi_txe_notify_cmd
*
)
skb
->
data
;
cmd
->
rate
=
cpu_to_le32
(
rate
);
cmd
->
pkts
=
cpu_to_le32
(
pkts
);
cmd
->
intvl
=
cpu_to_le32
(
intvl
);
return
ath6kl_wmi_cmd_send
(
wmi
,
idx
,
skb
,
WMI_SET_TXE_NOTIFY_CMDID
,
NO_SYNC_WMIFLAG
);
}
int
ath6kl_wmi_set_rssi_filter_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
s8
rssi
)
{
struct
sk_buff
*
skb
;
struct
wmi_set_rssi_filter_cmd
*
cmd
;
int
ret
;
skb
=
ath6kl_wmi_get_new_buf
(
sizeof
(
*
cmd
));
if
(
!
skb
)
return
-
ENOMEM
;
cmd
=
(
struct
wmi_set_rssi_filter_cmd
*
)
skb
->
data
;
cmd
->
rssi
=
rssi
;
ret
=
ath6kl_wmi_cmd_send
(
wmi
,
if_idx
,
skb
,
WMI_SET_RSSI_FILTER_CMDID
,
NO_SYNC_WMIFLAG
);
return
ret
;
}
static
int
ath6kl_wmi_send_snr_threshold_params
(
struct
wmi
*
wmi
,
struct
wmi_snr_threshold_params_cmd
*
snr_cmd
)
{
...
...
@@ -1677,8 +1746,11 @@ int ath6kl_wmi_cmd_send(struct wmi *wmi, u8 if_idx, struct sk_buff *skb,
int
ret
;
u16
info1
;
if
(
WARN_ON
(
skb
==
NULL
||
(
if_idx
>
(
wmi
->
parent_dev
->
vif_max
-
1
))))
if
(
WARN_ON
(
skb
==
NULL
||
(
if_idx
>
(
wmi
->
parent_dev
->
vif_max
-
1
))))
{
dev_kfree_skb
(
skb
);
return
-
EINVAL
;
}
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"wmi tx id %d len %d flag %d
\n
"
,
cmd_id
,
skb
->
len
,
sync_flag
);
...
...
@@ -1833,6 +1905,59 @@ int ath6kl_wmi_disconnect_cmd(struct wmi *wmi, u8 if_idx)
return
ret
;
}
/* ath6kl_wmi_start_scan_cmd is to be deprecated. Use
* ath6kl_wmi_begin_scan_cmd instead. The new function supports P2P
* mgmt operations using station interface.
*/
static
int
ath6kl_wmi_startscan_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
enum
wmi_scan_type
scan_type
,
u32
force_fgscan
,
u32
is_legacy
,
u32
home_dwell_time
,
u32
force_scan_interval
,
s8
num_chan
,
u16
*
ch_list
)
{
struct
sk_buff
*
skb
;
struct
wmi_start_scan_cmd
*
sc
;
s8
size
;
int
i
,
ret
;
size
=
sizeof
(
struct
wmi_start_scan_cmd
);
if
((
scan_type
!=
WMI_LONG_SCAN
)
&&
(
scan_type
!=
WMI_SHORT_SCAN
))
return
-
EINVAL
;
if
(
num_chan
>
WMI_MAX_CHANNELS
)
return
-
EINVAL
;
if
(
num_chan
)
size
+=
sizeof
(
u16
)
*
(
num_chan
-
1
);
skb
=
ath6kl_wmi_get_new_buf
(
size
);
if
(
!
skb
)
return
-
ENOMEM
;
sc
=
(
struct
wmi_start_scan_cmd
*
)
skb
->
data
;
sc
->
scan_type
=
scan_type
;
sc
->
force_fg_scan
=
cpu_to_le32
(
force_fgscan
);
sc
->
is_legacy
=
cpu_to_le32
(
is_legacy
);
sc
->
home_dwell_time
=
cpu_to_le32
(
home_dwell_time
);
sc
->
force_scan_intvl
=
cpu_to_le32
(
force_scan_interval
);
sc
->
num_ch
=
num_chan
;
for
(
i
=
0
;
i
<
num_chan
;
i
++
)
sc
->
ch_list
[
i
]
=
cpu_to_le16
(
ch_list
[
i
]);
ret
=
ath6kl_wmi_cmd_send
(
wmi
,
if_idx
,
skb
,
WMI_START_SCAN_CMDID
,
NO_SYNC_WMIFLAG
);
return
ret
;
}
/*
* beginscan supports (compared to old startscan) P2P mgmt operations using
* station interface, send additional information like supported rates to
* advertise and xmit rates for probe requests
*/
int
ath6kl_wmi_beginscan_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
enum
wmi_scan_type
scan_type
,
u32
force_fgscan
,
u32
is_legacy
,
...
...
@@ -1848,6 +1973,15 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
int
num_rates
;
u32
ratemask
;
if
(
!
test_bit
(
ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX
,
ar
->
fw_capabilities
))
{
return
ath6kl_wmi_startscan_cmd
(
wmi
,
if_idx
,
scan_type
,
force_fgscan
,
is_legacy
,
home_dwell_time
,
force_scan_interval
,
num_chan
,
ch_list
);
}
size
=
sizeof
(
struct
wmi_begin_scan_cmd
);
if
((
scan_type
!=
WMI_LONG_SCAN
)
&&
(
scan_type
!=
WMI_SHORT_SCAN
))
...
...
@@ -1900,50 +2034,24 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
return
ret
;
}
/* ath6kl_wmi_start_scan_cmd is to be deprecated. Use
* ath6kl_wmi_begin_scan_cmd instead. The new function supports P2P
* mgmt operations using station interface.
*/
int
ath6kl_wmi_startscan_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
enum
wmi_scan_type
scan_type
,
u32
force_fgscan
,
u32
is_legacy
,
u32
home_dwell_time
,
u32
force_scan_interval
,
s8
num_chan
,
u16
*
ch_list
)
int
ath6kl_wmi_enable_sched_scan_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
bool
enable
)
{
struct
sk_buff
*
skb
;
struct
wmi_start_scan_cmd
*
sc
;
s8
size
;
int
i
,
ret
;
size
=
sizeof
(
struct
wmi_start_scan_cmd
);
if
((
scan_type
!=
WMI_LONG_SCAN
)
&&
(
scan_type
!=
WMI_SHORT_SCAN
))
return
-
EINVAL
;
if
(
num_chan
>
WMI_MAX_CHANNELS
)
return
-
EINVAL
;
if
(
num_chan
)
size
+=
sizeof
(
u16
)
*
(
num_chan
-
1
);
struct
wmi_enable_sched_scan_cmd
*
sc
;
int
ret
;
skb
=
ath6kl_wmi_get_new_buf
(
size
);
skb
=
ath6kl_wmi_get_new_buf
(
size
of
(
*
sc
)
);
if
(
!
skb
)
return
-
ENOMEM
;
sc
=
(
struct
wmi_start_scan_cmd
*
)
skb
->
data
;
sc
->
scan_type
=
scan_type
;
sc
->
force_fg_scan
=
cpu_to_le32
(
force_fgscan
);
sc
->
is_legacy
=
cpu_to_le32
(
is_legacy
);
sc
->
home_dwell_time
=
cpu_to_le32
(
home_dwell_time
);
sc
->
force_scan_intvl
=
cpu_to_le32
(
force_scan_interval
);
sc
->
num_ch
=
num_chan
;
for
(
i
=
0
;
i
<
num_chan
;
i
++
)
sc
->
ch_list
[
i
]
=
cpu_to_le16
(
ch_list
[
i
]);
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"%s scheduled scan on vif %d
\n
"
,
enable
?
"enabling"
:
"disabling"
,
if_idx
);
sc
=
(
struct
wmi_enable_sched_scan_cmd
*
)
skb
->
data
;
sc
->
enable
=
enable
?
1
:
0
;
ret
=
ath6kl_wmi_cmd_send
(
wmi
,
if_idx
,
skb
,
WMI_START_SCAN_CMDID
,
ret
=
ath6kl_wmi_cmd_send
(
wmi
,
if_idx
,
skb
,
WMI_ENABLE_SCHED_SCAN_CMDID
,
NO_SYNC_WMIFLAG
);
return
ret
;
}
...
...
@@ -2275,8 +2383,10 @@ static int ath6kl_wmi_data_sync_send(struct wmi *wmi, struct sk_buff *skb,
struct
wmi_data_hdr
*
data_hdr
;
int
ret
;
if
(
WARN_ON
(
skb
==
NULL
||
ep_id
==
wmi
->
ep_id
))
if
(
WARN_ON
(
skb
==
NULL
||
ep_id
==
wmi
->
ep_id
))
{
dev_kfree_skb
(
skb
);
return
-
EINVAL
;
}
skb_push
(
skb
,
sizeof
(
struct
wmi_data_hdr
));
...
...
@@ -2313,10 +2423,8 @@ static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx)
spin_unlock_bh
(
&
wmi
->
lock
);
skb
=
ath6kl_wmi_get_new_buf
(
sizeof
(
*
cmd
));
if
(
!
skb
)
{
ret
=
-
ENOMEM
;
goto
free_skb
;
}
if
(
!
skb
)
return
-
ENOMEM
;
cmd
=
(
struct
wmi_sync_cmd
*
)
skb
->
data
;
...
...
@@ -2339,7 +2447,7 @@ static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx)
* then do not send the Synchronize cmd on the control ep
*/
if
(
ret
)
goto
free_skb
;
goto
free_
cmd_
skb
;
/*
* Send sync cmd followed by sync data messages on all
...
...
@@ -2349,15 +2457,12 @@ static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx)
NO_SYNC_WMIFLAG
);
if
(
ret
)
goto
free_skb
;
/* cmd buffer sent, we no longer own it */
skb
=
NULL
;
goto
free_data_skb
;
for
(
index
=
0
;
index
<
num_pri_streams
;
index
++
)
{
if
(
WARN_ON
(
!
data_sync_bufs
[
index
].
skb
))
break
;
goto
free_data_skb
;
ep_id
=
ath6kl_ac2_endpoint_id
(
wmi
->
parent_dev
,
data_sync_bufs
[
index
].
...
...
@@ -2366,17 +2471,20 @@ static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx)
ath6kl_wmi_data_sync_send
(
wmi
,
data_sync_bufs
[
index
].
skb
,
ep_id
,
if_idx
);
if
(
ret
)
break
;
data_sync_bufs
[
index
].
skb
=
NULL
;
if
(
ret
)
goto
free_data_skb
;
}
free_skb:
return
0
;
free_cmd_skb:
/* free up any resources left over (possibly due to an error) */
if
(
skb
)
dev_kfree_skb
(
skb
);
free_data_skb:
for
(
index
=
0
;
index
<
num_pri_streams
;
index
++
)
{
if
(
data_sync_bufs
[
index
].
skb
!=
NULL
)
{
dev_kfree_skb
((
struct
sk_buff
*
)
data_sync_bufs
[
index
].
...
...
@@ -2618,11 +2726,13 @@ static int ath6kl_set_bitrate_mask64(struct wmi *wmi, u8 if_idx,
{
struct
sk_buff
*
skb
;
int
ret
,
mode
,
band
;
u64
mcsrate
,
ratemask
[
IEEE80211
_NUM_BANDS
];
u64
mcsrate
,
ratemask
[
ATH6KL
_NUM_BANDS
];
struct
wmi_set_tx_select_rates64_cmd
*
cmd
;
memset
(
&
ratemask
,
0
,
sizeof
(
ratemask
));
for
(
band
=
0
;
band
<
IEEE80211_NUM_BANDS
;
band
++
)
{
/* only check 2.4 and 5 GHz bands, skip the rest */
for
(
band
=
0
;
band
<=
IEEE80211_BAND_5GHZ
;
band
++
)
{
/* copy legacy rate mask */
ratemask
[
band
]
=
mask
->
control
[
band
].
legacy
;
if
(
band
==
IEEE80211_BAND_5GHZ
)
...
...
@@ -2668,11 +2778,13 @@ static int ath6kl_set_bitrate_mask32(struct wmi *wmi, u8 if_idx,
{
struct
sk_buff
*
skb
;
int
ret
,
mode
,
band
;
u32
mcsrate
,
ratemask
[
IEEE80211
_NUM_BANDS
];
u32
mcsrate
,
ratemask
[
ATH6KL
_NUM_BANDS
];
struct
wmi_set_tx_select_rates32_cmd
*
cmd
;
memset
(
&
ratemask
,
0
,
sizeof
(
ratemask
));
for
(
band
=
0
;
band
<
IEEE80211_NUM_BANDS
;
band
++
)
{
/* only check 2.4 and 5 GHz bands, skip the rest */
for
(
band
=
0
;
band
<=
IEEE80211_BAND_5GHZ
;
band
++
)
{
/* copy legacy rate mask */
ratemask
[
band
]
=
mask
->
control
[
band
].
legacy
;
if
(
band
==
IEEE80211_BAND_5GHZ
)
...
...
@@ -2716,7 +2828,7 @@ int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
{
struct
ath6kl
*
ar
=
wmi
->
parent_dev
;
if
(
ar
->
hw
.
flags
&
ATH6KL_HW_
FLAG_
64BIT_RATES
)
if
(
ar
->
hw
.
flags
&
ATH6KL_HW_64BIT_RATES
)
return
ath6kl_set_bitrate_mask64
(
wmi
,
if_idx
,
mask
);
else
return
ath6kl_set_bitrate_mask32
(
wmi
,
if_idx
,
mask
);
...
...
@@ -3139,12 +3251,40 @@ int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enhance)
return
ret
;
}
int
ath6kl_wmi_set_regdomain_cmd
(
struct
wmi
*
wmi
,
const
char
*
alpha2
)
{
struct
sk_buff
*
skb
;
struct
wmi_set_regdomain_cmd
*
cmd
;
skb
=
ath6kl_wmi_get_new_buf
(
sizeof
(
*
cmd
));
if
(
!
skb
)
return
-
ENOMEM
;
cmd
=
(
struct
wmi_set_regdomain_cmd
*
)
skb
->
data
;
memcpy
(
cmd
->
iso_name
,
alpha2
,
2
);
return
ath6kl_wmi_cmd_send
(
wmi
,
0
,
skb
,
WMI_SET_REGDOMAIN_CMDID
,
NO_SYNC_WMIFLAG
);
}
s32
ath6kl_wmi_get_rate
(
s8
rate_index
)
{
u8
sgi
=
0
;
if
(
rate_index
==
RATE_AUTO
)
return
0
;
return
wmi_rate_tbl
[(
u32
)
rate_index
][
0
];
/* SGI is stored as the MSB of the rate_index */
if
(
rate_index
&
RATE_INDEX_MSB
)
{
rate_index
&=
RATE_INDEX_WITHOUT_SGI_MASK
;
sgi
=
1
;
}
if
(
WARN_ON
(
rate_index
>
RATE_MCS_7_40
))
rate_index
=
RATE_MCS_7_40
;
return
wmi_rate_tbl
[(
u32
)
rate_index
][
sgi
];
}
static
int
ath6kl_wmi_get_pmkid_list_event_rx
(
struct
wmi
*
wmi
,
u8
*
datap
,
...
...
@@ -3634,6 +3774,19 @@ int ath6kl_wmi_set_inact_period(struct wmi *wmi, u8 if_idx, int inact_timeout)
NO_SYNC_WMIFLAG
);
}
static
void
ath6kl_wmi_hb_challenge_resp_event
(
struct
wmi
*
wmi
,
u8
*
datap
,
int
len
)
{
struct
wmix_hb_challenge_resp_cmd
*
cmd
;
if
(
len
<
sizeof
(
struct
wmix_hb_challenge_resp_cmd
))
return
;
cmd
=
(
struct
wmix_hb_challenge_resp_cmd
*
)
datap
;
ath6kl_recovery_hb_event
(
wmi
->
parent_dev
,
le32_to_cpu
(
cmd
->
cookie
));
}
static
int
ath6kl_wmi_control_rx_xtnd
(
struct
wmi
*
wmi
,
struct
sk_buff
*
skb
)
{
struct
wmix_cmd_hdr
*
cmd
;
...
...
@@ -3658,6 +3811,7 @@ static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb)
switch
(
id
)
{
case
WMIX_HB_CHALLENGE_RESP_EVENTID
:
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"wmi event hb challenge resp
\n
"
);
ath6kl_wmi_hb_challenge_resp_event
(
wmi
,
datap
,
len
);
break
;
case
WMIX_DBGLOG_EVENTID
:
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"wmi event dbglog len %d
\n
"
,
len
);
...
...
@@ -3750,6 +3904,9 @@ static int ath6kl_wmi_proc_events_vif(struct wmi *wmi, u16 if_idx, u16 cmd_id,
case
WMI_RX_ACTION_EVENTID
:
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_RX_ACTION_EVENTID
\n
"
);
return
ath6kl_wmi_rx_action_event_rx
(
wmi
,
datap
,
len
,
vif
);
case
WMI_TXE_NOTIFY_EVENTID
:
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"WMI_TXE_NOTIFY_EVENTID
\n
"
);
return
ath6kl_wmi_txe_notify_event_rx
(
wmi
,
datap
,
len
,
vif
);
default:
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"unknown cmd id 0x%x
\n
"
,
cmd_id
);
return
-
EINVAL
;
...
...
drivers/net/wireless/ath/ath6kl/wmi.h
View file @
1e5023c7
...
...
@@ -48,7 +48,7 @@
#define A_BAND_24GHZ 0
#define A_BAND_5GHZ 1
#define A
_NUM_BANDS
2
#define A
TH6KL_NUM_BANDS
2
/* in ms */
#define WMI_IMPLICIT_PSTREAM_INACTIVITY_INT 5000
...
...
@@ -628,6 +628,20 @@ enum wmi_cmd_id {
WMI_SET_MCASTRATE
,
WMI_STA_BMISS_ENHANCE_CMDID
,
WMI_SET_REGDOMAIN_CMDID
,
WMI_SET_RSSI_FILTER_CMDID
,
WMI_SET_KEEP_ALIVE_EXT
,
WMI_VOICE_DETECTION_ENABLE_CMDID
,
WMI_SET_TXE_NOTIFY_CMDID
,
WMI_SET_RECOVERY_TEST_PARAMETER_CMDID
,
/*0xf094*/
WMI_ENABLE_SCHED_SCAN_CMDID
,
};
enum
wmi_mgmt_frame_type
{
...
...
@@ -843,7 +857,7 @@ struct wmi_begin_scan_cmd {
u8
scan_type
;
/* Supported rates to advertise in the probe request frames */
struct
wmi_supp_rates
supp_rates
[
IEEE80211
_NUM_BANDS
];
struct
wmi_supp_rates
supp_rates
[
ATH6KL
_NUM_BANDS
];
/* how many channels follow */
u8
num_ch
;
...
...
@@ -941,6 +955,11 @@ struct wmi_scan_params_cmd {
__le32
max_dfsch_act_time
;
}
__packed
;
/* WMI_ENABLE_SCHED_SCAN_CMDID */
struct
wmi_enable_sched_scan_cmd
{
u8
enable
;
}
__packed
;
/* WMI_SET_BSS_FILTER_CMDID */
enum
wmi_bss_filter
{
/* no beacons forwarded */
...
...
@@ -1032,6 +1051,11 @@ struct wmi_sta_bmiss_enhance_cmd {
u8
enable
;
}
__packed
;
struct
wmi_set_regdomain_cmd
{
u8
length
;
u8
iso_name
[
2
];
}
__packed
;
/* WMI_SET_POWER_MODE_CMDID */
enum
wmi_power_mode
{
REC_POWER
=
0x01
,
...
...
@@ -1276,6 +1300,11 @@ struct wmi_snr_threshold_params_cmd {
u8
reserved
[
3
];
}
__packed
;
/* Don't report BSSs with signal (RSSI) below this threshold */
struct
wmi_set_rssi_filter_cmd
{
s8
rssi
;
}
__packed
;
enum
wmi_preamble_policy
{
WMI_IGNORE_BARKER_IN_ERP
=
0
,
WMI_FOLLOW_BARKER_IN_ERP
,
...
...
@@ -1455,6 +1484,20 @@ enum wmi_event_id {
WMI_P2P_CAPABILITIES_EVENTID
,
WMI_RX_ACTION_EVENTID
,
WMI_P2P_INFO_EVENTID
,
/* WPS Events */
WMI_WPS_GET_STATUS_EVENTID
,
WMI_WPS_PROFILE_EVENTID
,
/* more P2P events */
WMI_NOA_INFO_EVENTID
,
WMI_OPPPS_INFO_EVENTID
,
WMI_PORT_STATUS_EVENTID
,
/* 802.11w */
WMI_GET_RSN_CAP_EVENTID
,
WMI_TXE_NOTIFY_EVENTID
,
};
struct
wmi_ready_event_2
{
...
...
@@ -1749,6 +1792,9 @@ struct rx_stats {
a_sle32
ucast_rate
;
}
__packed
;
#define RATE_INDEX_WITHOUT_SGI_MASK 0x7f
#define RATE_INDEX_MSB 0x80
struct
tkip_ccmp_stats
{
__le32
tkip_local_mic_fail
;
__le32
tkip_cnter_measures_invoked
;
...
...
@@ -2019,7 +2065,6 @@ struct wmi_set_ie_cmd {
#define WOW_MAX_FILTERS_PER_LIST 4
#define WOW_PATTERN_SIZE 64
#define WOW_MASK_SIZE 64
#define MAC_MAX_FILTERS_PER_LIST 4
...
...
@@ -2028,7 +2073,7 @@ struct wow_filter {
u8
wow_filter_id
;
u8
wow_filter_size
;
u8
wow_filter_offset
;
u8
wow_filter_mask
[
WOW_
MASK
_SIZE
];
u8
wow_filter_mask
[
WOW_
PATTERN
_SIZE
];
u8
wow_filter_pattern
[
WOW_PATTERN_SIZE
];
}
__packed
;
...
...
@@ -2087,6 +2132,19 @@ struct wmi_del_wow_pattern_cmd {
__le16
filter_id
;
}
__packed
;
/* WMI_SET_TXE_NOTIFY_CMDID */
struct
wmi_txe_notify_cmd
{
__le32
rate
;
__le32
pkts
;
__le32
intvl
;
}
__packed
;
/* WMI_TXE_NOTIFY_EVENTID */
struct
wmi_txe_notify_event
{
__le32
rate
;
__le32
pkts
;
}
__packed
;
/* WMI_SET_AKMP_PARAMS_CMD */
struct
wmi_pmkid
{
...
...
@@ -2505,11 +2563,6 @@ int ath6kl_wmi_connect_cmd(struct wmi *wmi, u8 if_idx,
int
ath6kl_wmi_reconnect_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
u8
*
bssid
,
u16
channel
);
int
ath6kl_wmi_disconnect_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
);
int
ath6kl_wmi_startscan_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
enum
wmi_scan_type
scan_type
,
u32
force_fgscan
,
u32
is_legacy
,
u32
home_dwell_time
,
u32
force_scan_interval
,
s8
num_chan
,
u16
*
ch_list
);
int
ath6kl_wmi_beginscan_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
enum
wmi_scan_type
scan_type
,
...
...
@@ -2517,6 +2570,7 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
u32
home_dwell_time
,
u32
force_scan_interval
,
s8
num_chan
,
u16
*
ch_list
,
u32
no_cck
,
u32
*
rates
);
int
ath6kl_wmi_enable_sched_scan_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
bool
enable
);
int
ath6kl_wmi_scanparams_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
u16
fg_start_sec
,
u16
fg_end_sec
,
u16
bg_sec
,
...
...
@@ -2592,6 +2646,7 @@ int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
const
u8
*
mask
);
int
ath6kl_wmi_del_wow_pattern_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
u16
list_id
,
u16
filter_id
);
int
ath6kl_wmi_set_rssi_filter_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
s8
rssi
);
int
ath6kl_wmi_set_roam_lrssi_cmd
(
struct
wmi
*
wmi
,
u8
lrssi
);
int
ath6kl_wmi_ap_set_dtim_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
u32
dtim_period
);
int
ath6kl_wmi_force_roam_cmd
(
struct
wmi
*
wmi
,
const
u8
*
bssid
);
...
...
@@ -2600,6 +2655,9 @@ int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on);
int
ath6kl_wmi_add_del_mcast_filter_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
u8
*
filter
,
bool
add_filter
);
int
ath6kl_wmi_sta_bmiss_enhance_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
bool
enable
);
int
ath6kl_wmi_set_txe_notify
(
struct
wmi
*
wmi
,
u8
idx
,
u32
rate
,
u32
pkts
,
u32
intvl
);
int
ath6kl_wmi_set_regdomain_cmd
(
struct
wmi
*
wmi
,
const
char
*
alpha2
);
/* AP mode uAPSD */
int
ath6kl_wmi_ap_set_apsd
(
struct
wmi
*
wmi
,
u8
if_idx
,
u8
enable
);
...
...
@@ -2658,6 +2716,8 @@ int ath6kl_wmi_set_inact_period(struct wmi *wmi, u8 if_idx, int inact_timeout);
void
ath6kl_wmi_sscan_timer
(
unsigned
long
ptr
);
int
ath6kl_wmi_get_challenge_resp_cmd
(
struct
wmi
*
wmi
,
u32
cookie
,
u32
source
);
struct
ath6kl_vif
*
ath6kl_get_vif_by_index
(
struct
ath6kl
*
ar
,
u8
if_idx
);
void
*
ath6kl_wmi_init
(
struct
ath6kl
*
devt
);
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