Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
1698aca0
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
161
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看板
提交
1698aca0
编写于
3月 14, 2014
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'for-linville' of
git://github.com/kvalo/ath
上级
4e3b3bcd
70dd77b4
变更
13
展开全部
隐藏空白更改
内联
并排
Showing
13 changed file
with
638 addition
and
657 deletion
+638
-657
drivers/net/wireless/ath/ath10k/ce.c
drivers/net/wireless/ath/ath10k/ce.c
+8
-8
drivers/net/wireless/ath/ath10k/ce.h
drivers/net/wireless/ath/ath10k/ce.h
+8
-1
drivers/net/wireless/ath/ath10k/core.h
drivers/net/wireless/ath/ath10k/core.h
+3
-31
drivers/net/wireless/ath/ath10k/hif.h
drivers/net/wireless/ath/ath10k/hif.h
+15
-10
drivers/net/wireless/ath/ath10k/htc.c
drivers/net/wireless/ath/ath10k/htc.c
+17
-8
drivers/net/wireless/ath/ath10k/htt.h
drivers/net/wireless/ath/ath10k/htt.h
+18
-0
drivers/net/wireless/ath/ath10k/htt_rx.c
drivers/net/wireless/ath/ath10k/htt_rx.c
+176
-60
drivers/net/wireless/ath/ath10k/htt_tx.c
drivers/net/wireless/ath/ath10k/htt_tx.c
+110
-95
drivers/net/wireless/ath/ath10k/mac.c
drivers/net/wireless/ath/ath10k/mac.c
+172
-96
drivers/net/wireless/ath/ath10k/pci.c
drivers/net/wireless/ath/ath10k/pci.c
+82
-307
drivers/net/wireless/ath/ath10k/pci.h
drivers/net/wireless/ath/ath10k/pci.h
+0
-28
drivers/net/wireless/ath/ath10k/txrx.c
drivers/net/wireless/ath/ath10k/txrx.c
+15
-9
drivers/net/wireless/ath/ath10k/wmi.c
drivers/net/wireless/ath/ath10k/wmi.c
+14
-4
未找到文件。
drivers/net/wireless/ath/ath10k/ce.c
浏览文件 @
1698aca0
...
...
@@ -266,12 +266,12 @@ static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar,
* ath10k_ce_sendlist_send.
* The caller takes responsibility for any needed locking.
*/
static
int
ath10k_ce_send_nolock
(
struct
ath10k_ce_pipe
*
ce_state
,
void
*
per_transfer_context
,
u32
buffer
,
unsigned
int
nbytes
,
unsigned
int
transfer_id
,
unsigned
int
flags
)
int
ath10k_ce_send_nolock
(
struct
ath10k_ce_pipe
*
ce_state
,
void
*
per_transfer_context
,
u32
buffer
,
unsigned
int
nbytes
,
unsigned
int
transfer_id
,
unsigned
int
flags
)
{
struct
ath10k
*
ar
=
ce_state
->
ar
;
struct
ath10k_ce_ring
*
src_ring
=
ce_state
->
src_ring
;
...
...
@@ -1067,9 +1067,9 @@ struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar,
*
* For the lack of a better place do the check here.
*/
BUILD_BUG_ON
(
TARGET_NUM_MSDU_DESC
>
BUILD_BUG_ON
(
2
*
TARGET_NUM_MSDU_DESC
>
(
CE_HTT_H2T_MSG_SRC_NENTRIES
-
1
));
BUILD_BUG_ON
(
TARGET_10X_NUM_MSDU_DESC
>
BUILD_BUG_ON
(
2
*
TARGET_10X_NUM_MSDU_DESC
>
(
CE_HTT_H2T_MSG_SRC_NENTRIES
-
1
));
ret
=
ath10k_pci_wake
(
ar
);
...
...
drivers/net/wireless/ath/ath10k/ce.h
浏览文件 @
1698aca0
...
...
@@ -23,7 +23,7 @@
/* Maximum number of Copy Engine's supported */
#define CE_COUNT_MAX 8
#define CE_HTT_H2T_MSG_SRC_NENTRIES
2048
#define CE_HTT_H2T_MSG_SRC_NENTRIES
4096
/* Descriptor rings must be aligned to this boundary */
#define CE_DESC_RING_ALIGN 8
...
...
@@ -152,6 +152,13 @@ int ath10k_ce_send(struct ath10k_ce_pipe *ce_state,
unsigned
int
transfer_id
,
unsigned
int
flags
);
int
ath10k_ce_send_nolock
(
struct
ath10k_ce_pipe
*
ce_state
,
void
*
per_transfer_context
,
u32
buffer
,
unsigned
int
nbytes
,
unsigned
int
transfer_id
,
unsigned
int
flags
);
void
ath10k_ce_send_cb_register
(
struct
ath10k_ce_pipe
*
ce_state
,
void
(
*
send_cb
)(
struct
ath10k_ce_pipe
*
),
int
disable_interrupts
);
...
...
drivers/net/wireless/ath/ath10k/core.h
浏览文件 @
1698aca0
...
...
@@ -62,16 +62,13 @@ struct ath10k;
struct
ath10k_skb_cb
{
dma_addr_t
paddr
;
bool
is_mapped
;
bool
is_aborted
;
u8
vdev_id
;
struct
{
u8
tid
;
bool
is_offchan
;
u8
frag_len
;
u8
pad_len
;
struct
ath10k_htt_txbuf
*
txbuf
;
u32
txbuf_paddr
;
}
__packed
htt
;
struct
{
...
...
@@ -87,32 +84,6 @@ static inline struct ath10k_skb_cb *ATH10K_SKB_CB(struct sk_buff *skb)
return
(
struct
ath10k_skb_cb
*
)
&
IEEE80211_SKB_CB
(
skb
)
->
driver_data
;
}
static
inline
int
ath10k_skb_map
(
struct
device
*
dev
,
struct
sk_buff
*
skb
)
{
if
(
ATH10K_SKB_CB
(
skb
)
->
is_mapped
)
return
-
EINVAL
;
ATH10K_SKB_CB
(
skb
)
->
paddr
=
dma_map_single
(
dev
,
skb
->
data
,
skb
->
len
,
DMA_TO_DEVICE
);
if
(
unlikely
(
dma_mapping_error
(
dev
,
ATH10K_SKB_CB
(
skb
)
->
paddr
)))
return
-
EIO
;
ATH10K_SKB_CB
(
skb
)
->
is_mapped
=
true
;
return
0
;
}
static
inline
int
ath10k_skb_unmap
(
struct
device
*
dev
,
struct
sk_buff
*
skb
)
{
if
(
!
ATH10K_SKB_CB
(
skb
)
->
is_mapped
)
return
-
EINVAL
;
dma_unmap_single
(
dev
,
ATH10K_SKB_CB
(
skb
)
->
paddr
,
skb
->
len
,
DMA_TO_DEVICE
);
ATH10K_SKB_CB
(
skb
)
->
is_mapped
=
false
;
return
0
;
}
static
inline
u32
host_interest_item_address
(
u32
item_offset
)
{
return
QCA988X_HOST_INTEREST_ADDRESS
+
item_offset
;
...
...
@@ -288,6 +259,7 @@ struct ath10k_vif {
u8
fixed_rate
;
u8
fixed_nss
;
u8
force_sgi
;
};
struct
ath10k_vif_iter
{
...
...
drivers/net/wireless/ath/ath10k/hif.h
浏览文件 @
1698aca0
...
...
@@ -21,6 +21,14 @@
#include <linux/kernel.h>
#include "core.h"
struct
ath10k_hif_sg_item
{
u16
transfer_id
;
void
*
transfer_context
;
/* NULL = tx completion callback not called */
void
*
vaddr
;
/* for debugging mostly */
u32
paddr
;
u16
len
;
};
struct
ath10k_hif_cb
{
int
(
*
tx_completion
)(
struct
ath10k
*
ar
,
struct
sk_buff
*
wbuf
,
...
...
@@ -31,11 +39,9 @@ struct ath10k_hif_cb {
};
struct
ath10k_hif_ops
{
/* Send the head of a buffer to HIF for transmission to the target. */
int
(
*
send_head
)(
struct
ath10k
*
ar
,
u8
pipe_id
,
unsigned
int
transfer_id
,
unsigned
int
nbytes
,
struct
sk_buff
*
buf
);
/* send a scatter-gather list to the target */
int
(
*
tx_sg
)(
struct
ath10k
*
ar
,
u8
pipe_id
,
struct
ath10k_hif_sg_item
*
items
,
int
n_items
);
/*
* API to handle HIF-specific BMI message exchanges, this API is
...
...
@@ -86,12 +92,11 @@ struct ath10k_hif_ops {
};
static
inline
int
ath10k_hif_send_head
(
struct
ath10k
*
ar
,
u8
pipe_id
,
unsigned
int
transfer_id
,
unsigned
int
nbytes
,
struct
sk_buff
*
buf
)
static
inline
int
ath10k_hif_tx_sg
(
struct
ath10k
*
ar
,
u8
pipe_id
,
struct
ath10k_hif_sg_item
*
items
,
int
n_items
)
{
return
ar
->
hif
.
ops
->
send_head
(
ar
,
pipe_id
,
transfer_id
,
nbytes
,
buf
);
return
ar
->
hif
.
ops
->
tx_sg
(
ar
,
pipe_id
,
items
,
n_items
);
}
static
inline
int
ath10k_hif_exchange_bmi_msg
(
struct
ath10k
*
ar
,
...
...
drivers/net/wireless/ath/ath10k/htc.c
浏览文件 @
1698aca0
...
...
@@ -63,7 +63,9 @@ static struct sk_buff *ath10k_htc_build_tx_ctrl_skb(void *ar)
static
inline
void
ath10k_htc_restore_tx_skb
(
struct
ath10k_htc
*
htc
,
struct
sk_buff
*
skb
)
{
ath10k_skb_unmap
(
htc
->
ar
->
dev
,
skb
);
struct
ath10k_skb_cb
*
skb_cb
=
ATH10K_SKB_CB
(
skb
);
dma_unmap_single
(
htc
->
ar
->
dev
,
skb_cb
->
paddr
,
skb
->
len
,
DMA_TO_DEVICE
);
skb_pull
(
skb
,
sizeof
(
struct
ath10k_htc_hdr
));
}
...
...
@@ -122,6 +124,9 @@ int ath10k_htc_send(struct ath10k_htc *htc,
struct
sk_buff
*
skb
)
{
struct
ath10k_htc_ep
*
ep
=
&
htc
->
endpoint
[
eid
];
struct
ath10k_skb_cb
*
skb_cb
=
ATH10K_SKB_CB
(
skb
);
struct
ath10k_hif_sg_item
sg_item
;
struct
device
*
dev
=
htc
->
ar
->
dev
;
int
credits
=
0
;
int
ret
;
...
...
@@ -157,19 +162,25 @@ int ath10k_htc_send(struct ath10k_htc *htc,
ath10k_htc_prepare_tx_skb
(
ep
,
skb
);
ret
=
ath10k_skb_map
(
htc
->
ar
->
dev
,
skb
);
skb_cb
->
paddr
=
dma_map_single
(
dev
,
skb
->
data
,
skb
->
len
,
DMA_TO_DEVICE
);
ret
=
dma_mapping_error
(
dev
,
skb_cb
->
paddr
);
if
(
ret
)
goto
err_credits
;
ret
=
ath10k_hif_send_head
(
htc
->
ar
,
ep
->
ul_pipe_id
,
ep
->
eid
,
skb
->
len
,
skb
);
sg_item
.
transfer_id
=
ep
->
eid
;
sg_item
.
transfer_context
=
skb
;
sg_item
.
vaddr
=
skb
->
data
;
sg_item
.
paddr
=
skb_cb
->
paddr
;
sg_item
.
len
=
skb
->
len
;
ret
=
ath10k_hif_tx_sg
(
htc
->
ar
,
ep
->
ul_pipe_id
,
&
sg_item
,
1
);
if
(
ret
)
goto
err_unmap
;
return
0
;
err_unmap:
ath10k_skb_unmap
(
htc
->
ar
->
dev
,
skb
);
dma_unmap_single
(
dev
,
skb_cb
->
paddr
,
skb
->
len
,
DMA_TO_DEVICE
);
err_credits:
if
(
ep
->
tx_credit_flow_enabled
)
{
spin_lock_bh
(
&
htc
->
tx_lock
);
...
...
@@ -191,10 +202,8 @@ static int ath10k_htc_tx_completion_handler(struct ath10k *ar,
struct
ath10k_htc
*
htc
=
&
ar
->
htc
;
struct
ath10k_htc_ep
*
ep
=
&
htc
->
endpoint
[
eid
];
if
(
!
skb
)
{
ath10k_warn
(
"invalid sk_buff completion - NULL pointer. firmware crashed?
\n
"
);
if
(
WARN_ON_ONCE
(
!
skb
))
return
0
;
}
ath10k_htc_notify_tx_completion
(
ep
,
skb
);
/* the skb now belongs to the completion handler */
...
...
drivers/net/wireless/ath/ath10k/htt.h
浏览文件 @
1698aca0
...
...
@@ -20,6 +20,7 @@
#include <linux/bug.h>
#include <linux/interrupt.h>
#include <linux/dmapool.h>
#include "htc.h"
#include "rx_desc.h"
...
...
@@ -1181,11 +1182,20 @@ struct htt_rx_info {
u32
info1
;
u32
info2
;
}
rate
;
u32
tsf
;
bool
fcs_err
;
bool
amsdu_more
;
bool
mic_err
;
};
struct
ath10k_htt_txbuf
{
struct
htt_data_tx_desc_frag
frags
[
2
];
struct
ath10k_htc_hdr
htc_hdr
;
struct
htt_cmd_hdr
cmd_hdr
;
struct
htt_data_tx_desc
cmd_tx
;
}
__packed
;
struct
ath10k_htt
{
struct
ath10k
*
ar
;
enum
ath10k_htc_ep_id
eid
;
...
...
@@ -1267,11 +1277,18 @@ struct ath10k_htt {
struct
sk_buff
**
pending_tx
;
unsigned
long
*
used_msdu_ids
;
/* bitmap */
wait_queue_head_t
empty_tx_wq
;
struct
dma_pool
*
tx_pool
;
/* set if host-fw communication goes haywire
* used to avoid further failures */
bool
rx_confused
;
struct
tasklet_struct
rx_replenish_task
;
/* This is used to group tx/rx completions separately and process them
* in batches to reduce cache stalls */
struct
tasklet_struct
txrx_compl_task
;
struct
sk_buff_head
tx_compl_q
;
struct
sk_buff_head
rx_compl_q
;
};
#define RX_HTT_HDR_STATUS_LEN 64
...
...
@@ -1343,4 +1360,5 @@ int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt);
void
ath10k_htt_tx_free_msdu_id
(
struct
ath10k_htt
*
htt
,
u16
msdu_id
);
int
ath10k_htt_mgmt_tx
(
struct
ath10k_htt
*
htt
,
struct
sk_buff
*
);
int
ath10k_htt_tx
(
struct
ath10k_htt
*
htt
,
struct
sk_buff
*
);
#endif
drivers/net/wireless/ath/ath10k/htt_rx.c
浏览文件 @
1698aca0
...
...
@@ -43,7 +43,7 @@
static
int
ath10k_htt_rx_get_csum_state
(
struct
sk_buff
*
skb
);
static
void
ath10k_htt_txrx_compl_task
(
unsigned
long
ptr
);
static
int
ath10k_htt_rx_ring_size
(
struct
ath10k_htt
*
htt
)
{
...
...
@@ -225,18 +225,16 @@ static void ath10k_htt_rx_ring_refill_retry(unsigned long arg)
ath10k_htt_rx_msdu_buff_replenish
(
htt
);
}
static
unsigned
ath10k_htt_rx_ring_elems
(
struct
ath10k_htt
*
htt
)
{
return
(
__le32_to_cpu
(
*
htt
->
rx_ring
.
alloc_idx
.
vaddr
)
-
htt
->
rx_ring
.
sw_rd_idx
.
msdu_payld
)
&
htt
->
rx_ring
.
size_mask
;
}
void
ath10k_htt_rx_detach
(
struct
ath10k_htt
*
htt
)
{
int
sw_rd_idx
=
htt
->
rx_ring
.
sw_rd_idx
.
msdu_payld
;
del_timer_sync
(
&
htt
->
rx_ring
.
refill_retry_timer
);
tasklet_kill
(
&
htt
->
rx_replenish_task
);
tasklet_kill
(
&
htt
->
txrx_compl_task
);
skb_queue_purge
(
&
htt
->
tx_compl_q
);
skb_queue_purge
(
&
htt
->
rx_compl_q
);
while
(
sw_rd_idx
!=
__le32_to_cpu
(
*
(
htt
->
rx_ring
.
alloc_idx
.
vaddr
)))
{
struct
sk_buff
*
skb
=
...
...
@@ -270,10 +268,12 @@ static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt)
int
idx
;
struct
sk_buff
*
msdu
;
spin_lock_bh
(
&
htt
->
rx_ring
.
lock
);
lockdep_assert_held
(
&
htt
->
rx_ring
.
lock
);
if
(
ath10k_htt_rx_ring_elems
(
htt
)
==
0
)
ath10k_warn
(
"htt rx ring is empty!
\n
"
);
if
(
htt
->
rx_ring
.
fill_cnt
==
0
)
{
ath10k_warn
(
"tried to pop sk_buff from an empty rx ring
\n
"
);
return
NULL
;
}
idx
=
htt
->
rx_ring
.
sw_rd_idx
.
msdu_payld
;
msdu
=
htt
->
rx_ring
.
netbufs_ring
[
idx
];
...
...
@@ -283,7 +283,6 @@ static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt)
htt
->
rx_ring
.
sw_rd_idx
.
msdu_payld
=
idx
;
htt
->
rx_ring
.
fill_cnt
--
;
spin_unlock_bh
(
&
htt
->
rx_ring
.
lock
);
return
msdu
;
}
...
...
@@ -307,8 +306,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
struct
sk_buff
*
msdu
;
struct
htt_rx_desc
*
rx_desc
;
if
(
ath10k_htt_rx_ring_elems
(
htt
)
==
0
)
ath10k_warn
(
"htt rx ring is empty!
\n
"
);
lockdep_assert_held
(
&
htt
->
rx_ring
.
lock
);
if
(
htt
->
rx_confused
)
{
ath10k_warn
(
"htt is confused. refusing rx
\n
"
);
...
...
@@ -400,6 +398,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
msdu_len
=
MS
(
__le32_to_cpu
(
rx_desc
->
msdu_start
.
info0
),
RX_MSDU_START_INFO0_MSDU_LENGTH
);
msdu_chained
=
rx_desc
->
frag_info
.
ring2_more_count
;
msdu_chaining
=
msdu_chained
;
if
(
msdu_len_invalid
)
msdu_len
=
0
;
...
...
@@ -427,7 +426,6 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
msdu
->
next
=
next
;
msdu
=
next
;
msdu_chaining
=
1
;
}
last_msdu
=
__le32_to_cpu
(
rx_desc
->
msdu_end
.
info0
)
&
...
...
@@ -529,6 +527,12 @@ int ath10k_htt_rx_attach(struct ath10k_htt *htt)
tasklet_init
(
&
htt
->
rx_replenish_task
,
ath10k_htt_rx_replenish_task
,
(
unsigned
long
)
htt
);
skb_queue_head_init
(
&
htt
->
tx_compl_q
);
skb_queue_head_init
(
&
htt
->
rx_compl_q
);
tasklet_init
(
&
htt
->
txrx_compl_task
,
ath10k_htt_txrx_compl_task
,
(
unsigned
long
)
htt
);
ath10k_dbg
(
ATH10K_DBG_BOOT
,
"htt rx ring size %d fill_level %d
\n
"
,
htt
->
rx_ring
.
size
,
htt
->
rx_ring
.
fill_level
);
return
0
;
...
...
@@ -632,6 +636,12 @@ struct amsdu_subframe_hdr {
__be16
len
;
}
__packed
;
static
int
ath10k_htt_rx_nwifi_hdrlen
(
struct
ieee80211_hdr
*
hdr
)
{
/* nwifi header is padded to 4 bytes. this fixes 4addr rx */
return
round_up
(
ieee80211_hdrlen
(
hdr
->
frame_control
),
4
);
}
static
void
ath10k_htt_rx_amsdu
(
struct
ath10k_htt
*
htt
,
struct
htt_rx_info
*
info
)
{
...
...
@@ -681,7 +691,7 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
case
RX_MSDU_DECAP_NATIVE_WIFI
:
/* pull decapped header and copy DA */
hdr
=
(
struct
ieee80211_hdr
*
)
skb
->
data
;
hdr_len
=
ieee80211_hdrlen
(
hdr
->
frame_control
);
hdr_len
=
ath10k_htt_rx_nwifi_hdrlen
(
hdr
);
memcpy
(
addr
,
ieee80211_get_DA
(
hdr
),
ETH_ALEN
);
skb_pull
(
skb
,
hdr_len
);
...
...
@@ -768,7 +778,7 @@ static void ath10k_htt_rx_msdu(struct ath10k_htt *htt, struct htt_rx_info *info)
case
RX_MSDU_DECAP_NATIVE_WIFI
:
/* Pull decapped header */
hdr
=
(
struct
ieee80211_hdr
*
)
skb
->
data
;
hdr_len
=
ieee80211_hdrlen
(
hdr
->
frame_control
);
hdr_len
=
ath10k_htt_rx_nwifi_hdrlen
(
hdr
);
skb_pull
(
skb
,
hdr_len
);
/* Push original header */
...
...
@@ -846,6 +856,20 @@ static bool ath10k_htt_rx_has_mic_err(struct sk_buff *skb)
return
false
;
}
static
bool
ath10k_htt_rx_is_mgmt
(
struct
sk_buff
*
skb
)
{
struct
htt_rx_desc
*
rxd
;
u32
flags
;
rxd
=
(
void
*
)
skb
->
data
-
sizeof
(
*
rxd
);
flags
=
__le32_to_cpu
(
rxd
->
attention
.
flags
);
if
(
flags
&
RX_ATTENTION_FLAGS_MGMT_TYPE
)
return
true
;
return
false
;
}
static
int
ath10k_htt_rx_get_csum_state
(
struct
sk_buff
*
skb
)
{
struct
htt_rx_desc
*
rxd
;
...
...
@@ -877,6 +901,57 @@ static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb)
return
CHECKSUM_UNNECESSARY
;
}
static
int
ath10k_unchain_msdu
(
struct
sk_buff
*
msdu_head
)
{
struct
sk_buff
*
next
=
msdu_head
->
next
;
struct
sk_buff
*
to_free
=
next
;
int
space
;
int
total_len
=
0
;
/* TODO: Might could optimize this by using
* skb_try_coalesce or similar method to
* decrease copying, or maybe get mac80211 to
* provide a way to just receive a list of
* skb?
*/
msdu_head
->
next
=
NULL
;
/* Allocate total length all at once. */
while
(
next
)
{
total_len
+=
next
->
len
;
next
=
next
->
next
;
}
space
=
total_len
-
skb_tailroom
(
msdu_head
);
if
((
space
>
0
)
&&
(
pskb_expand_head
(
msdu_head
,
0
,
space
,
GFP_ATOMIC
)
<
0
))
{
/* TODO: bump some rx-oom error stat */
/* put it back together so we can free the
* whole list at once.
*/
msdu_head
->
next
=
to_free
;
return
-
1
;
}
/* Walk list again, copying contents into
* msdu_head
*/
next
=
to_free
;
while
(
next
)
{
skb_copy_from_linear_data
(
next
,
skb_put
(
msdu_head
,
next
->
len
),
next
->
len
);
next
=
next
->
next
;
}
/* If here, we have consolidated skb. Free the
* fragments and pass the main skb on up the
* stack.
*/
ath10k_htt_rx_free_msdu_chain
(
to_free
);
return
0
;
}
static
void
ath10k_htt_rx_handler
(
struct
ath10k_htt
*
htt
,
struct
htt_rx_indication
*
rx
)
{
...
...
@@ -888,6 +963,8 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
u8
*
fw_desc
;
int
i
,
j
;
lockdep_assert_held
(
&
htt
->
rx_ring
.
lock
);
memset
(
&
info
,
0
,
sizeof
(
info
));
fw_desc_len
=
__le16_to_cpu
(
rx
->
prefix
.
fw_rx_desc_bytes
);
...
...
@@ -940,7 +1017,8 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
status
=
info
.
status
;
/* Skip mgmt frames while we handle this in WMI */
if
(
status
==
HTT_RX_IND_MPDU_STATUS_MGMT_CTRL
)
{
if
(
status
==
HTT_RX_IND_MPDU_STATUS_MGMT_CTRL
||
ath10k_htt_rx_is_mgmt
(
msdu_head
))
{
ath10k_dbg
(
ATH10K_DBG_HTT
,
"htt rx mgmt ctrl
\n
"
);
ath10k_htt_rx_free_msdu_chain
(
msdu_head
);
continue
;
...
...
@@ -964,10 +1042,8 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
continue
;
}
/* FIXME: we do not support chaining yet.
* this needs investigation */
if
(
msdu_chaining
)
{
ath10k_warn
(
"htt rx msdu_chaining is true
\n
"
);
if
(
msdu_chaining
&&
(
ath10k_unchain_msdu
(
msdu_head
)
<
0
))
{
ath10k_htt_rx_free_msdu_chain
(
msdu_head
);
continue
;
}
...
...
@@ -990,6 +1066,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
info
.
rate
.
info0
=
rx
->
ppdu
.
info0
;
info
.
rate
.
info1
=
__le32_to_cpu
(
rx
->
ppdu
.
info1
);
info
.
rate
.
info2
=
__le32_to_cpu
(
rx
->
ppdu
.
info2
);
info
.
tsf
=
__le32_to_cpu
(
rx
->
ppdu
.
tsf
);
hdr
=
ath10k_htt_rx_skb_get_hdr
(
msdu_head
);
...
...
@@ -1023,8 +1100,11 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
msdu_head
=
NULL
;
msdu_tail
=
NULL
;
spin_lock_bh
(
&
htt
->
rx_ring
.
lock
);
msdu_chaining
=
ath10k_htt_rx_amsdu_pop
(
htt
,
&
fw_desc
,
&
fw_desc_len
,
&
msdu_head
,
&
msdu_tail
);
spin_unlock_bh
(
&
htt
->
rx_ring
.
lock
);
ath10k_dbg
(
ATH10K_DBG_HTT_DUMP
,
"htt rx frag ahead
\n
"
);
...
...
@@ -1116,6 +1196,45 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
}
}
static
void
ath10k_htt_rx_frm_tx_compl
(
struct
ath10k
*
ar
,
struct
sk_buff
*
skb
)
{
struct
ath10k_htt
*
htt
=
&
ar
->
htt
;
struct
htt_resp
*
resp
=
(
struct
htt_resp
*
)
skb
->
data
;
struct
htt_tx_done
tx_done
=
{};
int
status
=
MS
(
resp
->
data_tx_completion
.
flags
,
HTT_DATA_TX_STATUS
);
__le16
msdu_id
;
int
i
;
lockdep_assert_held
(
&
htt
->
tx_lock
);
switch
(
status
)
{
case
HTT_DATA_TX_STATUS_NO_ACK
:
tx_done
.
no_ack
=
true
;
break
;
case
HTT_DATA_TX_STATUS_OK
:
break
;
case
HTT_DATA_TX_STATUS_DISCARD
:
case
HTT_DATA_TX_STATUS_POSTPONE
:
case
HTT_DATA_TX_STATUS_DOWNLOAD_FAIL
:
tx_done
.
discard
=
true
;
break
;
default:
ath10k_warn
(
"unhandled tx completion status %d
\n
"
,
status
);
tx_done
.
discard
=
true
;
break
;
}
ath10k_dbg
(
ATH10K_DBG_HTT
,
"htt tx completion num_msdus %d
\n
"
,
resp
->
data_tx_completion
.
num_msdus
);
for
(
i
=
0
;
i
<
resp
->
data_tx_completion
.
num_msdus
;
i
++
)
{
msdu_id
=
resp
->
data_tx_completion
.
msdus
[
i
];
tx_done
.
msdu_id
=
__le16_to_cpu
(
msdu_id
);
ath10k_txrx_tx_unref
(
htt
,
&
tx_done
);
}
}
void
ath10k_htt_t2h_msg_handler
(
struct
ath10k
*
ar
,
struct
sk_buff
*
skb
)
{
struct
ath10k_htt
*
htt
=
&
ar
->
htt
;
...
...
@@ -1134,10 +1253,12 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
complete
(
&
htt
->
target_version_received
);
break
;
}
case
HTT_T2H_MSG_TYPE_RX_IND
:
{
ath10k_htt_rx_handler
(
htt
,
&
resp
->
rx_ind
);
break
;
}
case
HTT_T2H_MSG_TYPE_RX_IND
:
spin_lock_bh
(
&
htt
->
rx_ring
.
lock
);
__skb_queue_tail
(
&
htt
->
rx_compl_q
,
skb
);
spin_unlock_bh
(
&
htt
->
rx_ring
.
lock
);
tasklet_schedule
(
&
htt
->
txrx_compl_task
);
return
;
case
HTT_T2H_MSG_TYPE_PEER_MAP
:
{
struct
htt_peer_map_event
ev
=
{
.
vdev_id
=
resp
->
peer_map
.
vdev_id
,
...
...
@@ -1172,44 +1293,17 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
break
;
}
spin_lock_bh
(
&
htt
->
tx_lock
);
ath10k_txrx_tx_unref
(
htt
,
&
tx_done
);
spin_unlock_bh
(
&
htt
->
tx_lock
);
break
;
}
case
HTT_T2H_MSG_TYPE_TX_COMPL_IND
:
{
struct
htt_tx_done
tx_done
=
{};
int
status
=
MS
(
resp
->
data_tx_completion
.
flags
,
HTT_DATA_TX_STATUS
);
__le16
msdu_id
;
int
i
;
switch
(
status
)
{
case
HTT_DATA_TX_STATUS_NO_ACK
:
tx_done
.
no_ack
=
true
;
break
;
case
HTT_DATA_TX_STATUS_OK
:
break
;
case
HTT_DATA_TX_STATUS_DISCARD
:
case
HTT_DATA_TX_STATUS_POSTPONE
:
case
HTT_DATA_TX_STATUS_DOWNLOAD_FAIL
:
tx_done
.
discard
=
true
;
break
;
default:
ath10k_warn
(
"unhandled tx completion status %d
\n
"
,
status
);
tx_done
.
discard
=
true
;
break
;
}
ath10k_dbg
(
ATH10K_DBG_HTT
,
"htt tx completion num_msdus %d
\n
"
,
resp
->
data_tx_completion
.
num_msdus
);
for
(
i
=
0
;
i
<
resp
->
data_tx_completion
.
num_msdus
;
i
++
)
{
msdu_id
=
resp
->
data_tx_completion
.
msdus
[
i
];
tx_done
.
msdu_id
=
__le16_to_cpu
(
msdu_id
);
ath10k_txrx_tx_unref
(
htt
,
&
tx_done
);
}
break
;
}
case
HTT_T2H_MSG_TYPE_TX_COMPL_IND
:
spin_lock_bh
(
&
htt
->
tx_lock
);
__skb_queue_tail
(
&
htt
->
tx_compl_q
,
skb
);
spin_unlock_bh
(
&
htt
->
tx_lock
);
tasklet_schedule
(
&
htt
->
txrx_compl_task
);
return
;
case
HTT_T2H_MSG_TYPE_SEC_IND
:
{
struct
ath10k
*
ar
=
htt
->
ar
;
struct
htt_security_indication
*
ev
=
&
resp
->
security_indication
;
...
...
@@ -1249,3 +1343,25 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
/* Free the indication buffer */
dev_kfree_skb_any
(
skb
);
}
static
void
ath10k_htt_txrx_compl_task
(
unsigned
long
ptr
)
{
struct
ath10k_htt
*
htt
=
(
struct
ath10k_htt
*
)
ptr
;
struct
htt_resp
*
resp
;
struct
sk_buff
*
skb
;
spin_lock_bh
(
&
htt
->
tx_lock
);
while
((
skb
=
__skb_dequeue
(
&
htt
->
tx_compl_q
)))
{
ath10k_htt_rx_frm_tx_compl
(
htt
->
ar
,
skb
);
dev_kfree_skb_any
(
skb
);
}
spin_unlock_bh
(
&
htt
->
tx_lock
);
spin_lock_bh
(
&
htt
->
rx_ring
.
lock
);
while
((
skb
=
__skb_dequeue
(
&
htt
->
rx_compl_q
)))
{
resp
=
(
struct
htt_resp
*
)
skb
->
data
;
ath10k_htt_rx_handler
(
htt
,
&
resp
->
rx_ind
);
dev_kfree_skb_any
(
skb
);
}
spin_unlock_bh
(
&
htt
->
rx_ring
.
lock
);
}
drivers/net/wireless/ath/ath10k/htt_tx.c
浏览文件 @
1698aca0
...
...
@@ -109,6 +109,14 @@ int ath10k_htt_tx_attach(struct ath10k_htt *htt)
return
-
ENOMEM
;
}
htt
->
tx_pool
=
dma_pool_create
(
"ath10k htt tx pool"
,
htt
->
ar
->
dev
,
sizeof
(
struct
ath10k_htt_txbuf
),
4
,
0
);
if
(
!
htt
->
tx_pool
)
{
kfree
(
htt
->
used_msdu_ids
);
kfree
(
htt
->
pending_tx
);
return
-
ENOMEM
;
}
return
0
;
}
...
...
@@ -117,9 +125,7 @@ static void ath10k_htt_tx_cleanup_pending(struct ath10k_htt *htt)
struct
htt_tx_done
tx_done
=
{
0
};
int
msdu_id
;
/* No locks needed. Called after communication with the device has
* been stopped. */
spin_lock_bh
(
&
htt
->
tx_lock
);
for
(
msdu_id
=
0
;
msdu_id
<
htt
->
max_num_pending_tx
;
msdu_id
++
)
{
if
(
!
test_bit
(
msdu_id
,
htt
->
used_msdu_ids
))
continue
;
...
...
@@ -132,6 +138,7 @@ static void ath10k_htt_tx_cleanup_pending(struct ath10k_htt *htt)
ath10k_txrx_tx_unref
(
htt
,
&
tx_done
);
}
spin_unlock_bh
(
&
htt
->
tx_lock
);
}
void
ath10k_htt_tx_detach
(
struct
ath10k_htt
*
htt
)
...
...
@@ -139,6 +146,7 @@ void ath10k_htt_tx_detach(struct ath10k_htt *htt)
ath10k_htt_tx_cleanup_pending
(
htt
);
kfree
(
htt
->
pending_tx
);
kfree
(
htt
->
used_msdu_ids
);
dma_pool_destroy
(
htt
->
tx_pool
);
return
;
}
...
...
@@ -334,7 +342,9 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
goto
err_free_msdu_id
;
}
res
=
ath10k_skb_map
(
dev
,
msdu
);
skb_cb
->
paddr
=
dma_map_single
(
dev
,
msdu
->
data
,
msdu
->
len
,
DMA_TO_DEVICE
);
res
=
dma_mapping_error
(
dev
,
skb_cb
->
paddr
);
if
(
res
)
goto
err_free_txdesc
;
...
...
@@ -348,8 +358,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
memcpy
(
cmd
->
mgmt_tx
.
hdr
,
msdu
->
data
,
min_t
(
int
,
msdu
->
len
,
HTT_MGMT_FRM_HDR_DOWNLOAD_LEN
));
skb_cb
->
htt
.
frag_len
=
0
;
skb_cb
->
htt
.
pad_len
=
0
;
skb_cb
->
htt
.
txbuf
=
NULL
;
res
=
ath10k_htc_send
(
&
htt
->
ar
->
htc
,
htt
->
eid
,
txdesc
);
if
(
res
)
...
...
@@ -358,7 +367,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
return
0
;
err_unmap_msdu:
ath10k_skb_unmap
(
dev
,
msdu
);
dma_unmap_single
(
dev
,
skb_cb
->
paddr
,
msdu
->
len
,
DMA_TO_DEVICE
);
err_free_txdesc:
dev_kfree_skb_any
(
txdesc
);
err_free_msdu_id:
...
...
@@ -375,19 +384,19 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
int
ath10k_htt_tx
(
struct
ath10k_htt
*
htt
,
struct
sk_buff
*
msdu
)
{
struct
device
*
dev
=
htt
->
ar
->
dev
;
struct
htt_cmd
*
cmd
;
struct
htt_data_tx_desc_frag
*
tx_frags
;
struct
ieee80211_hdr
*
hdr
=
(
struct
ieee80211_hdr
*
)
msdu
->
data
;
struct
ath10k_skb_cb
*
skb_cb
=
ATH10K_SKB_CB
(
msdu
);
struct
sk_buff
*
txdesc
=
NULL
;
bool
use_frags
;
u8
vdev_id
=
ATH10K_SKB_CB
(
msdu
)
->
vdev_id
;
u8
tid
;
int
prefetch_len
,
desc_len
;
int
msdu_id
=
-
1
;
struct
ath10k_hif_sg_item
sg_items
[
2
];
struct
htt_data_tx_desc_frag
*
frags
;
u8
vdev_id
=
skb_cb
->
vdev_id
;
u8
tid
=
skb_cb
->
htt
.
tid
;
int
prefetch_len
;
int
res
;
u8
flags0
;
u16
flags1
;
u8
flags0
=
0
;
u16
msdu_id
,
flags1
=
0
;
dma_addr_t
paddr
;
u32
frags_paddr
;
bool
use_frags
;
res
=
ath10k_htt_tx_inc_pending
(
htt
);
if
(
res
)
...
...
@@ -406,114 +415,120 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
prefetch_len
=
min
(
htt
->
prefetch_len
,
msdu
->
len
);
prefetch_len
=
roundup
(
prefetch_len
,
4
);
desc_len
=
sizeof
(
cmd
->
hdr
)
+
sizeof
(
cmd
->
data_tx
)
+
prefetch_len
;
txdesc
=
ath10k_htc_alloc_skb
(
desc_len
);
if
(
!
txdesc
)
{
res
=
-
ENOMEM
;
goto
err_free_msdu_id
;
}
/* Since HTT 3.0 there is no separate mgmt tx command. However in case
* of mgmt tx using TX_FRM there is not tx fragment list. Instead of tx
* fragment list host driver specifies directly frame pointer. */
use_frags
=
htt
->
target_version_major
<
3
||
!
ieee80211_is_mgmt
(
hdr
->
frame_control
);
if
(
!
IS_ALIGNED
((
unsigned
long
)
txdesc
->
data
,
4
))
{
ath10k_warn
(
"htt alignment check failed. dropping packet.
\n
"
);
res
=
-
EIO
;
goto
err_free_
txdesc
;
}
skb_cb
->
htt
.
txbuf
=
dma_pool_alloc
(
htt
->
tx_pool
,
GFP_ATOMIC
,
&
paddr
);
if
(
!
skb_cb
->
htt
.
txbuf
)
goto
err_free_
msdu_id
;
skb_cb
->
htt
.
txbuf_paddr
=
paddr
;
if
(
use_frags
)
{
skb_cb
->
htt
.
frag_len
=
sizeof
(
*
tx_frags
)
*
2
;
skb_cb
->
htt
.
pad_len
=
(
unsigned
long
)
msdu
->
data
-
round_down
((
unsigned
long
)
msdu
->
data
,
4
);
skb_cb
->
paddr
=
dma_map_single
(
dev
,
msdu
->
data
,
msdu
->
len
,
DMA_TO_DEVICE
);
res
=
dma_mapping_error
(
dev
,
skb_cb
->
paddr
);
if
(
res
)
goto
err_free_txbuf
;
skb_push
(
msdu
,
skb_cb
->
htt
.
frag_len
+
skb_cb
->
htt
.
pad_len
);
}
else
{
skb_cb
->
htt
.
frag_len
=
0
;
skb_cb
->
htt
.
pad_len
=
0
;
}
if
(
likely
(
use_frags
))
{
frags
=
skb_cb
->
htt
.
txbuf
->
frags
;
res
=
ath10k_skb_map
(
dev
,
msdu
);
if
(
res
)
goto
err_pull_txfrag
;
if
(
use_frags
)
{
dma_sync_single_for_cpu
(
dev
,
skb_cb
->
paddr
,
msdu
->
len
,
DMA_TO_DEVICE
);
/* tx fragment list must be terminated with zero-entry */
tx_frags
=
(
struct
htt_data_tx_desc_frag
*
)
msdu
->
data
;
tx_frags
[
0
].
paddr
=
__cpu_to_le32
(
skb_cb
->
paddr
+
skb_cb
->
htt
.
frag_len
+
skb_cb
->
htt
.
pad_len
);
tx_frags
[
0
].
len
=
__cpu_to_le32
(
msdu
->
len
-
skb_cb
->
htt
.
frag_len
-
skb_cb
->
htt
.
pad_len
);
tx_frags
[
1
].
paddr
=
__cpu_to_le32
(
0
);
tx_frags
[
1
].
len
=
__cpu_to_le32
(
0
);
dma_sync_single_for_device
(
dev
,
skb_cb
->
paddr
,
msdu
->
len
,
DMA_TO_DEVICE
);
}
frags
[
0
].
paddr
=
__cpu_to_le32
(
skb_cb
->
paddr
);
frags
[
0
].
len
=
__cpu_to_le32
(
msdu
->
len
);
frags
[
1
].
paddr
=
0
;
frags
[
1
].
len
=
0
;
ath10k_dbg
(
ATH10K_DBG_HTT
,
"tx-msdu 0x%llx
\n
"
,
(
unsigned
long
long
)
ATH10K_SKB_CB
(
msdu
)
->
paddr
);
ath10k_dbg_dump
(
ATH10K_DBG_HTT_DUMP
,
NULL
,
"tx-msdu: "
,
msdu
->
data
,
msdu
->
len
);
flags0
|=
SM
(
ATH10K_HW_TXRX_NATIVE_WIFI
,
HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE
);
skb_put
(
txdesc
,
desc_len
);
cmd
=
(
struct
htt_cmd
*
)
txdesc
->
data
;
frags_paddr
=
skb_cb
->
htt
.
txbuf_paddr
;
}
else
{
flags0
|=
SM
(
ATH10K_HW_TXRX_MGMT
,
HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE
);
tid
=
ATH10K_SKB_CB
(
msdu
)
->
htt
.
tid
;
frags_paddr
=
skb_cb
->
paddr
;
}
ath10k_dbg
(
ATH10K_DBG_HTT
,
"htt data tx using tid %hhu
\n
"
,
tid
);
/* Normally all commands go through HTC which manages tx credits for
* each endpoint and notifies when tx is completed.
*
* HTT endpoint is creditless so there's no need to care about HTC
* flags. In that case it is trivial to fill the HTC header here.
*
* MSDU transmission is considered completed upon HTT event. This
* implies no relevant resources can be freed until after the event is
* received. That's why HTC tx completion handler itself is ignored by
* setting NULL to transfer_context for all sg items.
*
* There is simply no point in pushing HTT TX_FRM through HTC tx path
* as it's a waste of resources. By bypassing HTC it is possible to
* avoid extra memory allocations, compress data structures and thus
* improve performance. */
skb_cb
->
htt
.
txbuf
->
htc_hdr
.
eid
=
htt
->
eid
;
skb_cb
->
htt
.
txbuf
->
htc_hdr
.
len
=
__cpu_to_le16
(
sizeof
(
skb_cb
->
htt
.
txbuf
->
cmd_hdr
)
+
sizeof
(
skb_cb
->
htt
.
txbuf
->
cmd_tx
)
+
prefetch_len
);
skb_cb
->
htt
.
txbuf
->
htc_hdr
.
flags
=
0
;
flags0
=
0
;
if
(
!
ieee80211_has_protected
(
hdr
->
frame_control
))
flags0
|=
HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT
;
flags0
|=
HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT
;
if
(
use_frags
)
flags0
|=
SM
(
ATH10K_HW_TXRX_NATIVE_WIFI
,
HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE
);
else
flags0
|=
SM
(
ATH10K_HW_TXRX_MGMT
,
HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE
);
flags0
|=
HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT
;
flags1
=
0
;
flags1
|=
SM
((
u16
)
vdev_id
,
HTT_DATA_TX_DESC_FLAGS1_VDEV_ID
);
flags1
|=
SM
((
u16
)
tid
,
HTT_DATA_TX_DESC_FLAGS1_EXT_TID
);
flags1
|=
HTT_DATA_TX_DESC_FLAGS1_CKSUM_L3_OFFLOAD
;
flags1
|=
HTT_DATA_TX_DESC_FLAGS1_CKSUM_L4_OFFLOAD
;
cmd
->
hdr
.
msg_type
=
HTT_H2T_MSG_TYPE_TX_FRM
;
cmd
->
data_tx
.
flags0
=
flags0
;
cmd
->
data_tx
.
flags1
=
__cpu_to_le16
(
flags1
);
cmd
->
data_tx
.
len
=
__cpu_to_le16
(
msdu
->
len
-
skb_cb
->
htt
.
frag_len
-
skb_cb
->
htt
.
pad_len
);
cmd
->
data_tx
.
id
=
__cpu_to_le16
(
msdu_id
);
cmd
->
data_tx
.
frags_paddr
=
__cpu_to_le32
(
skb_cb
->
paddr
);
cmd
->
data_tx
.
peerid
=
__cpu_to_le32
(
HTT_INVALID_PEERID
);
memcpy
(
cmd
->
data_tx
.
prefetch
,
hdr
,
prefetch_len
);
skb_cb
->
htt
.
txbuf
->
cmd_hdr
.
msg_type
=
HTT_H2T_MSG_TYPE_TX_FRM
;
skb_cb
->
htt
.
txbuf
->
cmd_tx
.
flags0
=
flags0
;
skb_cb
->
htt
.
txbuf
->
cmd_tx
.
flags1
=
__cpu_to_le16
(
flags1
);
skb_cb
->
htt
.
txbuf
->
cmd_tx
.
len
=
__cpu_to_le16
(
msdu
->
len
);
skb_cb
->
htt
.
txbuf
->
cmd_tx
.
id
=
__cpu_to_le16
(
msdu_id
);
skb_cb
->
htt
.
txbuf
->
cmd_tx
.
frags_paddr
=
__cpu_to_le32
(
frags_paddr
);
skb_cb
->
htt
.
txbuf
->
cmd_tx
.
peerid
=
__cpu_to_le32
(
HTT_INVALID_PEERID
);
ath10k_dbg
(
ATH10K_DBG_HTT
,
"htt tx flags0 %hhu flags1 %hu len %d id %hu frags_paddr %08x, msdu_paddr %08x vdev %hhu tid %hhu
\n
"
,
flags0
,
flags1
,
msdu
->
len
,
msdu_id
,
frags_paddr
,
(
u32
)
skb_cb
->
paddr
,
vdev_id
,
tid
);
ath10k_dbg_dump
(
ATH10K_DBG_HTT_DUMP
,
NULL
,
"htt tx msdu: "
,
msdu
->
data
,
msdu
->
len
);
res
=
ath10k_htc_send
(
&
htt
->
ar
->
htc
,
htt
->
eid
,
txdesc
);
sg_items
[
0
].
transfer_id
=
0
;
sg_items
[
0
].
transfer_context
=
NULL
;
sg_items
[
0
].
vaddr
=
&
skb_cb
->
htt
.
txbuf
->
htc_hdr
;
sg_items
[
0
].
paddr
=
skb_cb
->
htt
.
txbuf_paddr
+
sizeof
(
skb_cb
->
htt
.
txbuf
->
frags
);
sg_items
[
0
].
len
=
sizeof
(
skb_cb
->
htt
.
txbuf
->
htc_hdr
)
+
sizeof
(
skb_cb
->
htt
.
txbuf
->
cmd_hdr
)
+
sizeof
(
skb_cb
->
htt
.
txbuf
->
cmd_tx
);
sg_items
[
1
].
transfer_id
=
0
;
sg_items
[
1
].
transfer_context
=
NULL
;
sg_items
[
1
].
vaddr
=
msdu
->
data
;
sg_items
[
1
].
paddr
=
skb_cb
->
paddr
;
sg_items
[
1
].
len
=
prefetch_len
;
res
=
ath10k_hif_tx_sg
(
htt
->
ar
,
htt
->
ar
->
htc
.
endpoint
[
htt
->
eid
].
ul_pipe_id
,
sg_items
,
ARRAY_SIZE
(
sg_items
));
if
(
res
)
goto
err_unmap_msdu
;
return
0
;
err_unmap_msdu:
ath10k_skb_unmap
(
dev
,
msdu
);
err_
pull_txfrag
:
skb_pull
(
msdu
,
skb_cb
->
htt
.
frag_len
+
skb_cb
->
htt
.
pad_len
);
err_free_txdesc:
dev_kfree_skb_any
(
txdesc
);
dma_unmap_single
(
dev
,
skb_cb
->
paddr
,
msdu
->
len
,
DMA_TO_DEVICE
);
err_
free_txbuf
:
dma_pool_free
(
htt
->
tx_pool
,
skb_cb
->
htt
.
txbuf
,
skb_cb
->
htt
.
txbuf_paddr
);
err_free_msdu_id:
spin_lock_bh
(
&
htt
->
tx_lock
);
htt
->
pending_tx
[
msdu_id
]
=
NULL
;
...
...
drivers/net/wireless/ath/ath10k/mac.c
浏览文件 @
1698aca0
此差异已折叠。
点击以展开。
drivers/net/wireless/ath/ath10k/pci.c
浏览文件 @
1698aca0
...
...
@@ -58,12 +58,10 @@ static DEFINE_PCI_DEVICE_TABLE(ath10k_pci_id_table) = {
static
int
ath10k_pci_diag_read_access
(
struct
ath10k
*
ar
,
u32
address
,
u32
*
data
);
static
void
ath10k_pci_process_ce
(
struct
ath10k
*
ar
);
static
int
ath10k_pci_post_rx
(
struct
ath10k
*
ar
);
static
int
ath10k_pci_post_rx_pipe
(
struct
ath10k_pci_pipe
*
pipe_info
,
int
num
);
static
void
ath10k_pci_rx_pipe_cleanup
(
struct
ath10k_pci_pipe
*
pipe_info
);
static
void
ath10k_pci_stop_ce
(
struct
ath10k
*
ar
);
static
int
ath10k_pci_cold_reset
(
struct
ath10k
*
ar
);
static
int
ath10k_pci_warm_reset
(
struct
ath10k
*
ar
);
static
int
ath10k_pci_wait_for_target_init
(
struct
ath10k
*
ar
);
...
...
@@ -74,7 +72,6 @@ static void ath10k_pci_free_irq(struct ath10k *ar);
static
int
ath10k_pci_bmi_wait
(
struct
ath10k_ce_pipe
*
tx_pipe
,
struct
ath10k_ce_pipe
*
rx_pipe
,
struct
bmi_xfer
*
xfer
);
static
void
ath10k_pci_cleanup_ce
(
struct
ath10k
*
ar
);
static
const
struct
ce_attr
host_ce_config_wlan
[]
=
{
/* CE0: host->target HTC control and raw streams */
...
...
@@ -679,34 +676,12 @@ void ath10k_do_pci_sleep(struct ath10k *ar)
}
}
/*
* FIXME: Handle OOM properly.
*/
static
inline
struct
ath10k_pci_compl
*
get_free_compl
(
struct
ath10k_pci_pipe
*
pipe_info
)
{
struct
ath10k_pci_compl
*
compl
=
NULL
;
spin_lock_bh
(
&
pipe_info
->
pipe_lock
);
if
(
list_empty
(
&
pipe_info
->
compl_free
))
{
ath10k_warn
(
"Completion buffers are full
\n
"
);
goto
exit
;
}
compl
=
list_first_entry
(
&
pipe_info
->
compl_free
,
struct
ath10k_pci_compl
,
list
);
list_del
(
&
compl
->
list
);
exit:
spin_unlock_bh
(
&
pipe_info
->
pipe_lock
);
return
compl
;
}
/* Called by lower (CE) layer when a send to Target completes. */
static
void
ath10k_pci_ce_send_done
(
struct
ath10k_ce_pipe
*
ce_state
)
{
struct
ath10k
*
ar
=
ce_state
->
ar
;
struct
ath10k_pci
*
ar_pci
=
ath10k_pci_priv
(
ar
);
struct
ath10k_pci_pipe
*
pipe_info
=
&
ar_pci
->
pipe_info
[
ce_state
->
id
];
struct
ath10k_pci_compl
*
compl
;
struct
ath10k_hif_cb
*
cb
=
&
ar_pci
->
msg_callbacks_current
;
void
*
transfer_context
;
u32
ce_data
;
unsigned
int
nbytes
;
...
...
@@ -715,27 +690,12 @@ static void ath10k_pci_ce_send_done(struct ath10k_ce_pipe *ce_state)
while
(
ath10k_ce_completed_send_next
(
ce_state
,
&
transfer_context
,
&
ce_data
,
&
nbytes
,
&
transfer_id
)
==
0
)
{
compl
=
get_free_compl
(
pipe_info
);
if
(
!
compl
)
break
;
compl
->
state
=
ATH10K_PCI_COMPL_SEND
;
compl
->
ce_state
=
ce_state
;
compl
->
pipe_info
=
pipe_info
;
compl
->
skb
=
transfer_context
;
compl
->
nbytes
=
nbytes
;
compl
->
transfer_id
=
transfer_id
;
compl
->
flags
=
0
;
/* no need to call tx completion for NULL pointers */
if
(
transfer_context
==
NULL
)
continue
;
/*
* Add the completion to the processing queue.
*/
spin_lock_bh
(
&
ar_pci
->
compl_lock
);
list_add_tail
(
&
compl
->
list
,
&
ar_pci
->
compl_process
);
spin_unlock_bh
(
&
ar_pci
->
compl_lock
);
cb
->
tx_completion
(
ar
,
transfer_context
,
transfer_id
);
}
ath10k_pci_process_ce
(
ar
);
}
/* Called by lower (CE) layer when data is received from the Target. */
...
...
@@ -744,77 +704,100 @@ static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state)
struct
ath10k
*
ar
=
ce_state
->
ar
;
struct
ath10k_pci
*
ar_pci
=
ath10k_pci_priv
(
ar
);
struct
ath10k_pci_pipe
*
pipe_info
=
&
ar_pci
->
pipe_info
[
ce_state
->
id
];
struct
ath10k_
pci_compl
*
compl
;
struct
ath10k_
hif_cb
*
cb
=
&
ar_pci
->
msg_callbacks_current
;
struct
sk_buff
*
skb
;
void
*
transfer_context
;
u32
ce_data
;
unsigned
int
nbytes
;
unsigned
int
nbytes
,
max_nbytes
;
unsigned
int
transfer_id
;
unsigned
int
flags
;
int
err
;
while
(
ath10k_ce_completed_recv_next
(
ce_state
,
&
transfer_context
,
&
ce_data
,
&
nbytes
,
&
transfer_id
,
&
flags
)
==
0
)
{
compl
=
get_free_compl
(
pipe_info
);
if
(
!
compl
)
break
;
compl
->
state
=
ATH10K_PCI_COMPL_RECV
;
compl
->
ce_state
=
ce_state
;
compl
->
pipe_info
=
pipe_info
;
compl
->
skb
=
transfer_context
;
compl
->
nbytes
=
nbytes
;
compl
->
transfer_id
=
transfer_id
;
compl
->
flags
=
flags
;
err
=
ath10k_pci_post_rx_pipe
(
pipe_info
,
1
);
if
(
unlikely
(
err
))
{
/* FIXME: retry */
ath10k_warn
(
"failed to replenish CE rx ring %d: %d
\n
"
,
pipe_info
->
pipe_num
,
err
);
}
skb
=
transfer_context
;
max_nbytes
=
skb
->
len
+
skb_tailroom
(
skb
);
dma_unmap_single
(
ar
->
dev
,
ATH10K_SKB_CB
(
skb
)
->
paddr
,
skb
->
len
+
skb_tailroom
(
skb
),
DMA_FROM_DEVICE
);
/*
* Add the completion to the processing queue.
*/
spin_lock_bh
(
&
ar_pci
->
compl_lock
);
list_add_tail
(
&
compl
->
list
,
&
ar_pci
->
compl_process
);
spin_unlock_bh
(
&
ar_pci
->
compl_lock
);
}
max_nbytes
,
DMA_FROM_DEVICE
);
ath10k_pci_process_ce
(
ar
);
if
(
unlikely
(
max_nbytes
<
nbytes
))
{
ath10k_warn
(
"rxed more than expected (nbytes %d, max %d)"
,
nbytes
,
max_nbytes
);
dev_kfree_skb_any
(
skb
);
continue
;
}
skb_put
(
skb
,
nbytes
);
cb
->
rx_completion
(
ar
,
skb
,
pipe_info
->
pipe_num
);
}
}
/* Send the first nbytes bytes of the buffer */
static
int
ath10k_pci_hif_send_head
(
struct
ath10k
*
ar
,
u8
pipe_id
,
unsigned
int
transfer_id
,
unsigned
int
bytes
,
struct
sk_buff
*
nbuf
)
static
int
ath10k_pci_hif_tx_sg
(
struct
ath10k
*
ar
,
u8
pipe_id
,
struct
ath10k_hif_sg_item
*
items
,
int
n_items
)
{
struct
ath10k_skb_cb
*
skb_cb
=
ATH10K_SKB_CB
(
nbuf
);
struct
ath10k_pci
*
ar_pci
=
ath10k_pci_priv
(
ar
);
struct
ath10k_pci_pipe
*
pipe_info
=
&
(
ar_pci
->
pipe_info
[
pipe_id
]);
struct
ath10k_ce_pipe
*
ce_hdl
=
pipe_info
->
ce_hdl
;
unsigned
int
len
;
u32
flags
=
0
;
int
ret
;
struct
ath10k_pci_pipe
*
pci_pipe
=
&
ar_pci
->
pipe_info
[
pipe_id
];
struct
ath10k_ce_pipe
*
ce_pipe
=
pci_pipe
->
ce_hdl
;
struct
ath10k_ce_ring
*
src_ring
=
ce_pipe
->
src_ring
;
unsigned
int
nentries_mask
=
src_ring
->
nentries_mask
;
unsigned
int
sw_index
=
src_ring
->
sw_index
;
unsigned
int
write_index
=
src_ring
->
write_index
;
int
err
,
i
;
len
=
min
(
bytes
,
nbuf
->
len
);
bytes
-=
len
;
spin_lock_bh
(
&
ar_pci
->
ce_lock
);
if
(
len
&
3
)
ath10k_warn
(
"skb not aligned to 4-byte boundary (%d)
\n
"
,
len
);
if
(
unlikely
(
CE_RING_DELTA
(
nentries_mask
,
write_index
,
sw_index
-
1
)
<
n_items
))
{
err
=
-
ENOBUFS
;
goto
unlock
;
}
ath10k_dbg
(
ATH10K_DBG_PCI
,
"pci send data vaddr %p paddr 0x%llx len %d as %d bytes
\n
"
,
nbuf
->
data
,
(
unsigned
long
long
)
skb_cb
->
paddr
,
nbuf
->
len
,
len
);
ath10k_dbg_dump
(
ATH10K_DBG_PCI_DUMP
,
NULL
,
"ath10k tx: data: "
,
nbuf
->
data
,
nbuf
->
len
);
ret
=
ath10k_ce_send
(
ce_hdl
,
nbuf
,
skb_cb
->
paddr
,
len
,
transfer_id
,
flags
);
if
(
ret
)
ath10k_warn
(
"failed to send sk_buff to CE: %p
\n
"
,
nbuf
);
for
(
i
=
0
;
i
<
n_items
-
1
;
i
++
)
{
ath10k_dbg
(
ATH10K_DBG_PCI
,
"pci tx item %d paddr 0x%08x len %d n_items %d
\n
"
,
i
,
items
[
i
].
paddr
,
items
[
i
].
len
,
n_items
);
ath10k_dbg_dump
(
ATH10K_DBG_PCI_DUMP
,
NULL
,
"item data: "
,
items
[
i
].
vaddr
,
items
[
i
].
len
);
return
ret
;
err
=
ath10k_ce_send_nolock
(
ce_pipe
,
items
[
i
].
transfer_context
,
items
[
i
].
paddr
,
items
[
i
].
len
,
items
[
i
].
transfer_id
,
CE_SEND_FLAG_GATHER
);
if
(
err
)
goto
unlock
;
}
/* `i` is equal to `n_items -1` after for() */
ath10k_dbg
(
ATH10K_DBG_PCI
,
"pci tx item %d paddr 0x%08x len %d n_items %d
\n
"
,
i
,
items
[
i
].
paddr
,
items
[
i
].
len
,
n_items
);
ath10k_dbg_dump
(
ATH10K_DBG_PCI_DUMP
,
NULL
,
"item data: "
,
items
[
i
].
vaddr
,
items
[
i
].
len
);
err
=
ath10k_ce_send_nolock
(
ce_pipe
,
items
[
i
].
transfer_context
,
items
[
i
].
paddr
,
items
[
i
].
len
,
items
[
i
].
transfer_id
,
0
);
if
(
err
)
goto
unlock
;
err
=
0
;
unlock:
spin_unlock_bh
(
&
ar_pci
->
ce_lock
);
return
err
;
}
static
u16
ath10k_pci_hif_get_free_queue_number
(
struct
ath10k
*
ar
,
u8
pipe
)
...
...
@@ -903,52 +886,6 @@ static void ath10k_pci_hif_set_callbacks(struct ath10k *ar,
sizeof
(
ar_pci
->
msg_callbacks_current
));
}
static
int
ath10k_pci_alloc_compl
(
struct
ath10k
*
ar
)
{
struct
ath10k_pci
*
ar_pci
=
ath10k_pci_priv
(
ar
);
const
struct
ce_attr
*
attr
;
struct
ath10k_pci_pipe
*
pipe_info
;
struct
ath10k_pci_compl
*
compl
;
int
i
,
pipe_num
,
completions
;
spin_lock_init
(
&
ar_pci
->
compl_lock
);
INIT_LIST_HEAD
(
&
ar_pci
->
compl_process
);
for
(
pipe_num
=
0
;
pipe_num
<
CE_COUNT
;
pipe_num
++
)
{
pipe_info
=
&
ar_pci
->
pipe_info
[
pipe_num
];
spin_lock_init
(
&
pipe_info
->
pipe_lock
);
INIT_LIST_HEAD
(
&
pipe_info
->
compl_free
);
/* Handle Diagnostic CE specially */
if
(
pipe_info
->
ce_hdl
==
ar_pci
->
ce_diag
)
continue
;
attr
=
&
host_ce_config_wlan
[
pipe_num
];
completions
=
0
;
if
(
attr
->
src_nentries
)
completions
+=
attr
->
src_nentries
;
if
(
attr
->
dest_nentries
)
completions
+=
attr
->
dest_nentries
;
for
(
i
=
0
;
i
<
completions
;
i
++
)
{
compl
=
kmalloc
(
sizeof
(
*
compl
),
GFP_KERNEL
);
if
(
!
compl
)
{
ath10k_warn
(
"No memory for completion state
\n
"
);
ath10k_pci_cleanup_ce
(
ar
);
return
-
ENOMEM
;
}
compl
->
state
=
ATH10K_PCI_COMPL_FREE
;
list_add_tail
(
&
compl
->
list
,
&
pipe_info
->
compl_free
);
}
}
return
0
;
}
static
int
ath10k_pci_setup_ce_irq
(
struct
ath10k
*
ar
)
{
struct
ath10k_pci
*
ar_pci
=
ath10k_pci_priv
(
ar
);
...
...
@@ -993,147 +930,6 @@ static void ath10k_pci_kill_tasklet(struct ath10k *ar)
tasklet_kill
(
&
ar_pci
->
pipe_info
[
i
].
intr
);
}
static
void
ath10k_pci_stop_ce
(
struct
ath10k
*
ar
)
{
struct
ath10k_pci
*
ar_pci
=
ath10k_pci_priv
(
ar
);
struct
ath10k_pci_compl
*
compl
;
struct
sk_buff
*
skb
;
/* Mark pending completions as aborted, so that upper layers free up
* their associated resources */
spin_lock_bh
(
&
ar_pci
->
compl_lock
);
list_for_each_entry
(
compl
,
&
ar_pci
->
compl_process
,
list
)
{
skb
=
compl
->
skb
;
ATH10K_SKB_CB
(
skb
)
->
is_aborted
=
true
;
}
spin_unlock_bh
(
&
ar_pci
->
compl_lock
);
}
static
void
ath10k_pci_cleanup_ce
(
struct
ath10k
*
ar
)
{
struct
ath10k_pci
*
ar_pci
=
ath10k_pci_priv
(
ar
);
struct
ath10k_pci_compl
*
compl
,
*
tmp
;
struct
ath10k_pci_pipe
*
pipe_info
;
struct
sk_buff
*
netbuf
;
int
pipe_num
;
/* Free pending completions. */
spin_lock_bh
(
&
ar_pci
->
compl_lock
);
if
(
!
list_empty
(
&
ar_pci
->
compl_process
))
ath10k_warn
(
"pending completions still present! possible memory leaks.
\n
"
);
list_for_each_entry_safe
(
compl
,
tmp
,
&
ar_pci
->
compl_process
,
list
)
{
list_del
(
&
compl
->
list
);
netbuf
=
compl
->
skb
;
dev_kfree_skb_any
(
netbuf
);
kfree
(
compl
);
}
spin_unlock_bh
(
&
ar_pci
->
compl_lock
);
/* Free unused completions for each pipe. */
for
(
pipe_num
=
0
;
pipe_num
<
CE_COUNT
;
pipe_num
++
)
{
pipe_info
=
&
ar_pci
->
pipe_info
[
pipe_num
];
spin_lock_bh
(
&
pipe_info
->
pipe_lock
);
list_for_each_entry_safe
(
compl
,
tmp
,
&
pipe_info
->
compl_free
,
list
)
{
list_del
(
&
compl
->
list
);
kfree
(
compl
);
}
spin_unlock_bh
(
&
pipe_info
->
pipe_lock
);
}
}
static
void
ath10k_pci_process_ce
(
struct
ath10k
*
ar
)
{
struct
ath10k_pci
*
ar_pci
=
ar
->
hif
.
priv
;
struct
ath10k_hif_cb
*
cb
=
&
ar_pci
->
msg_callbacks_current
;
struct
ath10k_pci_compl
*
compl
;
struct
sk_buff
*
skb
;
unsigned
int
nbytes
;
int
ret
,
send_done
=
0
;
/* Upper layers aren't ready to handle tx/rx completions in parallel so
* we must serialize all completion processing. */
spin_lock_bh
(
&
ar_pci
->
compl_lock
);
if
(
ar_pci
->
compl_processing
)
{
spin_unlock_bh
(
&
ar_pci
->
compl_lock
);
return
;
}
ar_pci
->
compl_processing
=
true
;
spin_unlock_bh
(
&
ar_pci
->
compl_lock
);
for
(;;)
{
spin_lock_bh
(
&
ar_pci
->
compl_lock
);
if
(
list_empty
(
&
ar_pci
->
compl_process
))
{
spin_unlock_bh
(
&
ar_pci
->
compl_lock
);
break
;
}
compl
=
list_first_entry
(
&
ar_pci
->
compl_process
,
struct
ath10k_pci_compl
,
list
);
list_del
(
&
compl
->
list
);
spin_unlock_bh
(
&
ar_pci
->
compl_lock
);
switch
(
compl
->
state
)
{
case
ATH10K_PCI_COMPL_SEND
:
cb
->
tx_completion
(
ar
,
compl
->
skb
,
compl
->
transfer_id
);
send_done
=
1
;
break
;
case
ATH10K_PCI_COMPL_RECV
:
ret
=
ath10k_pci_post_rx_pipe
(
compl
->
pipe_info
,
1
);
if
(
ret
)
{
ath10k_warn
(
"failed to post RX buffer for pipe %d: %d
\n
"
,
compl
->
pipe_info
->
pipe_num
,
ret
);
break
;
}
skb
=
compl
->
skb
;
nbytes
=
compl
->
nbytes
;
ath10k_dbg
(
ATH10K_DBG_PCI
,
"ath10k_pci_ce_recv_data netbuf=%p nbytes=%d
\n
"
,
skb
,
nbytes
);
ath10k_dbg_dump
(
ATH10K_DBG_PCI_DUMP
,
NULL
,
"ath10k rx: "
,
skb
->
data
,
nbytes
);
if
(
skb
->
len
+
skb_tailroom
(
skb
)
>=
nbytes
)
{
skb_trim
(
skb
,
0
);
skb_put
(
skb
,
nbytes
);
cb
->
rx_completion
(
ar
,
skb
,
compl
->
pipe_info
->
pipe_num
);
}
else
{
ath10k_warn
(
"rxed more than expected (nbytes %d, max %d)"
,
nbytes
,
skb
->
len
+
skb_tailroom
(
skb
));
}
break
;
case
ATH10K_PCI_COMPL_FREE
:
ath10k_warn
(
"free completion cannot be processed
\n
"
);
break
;
default:
ath10k_warn
(
"invalid completion state (%d)
\n
"
,
compl
->
state
);
break
;
}
compl
->
state
=
ATH10K_PCI_COMPL_FREE
;
/*
* Add completion back to the pipe's free list.
*/
spin_lock_bh
(
&
compl
->
pipe_info
->
pipe_lock
);
list_add_tail
(
&
compl
->
list
,
&
compl
->
pipe_info
->
compl_free
);
spin_unlock_bh
(
&
compl
->
pipe_info
->
pipe_lock
);
}
spin_lock_bh
(
&
ar_pci
->
compl_lock
);
ar_pci
->
compl_processing
=
false
;
spin_unlock_bh
(
&
ar_pci
->
compl_lock
);
}
/* TODO - temporary mapping while we have too few CE's */
static
int
ath10k_pci_hif_map_service_to_pipe
(
struct
ath10k
*
ar
,
u16
service_id
,
u8
*
ul_pipe
,
...
...
@@ -1305,17 +1101,11 @@ static int ath10k_pci_hif_start(struct ath10k *ar)
ath10k_pci_free_early_irq
(
ar
);
ath10k_pci_kill_tasklet
(
ar
);
ret
=
ath10k_pci_alloc_compl
(
ar
);
if
(
ret
)
{
ath10k_warn
(
"failed to allocate CE completions: %d
\n
"
,
ret
);
goto
err_early_irq
;
}
ret
=
ath10k_pci_request_irq
(
ar
);
if
(
ret
)
{
ath10k_warn
(
"failed to post RX buffers for all pipes: %d
\n
"
,
ret
);
goto
err_
free_compl
;
goto
err_
early_irq
;
}
ret
=
ath10k_pci_setup_ce_irq
(
ar
);
...
...
@@ -1339,10 +1129,6 @@ static int ath10k_pci_hif_start(struct ath10k *ar)
ath10k_ce_disable_interrupts
(
ar
);
ath10k_pci_free_irq
(
ar
);
ath10k_pci_kill_tasklet
(
ar
);
ath10k_pci_stop_ce
(
ar
);
ath10k_pci_process_ce
(
ar
);
err_free_compl:
ath10k_pci_cleanup_ce
(
ar
);
err_early_irq:
/* Though there should be no interrupts (device was reset)
* power_down() expects the early IRQ to be installed as per the
...
...
@@ -1413,18 +1199,10 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info)
while
(
ath10k_ce_cancel_send_next
(
ce_hdl
,
(
void
**
)
&
netbuf
,
&
ce_data
,
&
nbytes
,
&
id
)
==
0
)
{
/*
* Indicate the completion to higer layer to free
* the buffer
*/
if
(
!
netbuf
)
{
ath10k_warn
(
"invalid sk_buff on CE %d - NULL pointer. firmware crashed?
\n
"
,
ce_hdl
->
id
);
/* no need to call tx completion for NULL pointers */
if
(
!
netbuf
)
continue
;
}
ATH10K_SKB_CB
(
netbuf
)
->
is_aborted
=
true
;
ar_pci
->
msg_callbacks_current
.
tx_completion
(
ar
,
netbuf
,
id
);
...
...
@@ -1482,7 +1260,6 @@ static void ath10k_pci_hif_stop(struct ath10k *ar)
ath10k_pci_free_irq
(
ar
);
ath10k_pci_kill_tasklet
(
ar
);
ath10k_pci_stop_ce
(
ar
);
ret
=
ath10k_pci_request_early_irq
(
ar
);
if
(
ret
)
...
...
@@ -1492,8 +1269,6 @@ static void ath10k_pci_hif_stop(struct ath10k *ar)
* not DMA nor interrupt. We process the leftovers and then free
* everything else up. */
ath10k_pci_process_ce
(
ar
);
ath10k_pci_cleanup_ce
(
ar
);
ath10k_pci_buffer_cleanup
(
ar
);
/* Make the sure the device won't access any structures on the host by
...
...
@@ -2269,7 +2044,7 @@ static int ath10k_pci_hif_resume(struct ath10k *ar)
#endif
static
const
struct
ath10k_hif_ops
ath10k_pci_hif_ops
=
{
.
send_head
=
ath10k_pci_hif_send_head
,
.
tx_sg
=
ath10k_pci_hif_tx_sg
,
.
exchange_bmi_msg
=
ath10k_pci_hif_exchange_bmi_msg
,
.
start
=
ath10k_pci_hif_start
,
.
stop
=
ath10k_pci_hif_stop
,
...
...
drivers/net/wireless/ath/ath10k/pci.h
浏览文件 @
1698aca0
...
...
@@ -43,23 +43,6 @@ struct bmi_xfer {
u32
resp_len
;
};
enum
ath10k_pci_compl_state
{
ATH10K_PCI_COMPL_FREE
=
0
,
ATH10K_PCI_COMPL_SEND
,
ATH10K_PCI_COMPL_RECV
,
};
struct
ath10k_pci_compl
{
struct
list_head
list
;
enum
ath10k_pci_compl_state
state
;
struct
ath10k_ce_pipe
*
ce_state
;
struct
ath10k_pci_pipe
*
pipe_info
;
struct
sk_buff
*
skb
;
unsigned
int
nbytes
;
unsigned
int
transfer_id
;
unsigned
int
flags
;
};
/*
* PCI-specific Target state
*
...
...
@@ -175,9 +158,6 @@ struct ath10k_pci_pipe {
/* protects compl_free and num_send_allowed */
spinlock_t
pipe_lock
;
/* List of free CE completion slots */
struct
list_head
compl_free
;
struct
ath10k_pci
*
ar_pci
;
struct
tasklet_struct
intr
;
};
...
...
@@ -205,14 +185,6 @@ struct ath10k_pci {
atomic_t
keep_awake_count
;
bool
verified_awake
;
/* List of CE completions to be processed */
struct
list_head
compl_process
;
/* protects compl_processing and compl_process */
spinlock_t
compl_lock
;
bool
compl_processing
;
struct
ath10k_pci_pipe
pipe_info
[
CE_COUNT_MAX
];
struct
ath10k_hif_cb
msg_callbacks_current
;
...
...
drivers/net/wireless/ath/ath10k/txrx.c
浏览文件 @
1698aca0
...
...
@@ -51,7 +51,8 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
struct
ieee80211_tx_info
*
info
;
struct
ath10k_skb_cb
*
skb_cb
;
struct
sk_buff
*
msdu
;
int
ret
;
lockdep_assert_held
(
&
htt
->
tx_lock
);
ath10k_dbg
(
ATH10K_DBG_HTT
,
"htt tx completion msdu_id %u discard %d no_ack %d
\n
"
,
tx_done
->
msdu_id
,
!!
tx_done
->
discard
,
!!
tx_done
->
no_ack
);
...
...
@@ -65,12 +66,12 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
msdu
=
htt
->
pending_tx
[
tx_done
->
msdu_id
];
skb_cb
=
ATH10K_SKB_CB
(
msdu
);
ret
=
ath10k_skb_unmap
(
dev
,
msdu
);
if
(
ret
)
ath10k_warn
(
"data skb unmap failed (%d)
\n
"
,
ret
);
dma_unmap_single
(
dev
,
skb_cb
->
paddr
,
msdu
->
len
,
DMA_TO_DEVICE
);
if
(
skb_cb
->
htt
.
frag_len
)
skb_pull
(
msdu
,
skb_cb
->
htt
.
frag_len
+
skb_cb
->
htt
.
pad_len
);
if
(
skb_cb
->
htt
.
txbuf
)
dma_pool_free
(
htt
->
tx_pool
,
skb_cb
->
htt
.
txbuf
,
skb_cb
->
htt
.
txbuf_paddr
);
ath10k_report_offchan_tx
(
htt
->
ar
,
msdu
);
...
...
@@ -92,13 +93,11 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
/* we do not own the msdu anymore */
exit:
spin_lock_bh
(
&
htt
->
tx_lock
);
htt
->
pending_tx
[
tx_done
->
msdu_id
]
=
NULL
;
ath10k_htt_tx_free_msdu_id
(
htt
,
tx_done
->
msdu_id
);
__ath10k_htt_tx_dec_pending
(
htt
);
if
(
htt
->
num_pending_tx
==
0
)
wake_up
(
&
htt
->
empty_tx_wq
);
spin_unlock_bh
(
&
htt
->
tx_lock
);
}
static
const
u8
rx_legacy_rate_idx
[]
=
{
...
...
@@ -258,6 +257,12 @@ void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info)
status
->
band
=
ch
->
band
;
status
->
freq
=
ch
->
center_freq
;
if
(
info
->
rate
.
info0
&
HTT_RX_INDICATION_INFO0_END_VALID
)
{
/* TSF available only in 32-bit */
status
->
mactime
=
info
->
tsf
&
0xffffffff
;
status
->
flag
|=
RX_FLAG_MACTIME_END
;
}
ath10k_dbg
(
ATH10K_DBG_DATA
,
"rx skb %p len %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i
\n
"
,
info
->
skb
,
...
...
@@ -378,7 +383,8 @@ void ath10k_peer_unmap_event(struct ath10k_htt *htt,
spin_lock_bh
(
&
ar
->
data_lock
);
peer
=
ath10k_peer_find_by_id
(
ar
,
ev
->
peer_id
);
if
(
!
peer
)
{
ath10k_warn
(
"unknown peer id %d
\n
"
,
ev
->
peer_id
);
ath10k_warn
(
"peer-unmap-event: unknown peer id %d
\n
"
,
ev
->
peer_id
);
goto
exit
;
}
...
...
drivers/net/wireless/ath/ath10k/wmi.c
浏览文件 @
1698aca0
...
...
@@ -1360,7 +1360,7 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
struct
wmi_bcn_info
*
bcn_info
;
struct
ath10k_vif
*
arvif
;
struct
sk_buff
*
bcn
;
int
vdev_id
=
0
;
int
ret
,
vdev_id
=
0
;
ath10k_dbg
(
ATH10K_DBG_MGMT
,
"WMI_HOST_SWBA_EVENTID
\n
"
);
...
...
@@ -1435,16 +1435,27 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
ath10k_warn
(
"SWBA overrun on vdev %d
\n
"
,
arvif
->
vdev_id
);
ath10k_skb_unmap
(
ar
->
dev
,
arvif
->
beacon
);
dma_unmap_single
(
arvif
->
ar
->
dev
,
ATH10K_SKB_CB
(
arvif
->
beacon
)
->
paddr
,
arvif
->
beacon
->
len
,
DMA_TO_DEVICE
);
dev_kfree_skb_any
(
arvif
->
beacon
);
}
ath10k_skb_map
(
ar
->
dev
,
bcn
);
ATH10K_SKB_CB
(
bcn
)
->
paddr
=
dma_map_single
(
arvif
->
ar
->
dev
,
bcn
->
data
,
bcn
->
len
,
DMA_TO_DEVICE
);
ret
=
dma_mapping_error
(
arvif
->
ar
->
dev
,
ATH10K_SKB_CB
(
bcn
)
->
paddr
);
if
(
ret
)
{
ath10k_warn
(
"failed to map beacon: %d
\n
"
,
ret
);
goto
skip
;
}
arvif
->
beacon
=
bcn
;
arvif
->
beacon_sent
=
false
;
ath10k_wmi_tx_beacon_nowait
(
arvif
);
skip:
spin_unlock_bh
(
&
ar
->
data_lock
);
}
}
...
...
@@ -3382,7 +3393,6 @@ int ath10k_wmi_scan_chan_list(struct ath10k *ar,
ci
->
max_power
=
ch
->
max_power
;
ci
->
reg_power
=
ch
->
max_reg_power
;
ci
->
antenna_max
=
ch
->
max_antenna_gain
;
ci
->
antenna_max
=
0
;
/* mode & flags share storage */
ci
->
mode
=
ch
->
mode
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录