Skip to content

Commit cceb0a5

Browse files
Ping-Ke ShihKalle Valo
authored andcommitted
rtlwifi: Add work queue for c2h cmd.
btcoex needs to sleep, thus it must run in thread context. Signed-off-by: Ping-Ke Shih <[email protected]> Signed-off-by: Larry Finger <[email protected]> Signed-off-by: Kalle Valo <[email protected]>
1 parent 0ff78ad commit cceb0a5

File tree

12 files changed

+160
-13
lines changed

12 files changed

+160
-13
lines changed

drivers/net/wireless/realtek/rtlwifi/base.c

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,8 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
475475
(void *)rtl_swlps_rfon_wq_callback);
476476
INIT_DELAYED_WORK(&rtlpriv->works.fwevt_wq,
477477
(void *)rtl_fwevt_wq_callback);
478+
INIT_DELAYED_WORK(&rtlpriv->works.c2hcmd_wq,
479+
(void *)rtl_c2hcmd_wq_callback);
478480

479481
}
480482

@@ -489,6 +491,7 @@ void rtl_deinit_deferred_work(struct ieee80211_hw *hw)
489491
cancel_delayed_work(&rtlpriv->works.ps_work);
490492
cancel_delayed_work(&rtlpriv->works.ps_rfon_wq);
491493
cancel_delayed_work(&rtlpriv->works.fwevt_wq);
494+
cancel_delayed_work(&rtlpriv->works.c2hcmd_wq);
492495
}
493496
EXPORT_SYMBOL_GPL(rtl_deinit_deferred_work);
494497

@@ -556,13 +559,15 @@ int rtl_init_core(struct ieee80211_hw *hw)
556559
spin_lock_init(&rtlpriv->locks.rf_lock);
557560
spin_lock_init(&rtlpriv->locks.waitq_lock);
558561
spin_lock_init(&rtlpriv->locks.entry_list_lock);
562+
spin_lock_init(&rtlpriv->locks.c2hcmd_lock);
559563
spin_lock_init(&rtlpriv->locks.cck_and_rw_pagea_lock);
560564
spin_lock_init(&rtlpriv->locks.check_sendpkt_lock);
561565
spin_lock_init(&rtlpriv->locks.fw_ps_lock);
562566
spin_lock_init(&rtlpriv->locks.lps_lock);
563567
spin_lock_init(&rtlpriv->locks.iqk_lock);
564568
/* <5> init list */
565569
INIT_LIST_HEAD(&rtlpriv->entry_list);
570+
INIT_LIST_HEAD(&rtlpriv->c2hcmd_list);
566571

567572
rtlmac->link_state = MAC80211_NOLINK;
568573

@@ -575,6 +580,7 @@ EXPORT_SYMBOL_GPL(rtl_init_core);
575580

576581
void rtl_deinit_core(struct ieee80211_hw *hw)
577582
{
583+
rtl_c2hcmd_launcher(hw, 0);
578584
}
579585
EXPORT_SYMBOL_GPL(rtl_deinit_core);
580586

@@ -1729,6 +1735,93 @@ void rtl_fwevt_wq_callback(void *data)
17291735

