From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from mail-tul01m020-f174.google.com ([209.85.214.174]:49516 "EHLO mail-tul01m020-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756984Ab2CIPEW (ORCPT ); Fri, 9 Mar 2012 10:04:22 -0500 Message-ID: <4F5A1BF2.7080102@lwfinger.net> (sfid-20120309_160429_481486_EE6288FC) Date: Fri, 09 Mar 2012 09:04:18 -0600 From: Larry Finger MIME-Version: 1.0 To: jerome huang CC: "Xu, Andiry" , Sarah Sharp , linux-usb@vger.kernel.org, linux-wireless@vger.kernel.org Subject: Re: rt8192cu on USB3 References: <4F581AF8.4080001@lwfinger.net> <4F585BA9.6020903@amd.com> <2A76B9D36150BE4293842BC2FE8FF165016A31@SCYBEXDAG04.amd.com> <4F58F2D0.5060805@lwfinger.net> <4F59800B.80407@lwfinger.net> In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1; format=flowed Sender: linux-wireless-owner@vger.kernel.org List-ID: On 03/09/2012 01:39 AM, jerome huang wrote: > > Are other patches recommend besides b0302a? That is the main one. Others that you might consider, but they probably will not make any difference: 3eda95d rtlwifi: Remove extra debugging message accidentally left in 4e3c3b8 rtlwifi: Fix breakage in debug functions when built as a module This fixes a problem caused in commit 481b9606. ebecdcc rtlwifi: rtl8192c: Prevent sleeping from invalid context in rtl8192cu The patch below is currently under test. It is not likely to make any difference with your problem, but it changes USB reads a lot. Larry ======================================================================== The current version of rtlwifi for USB operations uses kmalloc to acquire a 32-bit buffer for reading. When _usb_read_sync() is called with the rcu_lock held, the result is a "sleeping function called from invalid context" BUG. This is reported for two cases in https://bugzilla.kernel.org/show_bug.cgi?id=42775. The first case where the lock originates from within rtlwifi and could be fixed by rearranging the locking; however, the second originates from within mac80211. The kmalloc() call is removed from _usb_read_sync() by creating a ring buffer pointer in the private area and allocating the buffer data in the probe routine. Signed-off-by: Larry Finger Cc: Stable [This version good for 3.3+ - different patch for 3.2 - 2.6.39] --- Index: wireless-testing-new/drivers/net/wireless/rtlwifi/usb.c =================================================================== --- wireless-testing-new.orig/drivers/net/wireless/rtlwifi/usb.c +++ wireless-testing-new/drivers/net/wireless/rtlwifi/usb.c @@ -124,46 +124,38 @@ static int _usbctrl_vendorreq_sync_read( return status; } -static u32 _usb_read_sync(struct usb_device *udev, u32 addr, u16 len) +static u32 _usb_read_sync(struct rtl_priv *rtlpriv, u32 addr, u16 len) { + struct device *dev = rtlpriv->io.dev; + struct usb_device *udev = to_usb_device(dev); u8 request; u16 wvalue; u16 index; - u32 *data; - u32 ret; + __le32 *data = &rtlpriv->usb_data[rtlpriv->usb_data_index]; - data = kmalloc(sizeof(u32), GFP_KERNEL); - if (!data) - return -ENOMEM; request = REALTEK_USB_VENQT_CMD_REQ; index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */ wvalue = (u16)addr; _usbctrl_vendorreq_sync_read(udev, request, wvalue, index, data, len); - ret = le32_to_cpu(*data); - kfree(data); - return ret; + if (++rtlpriv->usb_data_index >= RTL_USB_MAX_RX_COUNT) + rtlpriv->usb_data_index = 0; + return le32_to_cpu(*data); } static u8 _usb_read8_sync(struct rtl_priv *rtlpriv, u32 addr) { - struct device *dev = rtlpriv->io.dev; - - return (u8)_usb_read_sync(to_usb_device(dev), addr, 1); + return (u8)_usb_read_sync(rtlpriv, addr, 1); } static u16 _usb_read16_sync(struct rtl_priv *rtlpriv, u32 addr) { - struct device *dev = rtlpriv->io.dev; - - return (u16)_usb_read_sync(to_usb_device(dev), addr, 2); + return (u16)_usb_read_sync(rtlpriv, addr, 2); } static u32 _usb_read32_sync(struct rtl_priv *rtlpriv, u32 addr) { - struct device *dev = rtlpriv->io.dev; - - return _usb_read_sync(to_usb_device(dev), addr, 4); + return _usb_read_sync(rtlpriv, addr, 4); } static void _usb_write_async(struct usb_device *udev, u32 addr, u32 val, @@ -951,6 +943,13 @@ int __devinit rtl_usb_probe(struct usb_i return -ENOMEM; } rtlpriv = hw->priv; + rtlpriv->usb_data = kzalloc(RTL_USB_MAX_RX_COUNT * sizeof(u32), + GFP_KERNEL); + if (!rtlpriv->usb_data) { + RT_ASSERT(false, "USB data buffer allocation failed\n"); + return -ENOMEM; + } + rtlpriv->usb_data_index = 0; init_completion(&rtlpriv->firmware_loading_complete); SET_IEEE80211_DEV(hw, &intf->dev); udev = interface_to_usbdev(intf); @@ -1019,6 +1018,7 @@ void rtl_usb_disconnect(struct usb_inter /* rtl_deinit_rfkill(hw); */ rtl_usb_deinit(hw); rtl_deinit_core(hw); + kfree(rtlpriv->usb_data); rtlpriv->cfg->ops->deinit_sw_leds(hw); rtlpriv->cfg->ops->deinit_sw_vars(hw); _rtl_usb_io_handler_release(hw); Index: wireless-testing-new/drivers/net/wireless/rtlwifi/wifi.h =================================================================== --- wireless-testing-new.orig/drivers/net/wireless/rtlwifi/wifi.h +++ wireless-testing-new/drivers/net/wireless/rtlwifi/wifi.h @@ -67,7 +67,7 @@ #define QOS_QUEUE_NUM 4 #define RTL_MAC80211_NUM_QUEUE 5 #define REALTEK_USB_VENQT_MAX_BUF_SIZE 254 - +#define RTL_USB_MAX_RX_COUNT 100 #define QBSS_LOAD_SIZE 5 #define MAX_WMMELE_LENGTH 64 @@ -1629,6 +1629,10 @@ struct rtl_priv { interface or hardware */ unsigned long status; + /* data buffer pointer for USB reads */ + __le32 *usb_data; + int usb_data_index; + /*This must be the last item so that it points to the data allocated beyond this structure like: