aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLarry Finger <Larry.Finger@lwfinger.net>2011-11-17 13:14:43 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-11-21 16:20:45 -0500
commitff6ff96b5ba5b39f7ab3d8ea0cf9ec414452ac92 (patch)
treead1c3294691a2860f9b8205ece269a1b36ac2f77
parent040a72785cf19fd8032f24d584ee305158c87ac7 (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>
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c32
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h1
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/mac.c1
-rw-r--r--drivers/net/wireless/rtlwifi/usb.c26
-rw-r--r--drivers/net/wireless/rtlwifi/wifi.h7
5 files changed, 64 insertions, 3 deletions
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
index 49a064bdbce6..ebb73a2fae91 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)
72 } 72 }
73} 73}
74 74
75static void rtl_block_fw_writeN(struct ieee80211_hw *hw, const u8 *buffer,
76 u32 size)
77{
78 struct rtl_priv *rtlpriv = rtl_priv(hw);
79 u32 blockSize = REALTEK_USB_VENQT_MAX_BUF_SIZE - 20;
80 u8 *bufferPtr = (u8 *) buffer;
81 u32 i, offset, blockCount, remainSize;
82
83 blockCount = size / blockSize;
84 remainSize = size % blockSize;
85
86 for (i = 0; i < blockCount; i++) {
87 offset = i * blockSize;
88 rtlpriv->io.writeN_sync(rtlpriv,
89 (FW_8192C_START_ADDRESS + offset),
90 (void *)(bufferPtr + offset),
91 blockSize);
92 }
93
94 if (remainSize) {
95 offset = blockCount * blockSize;
96 rtlpriv->io.writeN_sync(rtlpriv,
97 (FW_8192C_START_ADDRESS + offset),
98 (void *)(bufferPtr + offset),
99 remainSize);
100 }
101}
102
75static void _rtl92c_fw_block_write(struct ieee80211_hw *hw, 103static void _rtl92c_fw_block_write(struct ieee80211_hw *hw,
76 const u8 *buffer, u32 size) 104 const u8 *buffer, u32 size)
77{ 105{
@@ -81,6 +109,10 @@ static void _rtl92c_fw_block_write(struct ieee80211_hw *hw,
81 u32 *pu4BytePtr = (u32 *) buffer; 109 u32 *pu4BytePtr = (u32 *) buffer;
82 u32 i, offset, blockCount, remainSize; 110 u32 i, offset, blockCount, remainSize;
83 111
112 if (rtlpriv->io.writeN_sync) {
113 rtl_block_fw_writeN(hw, buffer, size);
114 return;
115 }
84 blockCount = size / blockSize; 116 blockCount = size / blockSize;
85 remainSize = size % blockSize; 117 remainSize = size % blockSize;
86 118
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h
index fcc4032585dc..c55c0541ff15 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h
@@ -94,5 +94,6 @@ void rtl92c_firmware_selfreset(struct ieee80211_hw *hw);
94void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); 94void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
95void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); 95void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished);
96void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); 96void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
97void usb_writeN_async(struct rtl_priv *rtlpriv, u32 addr, void *data, u16 len);
97 98
98#endif 99#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
index 060a06f4a885..9e0c8fcdf90f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
@@ -84,6 +84,7 @@ void rtl92c_read_chip_version(struct ieee80211_hw *hw)
84 } 84 }
85 } 85 }
86 rtlhal->version = (enum version_8192c)chip_version; 86 rtlhal->version = (enum version_8192c)chip_version;
87 pr_info("rtl8192cu: Chip version 0x%x\n", chip_version);
87 switch (rtlhal->version) { 88 switch (rtlhal->version) {
88 case VERSION_NORMAL_TSMC_CHIP_92C_1T2R: 89 case VERSION_NORMAL_TSMC_CHIP_92C_1T2R:
89 RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, 90 RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
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
46static void usbctrl_async_callback(struct urb *urb) 45static 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
205static 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
206static void _rtl_usb_io_handler_init(struct device *dev, 229static 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
221static void _rtl_usb_io_handler_release(struct ieee80211_hw *hw) 245static void _rtl_usb_io_handler_release(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h
index 713c7ddba8eb..f3c132b55d42 100644
--- a/drivers/net/wireless/rtlwifi/wifi.h
+++ b/drivers/net/wireless/rtlwifi/wifi.h
@@ -63,6 +63,7 @@
63#define AC_MAX 4 63#define AC_MAX 4
64#define QOS_QUEUE_NUM 4 64#define QOS_QUEUE_NUM 4
65#define RTL_MAC80211_NUM_QUEUE 5 65#define RTL_MAC80211_NUM_QUEUE 5
66#define REALTEK_USB_VENQT_MAX_BUF_SIZE 254
66 67
67#define QBSS_LOAD_SIZE 5 68#define QBSS_LOAD_SIZE 5
68#define MAX_WMMELE_LENGTH 64 69#define MAX_WMMELE_LENGTH 64
@@ -943,8 +944,10 @@ struct rtl_io {
943 unsigned long pci_base_addr; /*device I/O address */ 944 unsigned long pci_base_addr; /*device I/O address */
944 945
945 void (*write8_async) (struct rtl_priv *rtlpriv, u32 addr, u8 val); 946 void (*write8_async) (struct rtl_priv *rtlpriv, u32 addr, u8 val);
946 void (*write16_async) (struct rtl_priv *rtlpriv, u32 addr, __le16 val); 947 void (*write16_async) (struct rtl_priv *rtlpriv, u32 addr, u16 val);
947 void (*write32_async) (struct rtl_priv *rtlpriv, u32 addr, __le32 val); 948 void (*write32_async) (struct rtl_priv *rtlpriv, u32 addr, u32 val);
949 void (*writeN_sync) (struct rtl_priv *rtlpriv, u32 addr, void *buf,
950 u16 len);
948 951
949 u8(*read8_sync) (struct rtl_priv *rtlpriv, u32 addr); 952 u8(*read8_sync) (struct rtl_priv *rtlpriv, u32 addr);
950 u16(*read16_sync) (struct rtl_priv *rtlpriv, u32 addr); 953 u16(*read16_sync) (struct rtl_priv *rtlpriv, u32 addr);