rtlwifi: rtl8192cu: Fix kernel deadlock
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rtlwifi / usb.c
index 76732b0cd221f13d937297f8fd1e4c08fd0c2d89..3ad79736b255814839a370a06c84b85f14918264 100644 (file)
@@ -119,7 +119,7 @@ static int _usbctrl_vendorreq_sync_read(struct usb_device *udev, u8 request,
 
        do {
                status = usb_control_msg(udev, pipe, request, reqtype, value,
-                                        index, pdata, len, 0); /*max. timeout*/
+                                        index, pdata, len, 1000);
                if (status < 0) {
                        /* firmware download is checksumed, don't retry */
                        if ((value >= FW_8192C_START_ADDRESS &&
@@ -477,6 +477,8 @@ static void _rtl_usb_rx_process_agg(struct ieee80211_hw *hw,
                        if (unicast)
                                rtlpriv->link_info.num_rx_inperiod++;
                }
+               /* static bcn for roaming */
+               rtl_beacon_statistic(hw, skb);
        }
 }
 
@@ -548,7 +550,7 @@ static void _rtl_rx_pre_process(struct ieee80211_hw *hw, struct sk_buff *skb)
        }
 }
 
-#define __RX_SKB_MAX_QUEUED    32
+#define __RX_SKB_MAX_QUEUED    64
 
 static void _rtl_rx_work(unsigned long param)
 {
@@ -824,6 +826,7 @@ static void rtl_usb_stop(struct ieee80211_hw *hw)
 
        /* should after adapter start and interrupt enable. */
        set_hal_stop(rtlhal);
+       cancel_work_sync(&rtlpriv->works.fill_h2c_cmd);
        /* Enable software */
        SET_USB_STOP(rtlusb);
        rtl_usb_deinit(hw);
@@ -1026,6 +1029,16 @@ static bool rtl_usb_tx_chk_waitq_insert(struct ieee80211_hw *hw,
        return false;
 }
 
+static void rtl_fill_h2c_cmd_work_callback(struct work_struct *work)
+{
+       struct rtl_works *rtlworks =
+           container_of(work, struct rtl_works, fill_h2c_cmd);
+       struct ieee80211_hw *hw = rtlworks->hw;
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+       rtlpriv->cfg->ops->fill_h2c_cmd(hw, H2C_RA_MASK, 5, rtlpriv->rate_mask);
+}
+
 static struct rtl_intf_ops rtl_usb_ops = {
        .adapter_start = rtl_usb_start,
        .adapter_stop = rtl_usb_stop,
@@ -1057,6 +1070,10 @@ int rtl_usb_probe(struct usb_interface *intf,
 
        /* this spin lock must be initialized early */
        spin_lock_init(&rtlpriv->locks.usb_lock);
+       INIT_WORK(&rtlpriv->works.fill_h2c_cmd,
+                 rtl_fill_h2c_cmd_work_callback);
+       INIT_WORK(&rtlpriv->works.lps_change_work,
+                 rtl_lps_change_work_callback);
 
        rtlpriv->usb_data_index = 0;
        init_completion(&rtlpriv->firmware_loading_complete);