rtlwifi: use sk_buff to queue C2H commands
authorPing-Ke Shih <pkshih@realtek.com>
Fri, 18 May 2018 09:30:05 +0000 (17:30 +0800)
committerKalle Valo <kvalo@codeaurora.org>
Tue, 29 May 2018 07:17:03 +0000 (10:17 +0300)
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>
drivers/net/wireless/realtek/rtlwifi/base.c
drivers/net/wireless/realtek/rtlwifi/base.h
drivers/net/wireless/realtek/rtlwifi/pci.c
drivers/net/wireless/realtek/rtlwifi/wifi.h

index 927b7d2315762de695eed4b95ed5b7a5bb350c5f..61f12f86fcd4d8238b014098c7df3f26ffacc0e5 100644 (file)
@@ -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);
        }
 }
 
index 3bf174e5b07eee0235a222f478647182e8295012..912f205779c39e68387269825fdae5c4fcaa206f 100644 (file)
@@ -161,10 +161,7 @@ void rtl_watchdog_wq_callback(void *data);
 void rtl_fwevt_wq_callback(void *data);
 void rtl_c2hcmd_wq_callback(void *data);
 void rtl_c2hcmd_launcher(struct ieee80211_hw *hw, int exec);
-void rtl_c2hcmd_enqueue(struct ieee80211_hw *hw, u8 tag, u8 len, u8 *val);
-void rtl_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id,
-                            u8 c2h_cmd_len, u8 *tmp_buf);
-void rtl_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len);
+void rtl_c2hcmd_enqueue(struct ieee80211_hw *hw, struct sk_buff *skb);
 
 u8 rtl_mrate_idx_to_arfr_id(struct ieee80211_hw *hw, u8 rate_index,
                            enum wireless_mode wirelessmode);
index dd51c67c09fa628324cc8b5f96c212572ff50120..ae13bcfb3bf09cc142a81c9ab78c31ad80fd035e 100644 (file)
@@ -831,8 +831,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
                }
                /* handle command packet here */
                if (stats.packet_report_type == C2H_PACKET) {
-                       rtl_c2h_packet_handler(hw, skb->data, (u8)skb->len);
-                       dev_kfree_skb_any(skb);
+                       rtl_c2hcmd_enqueue(hw, skb);
                        goto new_trx_end;
                }
 
index 930e1ec2280fd9d0eadaf666b8c4e33fad08e901..9e620b943f8c695f64d63b2eb064fd70169c8e47 100644 (file)
@@ -2791,7 +2791,7 @@ struct rtl_priv {
        struct list_head entry_list;
 
        /* c2hcmd list for kthread level access */
-       struct list_head c2hcmd_list;
+       struct sk_buff_head c2hcmd_queue;
 
        struct rtl_debug dbg;
        int max_fw_size;