diff options
author | Larry Finger <Larry.Finger@lwfinger.net> | 2011-11-17 13:14:43 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-11-21 16:20:45 -0500 |
commit | ff6ff96b5ba5b39f7ab3d8ea0cf9ec414452ac92 (patch) | |
tree | ad1c3294691a2860f9b8205ece269a1b36ac2f77 /drivers/net/wireless/rtlwifi/usb.c | |
parent | 040a72785cf19fd8032f24d584ee305158c87ac7 (diff) |
rtlwifi: rtl8192cu: Change firmware upload to use block writes
Driver rtl8192cu writes the firmware with 32-bit asynchronous writes. This
design is OK for USB 2.0 adapters, but the current implementation of
xhcu-hcd has a limited ring size, which is exceeded. By converting to
synchronous block writes, this error is avoided.
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rtlwifi/usb.c')
-rw-r--r-- | drivers/net/wireless/rtlwifi/usb.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 209105c8e3dc..a461822c05b3 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #define REALTEK_USB_VENQT_CMD_REQ 0x05 | 40 | #define REALTEK_USB_VENQT_CMD_REQ 0x05 |
41 | #define REALTEK_USB_VENQT_CMD_IDX 0x00 | 41 | #define REALTEK_USB_VENQT_CMD_IDX 0x00 |
42 | 42 | ||
43 | #define REALTEK_USB_VENQT_MAX_BUF_SIZE 254 | ||
44 | #define MAX_USBCTRL_VENDORREQ_TIMES 10 | 43 | #define MAX_USBCTRL_VENDORREQ_TIMES 10 |
45 | 44 | ||
46 | static void usbctrl_async_callback(struct urb *urb) | 45 | static void usbctrl_async_callback(struct urb *urb) |
@@ -203,6 +202,30 @@ static void _usb_write32_async(struct rtl_priv *rtlpriv, u32 addr, u32 val) | |||
203 | _usb_write_async(to_usb_device(dev), addr, val, 4); | 202 | _usb_write_async(to_usb_device(dev), addr, val, 4); |
204 | } | 203 | } |
205 | 204 | ||
205 | static void _usb_writeN_sync(struct rtl_priv *rtlpriv, u32 addr, void *data, | ||
206 | u16 len) | ||
207 | { | ||
208 | struct device *dev = rtlpriv->io.dev; | ||
209 | struct usb_device *udev = to_usb_device(dev); | ||
210 | u8 request = REALTEK_USB_VENQT_CMD_REQ; | ||
211 | u8 reqtype = REALTEK_USB_VENQT_WRITE; | ||
212 | u16 wvalue; | ||
213 | u16 index = REALTEK_USB_VENQT_CMD_IDX; | ||
214 | int pipe = usb_sndctrlpipe(udev, 0); /* write_out */ | ||
215 | u8 *buffer; | ||
216 | dma_addr_t dma_addr; | ||
217 | |||
218 | wvalue = (u16)(addr&0x0000ffff); | ||
219 | buffer = usb_alloc_coherent(udev, (size_t)len, GFP_ATOMIC, &dma_addr); | ||
220 | if (!buffer) | ||
221 | return; | ||
222 | memcpy(buffer, data, len); | ||
223 | usb_control_msg(udev, pipe, request, reqtype, wvalue, | ||
224 | index, buffer, len, 50); | ||
225 | |||
226 | usb_free_coherent(udev, (size_t)len, buffer, dma_addr); | ||
227 | } | ||
228 | |||
206 | static void _rtl_usb_io_handler_init(struct device *dev, | 229 | static void _rtl_usb_io_handler_init(struct device *dev, |
207 | struct ieee80211_hw *hw) | 230 | struct ieee80211_hw *hw) |
208 | { | 231 | { |
@@ -216,6 +239,7 @@ static void _rtl_usb_io_handler_init(struct device *dev, | |||
216 | rtlpriv->io.read8_sync = _usb_read8_sync; | 239 | rtlpriv->io.read8_sync = _usb_read8_sync; |
217 | rtlpriv->io.read16_sync = _usb_read16_sync; | 240 | rtlpriv->io.read16_sync = _usb_read16_sync; |
218 | rtlpriv->io.read32_sync = _usb_read32_sync; | 241 | rtlpriv->io.read32_sync = _usb_read32_sync; |
242 | rtlpriv->io.writeN_sync = _usb_writeN_sync; | ||
219 | } | 243 | } |
220 | 244 | ||
221 | static void _rtl_usb_io_handler_release(struct ieee80211_hw *hw) | 245 | static void _rtl_usb_io_handler_release(struct ieee80211_hw *hw) |