diff options
author | Larry Finger <Larry.Finger@lwfinger.net> | 2011-11-17 12:14:43 -0600 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-11-21 16:20:45 -0500 |
commit | ff6ff96b5ba5b39f7ab3d8ea0cf9ec414452ac92 (patch) | |
tree | ad1c3294691a2860f9b8205ece269a1b36ac2f77 /drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | |
parent | 040a72785cf19fd8032f24d584ee305158c87ac7 (diff) | |
download | op-kernel-dev-ff6ff96b5ba5b39f7ab3d8ea0cf9ec414452ac92.zip op-kernel-dev-ff6ff96b5ba5b39f7ab3d8ea0cf9ec414452ac92.tar.gz |
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/rtl8192c/fw_common.c')
-rw-r--r-- | drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c index 49a064b..ebb73a2 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c @@ -72,6 +72,34 @@ static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable) } } +static void rtl_block_fw_writeN(struct ieee80211_hw *hw, const u8 *buffer, + u32 size) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 blockSize = REALTEK_USB_VENQT_MAX_BUF_SIZE - 20; + u8 *bufferPtr = (u8 *) buffer; + u32 i, offset, blockCount, remainSize; + + blockCount = size / blockSize; + remainSize = size % blockSize; + + for (i = 0; i < blockCount; i++) { + offset = i * blockSize; + rtlpriv->io.writeN_sync(rtlpriv, + (FW_8192C_START_ADDRESS + offset), + (void *)(bufferPtr + offset), + blockSize); + } + + if (remainSize) { + offset = blockCount * blockSize; + rtlpriv->io.writeN_sync(rtlpriv, + (FW_8192C_START_ADDRESS + offset), + (void *)(bufferPtr + offset), + remainSize); + } +} + static void _rtl92c_fw_block_write(struct ieee80211_hw *hw, const u8 *buffer, u32 size) { @@ -81,6 +109,10 @@ static void _rtl92c_fw_block_write(struct ieee80211_hw *hw, u32 *pu4BytePtr = (u32 *) buffer; u32 i, offset, blockCount, remainSize; + if (rtlpriv->io.writeN_sync) { + rtl_block_fw_writeN(hw, buffer, size); + return; + } blockCount = size / blockSize; remainSize = size % blockSize; |