17301736
rtlpriv->cfg->ops->c2h_command_handle(hw);
17311737
}
1738+
1739+
void rtl_c2hcmd_enqueue(struct ieee80211_hw *hw, u8 tag, u8 len, u8 *val)
1740+
{
1741+
struct rtl_priv *rtlpriv = rtl_priv(hw);
1742+
unsigned long flags;
1743+
struct rtl_c2hcmd *c2hcmd;
1744+
1745+
c2hcmd = kmalloc(sizeof(*c2hcmd), GFP_KERNEL);
1746+
1747+
if (!c2hcmd)
1748+
goto label_err;
1749+
1750+
c2hcmd->val = kmalloc(len, GFP_KERNEL);
1751+
1752+
if (!c2hcmd->val)
1753+
goto label_err2;
1754+
1755+
/* fill data */
1756+
c2hcmd->tag = tag;
1757+
c2hcmd->len = len;
1758+
memcpy(c2hcmd->val, val, len);
1759+
1760+
/* enqueue */
1761+
spin_lock_irqsave(&rtlpriv->locks.c2hcmd_lock, flags);
1762+
1763+
list_add_tail(&c2hcmd->list, &rtlpriv->c2hcmd_list);
1764+
1765+
spin_unlock_irqrestore(&rtlpriv->locks.c2hcmd_lock, flags);
1766+
1767+
/* wake up wq */
1768+
queue_delayed_work(rtlpriv->works.rtl_wq, &rtlpriv->works.c2hcmd_wq, 0);
1769+
1770+
return;
1771+
1772+
label_err2:
1773+
kfree(c2hcmd);
1774+
1775+
label_err:
1776+
RT_TRACE(rtlpriv, COMP_CMD, DBG_WARNING,
1777+
"C2H cmd enqueue fail.\n");
1778+
}
1779+
EXPORT_SYMBOL(rtl_c2hcmd_enqueue);
1780+
1781+
void rtl_c2hcmd_launcher(struct ieee80211_hw *hw, int exec)
1782+
{
1783+
struct rtl_priv *rtlpriv = rtl_priv(hw);
1784+
unsigned long flags;
1785+
struct rtl_c2hcmd *c2hcmd;
1786+
int i;
1787+
1788+
for (i = 0; i < 200; i++) {
1789+
/* dequeue a task */
1790+
spin_lock_irqsave(&rtlpriv->locks.c2hcmd_lock, flags);
1791+
1792+
c2hcmd = list_first_entry_or_null(&rtlpriv->c2hcmd_list,
1793+
struct rtl_c2hcmd, list);
1794+
1795+
if (c2hcmd)
1796+
list_del(&c2hcmd->list);
1797+
1798+
spin_unlock_irqrestore(&rtlpriv->locks.c2hcmd_lock, flags);
1799+
1800+
/* do it */
1801+
if (!c2hcmd)
1802+
break;
1803+
1804+
if (rtlpriv->cfg->ops->c2h_content_parsing && exec)
1805+
rtlpriv->cfg->ops->c2h_content_parsing(hw,
1806+
c2hcmd->tag, c2hcmd->len, c2hcmd->val);
1807+
1808+
/* free */
1809+
kfree(c2hcmd->val);
1810+
1811+
kfree(c2hcmd);
1812+
}
1813+
}
1814+
1815+
void rtl_c2hcmd_wq_callback(void *data)
1816+
{
1817+
struct rtl_works *rtlworks = container_of_dwork_rtl(data,
1818+
struct rtl_works,
1819+
c2hcmd_wq);
1820+
struct ieee80211_hw *hw = rtlworks->hw;
1821+
1822+
rtl_c2hcmd_launcher(hw, 1);
1823+
}
1824+
17321825
void rtl_easy_concurrent_retrytimer_callback(unsigned long data)
17331826
{
17341827
struct ieee80211_hw *hw = (struct ieee80211_hw *)data;

drivers/net/wireless/realtek/rtlwifi/base.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ int rtl_rx_agg_stop(struct ieee80211_hw *hw,
136136
struct ieee80211_sta *sta, u16 tid);
137137
void rtl_watchdog_wq_callback(void *data);
138138
void rtl_fwevt_wq_callback(void *data);
139+
void rtl_c2hcmd_wq_callback(void *data);
140+
void rtl_c2hcmd_launcher(struct ieee80211_hw *hw, int exec);
141+
void rtl_c2hcmd_enqueue(struct ieee80211_hw *hw, u8 tag, u8 len, u8 *val);
139142

140143
void rtl_get_tcb_desc(struct ieee80211_hw *hw,
141144
struct ieee80211_tx_info *info,

drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -764,8 +764,8 @@ static void _rtl92ee_c2h_ra_report_handler(struct ieee80211_hw *hw,
764764
rtl92ee_dm_dynamic_arfb_select(hw, rate, collision_state);
765765
}
766766

767-
static void _rtl92ee_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id,
768-
u8 c2h_cmd_len, u8 *tmp_buf)
767+
void rtl92ee_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id,
768+
u8 c2h_cmd_len, u8 *tmp_buf)
769769
{
770770
struct rtl_priv *rtlpriv = rtl_priv(hw);
771771

@@ -820,5 +820,14 @@ void rtl92ee_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len)
820820
RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE,
821821
"[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len);
822822

