summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/realtek/rtlwifi/base.c
diff options
context:
space:
mode:
authorPing-Ke Shih <pkshih@realtek.com>2018-05-18 17:30:05 +0800
committerKalle Valo <kvalo@codeaurora.org>2018-05-29 10:17:03 +0300
commit9ae6ed271a60f0e4476fe94f0efc5aba184a9c57 (patch)
tree65bb6c504fa6009c98ab7380cc0f3aedccab75b0 /drivers/net/wireless/realtek/rtlwifi/base.c
parentb4f6ee489cff1e9c8637996b7c1079e8bdd979df (diff)
rtlwifi: use sk_buff to queue C2H commands
We use 'struct rtl_c2hcmd' to store C2H commands originally, and the code is slightly complex to enqueue and dequeue and also wastes time to allocate and memcpy data. Since C2H commands are asynchronous events, they can be processed in work queue, so RX ISR enqueues C2H result in removal of rtl_c2h_packet_handler(). Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/realtek/rtlwifi/base.c')
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/base.c96
1 files changed, 22 insertions, 74 deletions
diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c
index 927b7d231576..61f12f86fcd4 100644
--- a/drivers/net/wireless/realtek/rtlwifi/base.c
+++ b/drivers/net/wireless/realtek/rtlwifi/base.c
@@ -571,9 +571,9 @@ int rtl_init_core(struct ieee80211_hw *hw)
spin_lock_init(&rtlpriv->locks.iqk_lock);
/* <5> init list */
INIT_LIST_HEAD(&rtlpriv->entry_list);
- INIT_LIST_HEAD(&rtlpriv->c2hcmd_list);
INIT_LIST_HEAD(&rtlpriv->scan_list.list);
skb_queue_head_init(&rtlpriv->tx_report.queue);
+ skb_queue_head_init(&rtlpriv->c2hcmd_queue);
rtlmac->link_state = MAC80211_NOLINK;
@@ -2262,56 +2262,36 @@ void rtl_fwevt_wq_callback(void *data)
rtlpriv->cfg->ops->c2h_command_handle(hw);
}
-void rtl_c2hcmd_enqueue(struct ieee80211_hw *hw, u8 tag, u8 len, u8 *val)
+void rtl_c2hcmd_enqueue(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
unsigned long flags;
- struct rtl_c2hcmd *c2hcmd;
-
- c2hcmd = kmalloc(sizeof(*c2hcmd),
- in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
-
- if (!c2hcmd)
- goto label_err;
-
- c2hcmd->val = kmalloc(len,
- in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
-
- if (!c2hcmd->val)
- goto label_err2;
-
- /* fill data */
- c2hcmd->tag = tag;
- c2hcmd->len = len;
- memcpy(c2hcmd->val, val, len);
/* enqueue */
spin_lock_irqsave(&rtlpriv->locks.c2hcmd_lock, flags);
- list_add_tail(&c2hcmd->list, &rtlpriv->c2hcmd_list);
+ __skb_queue_tail(&rtlpriv->c2hcmd_queue, skb);
spin_unlock_irqrestore(&rtlpriv->locks.c2hcmd_lock, flags);
/* wake up wq */
queue_delayed_work(rtlpriv->works.rtl_wq, &rtlpriv->works.c2hcmd_wq, 0);
-
- return;
-
-label_err2:
- kfree(c2hcmd);
-
-label_err:
- RT_TRACE(rtlpriv, COMP_CMD, DBG_WARNING,
- "C2H cmd enqueue fail.\n");
}
EXPORT_SYMBOL(rtl_c2hcmd_enqueue);
-void rtl_c2h_content_parsing(struct ieee80211_hw *hw, u8 cmd_id,
- u8 cmd_len, u8 *cmd_buf)
+static void rtl_c2h_content_parsing(struct ieee80211_hw *hw,
+ struct sk_buff *skb)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal_ops *hal_ops = rtlpriv->cfg->ops;
const struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
+ u8 cmd_id, cmd_seq, cmd_len;
+ u8 *cmd_buf = NULL;
+
+ cmd_id = skb->data[0];
+ cmd_seq = skb->data[1];
+ cmd_len = skb->len - 2;
+ cmd_buf = skb->data + 2;
switch (cmd_id) {
case C2H_DBG:
@@ -2347,67 +2327,35 @@ void rtl_c2h_content_parsing(struct ieee80211_hw *hw, u8 cmd_id,
}
}
-void rtl_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
- u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0;
- u8 *tmp_buf = NULL;
-
- c2h_cmd_id = buffer[0];
- c2h_cmd_seq = buffer[1];
- c2h_cmd_len = len - 2;
- tmp_buf = buffer + 2;
-
- RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
- "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n",
- c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len);
-
- RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE,
- "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len);
-
- switch (c2h_cmd_id) {
- case C2H_BT_INFO:
- case C2H_BT_MP:
- rtl_c2hcmd_enqueue(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
- break;
- default:
- rtl_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
- break;
- }
-}
-EXPORT_SYMBOL_GPL(rtl_c2h_packet_handler);
-
void rtl_c2hcmd_launcher(struct ieee80211_hw *hw, int exec)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct sk_buff *skb;
unsigned long flags;
- struct rtl_c2hcmd *c2hcmd;
int i;
for (i = 0; i < 200; i++) {
/* dequeue a task */
spin_lock_irqsave(&rtlpriv->locks.c2hcmd_lock, flags);
- c2hcmd = list_first_entry_or_null(&rtlpriv->c2hcmd_list,
- struct rtl_c2hcmd, list);
-
- if (c2hcmd)
- list_del(&c2hcmd->list);
+ skb = __skb_dequeue(&rtlpriv->c2hcmd_queue);
spin_unlock_irqrestore(&rtlpriv->locks.c2hcmd_lock, flags);
/* do it */
- if (!c2hcmd)
+ if (!skb)
break;
+ RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, "C2H rx_desc_shift=%d\n",
+ *((u8 *)skb->cb));
+ RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_DMESG,
+ "C2H data: ", skb->data, skb->len);
+
if (exec)
- rtl_c2h_content_parsing(hw, c2hcmd->tag,
- c2hcmd->len, c2hcmd->val);
+ rtl_c2h_content_parsing(hw, skb);
/* free */
- kfree(c2hcmd->val);
-
- kfree(c2hcmd);
+ dev_kfree_skb_any(skb);
}
}