Skip to content

Commit 1ae5ca6

Browse files
Po-Hao HuangKalle Valo
authored andcommitted
wifi: rtw89: add function to wait for completion of TX skbs
Allocate a per-skb completion to track those skbs we are interested in and wait for them to complete transmission with TX status. Normally, the completion object is freed by wait side, but it could be timeout result that complete side should free the object instead. Add a owner field with RCU to determine which side should free the object. Signed-off-by: Po-Hao Huang <[email protected]> Signed-off-by: Zong-Zhe Yang <[email protected]> Signed-off-by: Ping-Ke Shih <[email protected]> Signed-off-by: Kalle Valo <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent d2b6da2 commit 1ae5ca6

File tree

4 files changed

+78
-2
lines changed

4 files changed

+78
-2
lines changed

drivers/net/wireless/realtek/rtw89/core.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -867,6 +867,37 @@ void rtw89_core_tx_kick_off(struct rtw89_dev *rtwdev, u8 qsel)
867867
rtw89_hci_tx_kick_off(rtwdev, ch_dma);
868868
}
869869

870+
int rtw89_core_tx_kick_off_and_wait(struct rtw89_dev *rtwdev, struct sk_buff *skb,
871+
int qsel, unsigned int timeout)
872+
{
873+
struct rtw89_tx_skb_data *skb_data = RTW89_TX_SKB_CB(skb);
874+
struct rtw89_tx_wait_info *wait;
875+
unsigned long time_left;
876+
int ret = 0;
877+
878+
wait = kzalloc(sizeof(*wait), GFP_KERNEL);
879+
if (!wait) {
880+
rtw89_core_tx_kick_off(rtwdev, qsel);
881+
return 0;
882+
}
883+
884+
init_completion(&wait->completion);
885+
rcu_assign_pointer(skb_data->wait, wait);
886+
887+
rtw89_core_tx_kick_off(rtwdev, qsel);
888+
time_left = wait_for_completion_timeout(&wait->completion,
889+
msecs_to_jiffies(timeout));
890+
if (time_left == 0)
891+
ret = -ETIMEDOUT;
892+
else if (!wait->tx_done)
893+
ret = -EAGAIN;
894+
895+
rcu_assign_pointer(skb_data->wait, NULL);
896+
kfree_rcu(wait, rcu_head);
897+
898+
return ret;
899+
}
900+
870901
int rtw89_h2c_tx(struct rtw89_dev *rtwdev,
871902
struct sk_buff *skb, bool fwdl)
872903
{

drivers/net/wireless/realtek/rtw89/core.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2623,6 +2623,17 @@ struct rtw89_phy_rate_pattern {
26232623
bool enable;
26242624
};
26252625

2626+
struct rtw89_tx_wait_info {
2627+
struct rcu_head rcu_head;
2628+
struct completion completion;
2629+
bool tx_done;
2630+
};
2631+
2632+
struct rtw89_tx_skb_data {
2633+
struct rtw89_tx_wait_info __rcu *wait;
2634+
u8 hci_priv[];
2635+
};
2636+
26262637
#define RTW89_P2P_MAX_NOA_NUM 2
26272638

26282639
struct rtw89_vif {
@@ -4179,6 +4190,14 @@ static inline void rtw89_hci_clear(struct rtw89_dev *rtwdev, struct pci_dev *pde
41794190
rtwdev->hci.ops->clear(rtwdev, pdev);
41804191
}
41814192

4193+
static inline
4194+
struct rtw89_tx_skb_data *RTW89_TX_SKB_CB(struct sk_buff *skb)
4195+
{
4196+
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
4197+
4198+
return (struct rtw89_tx_skb_data *)info->status.status_driver_data;
4199+
}
4200+
41824201
static inline u8 rtw89_read8(struct rtw89_dev *rtwdev, u32 addr)
41834202
{
41844203
return rtwdev->hci.ops->read8(rtwdev, addr);
@@ -4822,11 +4841,32 @@ static inline struct sk_buff *rtw89_alloc_skb_for_rx(struct rtw89_dev *rtwdev,
48224841
return dev_alloc_skb(length);
48234842
}
48244843

4844+
static inline void rtw89_core_tx_wait_complete(struct rtw89_dev *rtwdev,
4845+
struct rtw89_tx_skb_data *skb_data,
4846+
bool tx_done)
4847+
{
4848+
struct rtw89_tx_wait_info *wait;
4849+
4850+
rcu_read_lock();
4851+
4852+
wait = rcu_dereference(skb_data->wait);
4853+
if (!wait)
4854+
goto out;
4855+
4856+
wait->tx_done = tx_done;
4857+
complete(&wait->completion);
4858+
4859+
out:
4860+
rcu_read_unlock();
4861+
}
4862+
48254863
int rtw89_core_tx_write(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
48264864
struct ieee80211_sta *sta, struct sk_buff *skb, int *qsel);
48274865
int rtw89_h2c_tx(struct rtw89_dev *rtwdev,
48284866
struct sk_buff *skb, bool fwdl);
48294867
void rtw89_core_tx_kick_off(struct rtw89_dev *rtwdev, u8 qsel);
4868+
int rtw89_core_tx_kick_off_and_wait(struct rtw89_dev *rtwdev, struct sk_buff *skb,
4869+
int qsel, unsigned int timeout);
48304870
void rtw89_core_fill_txdesc(struct rtw89_dev *rtwdev,
48314871
struct rtw89_tx_desc_info *desc_info,
48324872
void *txdesc);

drivers/net/wireless/realtek/rtw89/pci.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,8 +364,11 @@ static void rtw89_pci_tx_status(struct rtw89_dev *rtwdev,
364364
struct rtw89_pci_tx_ring *tx_ring,
365365
struct sk_buff *skb, u8 tx_status)
366366
{
367+
struct rtw89_tx_skb_data *skb_data = RTW89_TX_SKB_CB(skb);
367368
struct ieee80211_tx_info *info;
368369

370+
rtw89_core_tx_wait_complete(rtwdev, skb_data, tx_status == RTW89_TX_DONE);
371+
369372
info = IEEE80211_SKB_CB(skb);
370373
ieee80211_tx_info_clear_status(info);
371374

@@ -1203,6 +1206,7 @@ static int rtw89_pci_txwd_submit(struct rtw89_dev *rtwdev,
12031206
struct pci_dev *pdev = rtwpci->pdev;
12041207
struct sk_buff *skb = tx_req->skb;
12051208
struct rtw89_pci_tx_data *tx_data = RTW89_PCI_TX_SKB_CB(skb);
1209+
struct rtw89_tx_skb_data *skb_data = RTW89_TX_SKB_CB(skb);
12061210
bool en_wd_info = desc_info->en_wd_info;
12071211
u32 txwd_len;
12081212
u32 txwp_len;
@@ -1218,6 +1222,7 @@ static int rtw89_pci_txwd_submit(struct rtw89_dev *rtwdev,
12181222
}
12191223

12201224
tx_data->dma = dma;
1225+
rcu_assign_pointer(skb_data->wait, NULL);
12211226

12221227
txwp_len = sizeof(*txwp_info);
12231228
txwd_len = chip->txwd_body_size;

drivers/net/wireless/realtek/rtw89/pci.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,9 +1004,9 @@ rtw89_pci_rxbd_increase(struct rtw89_pci_rx_ring *rx_ring, u32 cnt)
10041004

10051005
static inline struct rtw89_pci_tx_data *RTW89_PCI_TX_SKB_CB(struct sk_buff *skb)
10061006
{
1007-
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1007+
struct rtw89_tx_skb_data *data = RTW89_TX_SKB_CB(skb);
10081008

1009-
return (struct rtw89_pci_tx_data *)info->status.status_driver_data;
1009+
return (struct rtw89_pci_tx_data *)data->hci_priv;
10101010
}
10111011

10121012
static inline struct rtw89_pci_tx_bd_32 *

0 commit comments

Comments
 (0)