aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorLarry Finger <Larry.Finger@lwfinger.net>2012-03-19 16:44:31 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-04-11 15:01:44 -0400
commita7959c1394d4126a70a53b914ce4105f5173d0aa (patch)
tree62374a9502df20d3f5f949793ad870755f58c4b7 /drivers/net/wireless
parent011afa1ed8c408d694957d2474d89dc81a60b70c (diff)
rtlwifi: Preallocate USB read buffers and eliminate kalloc in read routine
The current version of rtlwifi for USB operations uses kmalloc to acquire a 32-bit buffer for each read of the device. 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 has the lock originating 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@lwfinger.net> Cc: Stable <stable@vger.kernel.org> [This version good for 3.3+ - different patch for 3.2 - 2.6.39] Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/rtlwifi/usb.c34
-rw-r--r--drivers/net/wireless/rtlwifi/wifi.h6
2 files changed, 21 insertions, 19 deletions
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c
index 2e1e352864bb..d04dbda13f5a 100644
--- a/drivers/net/wireless/rtlwifi/usb.c
+++ b/drivers/net/wireless/rtlwifi/usb.c
@@ -124,46 +124,38 @@ static int _usbctrl_vendorreq_sync_read(struct usb_device *udev, u8 request,
124 return status; 124 return status;
125} 125}
126 126
127static u32 _usb_read_sync(struct usb_device *udev, u32 addr, u16 len) 127static u32 _usb_read_sync(struct rtl_priv *rtlpriv, u32 addr, u16 len)
128{ 128{
129 struct device *dev = rtlpriv->io.dev;
130 struct usb_device *udev = to_usb_device(dev);
129 u8 request; 131 u8 request;
130 u16 wvalue; 132 u16 wvalue;
131 u16 index; 133 u16 index;
132 u32 *data; 134 __le32 *data = &rtlpriv->usb_data[rtlpriv->usb_data_index];
133 u32 ret;
134 135
135 data = kmalloc(sizeof(u32), GFP_KERNEL);
136 if (!data)
137 return -ENOMEM;
138 request = REALTEK_USB_VENQT_CMD_REQ; 136 request = REALTEK_USB_VENQT_CMD_REQ;
139 index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */ 137 index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */
140 138
141 wvalue = (u16)addr; 139 wvalue = (u16)addr;
142 _usbctrl_vendorreq_sync_read(udev, request, wvalue, index, data, len); 140 _usbctrl_vendorreq_sync_read(udev, request, wvalue, index, data, len);
143 ret = le32_to_cpu(*data); 141 if (++rtlpriv->usb_data_index >= RTL_USB_MAX_RX_COUNT)
144 kfree(data); 142 rtlpriv->usb_data_index = 0;
145 return ret; 143 return le32_to_cpu(*data);
146} 144}
147 145
148static u8 _usb_read8_sync(struct rtl_priv *rtlpriv, u32 addr) 146static u8 _usb_read8_sync(struct rtl_priv *rtlpriv, u32 addr)
149{ 147{
150 struct device *dev = rtlpriv->io.dev; 148 return (u8)_usb_read_sync(rtlpriv, addr, 1);
151
152 return (u8)_usb_read_sync(to_usb_device(dev), addr, 1);
153} 149}
154 150
155static u16 _usb_read16_sync(struct rtl_priv *rtlpriv, u32 addr) 151static u16 _usb_read16_sync(struct rtl_priv *rtlpriv, u32 addr)
156{ 152{
157 struct device *dev = rtlpriv->io.dev; 153 return (u16)_usb_read_sync(rtlpriv, addr, 2);
158
159 return (u16)_usb_read_sync(to_usb_device(dev), addr, 2);
160} 154}
161 155
162static u32 _usb_read32_sync(struct rtl_priv *rtlpriv, u32 addr) 156static u32 _usb_read32_sync(struct rtl_priv *rtlpriv, u32 addr)
163{ 157{
164 struct device *dev = rtlpriv->io.dev; 158 return _usb_read_sync(rtlpriv, addr, 4);
165
166 return _usb_read_sync(to_usb_device(dev), addr, 4);
167} 159}
168 160
169static void _usb_write_async(struct usb_device *udev, u32 addr, u32 val, 161static void _usb_write_async(struct usb_device *udev, u32 addr, u32 val,
@@ -955,6 +947,11 @@ int __devinit rtl_usb_probe(struct usb_interface *intf,
955 return -ENOMEM; 947 return -ENOMEM;
956 } 948 }
957 rtlpriv = hw->priv; 949 rtlpriv = hw->priv;
950 rtlpriv->usb_data = kzalloc(RTL_USB_MAX_RX_COUNT * sizeof(u32),
951 GFP_KERNEL);
952 if (!rtlpriv->usb_data)
953 return -ENOMEM;
954 rtlpriv->usb_data_index = 0;
958 init_completion(&rtlpriv->firmware_loading_complete); 955 init_completion(&rtlpriv->firmware_loading_complete);
959 SET_IEEE80211_DEV(hw, &intf->dev); 956 SET_IEEE80211_DEV(hw, &intf->dev);
960 udev = interface_to_usbdev(intf); 957 udev = interface_to_usbdev(intf);
@@ -1025,6 +1022,7 @@ void rtl_usb_disconnect(struct usb_interface *intf)
1025 /* rtl_deinit_rfkill(hw); */ 1022 /* rtl_deinit_rfkill(hw); */
1026 rtl_usb_deinit(hw); 1023 rtl_usb_deinit(hw);
1027 rtl_deinit_core(hw); 1024 rtl_deinit_core(hw);
1025 kfree(rtlpriv->usb_data);
1028 rtlpriv->cfg->ops->deinit_sw_leds(hw); 1026 rtlpriv->cfg->ops->deinit_sw_leds(hw);
1029 rtlpriv->cfg->ops->deinit_sw_vars(hw); 1027 rtlpriv->cfg->ops->deinit_sw_vars(hw);
1030 _rtl_usb_io_handler_release(hw); 1028 _rtl_usb_io_handler_release(hw);
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h
index b591614c3b9b..28ebc69218a3 100644
--- a/drivers/net/wireless/rtlwifi/wifi.h
+++ b/drivers/net/wireless/rtlwifi/wifi.h
@@ -67,7 +67,7 @@
67#define QOS_QUEUE_NUM 4 67#define QOS_QUEUE_NUM 4
68#define RTL_MAC80211_NUM_QUEUE 5 68#define RTL_MAC80211_NUM_QUEUE 5
69#define REALTEK_USB_VENQT_MAX_BUF_SIZE 254 69#define REALTEK_USB_VENQT_MAX_BUF_SIZE 254
70 70#define RTL_USB_MAX_RX_COUNT 100
71#define QBSS_LOAD_SIZE 5 71#define QBSS_LOAD_SIZE 5
72#define MAX_WMMELE_LENGTH 64 72#define MAX_WMMELE_LENGTH 64
73 73
@@ -1629,6 +1629,10 @@ struct rtl_priv {
1629 interface or hardware */ 1629 interface or hardware */
1630 unsigned long status; 1630 unsigned long status;
1631 1631
1632 /* data buffer pointer for USB reads */
1633 __le32 *usb_data;
1634 int usb_data_index;
1635
1632 /*This must be the last item so 1636 /*This must be the last item so
1633 that it points to the data allocated 1637 that it points to the data allocated
1634 beyond this structure like: 1638 beyond this structure like: