On 9 March 2012 23:04, Larry Finger <Larry.Finger@xxxxxxxxxxxx> wrote: > 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 <Larry.Finger@xxxxxxxxxxxx> > Cc: Stable <stable@xxxxxxxxxxxxxxx> [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: > > > Thanks for your help, Larry, will let you know the result. BR, Jerome -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html