Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
1f807827
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
160
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
1f807827
编写于
8月 02, 2013
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge tag 'for-linville-20130730' of
git://github.com/kvalo/ath6kl
上级
20416229
424121c3
变更
19
展开全部
显示空白变更内容
内联
并排
Showing
19 changed file
with
959 addition
and
454 deletion
+959
-454
drivers/net/wireless/ath/ath10k/bmi.c
drivers/net/wireless/ath/ath10k/bmi.c
+10
-2
drivers/net/wireless/ath/ath10k/bmi.h
drivers/net/wireless/ath/ath10k/bmi.h
+1
-0
drivers/net/wireless/ath/ath10k/ce.c
drivers/net/wireless/ath/ath10k/ce.c
+1
-1
drivers/net/wireless/ath/ath10k/core.c
drivers/net/wireless/ath/ath10k/core.c
+210
-111
drivers/net/wireless/ath/ath10k/core.h
drivers/net/wireless/ath/ath10k/core.h
+36
-14
drivers/net/wireless/ath/ath10k/debug.c
drivers/net/wireless/ath/ath10k/debug.c
+73
-14
drivers/net/wireless/ath/ath10k/hif.h
drivers/net/wireless/ath/ath10k/hif.h
+44
-5
drivers/net/wireless/ath/ath10k/htc.c
drivers/net/wireless/ath/ath10k/htc.c
+25
-36
drivers/net/wireless/ath/ath10k/htc.h
drivers/net/wireless/ath/ath10k/htc.h
+3
-5
drivers/net/wireless/ath/ath10k/htt.c
drivers/net/wireless/ath/ath10k/htt.c
+14
-13
drivers/net/wireless/ath/ath10k/htt.h
drivers/net/wireless/ath/ath10k/htt.h
+1
-2
drivers/net/wireless/ath/ath10k/htt_rx.c
drivers/net/wireless/ath/ath10k/htt_rx.c
+2
-1
drivers/net/wireless/ath/ath10k/htt_tx.c
drivers/net/wireless/ath/ath10k/htt_tx.c
+6
-6
drivers/net/wireless/ath/ath10k/mac.c
drivers/net/wireless/ath/ath10k/mac.c
+346
-63
drivers/net/wireless/ath/ath10k/mac.h
drivers/net/wireless/ath/ath10k/mac.h
+1
-0
drivers/net/wireless/ath/ath10k/pci.c
drivers/net/wireless/ath/ath10k/pci.c
+129
-175
drivers/net/wireless/ath/ath10k/pci.h
drivers/net/wireless/ath/ath10k/pci.h
+2
-2
drivers/net/wireless/ath/ath10k/wmi.c
drivers/net/wireless/ath/ath10k/wmi.c
+36
-4
drivers/net/wireless/ath/ath10k/wmi.h
drivers/net/wireless/ath/ath10k/wmi.h
+19
-0
未找到文件。
drivers/net/wireless/ath/ath10k/bmi.c
浏览文件 @
1f807827
...
...
@@ -20,6 +20,12 @@
#include "debug.h"
#include "htc.h"
void
ath10k_bmi_start
(
struct
ath10k
*
ar
)
{
ath10k_dbg
(
ATH10K_DBG_CORE
,
"BMI started
\n
"
);
ar
->
bmi
.
done_sent
=
false
;
}
int
ath10k_bmi_done
(
struct
ath10k
*
ar
)
{
struct
bmi_cmd
cmd
;
...
...
@@ -105,7 +111,8 @@ int ath10k_bmi_read_memory(struct ath10k *ar,
ret
=
ath10k_hif_exchange_bmi_msg
(
ar
,
&
cmd
,
cmdlen
,
&
resp
,
&
rxlen
);
if
(
ret
)
{
ath10k_warn
(
"unable to read from the device
\n
"
);
ath10k_warn
(
"unable to read from the device (%d)
\n
"
,
ret
);
return
ret
;
}
...
...
@@ -149,7 +156,8 @@ int ath10k_bmi_write_memory(struct ath10k *ar,
ret
=
ath10k_hif_exchange_bmi_msg
(
ar
,
&
cmd
,
hdrlen
+
txlen
,
NULL
,
NULL
);
if
(
ret
)
{
ath10k_warn
(
"unable to write to the device
\n
"
);
ath10k_warn
(
"unable to write to the device (%d)
\n
"
,
ret
);
return
ret
;
}
...
...
drivers/net/wireless/ath/ath10k/bmi.h
浏览文件 @
1f807827
...
...
@@ -184,6 +184,7 @@ struct bmi_target_info {
#define BMI_CE_NUM_TO_TARG 0
#define BMI_CE_NUM_TO_HOST 1
void
ath10k_bmi_start
(
struct
ath10k
*
ar
);
int
ath10k_bmi_done
(
struct
ath10k
*
ar
);
int
ath10k_bmi_get_target_info
(
struct
ath10k
*
ar
,
struct
bmi_target_info
*
target_info
);
...
...
drivers/net/wireless/ath/ath10k/ce.c
浏览文件 @
1f807827
...
...
@@ -79,7 +79,7 @@ static inline void ath10k_ce_src_ring_write_index_set(struct ath10k *ar,
struct
ath10k_pci
*
ar_pci
=
ath10k_pci_priv
(
ar
);
void
__iomem
*
indicator_addr
;
if
(
!
test_bit
(
ATH10K_PCI_FEATURE_HW_1_0_W
A
RKAROUND
,
ar_pci
->
features
))
{
if
(
!
test_bit
(
ATH10K_PCI_FEATURE_HW_1_0_W
O
RKAROUND
,
ar_pci
->
features
))
{
ath10k_pci_write32
(
ar
,
ce_ctrl_addr
+
SR_WR_INDEX_ADDRESS
,
n
);
return
;
}
...
...
drivers/net/wireless/ath/ath10k/core.c
浏览文件 @
1f807827
...
...
@@ -100,7 +100,7 @@ static int ath10k_init_connect_htc(struct ath10k *ar)
goto
conn_fail
;
/* Start HTC */
status
=
ath10k_htc_start
(
ar
->
htc
);
status
=
ath10k_htc_start
(
&
ar
->
htc
);
if
(
status
)
goto
conn_fail
;
...
...
@@ -116,7 +116,7 @@ static int ath10k_init_connect_htc(struct ath10k *ar)
return
0
;
timeout:
ath10k_htc_stop
(
ar
->
htc
);
ath10k_htc_stop
(
&
ar
->
htc
);
conn_fail:
return
status
;
}
...
...
@@ -247,19 +247,11 @@ static int ath10k_push_board_ext_data(struct ath10k *ar,
static
int
ath10k_download_board_data
(
struct
ath10k
*
ar
)
{
const
struct
firmware
*
fw
=
ar
->
board_data
;
u32
board_data_size
=
QCA988X_BOARD_DATA_SZ
;
u32
address
;
const
struct
firmware
*
fw
;
int
ret
;
fw
=
ath10k_fetch_fw_file
(
ar
,
ar
->
hw_params
.
fw
.
dir
,
ar
->
hw_params
.
fw
.
board
);
if
(
IS_ERR
(
fw
))
{
ath10k_err
(
"could not fetch board data fw file (%ld)
\n
"
,
PTR_ERR
(
fw
));
return
PTR_ERR
(
fw
);
}
ret
=
ath10k_push_board_ext_data
(
ar
,
fw
);
if
(
ret
)
{
ath10k_err
(
"could not push board ext data (%d)
\n
"
,
ret
);
...
...
@@ -286,32 +278,20 @@ static int ath10k_download_board_data(struct ath10k *ar)
}
exit:
release_firmware
(
fw
);
return
ret
;
}
static
int
ath10k_download_and_run_otp
(
struct
ath10k
*
ar
)
{
const
struct
firmware
*
fw
;
u32
address
;
const
struct
firmware
*
fw
=
ar
->
otp
;
u32
address
=
ar
->
hw_params
.
patch_load_addr
;
u32
exec_param
;
int
ret
;
/* OTP is optional */
if
(
ar
->
hw_params
.
fw
.
otp
==
NULL
)
{
ath10k_info
(
"otp file not defined
\n
"
);
return
0
;
}
address
=
ar
->
hw_params
.
patch_load_addr
;
fw
=
ath10k_fetch_fw_file
(
ar
,
ar
->
hw_params
.
fw
.
dir
,
ar
->
hw_params
.
fw
.
otp
);
if
(
IS_ERR
(
fw
))
{
ath10k_warn
(
"could not fetch otp (%ld)
\n
"
,
PTR_ERR
(
fw
));
if
(
!
ar
->
otp
)
return
0
;
}
ret
=
ath10k_bmi_fast_download
(
ar
,
address
,
fw
->
data
,
fw
->
size
);
if
(
ret
)
{
...
...
@@ -327,28 +307,17 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)
}
exit:
release_firmware
(
fw
);
return
ret
;
}
static
int
ath10k_download_fw
(
struct
ath10k
*
ar
)
{
const
struct
firmware
*
fw
;
const
struct
firmware
*
fw
=
ar
->
firmware
;
u32
address
;
int
ret
;
if
(
ar
->
hw_params
.
fw
.
fw
==
NULL
)
return
-
EINVAL
;
address
=
ar
->
hw_params
.
patch_load_addr
;
fw
=
ath10k_fetch_fw_file
(
ar
,
ar
->
hw_params
.
fw
.
dir
,
ar
->
hw_params
.
fw
.
fw
);
if
(
IS_ERR
(
fw
))
{
ath10k_err
(
"could not fetch fw (%ld)
\n
"
,
PTR_ERR
(
fw
));
return
PTR_ERR
(
fw
);
}
ret
=
ath10k_bmi_fast_download
(
ar
,
address
,
fw
->
data
,
fw
->
size
);
if
(
ret
)
{
ath10k_err
(
"could not write fw (%d)
\n
"
,
ret
);
...
...
@@ -356,7 +325,74 @@ static int ath10k_download_fw(struct ath10k *ar)
}
exit:
release_firmware
(
fw
);
return
ret
;
}
static
void
ath10k_core_free_firmware_files
(
struct
ath10k
*
ar
)
{
if
(
ar
->
board_data
&&
!
IS_ERR
(
ar
->
board_data
))
release_firmware
(
ar
->
board_data
);
if
(
ar
->
otp
&&
!
IS_ERR
(
ar
->
otp
))
release_firmware
(
ar
->
otp
);
if
(
ar
->
firmware
&&
!
IS_ERR
(
ar
->
firmware
))
release_firmware
(
ar
->
firmware
);
ar
->
board_data
=
NULL
;
ar
->
otp
=
NULL
;
ar
->
firmware
=
NULL
;
}
static
int
ath10k_core_fetch_firmware_files
(
struct
ath10k
*
ar
)
{
int
ret
=
0
;
if
(
ar
->
hw_params
.
fw
.
fw
==
NULL
)
{
ath10k_err
(
"firmware file not defined
\n
"
);
return
-
EINVAL
;
}
if
(
ar
->
hw_params
.
fw
.
board
==
NULL
)
{
ath10k_err
(
"board data file not defined"
);
return
-
EINVAL
;
}
ar
->
board_data
=
ath10k_fetch_fw_file
(
ar
,
ar
->
hw_params
.
fw
.
dir
,
ar
->
hw_params
.
fw
.
board
);
if
(
IS_ERR
(
ar
->
board_data
))
{
ret
=
PTR_ERR
(
ar
->
board_data
);
ath10k_err
(
"could not fetch board data (%d)
\n
"
,
ret
);
goto
err
;
}
ar
->
firmware
=
ath10k_fetch_fw_file
(
ar
,
ar
->
hw_params
.
fw
.
dir
,
ar
->
hw_params
.
fw
.
fw
);
if
(
IS_ERR
(
ar
->
firmware
))
{
ret
=
PTR_ERR
(
ar
->
firmware
);
ath10k_err
(
"could not fetch firmware (%d)
\n
"
,
ret
);
goto
err
;
}
/* OTP may be undefined. If so, don't fetch it at all */
if
(
ar
->
hw_params
.
fw
.
otp
==
NULL
)
return
0
;
ar
->
otp
=
ath10k_fetch_fw_file
(
ar
,
ar
->
hw_params
.
fw
.
dir
,
ar
->
hw_params
.
fw
.
otp
);
if
(
IS_ERR
(
ar
->
otp
))
{
ret
=
PTR_ERR
(
ar
->
otp
);
ath10k_err
(
"could not fetch otp (%d)
\n
"
,
ret
);
goto
err
;
}
return
0
;
err:
ath10k_core_free_firmware_files
(
ar
);
return
ret
;
}
...
...
@@ -440,8 +476,35 @@ static int ath10k_init_hw_params(struct ath10k *ar)
return
0
;
}
static
void
ath10k_core_restart
(
struct
work_struct
*
work
)
{
struct
ath10k
*
ar
=
container_of
(
work
,
struct
ath10k
,
restart_work
);
mutex_lock
(
&
ar
->
conf_mutex
);
switch
(
ar
->
state
)
{
case
ATH10K_STATE_ON
:
ath10k_halt
(
ar
);
ar
->
state
=
ATH10K_STATE_RESTARTING
;
ieee80211_restart_hw
(
ar
->
hw
);
break
;
case
ATH10K_STATE_OFF
:
/* this can happen if driver is being unloaded */
ath10k_warn
(
"cannot restart a device that hasn't been started
\n
"
);
break
;
case
ATH10K_STATE_RESTARTING
:
case
ATH10K_STATE_RESTARTED
:
ar
->
state
=
ATH10K_STATE_WEDGED
;
/* fall through */
case
ATH10K_STATE_WEDGED
:
ath10k_warn
(
"device is wedged, will not restart
\n
"
);
break
;
}
mutex_unlock
(
&
ar
->
conf_mutex
);
}
struct
ath10k
*
ath10k_core_create
(
void
*
hif_priv
,
struct
device
*
dev
,
enum
ath10k_bus
bus
,
const
struct
ath10k_hif_ops
*
hif_ops
)
{
struct
ath10k
*
ar
;
...
...
@@ -458,9 +521,6 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
ar
->
hif
.
priv
=
hif_priv
;
ar
->
hif
.
ops
=
hif_ops
;
ar
->
hif
.
bus
=
bus
;
ar
->
free_vdev_map
=
0xFF
;
/* 8 vdevs */
init_completion
(
&
ar
->
scan
.
started
);
init_completion
(
&
ar
->
scan
.
completed
);
...
...
@@ -487,6 +547,8 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
init_waitqueue_head
(
&
ar
->
event_queue
);
INIT_WORK
(
&
ar
->
restart_work
,
ath10k_core_restart
);
return
ar
;
err_wq:
...
...
@@ -504,24 +566,11 @@ void ath10k_core_destroy(struct ath10k *ar)
}
EXPORT_SYMBOL
(
ath10k_core_destroy
);
int
ath10k_core_register
(
struct
ath10k
*
ar
)
int
ath10k_core_start
(
struct
ath10k
*
ar
)
{
struct
ath10k_htc_ops
htc_ops
;
struct
bmi_target_info
target_info
;
int
status
;
memset
(
&
target_info
,
0
,
sizeof
(
target_info
));
status
=
ath10k_bmi_get_target_info
(
ar
,
&
target_info
);
if
(
status
)
goto
err
;
ar
->
target_version
=
target_info
.
version
;
ar
->
hw
->
wiphy
->
hw_version
=
target_info
.
version
;
status
=
ath10k_init_hw_params
(
ar
);
if
(
status
)
goto
err
;
ath10k_bmi_start
(
ar
);
if
(
ath10k_init_configure_target
(
ar
))
{
status
=
-
EINVAL
;
...
...
@@ -536,32 +585,32 @@ int ath10k_core_register(struct ath10k *ar)
if
(
status
)
goto
err
;
htc_ops
.
target_send_suspend_complete
=
ath10k_send_suspend_complete
;
ar
->
htc
.
htc_ops
.
target_send_suspend_complete
=
ath10k_send_suspend_complete
;
ar
->
htc
=
ath10k_htc_create
(
ar
,
&
htc_ops
);
if
(
IS_ERR
(
ar
->
htc
))
{
status
=
PTR_ERR
(
ar
->
htc
);
ath10k_err
(
"could not create HTC (%d)
\n
"
,
status
);
status
=
ath10k_htc_init
(
ar
);
if
(
status
)
{
ath10k_err
(
"could not init HTC (%d)
\n
"
,
status
);
goto
err
;
}
status
=
ath10k_bmi_done
(
ar
);
if
(
status
)
goto
err
_htc_destroy
;
goto
err
;
status
=
ath10k_wmi_attach
(
ar
);
if
(
status
)
{
ath10k_err
(
"WMI attach failed: %d
\n
"
,
status
);
goto
err
_htc_destroy
;
goto
err
;
}
status
=
ath10k_htc_wait_target
(
ar
->
htc
);
status
=
ath10k_htc_wait_target
(
&
ar
->
htc
);
if
(
status
)
goto
err_wmi_detach
;
ar
->
htt
=
ath10k_htt_attach
(
ar
);
if
(
!
ar
->
htt
)
{
status
=
-
ENOMEM
;
status
=
ath10k_htt_attach
(
ar
);
if
(
status
)
{
ath10k_err
(
"could not attach htt (%d)
\n
"
,
status
)
;
goto
err_wmi_detach
;
}
...
...
@@ -588,77 +637,127 @@ int ath10k_core_register(struct ath10k *ar)
goto
err_disconnect_htc
;
}
status
=
ath10k_htt_attach_target
(
ar
->
htt
);
if
(
status
)
goto
err_disconnect_htc
;
status
=
ath10k_mac_register
(
ar
);
status
=
ath10k_htt_attach_target
(
&
ar
->
htt
);
if
(
status
)
goto
err_disconnect_htc
;
status
=
ath10k_debug_create
(
ar
);
if
(
status
)
{
ath10k_err
(
"unable to initialize debugfs
\n
"
);
goto
err_unregister_mac
;
}
ar
->
free_vdev_map
=
(
1
<<
TARGET_NUM_VDEVS
)
-
1
;
return
0
;
err_unregister_mac:
ath10k_mac_unregister
(
ar
);
err_disconnect_htc:
ath10k_htc_stop
(
ar
->
htc
);
ath10k_htc_stop
(
&
ar
->
htc
);
err_htt_detach:
ath10k_htt_detach
(
ar
->
htt
);
ath10k_htt_detach
(
&
ar
->
htt
);
err_wmi_detach:
ath10k_wmi_detach
(
ar
);
err_htc_destroy:
ath10k_htc_destroy
(
ar
->
htc
);
err:
return
status
;
}
EXPORT_SYMBOL
(
ath10k_core_
register
);
EXPORT_SYMBOL
(
ath10k_core_
start
);
void
ath10k_core_
unregister
(
struct
ath10k
*
ar
)
void
ath10k_core_
stop
(
struct
ath10k
*
ar
)
{
/* We must unregister from mac80211 before we stop HTC and HIF.
* Otherwise we will fail to submit commands to FW and mac80211 will be
* unhappy about callback failures. */
ath10k_mac_unregister
(
ar
);
ath10k_htc_stop
(
ar
->
htc
);
ath10k_htt_detach
(
ar
->
htt
);
ath10k_htc_stop
(
&
ar
->
htc
);
ath10k_htt_detach
(
&
ar
->
htt
);
ath10k_wmi_detach
(
ar
);
ath10k_htc_destroy
(
ar
->
htc
);
}
EXPORT_SYMBOL
(
ath10k_core_
unregister
);
EXPORT_SYMBOL
(
ath10k_core_
stop
);
int
ath10k_core_target_suspend
(
struct
ath10k
*
ar
)
/* mac80211 manages fw/hw initialization through start/stop hooks. However in
* order to know what hw capabilities should be advertised to mac80211 it is
* necessary to load the firmware (and tear it down immediately since start
* hook will try to init it again) before registering */
static
int
ath10k_core_probe_fw
(
struct
ath10k
*
ar
)
{
int
ret
;
struct
bmi_target_info
target_info
;
int
ret
=
0
;
ath10k_dbg
(
ATH10K_DBG_CORE
,
"%s: called"
,
__func__
);
ret
=
ath10k_hif_power_up
(
ar
);
if
(
ret
)
{
ath10k_err
(
"could not start pci hif (%d)
\n
"
,
ret
);
return
ret
;
}
ret
=
ath10k_wmi_pdev_suspend_target
(
ar
);
if
(
ret
)
ath10k_warn
(
"could not suspend target (%d)
\n
"
,
ret
);
memset
(
&
target_info
,
0
,
sizeof
(
target_info
));
ret
=
ath10k_bmi_get_target_info
(
ar
,
&
target_info
);
if
(
ret
)
{
ath10k_err
(
"could not get target info (%d)
\n
"
,
ret
);
ath10k_hif_power_down
(
ar
);
return
ret
;
}
ar
->
target_version
=
target_info
.
version
;
ar
->
hw
->
wiphy
->
hw_version
=
target_info
.
version
;
ret
=
ath10k_init_hw_params
(
ar
);
if
(
ret
)
{
ath10k_err
(
"could not get hw params (%d)
\n
"
,
ret
);
ath10k_hif_power_down
(
ar
);
return
ret
;
}
ret
=
ath10k_core_fetch_firmware_files
(
ar
);
if
(
ret
)
{
ath10k_err
(
"could not fetch firmware files (%d)
\n
"
,
ret
);
ath10k_hif_power_down
(
ar
);
return
ret
;
}
ret
=
ath10k_core_start
(
ar
);
if
(
ret
)
{
ath10k_err
(
"could not init core (%d)
\n
"
,
ret
);
ath10k_core_free_firmware_files
(
ar
);
ath10k_hif_power_down
(
ar
);
return
ret
;
}
ath10k_core_stop
(
ar
);
ath10k_hif_power_down
(
ar
);
return
0
;
}
EXPORT_SYMBOL
(
ath10k_core_target_suspend
);
int
ath10k_core_
target_resume
(
struct
ath10k
*
ar
)
int
ath10k_core_
register
(
struct
ath10k
*
ar
)
{
int
ret
;
int
status
;
ath10k_dbg
(
ATH10K_DBG_CORE
,
"%s: called"
,
__func__
);
status
=
ath10k_core_probe_fw
(
ar
);
if
(
status
)
{
ath10k_err
(
"could not probe fw (%d)
\n
"
,
status
);
return
status
;
}
ret
=
ath10k_wmi_pdev_resume_target
(
ar
);
if
(
ret
)
ath10k_warn
(
"could not resume target (%d)
\n
"
,
ret
);
status
=
ath10k_mac_register
(
ar
);
if
(
status
)
{
ath10k_err
(
"could not register to mac80211 (%d)
\n
"
,
status
);
goto
err_release_fw
;
}
return
ret
;
status
=
ath10k_debug_create
(
ar
);
if
(
status
)
{
ath10k_err
(
"unable to initialize debugfs
\n
"
);
goto
err_unregister_mac
;
}
return
0
;
err_unregister_mac:
ath10k_mac_unregister
(
ar
);
err_release_fw:
ath10k_core_free_firmware_files
(
ar
);
return
status
;
}
EXPORT_SYMBOL
(
ath10k_core_target_resume
);
EXPORT_SYMBOL
(
ath10k_core_register
);
void
ath10k_core_unregister
(
struct
ath10k
*
ar
)
{
/* We must unregister from mac80211 before we stop HTC and HIF.
* Otherwise we will fail to submit commands to FW and mac80211 will be
* unhappy about callback failures. */
ath10k_mac_unregister
(
ar
);
ath10k_core_free_firmware_files
(
ar
);
}
EXPORT_SYMBOL
(
ath10k_core_unregister
);
MODULE_AUTHOR
(
"Qualcomm Atheros"
);
MODULE_DESCRIPTION
(
"Core module for QCA988X PCIe devices."
);
...
...
drivers/net/wireless/ath/ath10k/core.h
浏览文件 @
1f807827
...
...
@@ -23,6 +23,7 @@
#include <linux/types.h>
#include <linux/pci.h>
#include "htt.h"
#include "htc.h"
#include "hw.h"
#include "targaddrs.h"
...
...
@@ -43,10 +44,6 @@
struct
ath10k
;
enum
ath10k_bus
{
ATH10K_BUS_PCI
,
};
struct
ath10k_skb_cb
{
dma_addr_t
paddr
;
bool
is_mapped
;
...
...
@@ -250,6 +247,28 @@ struct ath10k_debug {
struct
completion
event_stats_compl
;
};
enum
ath10k_state
{
ATH10K_STATE_OFF
=
0
,
ATH10K_STATE_ON
,
/* When doing firmware recovery the device is first powered down.
* mac80211 is supposed to call in to start() hook later on. It is
* however possible that driver unloading and firmware crash overlap.
* mac80211 can wait on conf_mutex in stop() while the device is
* stopped in ath10k_core_restart() work holding conf_mutex. The state
* RESTARTED means that the device is up and mac80211 has started hw
* reconfiguration. Once mac80211 is done with the reconfiguration we
* set the state to STATE_ON in restart_complete(). */
ATH10K_STATE_RESTARTING
,
ATH10K_STATE_RESTARTED
,
/* The device has crashed while restarting hw. This state is like ON
* but commands are blocked in HTC and -ECOMM response is given. This
* prevents completion timeouts and makes the driver more responsive to
* userspace commands. This is also prevents recursive recovery. */
ATH10K_STATE_WEDGED
,
};
struct
ath10k
{
struct
ath_common
ath_common
;
struct
ieee80211_hw
*
hw
;
...
...
@@ -274,19 +293,16 @@ struct ath10k {
struct
{
void
*
priv
;
enum
ath10k_bus
bus
;
const
struct
ath10k_hif_ops
*
ops
;
}
hif
;
struct
ath10k_wmi
wmi
;
wait_queue_head_t
event_queue
;
bool
is_target_paused
;
struct
ath10k_bmi
bmi
;
struct
ath10k_htc
*
htc
;
struct
ath10k_htt
*
htt
;
struct
ath10k_wmi
wmi
;
struct
ath10k_htc
htc
;
struct
ath10k_htt
htt
;
struct
ath10k_hw_params
{
u32
id
;
...
...
@@ -301,6 +317,10 @@ struct ath10k {
}
fw
;
}
hw_params
;
const
struct
firmware
*
board_data
;
const
struct
firmware
*
otp
;
const
struct
firmware
*
firmware
;
struct
{
struct
completion
started
;
struct
completion
completed
;
...
...
@@ -350,20 +370,22 @@ struct ath10k {
struct
completion
offchan_tx_completed
;
struct
sk_buff
*
offchan_tx_skb
;
enum
ath10k_state
state
;
struct
work_struct
restart_work
;
#ifdef CONFIG_ATH10K_DEBUGFS
struct
ath10k_debug
debug
;
#endif
};
struct
ath10k
*
ath10k_core_create
(
void
*
hif_priv
,
struct
device
*
dev
,
enum
ath10k_bus
bus
,
const
struct
ath10k_hif_ops
*
hif_ops
);
void
ath10k_core_destroy
(
struct
ath10k
*
ar
);
int
ath10k_core_start
(
struct
ath10k
*
ar
);
void
ath10k_core_stop
(
struct
ath10k
*
ar
);
int
ath10k_core_register
(
struct
ath10k
*
ar
);
void
ath10k_core_unregister
(
struct
ath10k
*
ar
);
int
ath10k_core_target_suspend
(
struct
ath10k
*
ar
);
int
ath10k_core_target_resume
(
struct
ath10k
*
ar
);
#endif
/* _CORE_H_ */
drivers/net/wireless/ath/ath10k/debug.c
浏览文件 @
1f807827
...
...
@@ -161,7 +161,7 @@ void ath10k_debug_read_target_stats(struct ath10k *ar,
struct
wmi_pdev_stats
*
ps
;
int
i
;
mutex_lock
(
&
ar
->
conf_mutex
);
spin_lock_bh
(
&
ar
->
data_lock
);
stats
=
&
ar
->
debug
.
target_stats
;
...
...
@@ -259,6 +259,7 @@ void ath10k_debug_read_target_stats(struct ath10k *ar,
}
}
spin_unlock_bh
(
&
ar
->
data_lock
);
mutex_unlock
(
&
ar
->
conf_mutex
);
complete
(
&
ar
->
debug
.
event_stats_compl
);
}
...
...
@@ -268,35 +269,35 @@ static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf,
{
struct
ath10k
*
ar
=
file
->
private_data
;
struct
ath10k_target_stats
*
fw_stats
;
char
*
buf
;
char
*
buf
=
NULL
;
unsigned
int
len
=
0
,
buf_len
=
2500
;
ssize_t
ret_cnt
;
ssize_t
ret_cnt
=
0
;
long
left
;
int
i
;
int
ret
;
fw_stats
=
&
ar
->
debug
.
target_stats
;
mutex_lock
(
&
ar
->
conf_mutex
);
if
(
ar
->
state
!=
ATH10K_STATE_ON
)
goto
exit
;
buf
=
kzalloc
(
buf_len
,
GFP_KERNEL
);
if
(
!
buf
)
return
-
ENOMEM
;
goto
exit
;
ret
=
ath10k_wmi_request_stats
(
ar
,
WMI_REQUEST_PEER_STAT
);
if
(
ret
)
{
ath10k_warn
(
"could not request stats (%d)
\n
"
,
ret
);
kfree
(
buf
);
return
-
EIO
;
goto
exit
;
}
left
=
wait_for_completion_timeout
(
&
ar
->
debug
.
event_stats_compl
,
1
*
HZ
);
if
(
left
<=
0
)
goto
exit
;
if
(
left
<=
0
)
{
kfree
(
buf
);
return
-
ETIMEDOUT
;
}
mutex_lock
(
&
ar
->
conf_mutex
);
spin_lock_bh
(
&
ar
->
data_lock
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"
\n
"
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"%30s
\n
"
,
"ath10k PDEV stats"
);
...
...
@@ -424,14 +425,15 @@ static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf,
fw_stats
->
peer_stat
[
i
].
peer_tx_rate
);
len
+=
scnprintf
(
buf
+
len
,
buf_len
-
len
,
"
\n
"
);
}
spin_unlock_bh
(
&
ar
->
data_lock
);
if
(
len
>
buf_len
)
len
=
buf_len
;
ret_cnt
=
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
buf
,
len
);
exit:
mutex_unlock
(
&
ar
->
conf_mutex
);
kfree
(
buf
);
return
ret_cnt
;
}
...
...
@@ -443,6 +445,60 @@ static const struct file_operations fops_fw_stats = {
.
llseek
=
default_llseek
,
};
static
ssize_t
ath10k_read_simulate_fw_crash
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
const
char
buf
[]
=
"To simulate firmware crash write the keyword"
" `crash` to this file.
\n
This will force firmware"
" to report a crash to the host system.
\n
"
;
return
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
buf
,
strlen
(
buf
));
}
static
ssize_t
ath10k_write_simulate_fw_crash
(
struct
file
*
file
,
const
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
ath10k
*
ar
=
file
->
private_data
;
char
buf
[
32
]
=
{};
int
ret
;
mutex_lock
(
&
ar
->
conf_mutex
);
simple_write_to_buffer
(
buf
,
sizeof
(
buf
)
-
1
,
ppos
,
user_buf
,
count
);
if
(
strcmp
(
buf
,
"crash"
)
&&
strcmp
(
buf
,
"crash
\n
"
))
{
ret
=
-
EINVAL
;
goto
exit
;
}
if
(
ar
->
state
!=
ATH10K_STATE_ON
&&
ar
->
state
!=
ATH10K_STATE_RESTARTED
)
{
ret
=
-
ENETDOWN
;
goto
exit
;
}
ath10k_info
(
"simulating firmware crash
\n
"
);
ret
=
ath10k_wmi_force_fw_hang
(
ar
,
WMI_FORCE_FW_HANG_ASSERT
,
0
);
if
(
ret
)
ath10k_warn
(
"failed to force fw hang (%d)
\n
"
,
ret
);
if
(
ret
==
0
)
ret
=
count
;
exit:
mutex_unlock
(
&
ar
->
conf_mutex
);
return
ret
;
}
static
const
struct
file_operations
fops_simulate_fw_crash
=
{
.
read
=
ath10k_read_simulate_fw_crash
,
.
write
=
ath10k_write_simulate_fw_crash
,
.
open
=
simple_open
,
.
owner
=
THIS_MODULE
,
.
llseek
=
default_llseek
,
};
int
ath10k_debug_create
(
struct
ath10k
*
ar
)
{
ar
->
debug
.
debugfs_phy
=
debugfs_create_dir
(
"ath10k"
,
...
...
@@ -459,6 +515,9 @@ int ath10k_debug_create(struct ath10k *ar)
debugfs_create_file
(
"wmi_services"
,
S_IRUSR
,
ar
->
debug
.
debugfs_phy
,
ar
,
&
fops_wmi_services
);
debugfs_create_file
(
"simulate_fw_crash"
,
S_IRUSR
,
ar
->
debug
.
debugfs_phy
,
ar
,
&
fops_simulate_fw_crash
);
return
0
;
}
#endif
/* CONFIG_ATH10K_DEBUGFS */
...
...
drivers/net/wireless/ath/ath10k/hif.h
浏览文件 @
1f807827
...
...
@@ -46,8 +46,11 @@ struct ath10k_hif_ops {
void
*
request
,
u32
request_len
,
void
*
response
,
u32
*
response_len
);
/* Post BMI phase, after FW is loaded. Starts regular operation */
int
(
*
start
)(
struct
ath10k
*
ar
);
/* Clean up what start() did. This does not revert to BMI phase. If
* desired so, call power_down() and power_up() */
void
(
*
stop
)(
struct
ath10k
*
ar
);
int
(
*
map_service_to_pipe
)(
struct
ath10k
*
ar
,
u16
service_id
,
...
...
@@ -66,10 +69,20 @@ struct ath10k_hif_ops {
*/
void
(
*
send_complete_check
)(
struct
ath10k
*
ar
,
u8
pipe_id
,
int
force
);
void
(
*
init
)(
struct
ath10k
*
ar
,
void
(
*
set_callbacks
)(
struct
ath10k
*
ar
,
struct
ath10k_hif_cb
*
callbacks
);
u16
(
*
get_free_queue_number
)(
struct
ath10k
*
ar
,
u8
pipe_id
);
/* Power up the device and enter BMI transfer mode for FW download */
int
(
*
power_up
)(
struct
ath10k
*
ar
);
/* Power down the device and free up resources. stop() must be called
* before this if start() was called earlier */
void
(
*
power_down
)(
struct
ath10k
*
ar
);
int
(
*
suspend
)(
struct
ath10k
*
ar
);
int
(
*
resume
)(
struct
ath10k
*
ar
);
};
...
...
@@ -122,10 +135,10 @@ static inline void ath10k_hif_send_complete_check(struct ath10k *ar,
ar
->
hif
.
ops
->
send_complete_check
(
ar
,
pipe_id
,
force
);
}
static
inline
void
ath10k_hif_
init
(
struct
ath10k
*
ar
,
static
inline
void
ath10k_hif_
set_callbacks
(
struct
ath10k
*
ar
,
struct
ath10k_hif_cb
*
callbacks
)
{
ar
->
hif
.
ops
->
init
(
ar
,
callbacks
);
ar
->
hif
.
ops
->
set_callbacks
(
ar
,
callbacks
);
}
static
inline
u16
ath10k_hif_get_free_queue_number
(
struct
ath10k
*
ar
,
...
...
@@ -134,4 +147,30 @@ static inline u16 ath10k_hif_get_free_queue_number(struct ath10k *ar,
return
ar
->
hif
.
ops
->
get_free_queue_number
(
ar
,
pipe_id
);
}
static
inline
int
ath10k_hif_power_up
(
struct
ath10k
*
ar
)
{
return
ar
->
hif
.
ops
->
power_up
(
ar
);
}
static
inline
void
ath10k_hif_power_down
(
struct
ath10k
*
ar
)
{
ar
->
hif
.
ops
->
power_down
(
ar
);
}
static
inline
int
ath10k_hif_suspend
(
struct
ath10k
*
ar
)
{
if
(
!
ar
->
hif
.
ops
->
suspend
)
return
-
EOPNOTSUPP
;
return
ar
->
hif
.
ops
->
suspend
(
ar
);
}
static
inline
int
ath10k_hif_resume
(
struct
ath10k
*
ar
)
{
if
(
!
ar
->
hif
.
ops
->
resume
)
return
-
EOPNOTSUPP
;
return
ar
->
hif
.
ops
->
resume
(
ar
);
}
#endif
/* _HIF_H_ */
drivers/net/wireless/ath/ath10k/htc.c
浏览文件 @
1f807827
...
...
@@ -246,15 +246,22 @@ int ath10k_htc_send(struct ath10k_htc *htc,
{
struct
ath10k_htc_ep
*
ep
=
&
htc
->
endpoint
[
eid
];
if
(
htc
->
ar
->
state
==
ATH10K_STATE_WEDGED
)
return
-
ECOMM
;
if
(
eid
>=
ATH10K_HTC_EP_COUNT
)
{
ath10k_warn
(
"Invalid endpoint id: %d
\n
"
,
eid
);
return
-
ENOENT
;
}
skb_push
(
skb
,
sizeof
(
struct
ath10k_htc_hdr
));
spin_lock_bh
(
&
htc
->
tx_lock
);
if
(
htc
->
stopped
)
{
spin_unlock_bh
(
&
htc
->
tx_lock
);
return
-
ESHUTDOWN
;
}
__skb_queue_tail
(
&
ep
->
tx_queue
,
skb
);
skb_push
(
skb
,
sizeof
(
struct
ath10k_htc_hdr
));
spin_unlock_bh
(
&
htc
->
tx_lock
);
queue_work
(
htc
->
ar
->
workqueue
,
&
ep
->
send_work
);
...
...
@@ -265,25 +272,19 @@ static int ath10k_htc_tx_completion_handler(struct ath10k *ar,
struct
sk_buff
*
skb
,
unsigned
int
eid
)
{
struct
ath10k_htc
*
htc
=
ar
->
htc
;
struct
ath10k_htc
*
htc
=
&
ar
->
htc
;
struct
ath10k_htc_ep
*
ep
=
&
htc
->
endpoint
[
eid
];
bool
stopping
;
ath10k_htc_notify_tx_completion
(
ep
,
skb
);
/* the skb now belongs to the completion handler */
/* note: when using TX credit flow, the re-checking of queues happens
* when credits flow back from the target. in the non-TX credit case,
* we recheck after the packet completes */
spin_lock_bh
(
&
htc
->
tx_lock
);
stopping
=
htc
->
stopping
;
spin_unlock_bh
(
&
htc
->
tx_lock
);
if
(
!
ep
->
tx_credit_flow_enabled
&&
!
stopping
)
/*
* note: when using TX credit flow, the re-checking of
* queues happens when credits flow back from the target.
* in the non-TX credit case, we recheck after the packet
* completes
*/
if
(
!
ep
->
tx_credit_flow_enabled
&&
!
htc
->
stopped
)
queue_work
(
ar
->
workqueue
,
&
ep
->
send_work
);
spin_unlock_bh
(
&
htc
->
tx_lock
);
return
0
;
}
...
...
@@ -414,7 +415,7 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar,
u8
pipe_id
)
{
int
status
=
0
;
struct
ath10k_htc
*
htc
=
ar
->
htc
;
struct
ath10k_htc
*
htc
=
&
ar
->
htc
;
struct
ath10k_htc_hdr
*
hdr
;
struct
ath10k_htc_ep
*
ep
;
u16
payload_len
;
...
...
@@ -751,7 +752,8 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc,
tx_alloc
=
ath10k_htc_get_credit_allocation
(
htc
,
conn_req
->
service_id
);
if
(
!
tx_alloc
)
ath10k_warn
(
"HTC Service %s does not allocate target credits
\n
"
,
ath10k_dbg
(
ATH10K_DBG_HTC
,
"HTC Service %s does not allocate target credits
\n
"
,
htc_service_name
(
conn_req
->
service_id
));
skb
=
ath10k_htc_build_tx_ctrl_skb
(
htc
->
ar
);
...
...
@@ -947,7 +949,7 @@ void ath10k_htc_stop(struct ath10k_htc *htc)
struct
ath10k_htc_ep
*
ep
;
spin_lock_bh
(
&
htc
->
tx_lock
);
htc
->
stopp
ing
=
true
;
htc
->
stopp
ed
=
true
;
spin_unlock_bh
(
&
htc
->
tx_lock
);
for
(
i
=
ATH10K_HTC_EP_0
;
i
<
ATH10K_HTC_EP_COUNT
;
i
++
)
{
...
...
@@ -956,26 +958,18 @@ void ath10k_htc_stop(struct ath10k_htc *htc)
}
ath10k_hif_stop
(
htc
->
ar
);
ath10k_htc_reset_endpoint_states
(
htc
);
}
/* registered target arrival callback from the HIF layer */
struct
ath10k_htc
*
ath10k_htc_create
(
struct
ath10k
*
ar
,
struct
ath10k_htc_ops
*
htc_ops
)
int
ath10k_htc_init
(
struct
ath10k
*
ar
)
{
struct
ath10k_hif_cb
htc_callbacks
;
struct
ath10k_htc_ep
*
ep
=
NULL
;
struct
ath10k_htc
*
htc
=
NULL
;
/* FIXME: use struct ath10k instead */
htc
=
kzalloc
(
sizeof
(
struct
ath10k_htc
),
GFP_KERNEL
);
if
(
!
htc
)
return
ERR_PTR
(
-
ENOMEM
);
struct
ath10k_htc
*
htc
=
&
ar
->
htc
;
spin_lock_init
(
&
htc
->
tx_lock
);
memcpy
(
&
htc
->
htc_ops
,
htc_ops
,
sizeof
(
struct
ath10k_htc_ops
));
htc
->
stopped
=
false
;
ath10k_htc_reset_endpoint_states
(
htc
);
/* setup HIF layer callbacks */
...
...
@@ -986,15 +980,10 @@ struct ath10k_htc *ath10k_htc_create(struct ath10k *ar,
/* Get HIF default pipe for HTC message exchange */
ep
=
&
htc
->
endpoint
[
ATH10K_HTC_EP_0
];
ath10k_hif_
init
(
ar
,
&
htc_callbacks
);
ath10k_hif_
set_callbacks
(
ar
,
&
htc_callbacks
);
ath10k_hif_get_default_pipe
(
ar
,
&
ep
->
ul_pipe_id
,
&
ep
->
dl_pipe_id
);
init_completion
(
&
htc
->
ctl_resp
);
return
htc
;
}
void
ath10k_htc_destroy
(
struct
ath10k_htc
*
htc
)
{
kfree
(
htc
);
return
0
;
}
drivers/net/wireless/ath/ath10k/htc.h
浏览文件 @
1f807827
...
...
@@ -335,7 +335,7 @@ struct ath10k_htc {
struct
ath10k
*
ar
;
struct
ath10k_htc_ep
endpoint
[
ATH10K_HTC_EP_COUNT
];
/* protects endpoint and stopp
ing
fields */
/* protects endpoint and stopp
ed
fields */
spinlock_t
tx_lock
;
struct
ath10k_htc_ops
htc_ops
;
...
...
@@ -349,11 +349,10 @@ struct ath10k_htc {
struct
ath10k_htc_svc_tx_credits
service_tx_alloc
[
ATH10K_HTC_EP_COUNT
];
int
target_credit_size
;
bool
stopp
ing
;
bool
stopp
ed
;
};
struct
ath10k_htc
*
ath10k_htc_create
(
struct
ath10k
*
ar
,
struct
ath10k_htc_ops
*
htc_ops
);
int
ath10k_htc_init
(
struct
ath10k
*
ar
);
int
ath10k_htc_wait_target
(
struct
ath10k_htc
*
htc
);
int
ath10k_htc_start
(
struct
ath10k_htc
*
htc
);
int
ath10k_htc_connect_service
(
struct
ath10k_htc
*
htc
,
...
...
@@ -362,7 +361,6 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc,
int
ath10k_htc_send
(
struct
ath10k_htc
*
htc
,
enum
ath10k_htc_ep_id
eid
,
struct
sk_buff
*
packet
);
void
ath10k_htc_stop
(
struct
ath10k_htc
*
htc
);
void
ath10k_htc_destroy
(
struct
ath10k_htc
*
htc
);
struct
sk_buff
*
ath10k_htc_alloc_skb
(
int
size
);
#endif
drivers/net/wireless/ath/ath10k/htt.c
浏览文件 @
1f807827
...
...
@@ -16,6 +16,7 @@
*/
#include <linux/slab.h>
#include <linux/if_ether.h>
#include "htt.h"
#include "core.h"
...
...
@@ -36,7 +37,7 @@ static int ath10k_htt_htc_attach(struct ath10k_htt *htt)
/* connect to control service */
conn_req
.
service_id
=
ATH10K_HTC_SVC_ID_HTT_DATA_MSG
;
status
=
ath10k_htc_connect_service
(
htt
->
ar
->
htc
,
&
conn_req
,
status
=
ath10k_htc_connect_service
(
&
htt
->
ar
->
htc
,
&
conn_req
,
&
conn_resp
);
if
(
status
)
...
...
@@ -47,15 +48,11 @@ static int ath10k_htt_htc_attach(struct ath10k_htt *htt)
return
0
;
}
struct
ath10k_htt
*
ath10k_htt_attach
(
struct
ath10k
*
ar
)
int
ath10k_htt_attach
(
struct
ath10k
*
ar
)
{
struct
ath10k_htt
*
htt
;
struct
ath10k_htt
*
htt
=
&
ar
->
htt
;
int
ret
;
htt
=
kzalloc
(
sizeof
(
*
htt
),
GFP_KERNEL
);
if
(
!
htt
)
return
NULL
;
htt
->
ar
=
ar
;
htt
->
max_throughput_mbps
=
800
;
...
...
@@ -65,8 +62,11 @@ struct ath10k_htt *ath10k_htt_attach(struct ath10k *ar)
* since ath10k_htt_rx_attach involves sending a rx ring configure
* message to the target.
*/
if
(
ath10k_htt_htc_attach
(
htt
))
ret
=
ath10k_htt_htc_attach
(
htt
);
if
(
ret
)
{
ath10k_err
(
"could not attach htt htc (%d)
\n
"
,
ret
);
goto
err_htc_attach
;
}
ret
=
ath10k_htt_tx_attach
(
htt
);
if
(
ret
)
{
...
...
@@ -74,8 +74,11 @@ struct ath10k_htt *ath10k_htt_attach(struct ath10k *ar)
goto
err_htc_attach
;
}
if
(
ath10k_htt_rx_attach
(
htt
))
ret
=
ath10k_htt_rx_attach
(
htt
);
if
(
ret
)
{
ath10k_err
(
"could not attach htt rx (%d)
\n
"
,
ret
);
goto
err_rx_attach
;
}
/*
* Prefetch enough data to satisfy target
...
...
@@ -89,13 +92,12 @@ struct ath10k_htt *ath10k_htt_attach(struct ath10k *ar)
8
+
/* llc snap */
2
;
/* ip4 dscp or ip6 priority */
return
htt
;
return
0
;
err_rx_attach:
ath10k_htt_tx_detach
(
htt
);
err_htc_attach:
kfree
(
htt
);
return
NULL
;
return
ret
;
}
#define HTT_TARGET_VERSION_TIMEOUT_HZ (3*HZ)
...
...
@@ -148,5 +150,4 @@ void ath10k_htt_detach(struct ath10k_htt *htt)
{
ath10k_htt_rx_detach
(
htt
);
ath10k_htt_tx_detach
(
htt
);
kfree
(
htt
);
}
drivers/net/wireless/ath/ath10k/htt.h
浏览文件 @
1f807827
...
...
@@ -20,7 +20,6 @@
#include <linux/bug.h>
#include "core.h"
#include "htc.h"
#include "rx_desc.h"
...
...
@@ -1317,7 +1316,7 @@ struct htt_rx_desc {
#define HTT_LOG2_MAX_CACHE_LINE_SIZE 7
/* 2^7 = 128 */
#define HTT_MAX_CACHE_LINE_SIZE_MASK ((1 << HTT_LOG2_MAX_CACHE_LINE_SIZE) - 1)
struct
ath10k_htt
*
ath10k_htt_attach
(
struct
ath10k
*
ar
);
int
ath10k_htt_attach
(
struct
ath10k
*
ar
);
int
ath10k_htt_attach_target
(
struct
ath10k_htt
*
htt
);
void
ath10k_htt_detach
(
struct
ath10k_htt
*
htt
);
...
...
drivers/net/wireless/ath/ath10k/htt_rx.c
浏览文件 @
1f807827
...
...
@@ -15,6 +15,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "core.h"
#include "htc.h"
#include "htt.h"
#include "txrx.h"
...
...
@@ -1036,7 +1037,7 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
void
ath10k_htt_t2h_msg_handler
(
struct
ath10k
*
ar
,
struct
sk_buff
*
skb
)
{
struct
ath10k_htt
*
htt
=
ar
->
htt
;
struct
ath10k_htt
*
htt
=
&
ar
->
htt
;
struct
htt_resp
*
resp
=
(
struct
htt_resp
*
)
skb
->
data
;
/* confirm alignment */
...
...
drivers/net/wireless/ath/ath10k/htt_tx.c
浏览文件 @
1f807827
...
...
@@ -92,7 +92,7 @@ int ath10k_htt_tx_attach(struct ath10k_htt *htt)
/* At the beginning free queue number should hint us the maximum
* queue length */
pipe
=
htt
->
ar
->
htc
->
endpoint
[
htt
->
eid
].
ul_pipe_id
;
pipe
=
htt
->
ar
->
htc
.
endpoint
[
htt
->
eid
].
ul_pipe_id
;
htt
->
max_num_pending_tx
=
ath10k_hif_get_free_queue_number
(
htt
->
ar
,
pipe
);
...
...
@@ -153,7 +153,7 @@ void ath10k_htt_tx_detach(struct ath10k_htt *htt)
void
ath10k_htt_htc_tx_complete
(
struct
ath10k
*
ar
,
struct
sk_buff
*
skb
)
{
struct
ath10k_skb_cb
*
skb_cb
=
ATH10K_SKB_CB
(
skb
);
struct
ath10k_htt
*
htt
=
ar
->
htt
;
struct
ath10k_htt
*
htt
=
&
ar
->
htt
;
if
(
skb_cb
->
htt
.
is_conf
)
{
dev_kfree_skb_any
(
skb
);
...
...
@@ -194,7 +194,7 @@ int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt)
ATH10K_SKB_CB
(
skb
)
->
htt
.
is_conf
=
true
;
ret
=
ath10k_htc_send
(
htt
->
ar
->
htc
,
htt
->
eid
,
skb
);
ret
=
ath10k_htc_send
(
&
htt
->
ar
->
htc
,
htt
->
eid
,
skb
);
if
(
ret
)
{
dev_kfree_skb_any
(
skb
);
return
ret
;
...
...
@@ -281,7 +281,7 @@ int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt)
ATH10K_SKB_CB
(
skb
)
->
htt
.
is_conf
=
true
;
ret
=
ath10k_htc_send
(
htt
->
ar
->
htc
,
htt
->
eid
,
skb
);
ret
=
ath10k_htc_send
(
&
htt
->
ar
->
htc
,
htt
->
eid
,
skb
);
if
(
ret
)
{
dev_kfree_skb_any
(
skb
);
return
ret
;
...
...
@@ -346,7 +346,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
skb_cb
->
htt
.
refcount
=
2
;
skb_cb
->
htt
.
msdu
=
msdu
;
res
=
ath10k_htc_send
(
htt
->
ar
->
htc
,
htt
->
eid
,
txdesc
);
res
=
ath10k_htc_send
(
&
htt
->
ar
->
htc
,
htt
->
eid
,
txdesc
);
if
(
res
)
goto
err
;
...
...
@@ -486,7 +486,7 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
skb_cb
->
htt
.
txfrag
=
txfrag
;
skb_cb
->
htt
.
msdu
=
msdu
;
res
=
ath10k_htc_send
(
htt
->
ar
->
htc
,
htt
->
eid
,
txdesc
);
res
=
ath10k_htc_send
(
&
htt
->
ar
->
htc
,
htt
->
eid
,
txdesc
);
if
(
res
)
goto
err
;
...
...
drivers/net/wireless/ath/ath10k/mac.c
浏览文件 @
1f807827
此差异已折叠。
点击以展开。
drivers/net/wireless/ath/ath10k/mac.h
浏览文件 @
1f807827
...
...
@@ -34,6 +34,7 @@ struct ath10k_vif *ath10k_get_arvif(struct ath10k *ar, u32 vdev_id);
void
ath10k_reset_scan
(
unsigned
long
ptr
);
void
ath10k_offchan_tx_purge
(
struct
ath10k
*
ar
);
void
ath10k_offchan_tx_work
(
struct
work_struct
*
work
);
void
ath10k_halt
(
struct
ath10k
*
ar
);
static
inline
struct
ath10k_vif
*
ath10k_vif_to_arvif
(
struct
ieee80211_vif
*
vif
)
{
...
...
drivers/net/wireless/ath/ath10k/pci.c
浏览文件 @
1f807827
...
...
@@ -54,6 +54,8 @@ static int ath10k_pci_post_rx_pipe(struct hif_ce_pipe_info *pipe_info,
int
num
);
static
void
ath10k_pci_rx_pipe_cleanup
(
struct
hif_ce_pipe_info
*
pipe_info
);
static
void
ath10k_pci_stop_ce
(
struct
ath10k
*
ar
);
static
void
ath10k_pci_device_reset
(
struct
ath10k
*
ar
);
static
int
ath10k_pci_reset_target
(
struct
ath10k
*
ar
);
static
const
struct
ce_attr
host_ce_config_wlan
[]
=
{
/* host->target HTC control and raw streams */
...
...
@@ -718,6 +720,8 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar)
reg_dump_values
[
i
+
1
],
reg_dump_values
[
i
+
2
],
reg_dump_values
[
i
+
3
]);
ieee80211_queue_work
(
ar
->
hw
,
&
ar
->
restart_work
);
}
static
void
ath10k_pci_hif_send_complete_check
(
struct
ath10k
*
ar
,
u8
pipe
,
...
...
@@ -744,7 +748,7 @@ static void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe,
ath10k_ce_per_engine_service
(
ar
,
pipe
);
}
static
void
ath10k_pci_hif_
post_init
(
struct
ath10k
*
ar
,
static
void
ath10k_pci_hif_
set_callbacks
(
struct
ath10k
*
ar
,
struct
ath10k_hif_cb
*
callbacks
)
{
struct
ath10k_pci
*
ar_pci
=
ath10k_pci_priv
(
ar
);
...
...
@@ -1263,7 +1267,6 @@ static void ath10k_pci_hif_stop(struct ath10k *ar)
ath10k_pci_process_ce
(
ar
);
ath10k_pci_cleanup_ce
(
ar
);
ath10k_pci_buffer_cleanup
(
ar
);
ath10k_pci_ce_deinit
(
ar
);
}
static
int
ath10k_pci_hif_exchange_bmi_msg
(
struct
ath10k
*
ar
,
...
...
@@ -1735,6 +1738,115 @@ static void ath10k_pci_fw_interrupt_handler(struct ath10k *ar)
ath10k_pci_sleep
(
ar
);
}
static
int
ath10k_pci_hif_power_up
(
struct
ath10k
*
ar
)
{
int
ret
;
/*
* Bring the target up cleanly.
*
* The target may be in an undefined state with an AUX-powered Target
* and a Host in WoW mode. If the Host crashes, loses power, or is
* restarted (without unloading the driver) then the Target is left
* (aux) powered and running. On a subsequent driver load, the Target
* is in an unexpected state. We try to catch that here in order to
* reset the Target and retry the probe.
*/
ath10k_pci_device_reset
(
ar
);
ret
=
ath10k_pci_reset_target
(
ar
);
if
(
ret
)
goto
err
;
if
(
ath10k_target_ps
)
{
ath10k_dbg
(
ATH10K_DBG_PCI
,
"on-chip power save enabled
\n
"
);
}
else
{
/* Force AWAKE forever */
ath10k_dbg
(
ATH10K_DBG_PCI
,
"on-chip power save disabled
\n
"
);
ath10k_do_pci_wake
(
ar
);
}
ret
=
ath10k_pci_ce_init
(
ar
);
if
(
ret
)
goto
err_ps
;
ret
=
ath10k_pci_init_config
(
ar
);
if
(
ret
)
goto
err_ce
;
ret
=
ath10k_pci_wake_target_cpu
(
ar
);
if
(
ret
)
{
ath10k_err
(
"could not wake up target CPU (%d)
\n
"
,
ret
);
goto
err_ce
;
}
return
0
;
err_ce:
ath10k_pci_ce_deinit
(
ar
);
err_ps:
if
(
!
ath10k_target_ps
)
ath10k_do_pci_sleep
(
ar
);
err:
return
ret
;
}
static
void
ath10k_pci_hif_power_down
(
struct
ath10k
*
ar
)
{
ath10k_pci_ce_deinit
(
ar
);
if
(
!
ath10k_target_ps
)
ath10k_do_pci_sleep
(
ar
);
}
#ifdef CONFIG_PM
#define ATH10K_PCI_PM_CONTROL 0x44
static
int
ath10k_pci_hif_suspend
(
struct
ath10k
*
ar
)
{
struct
ath10k_pci
*
ar_pci
=
ath10k_pci_priv
(
ar
);
struct
pci_dev
*
pdev
=
ar_pci
->
pdev
;
u32
val
;
pci_read_config_dword
(
pdev
,
ATH10K_PCI_PM_CONTROL
,
&
val
);
if
((
val
&
0x000000ff
)
!=
0x3
)
{
pci_save_state
(
pdev
);
pci_disable_device
(
pdev
);
pci_write_config_dword
(
pdev
,
ATH10K_PCI_PM_CONTROL
,
(
val
&
0xffffff00
)
|
0x03
);
}
return
0
;
}
static
int
ath10k_pci_hif_resume
(
struct
ath10k
*
ar
)
{
struct
ath10k_pci
*
ar_pci
=
ath10k_pci_priv
(
ar
);
struct
pci_dev
*
pdev
=
ar_pci
->
pdev
;
u32
val
;
pci_read_config_dword
(
pdev
,
ATH10K_PCI_PM_CONTROL
,
&
val
);
if
((
val
&
0x000000ff
)
!=
0
)
{
pci_restore_state
(
pdev
);
pci_write_config_dword
(
pdev
,
ATH10K_PCI_PM_CONTROL
,
val
&
0xffffff00
);
/*
* Suspend/Resume resets the PCI configuration space,
* so we have to re-disable the RETRY_TIMEOUT register (0x41)
* to keep PCI Tx retries from interfering with C3 CPU state
*/
pci_read_config_dword
(
pdev
,
0x40
,
&
val
);
if
((
val
&
0x0000ff00
)
!=
0
)
pci_write_config_dword
(
pdev
,
0x40
,
val
&
0xffff00ff
);
}
return
0
;
}
#endif
static
const
struct
ath10k_hif_ops
ath10k_pci_hif_ops
=
{
.
send_head
=
ath10k_pci_hif_send_head
,
.
exchange_bmi_msg
=
ath10k_pci_hif_exchange_bmi_msg
,
...
...
@@ -1743,8 +1855,14 @@ static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
.
map_service_to_pipe
=
ath10k_pci_hif_map_service_to_pipe
,
.
get_default_pipe
=
ath10k_pci_hif_get_default_pipe
,
.
send_complete_check
=
ath10k_pci_hif_send_complete_check
,
.
init
=
ath10k_pci_hif_post_init
,
.
set_callbacks
=
ath10k_pci_hif_set_callbacks
,
.
get_free_queue_number
=
ath10k_pci_hif_get_free_queue_number
,
.
power_up
=
ath10k_pci_hif_power_up
,
.
power_down
=
ath10k_pci_hif_power_down
,
#ifdef CONFIG_PM
.
suspend
=
ath10k_pci_hif_suspend
,
.
resume
=
ath10k_pci_hif_resume
,
#endif
};
static
void
ath10k_pci_ce_tasklet
(
unsigned
long
ptr
)
...
...
@@ -2059,9 +2177,9 @@ static int ath10k_pci_reset_target(struct ath10k *ar)
return
0
;
}
static
void
ath10k_pci_device_reset
(
struct
ath10k
_pci
*
ar_pci
)
static
void
ath10k_pci_device_reset
(
struct
ath10k
*
ar
)
{
struct
ath10k
*
ar
=
ar_pci
->
ar
;
struct
ath10k
_pci
*
ar_pci
=
ath10k_pci_priv
(
ar
)
;
void
__iomem
*
mem
=
ar_pci
->
mem
;
int
i
;
u32
val
;
...
...
@@ -2118,7 +2236,7 @@ static void ath10k_pci_dump_features(struct ath10k_pci *ar_pci)
case
ATH10K_PCI_FEATURE_MSI_X
:
ath10k_dbg
(
ATH10K_DBG_PCI
,
"device supports MSI-X
\n
"
);
break
;
case
ATH10K_PCI_FEATURE_HW_1_0_W
A
RKAROUND
:
case
ATH10K_PCI_FEATURE_HW_1_0_W
O
RKAROUND
:
ath10k_dbg
(
ATH10K_DBG_PCI
,
"QCA988X_1.0 workaround enabled
\n
"
);
break
;
}
...
...
@@ -2145,7 +2263,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
switch
(
pci_dev
->
device
)
{
case
QCA988X_1_0_DEVICE_ID
:
set_bit
(
ATH10K_PCI_FEATURE_HW_1_0_W
A
RKAROUND
,
ar_pci
->
features
);
set_bit
(
ATH10K_PCI_FEATURE_HW_1_0_W
O
RKAROUND
,
ar_pci
->
features
);
break
;
case
QCA988X_2_0_DEVICE_ID
:
set_bit
(
ATH10K_PCI_FEATURE_MSI_X
,
ar_pci
->
features
);
...
...
@@ -2158,8 +2276,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
ath10k_pci_dump_features
(
ar_pci
);
ar
=
ath10k_core_create
(
ar_pci
,
ar_pci
->
dev
,
ATH10K_BUS_PCI
,
&
ath10k_pci_hif_ops
);
ar
=
ath10k_core_create
(
ar_pci
,
ar_pci
->
dev
,
&
ath10k_pci_hif_ops
);
if
(
!
ar
)
{
ath10k_err
(
"ath10k_core_create failed!
\n
"
);
ret
=
-
EINVAL
;
...
...
@@ -2167,7 +2284,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
}
/* Enable QCA988X_1.0 HW workarounds */
if
(
test_bit
(
ATH10K_PCI_FEATURE_HW_1_0_W
A
RKAROUND
,
ar_pci
->
features
))
if
(
test_bit
(
ATH10K_PCI_FEATURE_HW_1_0_W
O
RKAROUND
,
ar_pci
->
features
))
spin_lock_init
(
&
ar_pci
->
hw_v1_workaround_lock
);
ar_pci
->
ar
=
ar
;
...
...
@@ -2247,54 +2364,14 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
goto
err_iomap
;
}
/*
* Bring the target up cleanly.
*
* The target may be in an undefined state with an AUX-powered Target
* and a Host in WoW mode. If the Host crashes, loses power, or is
* restarted (without unloading the driver) then the Target is left
* (aux) powered and running. On a subsequent driver load, the Target
* is in an unexpected state. We try to catch that here in order to
* reset the Target and retry the probe.
*/
ath10k_pci_device_reset
(
ar_pci
);
ret
=
ath10k_pci_reset_target
(
ar
);
if
(
ret
)
goto
err_intr
;
if
(
ath10k_target_ps
)
{
ath10k_dbg
(
ATH10K_DBG_PCI
,
"on-chip power save enabled
\n
"
);
}
else
{
/* Force AWAKE forever */
ath10k_dbg
(
ATH10K_DBG_PCI
,
"on-chip power save disabled
\n
"
);
ath10k_do_pci_wake
(
ar
);
}
ret
=
ath10k_pci_ce_init
(
ar
);
if
(
ret
)
goto
err_intr
;
ret
=
ath10k_pci_init_config
(
ar
);
if
(
ret
)
goto
err_ce
;
ret
=
ath10k_pci_wake_target_cpu
(
ar
);
if
(
ret
)
{
ath10k_err
(
"could not wake up target CPU (%d)
\n
"
,
ret
);
goto
err_ce
;
}
ret
=
ath10k_core_register
(
ar
);
if
(
ret
)
{
ath10k_err
(
"could not register driver core (%d)
\n
"
,
ret
);
goto
err_
ce
;
goto
err_
intr
;
}
return
0
;
err_ce:
ath10k_pci_ce_deinit
(
ar
);
err_intr:
ath10k_pci_stop_intr
(
ar
);
err_iomap:
...
...
@@ -2345,128 +2422,6 @@ static void ath10k_pci_remove(struct pci_dev *pdev)
kfree
(
ar_pci
);
}
#if defined(CONFIG_PM_SLEEP)
#define ATH10K_PCI_PM_CONTROL 0x44
static
int
ath10k_pci_suspend
(
struct
device
*
device
)
{
struct
pci_dev
*
pdev
=
to_pci_dev
(
device
);
struct
ath10k
*
ar
=
pci_get_drvdata
(
pdev
);
struct
ath10k_pci
*
ar_pci
;
u32
val
;
int
ret
,
retval
;
ath10k_dbg
(
ATH10K_DBG_PCI
,
"%s
\n
"
,
__func__
);
if
(
!
ar
)
return
-
ENODEV
;
ar_pci
=
ath10k_pci_priv
(
ar
);
if
(
!
ar_pci
)
return
-
ENODEV
;
if
(
ath10k_core_target_suspend
(
ar
))
return
-
EBUSY
;
ret
=
wait_event_interruptible_timeout
(
ar
->
event_queue
,
ar
->
is_target_paused
==
true
,
1
*
HZ
);
if
(
ret
<
0
)
{
ath10k_warn
(
"suspend interrupted (%d)
\n
"
,
ret
);
retval
=
ret
;
goto
resume
;
}
else
if
(
ret
==
0
)
{
ath10k_warn
(
"suspend timed out - target pause event never came
\n
"
);
retval
=
EIO
;
goto
resume
;
}
/*
* reset is_target_paused and host can check that in next time,
* or it will always be TRUE and host just skip the waiting
* condition, it causes target assert due to host already
* suspend
*/
ar
->
is_target_paused
=
false
;
pci_read_config_dword
(
pdev
,
ATH10K_PCI_PM_CONTROL
,
&
val
);
if
((
val
&
0x000000ff
)
!=
0x3
)
{
pci_save_state
(
pdev
);
pci_disable_device
(
pdev
);
pci_write_config_dword
(
pdev
,
ATH10K_PCI_PM_CONTROL
,
(
val
&
0xffffff00
)
|
0x03
);
}
return
0
;
resume:
ret
=
ath10k_core_target_resume
(
ar
);
if
(
ret
)
ath10k_warn
(
"could not resume (%d)
\n
"
,
ret
);
return
retval
;
}
static
int
ath10k_pci_resume
(
struct
device
*
device
)
{
struct
pci_dev
*
pdev
=
to_pci_dev
(
device
);
struct
ath10k
*
ar
=
pci_get_drvdata
(
pdev
);
struct
ath10k_pci
*
ar_pci
;
int
ret
;
u32
val
;
ath10k_dbg
(
ATH10K_DBG_PCI
,
"%s
\n
"
,
__func__
);
if
(
!
ar
)
return
-
ENODEV
;
ar_pci
=
ath10k_pci_priv
(
ar
);
if
(
!
ar_pci
)
return
-
ENODEV
;
ret
=
pci_enable_device
(
pdev
);
if
(
ret
)
{
ath10k_warn
(
"cannot enable PCI device: %d
\n
"
,
ret
);
return
ret
;
}
pci_read_config_dword
(
pdev
,
ATH10K_PCI_PM_CONTROL
,
&
val
);
if
((
val
&
0x000000ff
)
!=
0
)
{
pci_restore_state
(
pdev
);
pci_write_config_dword
(
pdev
,
ATH10K_PCI_PM_CONTROL
,
val
&
0xffffff00
);
/*
* Suspend/Resume resets the PCI configuration space,
* so we have to re-disable the RETRY_TIMEOUT register (0x41)
* to keep PCI Tx retries from interfering with C3 CPU state
*/
pci_read_config_dword
(
pdev
,
0x40
,
&
val
);
if
((
val
&
0x0000ff00
)
!=
0
)
pci_write_config_dword
(
pdev
,
0x40
,
val
&
0xffff00ff
);
}
ret
=
ath10k_core_target_resume
(
ar
);
if
(
ret
)
ath10k_warn
(
"target resume failed: %d
\n
"
,
ret
);
return
ret
;
}
static
SIMPLE_DEV_PM_OPS
(
ath10k_dev_pm_ops
,
ath10k_pci_suspend
,
ath10k_pci_resume
);
#define ATH10K_PCI_PM_OPS (&ath10k_dev_pm_ops)
#else
#define ATH10K_PCI_PM_OPS NULL
#endif
/* CONFIG_PM_SLEEP */
MODULE_DEVICE_TABLE
(
pci
,
ath10k_pci_id_table
);
static
struct
pci_driver
ath10k_pci_driver
=
{
...
...
@@ -2474,7 +2429,6 @@ static struct pci_driver ath10k_pci_driver = {
.
id_table
=
ath10k_pci_id_table
,
.
probe
=
ath10k_pci_probe
,
.
remove
=
ath10k_pci_remove
,
.
driver
.
pm
=
ATH10K_PCI_PM_OPS
,
};
static
int
__init
ath10k_pci_init
(
void
)
...
...
drivers/net/wireless/ath/ath10k/pci.h
浏览文件 @
1f807827
...
...
@@ -152,7 +152,7 @@ struct service_to_pipe {
enum
ath10k_pci_features
{
ATH10K_PCI_FEATURE_MSI_X
=
0
,
ATH10K_PCI_FEATURE_HW_1_0_W
A
RKAROUND
=
1
,
ATH10K_PCI_FEATURE_HW_1_0_W
O
RKAROUND
=
1
,
/* keep last */
ATH10K_PCI_FEATURE_COUNT
...
...
@@ -311,7 +311,7 @@ static inline void ath10k_pci_write32(struct ath10k *ar, u32 offset,
struct
ath10k_pci
*
ar_pci
=
ath10k_pci_priv
(
ar
);
void
__iomem
*
addr
=
ar_pci
->
mem
;
if
(
test_bit
(
ATH10K_PCI_FEATURE_HW_1_0_W
A
RKAROUND
,
ar_pci
->
features
))
{
if
(
test_bit
(
ATH10K_PCI_FEATURE_HW_1_0_W
O
RKAROUND
,
ar_pci
->
features
))
{
unsigned
long
irq_flags
;
spin_lock_irqsave
(
&
ar_pci
->
hw_v1_workaround_lock
,
irq_flags
);
...
...
drivers/net/wireless/ath/ath10k/wmi.c
浏览文件 @
1f807827
...
...
@@ -27,6 +27,13 @@ void ath10k_wmi_flush_tx(struct ath10k *ar)
{
int
ret
;
lockdep_assert_held
(
&
ar
->
conf_mutex
);
if
(
ar
->
state
==
ATH10K_STATE_WEDGED
)
{
ath10k_warn
(
"wmi flush skipped - device is wedged anyway
\n
"
);
return
;
}
ret
=
wait_event_timeout
(
ar
->
wmi
.
wq
,
atomic_read
(
&
ar
->
wmi
.
pending_tx_count
)
==
0
,
5
*
HZ
);
...
...
@@ -111,7 +118,7 @@ static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb,
trace_ath10k_wmi_cmd
(
cmd_id
,
skb
->
data
,
skb
->
len
);
status
=
ath10k_htc_send
(
ar
->
htc
,
ar
->
wmi
.
eid
,
skb
);
status
=
ath10k_htc_send
(
&
ar
->
htc
,
ar
->
wmi
.
eid
,
skb
);
if
(
status
)
{
dev_kfree_skb_any
(
skb
);
atomic_dec
(
&
ar
->
wmi
.
pending_tx_count
);
...
...
@@ -501,7 +508,7 @@ static void ath10k_wmi_update_tim(struct ath10k *ar,
ie
=
(
u8
*
)
cfg80211_find_ie
(
WLAN_EID_TIM
,
ies
,
(
u8
*
)
skb_tail_pointer
(
bcn
)
-
ies
);
if
(
!
ie
)
{
/* highly unlikely for mac80211 */
if
(
arvif
->
vdev_type
!=
WMI_VDEV_TYPE_IBSS
)
ath10k_warn
(
"no tim ie found;
\n
"
);
return
;
}
...
...
@@ -1114,7 +1121,7 @@ int ath10k_wmi_connect_htc_service(struct ath10k *ar)
/* connect to control service */
conn_req
.
service_id
=
ATH10K_HTC_SVC_ID_WMI_CONTROL
;
status
=
ath10k_htc_connect_service
(
ar
->
htc
,
&
conn_req
,
&
conn_resp
);
status
=
ath10k_htc_connect_service
(
&
ar
->
htc
,
&
conn_req
,
&
conn_resp
);
if
(
status
)
{
ath10k_warn
(
"failed to connect to WMI CONTROL service status: %d
\n
"
,
status
);
...
...
@@ -1748,6 +1755,9 @@ int ath10k_wmi_vdev_install_key(struct ath10k *ar,
if
(
arg
->
key_data
)
memcpy
(
cmd
->
key_data
,
arg
->
key_data
,
arg
->
key_len
);
ath10k_dbg
(
ATH10K_DBG_WMI
,
"wmi vdev install key idx %d cipher %d len %d
\n
"
,
arg
->
key_idx
,
arg
->
key_cipher
,
arg
->
key_len
);
return
ath10k_wmi_cmd_send
(
ar
,
skb
,
WMI_VDEV_INSTALL_KEY_CMDID
);
}
...
...
@@ -2011,6 +2021,9 @@ int ath10k_wmi_peer_assoc(struct ath10k *ar,
cmd
->
peer_vht_rates
.
tx_mcs_set
=
__cpu_to_le32
(
arg
->
peer_vht_rates
.
tx_mcs_set
);
ath10k_dbg
(
ATH10K_DBG_WMI
,
"wmi peer assoc vdev %d addr %pM
\n
"
,
arg
->
vdev_id
,
arg
->
addr
);
return
ath10k_wmi_cmd_send
(
ar
,
skb
,
WMI_PEER_ASSOC_CMDID
);
}
...
...
@@ -2079,3 +2092,22 @@ int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id)
ath10k_dbg
(
ATH10K_DBG_WMI
,
"wmi request stats %d
\n
"
,
(
int
)
stats_id
);
return
ath10k_wmi_cmd_send
(
ar
,
skb
,
WMI_REQUEST_STATS_CMDID
);
}
int
ath10k_wmi_force_fw_hang
(
struct
ath10k
*
ar
,
enum
wmi_force_fw_hang_type
type
,
u32
delay_ms
)
{
struct
wmi_force_fw_hang_cmd
*
cmd
;
struct
sk_buff
*
skb
;
skb
=
ath10k_wmi_alloc_skb
(
sizeof
(
*
cmd
));
if
(
!
skb
)
return
-
ENOMEM
;
cmd
=
(
struct
wmi_force_fw_hang_cmd
*
)
skb
->
data
;
cmd
->
type
=
__cpu_to_le32
(
type
);
cmd
->
delay_ms
=
__cpu_to_le32
(
delay_ms
);
ath10k_dbg
(
ATH10K_DBG_WMI
,
"wmi force fw hang %d delay %d
\n
"
,
type
,
delay_ms
);
return
ath10k_wmi_cmd_send
(
ar
,
skb
,
WMI_FORCE_FW_HANG_CMDID
);
}
drivers/net/wireless/ath/ath10k/wmi.h
浏览文件 @
1f807827
...
...
@@ -416,6 +416,7 @@ enum wmi_cmd_id {
WMI_PDEV_FTM_INTG_CMDID
,
WMI_VDEV_SET_KEEPALIVE_CMDID
,
WMI_VDEV_GET_KEEPALIVE_CMDID
,
WMI_FORCE_FW_HANG_CMDID
,
/* GPIO Configuration */
WMI_GPIO_CONFIG_CMDID
=
WMI_CMD_GRP
(
WMI_GRP_GPIO
),
...
...
@@ -2972,6 +2973,22 @@ struct wmi_sta_keepalive_cmd {
struct
wmi_sta_keepalive_arp_resp
arp_resp
;
}
__packed
;
enum
wmi_force_fw_hang_type
{
WMI_FORCE_FW_HANG_ASSERT
=
1
,
WMI_FORCE_FW_HANG_NO_DETECT
,
WMI_FORCE_FW_HANG_CTRL_EP_FULL
,
WMI_FORCE_FW_HANG_EMPTY_POINT
,
WMI_FORCE_FW_HANG_STACK_OVERFLOW
,
WMI_FORCE_FW_HANG_INFINITE_LOOP
,
};
#define WMI_FORCE_FW_HANG_RANDOM_TIME 0xFFFFFFFF
struct
wmi_force_fw_hang_cmd
{
__le32
type
;
__le32
delay_ms
;
}
__packed
;
#define ATH10K_RTS_MAX 2347
#define ATH10K_FRAGMT_THRESHOLD_MIN 540
#define ATH10K_FRAGMT_THRESHOLD_MAX 2346
...
...
@@ -3048,5 +3065,7 @@ int ath10k_wmi_beacon_send(struct ath10k *ar, const struct wmi_bcn_tx_arg *arg);
int
ath10k_wmi_pdev_set_wmm_params
(
struct
ath10k
*
ar
,
const
struct
wmi_pdev_set_wmm_params_arg
*
arg
);
int
ath10k_wmi_request_stats
(
struct
ath10k
*
ar
,
enum
wmi_stats_id
stats_id
);
int
ath10k_wmi_force_fw_hang
(
struct
ath10k
*
ar
,
enum
wmi_force_fw_hang_type
type
,
u32
delay_ms
);
#endif
/* _WMI_H_ */
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录