823-
_rtl92ee_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
823+
switch (c2h_cmd_id) {
824+
case C2H_8192E_BT_INFO:
825+
case C2H_8192E_BT_MP:
826+
rtl_c2hcmd_enqueue(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
827+
break;
828+
default:
829+
rtl92ee_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len,
830+
tmp_buf);
831+
break;
832+
}
824833
}

drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,5 +185,6 @@ void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus);
185185
void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished);
186186
void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state);
187187
void rtl92ee_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len);
188-
188+
void rtl92ee_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id,
189+
u8 c2h_cmd_len, u8 *tmp_buf);
189190
#endif

drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ static struct rtl_hal_ops rtl8192ee_hal_ops = {
248248
.fill_h2c_cmd = rtl92ee_fill_h2c_cmd,
249249
.get_btc_status = rtl92ee_get_btc_status,
250250
.rx_command_packet = rtl92ee_rx_command_packet,
251+
.c2h_content_parsing = rtl92ee_c2h_content_parsing,
251252
};
252253

253254
static struct rtl_mod_params rtl92ee_mod_params = {

drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -585,9 +585,9 @@ void rtl8723be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw,
585585
(u8 *)p2p_ps_offload);
586586
}
587587

588-
static void _rtl8723be_c2h_content_parsing(struct ieee80211_hw *hw,
589-
u8 c2h_cmd_id,
590-
u8 c2h_cmd_len, u8 *tmp_buf)
588+
void rtl8723be_c2h_content_parsing(struct ieee80211_hw *hw,
589+
u8 c2h_cmd_id,
590+
u8 c2h_cmd_len, u8 *tmp_buf)
591591
{
592592
struct rtl_priv *rtlpriv = rtl_priv(hw);
593593

@@ -635,5 +635,15 @@ void rtl8723be_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len)
635635
RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE,
636636
"[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len);
637637

638-
_rtl8723be_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
638+
switch (c2h_cmd_id) {
639+
case C2H_8723B_BT_INFO:
640+
case C2H_8723B_BT_MP:
641+
rtl_c2hcmd_enqueue(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
642+
break;
643+
644+
default:
645+
rtl8723be_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len,
646+
tmp_buf);
647+
break;
648+
}
639649
}

drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,5 +148,6 @@ void rtl8723be_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus);
148148
void rtl8723be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished);
149149
void rtl8723be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state);
150150
void rtl8723be_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len);
151-
151+
void rtl8723be_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id,
152+
u8 c2h_cmd_len, u8 *tmp_buf);
152153
#endif

drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ static struct rtl_hal_ops rtl8723be_hal_ops = {
260260
.get_btc_status = rtl8723be_get_btc_status,
261261
.rx_command_packet = rtl8723be_rx_command_packet,
262262
.is_fw_header = is_fw_header,
263+
.c2h_content_parsing = rtl8723be_c2h_content_parsing,
263264
};
264265

265266
static struct rtl_mod_params rtl8723be_mod_params = {

drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1740,9 +1740,9 @@ static void rtl8821ae_c2h_ra_report_handler(struct ieee80211_hw *hw,
17401740
rtl8821ae_dm_update_init_rate(hw, rate);
17411741
}
17421742

1743-
static void _rtl8821ae_c2h_content_parsing(struct ieee80211_hw *hw,
1744-
u8 c2h_cmd_id, u8 c2h_cmd_len,
1745-
u8 *tmp_buf)
1743+
void rtl8821ae_c2h_content_parsing(struct ieee80211_hw *hw,
1744+
u8 c2h_cmd_id, u8 c2h_cmd_len,
1745+
u8 *tmp_buf)
17461746
{
17471747
struct rtl_priv *rtlpriv = rtl_priv(hw);
17481748

@@ -1784,5 +1784,15 @@ void rtl8821ae_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer,
17841784

17851785
RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_LOUD,
17861786
"[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len);
1787-
_rtl8821ae_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
1787+
1788+
switch (c2h_cmd_id) {
1789+
case C2H_8812_BT_INFO:
1790+
rtl_c2hcmd_enqueue(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
1791+
break;
1792+
1793+
default:
1794+
rtl8821ae_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len,
1795+
tmp_buf);
1796+
break;
1797+
}
17881798
}

drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,4 +329,7 @@ void rtl8821ae_set_fw_disconnect_decision_ctrl_cmd(struct ieee80211_hw *hw,
329329
void rtl8821ae_set_fw_global_info_cmd(struct ieee80211_hw *hw);
330330
void rtl8821ae_c2h_packet_handler(struct ieee80211_hw *hw,
331331
u8 *buffer, u8 length);
332+
void rtl8821ae_c2h_content_parsing(struct ieee80211_hw *hw,
333+
u8 c2h_cmd_id, u8 c2h_cmd_len,
334+
u8 *tmp_buf);
332335
#endif

drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ static struct rtl_hal_ops rtl8821ae_hal_ops = {
297297
.fill_h2c_cmd = rtl8821ae_fill_h2c_cmd,
298298
.get_btc_status = rtl8821ae_get_btc_status,
299299
.rx_command_packet = rtl8821ae_rx_command_packet,
300+
.c2h_content_parsing = rtl8821ae_c2h_content_parsing,
300301
.add_wowlan_pattern = rtl8821ae_add_wowlan_pattern,
301302
};
302303

drivers/net/wireless/realtek/rtlwifi/wifi.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2202,6 +2202,8 @@ struct rtl_hal_ops {
22022202
struct rtl_wow_pattern *rtl_pattern,
22032203
u8 index);
22042204
u16 (*get_available_desc)(struct ieee80211_hw *hw, u8 q_idx);
2205+
void (*c2h_content_parsing)(struct ieee80211_hw *hw, u8 tag, u8 len,
2206+
u8 *val);
22052207
};
22062208

22072209
struct rtl_intf_ops {
@@ -2317,6 +2319,7 @@ struct rtl_locks {
23172319
spinlock_t waitq_lock;
23182320
spinlock_t entry_list_lock;
23192321
spinlock_t usb_lock;
2322+
spinlock_t c2hcmd_lock;
23202323

23212324
/*FW clock change */
23222325
spinlock_t fw_ps_lock;
@@ -2346,6 +2349,7 @@ struct rtl_works {
23462349
struct workqueue_struct *rtl_wq;
23472350
struct delayed_work watchdog_wq;
23482351
struct delayed_work ips_nic_off_wq;
2352+
struct delayed_work c2hcmd_wq;
23492353

23502354
/* For SW LPS */
23512355
struct delayed_work ps_work;
@@ -2553,6 +2557,13 @@ struct proxim {
25532557
u8 (*proxim_get_var)(struct ieee80211_hw *hw, u8 type);
25542558
};
25552559

2560+
struct rtl_c2hcmd {
2561+
struct list_head list;
2562+
u8 tag;
2563+
u8 len;
2564+
u8 *val;
2565+
};
2566+
25562567
struct rtl_priv {
25572568
struct ieee80211_hw *hw;
25582569
struct completion firmware_loading_complete;
@@ -2585,6 +2596,9 @@ struct rtl_priv {
25852596
/* sta entry list for ap adhoc or mesh */
25862597
struct list_head entry_list;
25872598

2599+
/* c2hcmd list for kthread level access */
2600+
struct list_head c2hcmd_list;
2601+
25882602
int max_fw_size;
25892603

25902604
/*

0 commit comments

Comments
 (0)