George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 1 | /****************************************************************************** |
| 2 | * |
Larry Finger | c1d6604 | 2012-01-07 20:46:45 -0600 | [diff] [blame] | 3 | * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of version 2 of the GNU General Public License as |
| 7 | * published by the Free Software Foundation. |
| 8 | * |
| 9 | * This program is distributed in the hope that it will be useful, but WITHOUT |
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 12 | * more details. |
| 13 | * |
| 14 | * You should have received a copy of the GNU General Public License along with |
| 15 | * this program; if not, write to the Free Software Foundation, Inc., |
| 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA |
| 17 | * |
| 18 | * The full GNU General Public License is included in this distribution in the |
| 19 | * file called LICENSE. |
| 20 | * |
| 21 | * Contact Information: |
| 22 | * wlanfae <wlanfae@realtek.com> |
| 23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, |
| 24 | * Hsinchu 300, Taiwan. |
| 25 | * |
| 26 | * Larry Finger <Larry.Finger@lwfinger.net> |
| 27 | * |
| 28 | *****************************************************************************/ |
| 29 | |
| 30 | #include "../wifi.h" |
| 31 | #include "../usb.h" |
| 32 | #include "../ps.h" |
| 33 | #include "../base.h" |
| 34 | #include "reg.h" |
| 35 | #include "def.h" |
| 36 | #include "phy.h" |
| 37 | #include "rf.h" |
| 38 | #include "dm.h" |
| 39 | #include "mac.h" |
| 40 | #include "trx.h" |
| 41 | |
| 42 | static int _ConfigVerTOutEP(struct ieee80211_hw *hw) |
| 43 | { |
| 44 | u8 ep_cfg, txqsele; |
| 45 | u8 ep_nums = 0; |
| 46 | |
| 47 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 48 | struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); |
| 49 | struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); |
| 50 | |
| 51 | rtlusb->out_queue_sel = 0; |
| 52 | ep_cfg = rtl_read_byte(rtlpriv, REG_TEST_SIE_OPTIONAL); |
| 53 | ep_cfg = (ep_cfg & USB_TEST_EP_MASK) >> USB_TEST_EP_SHIFT; |
| 54 | switch (ep_cfg) { |
| 55 | case 0: /* 2 bulk OUT, 1 bulk IN */ |
| 56 | case 3: |
| 57 | rtlusb->out_queue_sel = TX_SELE_HQ | TX_SELE_LQ; |
| 58 | ep_nums = 2; |
| 59 | break; |
| 60 | case 1: /* 1 bulk IN/OUT => map all endpoint to Low queue */ |
| 61 | case 2: /* 1 bulk IN, 1 bulk OUT => map all endpoint to High queue */ |
| 62 | txqsele = rtl_read_byte(rtlpriv, REG_TEST_USB_TXQS); |
| 63 | if (txqsele & 0x0F) /* /map all endpoint to High queue */ |
| 64 | rtlusb->out_queue_sel = TX_SELE_HQ; |
| 65 | else if (txqsele&0xF0) /* map all endpoint to Low queue */ |
| 66 | rtlusb->out_queue_sel = TX_SELE_LQ; |
| 67 | ep_nums = 1; |
| 68 | break; |
| 69 | default: |
| 70 | break; |
| 71 | } |
| 72 | return (rtlusb->out_ep_nums == ep_nums) ? 0 : -EINVAL; |
| 73 | } |
| 74 | |
| 75 | static int _ConfigVerNOutEP(struct ieee80211_hw *hw) |
| 76 | { |
| 77 | u8 ep_cfg; |
| 78 | u8 ep_nums = 0; |
| 79 | |
| 80 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 81 | struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); |
| 82 | struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); |
| 83 | |
| 84 | rtlusb->out_queue_sel = 0; |
| 85 | /* Normal and High queue */ |
| 86 | ep_cfg = rtl_read_byte(rtlpriv, (REG_NORMAL_SIE_EP + 1)); |
| 87 | if (ep_cfg & USB_NORMAL_SIE_EP_MASK) { |
| 88 | rtlusb->out_queue_sel |= TX_SELE_HQ; |
| 89 | ep_nums++; |
| 90 | } |
| 91 | if ((ep_cfg >> USB_NORMAL_SIE_EP_SHIFT) & USB_NORMAL_SIE_EP_MASK) { |
| 92 | rtlusb->out_queue_sel |= TX_SELE_NQ; |
| 93 | ep_nums++; |
| 94 | } |
| 95 | /* Low queue */ |
| 96 | ep_cfg = rtl_read_byte(rtlpriv, (REG_NORMAL_SIE_EP + 2)); |
| 97 | if (ep_cfg & USB_NORMAL_SIE_EP_MASK) { |
| 98 | rtlusb->out_queue_sel |= TX_SELE_LQ; |
| 99 | ep_nums++; |
| 100 | } |
| 101 | return (rtlusb->out_ep_nums == ep_nums) ? 0 : -EINVAL; |
| 102 | } |
| 103 | |
| 104 | static void _TwoOutEpMapping(struct ieee80211_hw *hw, bool bIsChipB, |
| 105 | bool bwificfg, struct rtl_ep_map *ep_map) |
| 106 | { |
| 107 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 108 | |
| 109 | if (bwificfg) { /* for WMM */ |
| 110 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, |
Joe Perches | f30d750 | 2012-01-04 19:40:41 -0800 | [diff] [blame] | 111 | "USB Chip-B & WMM Setting.....\n"); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 112 | ep_map->ep_mapping[RTL_TXQ_BE] = 2; |
| 113 | ep_map->ep_mapping[RTL_TXQ_BK] = 3; |
| 114 | ep_map->ep_mapping[RTL_TXQ_VI] = 3; |
| 115 | ep_map->ep_mapping[RTL_TXQ_VO] = 2; |
| 116 | ep_map->ep_mapping[RTL_TXQ_MGT] = 2; |
| 117 | ep_map->ep_mapping[RTL_TXQ_BCN] = 2; |
| 118 | ep_map->ep_mapping[RTL_TXQ_HI] = 2; |
| 119 | } else { /* typical setting */ |
| 120 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, |
Joe Perches | f30d750 | 2012-01-04 19:40:41 -0800 | [diff] [blame] | 121 | "USB typical Setting.....\n"); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 122 | ep_map->ep_mapping[RTL_TXQ_BE] = 3; |
| 123 | ep_map->ep_mapping[RTL_TXQ_BK] = 3; |
| 124 | ep_map->ep_mapping[RTL_TXQ_VI] = 2; |
| 125 | ep_map->ep_mapping[RTL_TXQ_VO] = 2; |
| 126 | ep_map->ep_mapping[RTL_TXQ_MGT] = 2; |
| 127 | ep_map->ep_mapping[RTL_TXQ_BCN] = 2; |
| 128 | ep_map->ep_mapping[RTL_TXQ_HI] = 2; |
| 129 | } |
| 130 | } |
| 131 | |
| 132 | static void _ThreeOutEpMapping(struct ieee80211_hw *hw, bool bwificfg, |
| 133 | struct rtl_ep_map *ep_map) |
| 134 | { |
| 135 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 136 | if (bwificfg) { /* for WMM */ |
| 137 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, |
Joe Perches | f30d750 | 2012-01-04 19:40:41 -0800 | [diff] [blame] | 138 | "USB 3EP Setting for WMM.....\n"); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 139 | ep_map->ep_mapping[RTL_TXQ_BE] = 5; |
| 140 | ep_map->ep_mapping[RTL_TXQ_BK] = 3; |
| 141 | ep_map->ep_mapping[RTL_TXQ_VI] = 3; |
| 142 | ep_map->ep_mapping[RTL_TXQ_VO] = 2; |
| 143 | ep_map->ep_mapping[RTL_TXQ_MGT] = 2; |
| 144 | ep_map->ep_mapping[RTL_TXQ_BCN] = 2; |
| 145 | ep_map->ep_mapping[RTL_TXQ_HI] = 2; |
| 146 | } else { /* typical setting */ |
| 147 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, |
Joe Perches | f30d750 | 2012-01-04 19:40:41 -0800 | [diff] [blame] | 148 | "USB 3EP Setting for typical.....\n"); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 149 | ep_map->ep_mapping[RTL_TXQ_BE] = 5; |
| 150 | ep_map->ep_mapping[RTL_TXQ_BK] = 5; |
| 151 | ep_map->ep_mapping[RTL_TXQ_VI] = 3; |
| 152 | ep_map->ep_mapping[RTL_TXQ_VO] = 2; |
| 153 | ep_map->ep_mapping[RTL_TXQ_MGT] = 2; |
| 154 | ep_map->ep_mapping[RTL_TXQ_BCN] = 2; |
| 155 | ep_map->ep_mapping[RTL_TXQ_HI] = 2; |
| 156 | } |
| 157 | } |
| 158 | |
| 159 | static void _OneOutEpMapping(struct ieee80211_hw *hw, struct rtl_ep_map *ep_map) |
| 160 | { |
| 161 | ep_map->ep_mapping[RTL_TXQ_BE] = 2; |
| 162 | ep_map->ep_mapping[RTL_TXQ_BK] = 2; |
| 163 | ep_map->ep_mapping[RTL_TXQ_VI] = 2; |
| 164 | ep_map->ep_mapping[RTL_TXQ_VO] = 2; |
| 165 | ep_map->ep_mapping[RTL_TXQ_MGT] = 2; |
| 166 | ep_map->ep_mapping[RTL_TXQ_BCN] = 2; |
| 167 | ep_map->ep_mapping[RTL_TXQ_HI] = 2; |
| 168 | } |
| 169 | static int _out_ep_mapping(struct ieee80211_hw *hw) |
| 170 | { |
| 171 | int err = 0; |
| 172 | bool bIsChipN, bwificfg = false; |
| 173 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
| 174 | struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); |
| 175 | struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); |
| 176 | struct rtl_ep_map *ep_map = &(rtlusb->ep_map); |
| 177 | |
| 178 | bIsChipN = IS_NORMAL_CHIP(rtlhal->version); |
| 179 | switch (rtlusb->out_ep_nums) { |
| 180 | case 2: |
| 181 | _TwoOutEpMapping(hw, bIsChipN, bwificfg, ep_map); |
| 182 | break; |
| 183 | case 3: |
| 184 | /* Test chip doesn't support three out EPs. */ |
| 185 | if (!bIsChipN) { |
| 186 | err = -EINVAL; |
| 187 | goto err_out; |
| 188 | } |
| 189 | _ThreeOutEpMapping(hw, bIsChipN, ep_map); |
| 190 | break; |
| 191 | case 1: |
| 192 | _OneOutEpMapping(hw, ep_map); |
| 193 | break; |
| 194 | default: |
| 195 | err = -EINVAL; |
| 196 | break; |
| 197 | } |
| 198 | err_out: |
| 199 | return err; |
| 200 | |
| 201 | } |
| 202 | /* endpoint mapping */ |
| 203 | int rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw) |
| 204 | { |
| 205 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
| 206 | int error = 0; |
| 207 | if (likely(IS_NORMAL_CHIP(rtlhal->version))) |
| 208 | error = _ConfigVerNOutEP(hw); |
| 209 | else |
| 210 | error = _ConfigVerTOutEP(hw); |
| 211 | if (error) |
| 212 | goto err_out; |
| 213 | error = _out_ep_mapping(hw); |
| 214 | if (error) |
| 215 | goto err_out; |
| 216 | err_out: |
| 217 | return error; |
| 218 | } |
| 219 | |
| 220 | u16 rtl8192cu_mq_to_hwq(__le16 fc, u16 mac80211_queue_index) |
| 221 | { |
| 222 | u16 hw_queue_index; |
| 223 | |
| 224 | if (unlikely(ieee80211_is_beacon(fc))) { |
| 225 | hw_queue_index = RTL_TXQ_BCN; |
| 226 | goto out; |
| 227 | } |
| 228 | if (ieee80211_is_mgmt(fc)) { |
| 229 | hw_queue_index = RTL_TXQ_MGT; |
| 230 | goto out; |
| 231 | } |
| 232 | switch (mac80211_queue_index) { |
| 233 | case 0: |
| 234 | hw_queue_index = RTL_TXQ_VO; |
| 235 | break; |
| 236 | case 1: |
| 237 | hw_queue_index = RTL_TXQ_VI; |
| 238 | break; |
| 239 | case 2: |
| 240 | hw_queue_index = RTL_TXQ_BE; |
| 241 | break; |
| 242 | case 3: |
| 243 | hw_queue_index = RTL_TXQ_BK; |
| 244 | break; |
| 245 | default: |
| 246 | hw_queue_index = RTL_TXQ_BE; |
Joe Perches | 9d833ed | 2012-01-04 19:40:43 -0800 | [diff] [blame] | 247 | RT_ASSERT(false, "QSLT_BE queue, skb_queue:%d\n", |
| 248 | mac80211_queue_index); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 249 | break; |
| 250 | } |
| 251 | out: |
| 252 | return hw_queue_index; |
| 253 | } |
| 254 | |
| 255 | static enum rtl_desc_qsel _rtl8192cu_mq_to_descq(struct ieee80211_hw *hw, |
| 256 | __le16 fc, u16 mac80211_queue_index) |
| 257 | { |
| 258 | enum rtl_desc_qsel qsel; |
| 259 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 260 | |
| 261 | if (unlikely(ieee80211_is_beacon(fc))) { |
| 262 | qsel = QSLT_BEACON; |
| 263 | goto out; |
| 264 | } |
| 265 | if (ieee80211_is_mgmt(fc)) { |
| 266 | qsel = QSLT_MGNT; |
| 267 | goto out; |
| 268 | } |
| 269 | switch (mac80211_queue_index) { |
| 270 | case 0: /* VO */ |
| 271 | qsel = QSLT_VO; |
| 272 | RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG, |
Joe Perches | f30d750 | 2012-01-04 19:40:41 -0800 | [diff] [blame] | 273 | "VO queue, set qsel = 0x%x\n", QSLT_VO); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 274 | break; |
| 275 | case 1: /* VI */ |
| 276 | qsel = QSLT_VI; |
| 277 | RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG, |
Joe Perches | f30d750 | 2012-01-04 19:40:41 -0800 | [diff] [blame] | 278 | "VI queue, set qsel = 0x%x\n", QSLT_VI); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 279 | break; |
| 280 | case 3: /* BK */ |
| 281 | qsel = QSLT_BK; |
| 282 | RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG, |
Joe Perches | f30d750 | 2012-01-04 19:40:41 -0800 | [diff] [blame] | 283 | "BK queue, set qsel = 0x%x\n", QSLT_BK); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 284 | break; |
| 285 | case 2: /* BE */ |
| 286 | default: |
| 287 | qsel = QSLT_BE; |
| 288 | RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG, |
Joe Perches | f30d750 | 2012-01-04 19:40:41 -0800 | [diff] [blame] | 289 | "BE queue, set qsel = 0x%x\n", QSLT_BE); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 290 | break; |
| 291 | } |
| 292 | out: |
| 293 | return qsel; |
| 294 | } |
| 295 | |
| 296 | /* =============================================================== */ |
| 297 | |
| 298 | /*---------------------------------------------------------------------- |
| 299 | * |
| 300 | * Rx handler |
| 301 | * |
| 302 | *---------------------------------------------------------------------- */ |
| 303 | bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw, |
| 304 | struct rtl_stats *stats, |
| 305 | struct ieee80211_rx_status *rx_status, |
| 306 | u8 *p_desc, struct sk_buff *skb) |
| 307 | { |
| 308 | struct rx_fwinfo_92c *p_drvinfo; |
| 309 | struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc; |
| 310 | u32 phystatus = GET_RX_DESC_PHY_STATUS(pdesc); |
| 311 | |
| 312 | stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc); |
| 313 | stats->rx_drvinfo_size = (u8)GET_RX_DESC_DRVINFO_SIZE(pdesc) * |
| 314 | RX_DRV_INFO_SIZE_UNIT; |
| 315 | stats->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03); |
| 316 | stats->icv = (u16) GET_RX_DESC_ICV(pdesc); |
| 317 | stats->crc = (u16) GET_RX_DESC_CRC32(pdesc); |
| 318 | stats->hwerror = (stats->crc | stats->icv); |
| 319 | stats->decrypted = !GET_RX_DESC_SWDEC(pdesc); |
| 320 | stats->rate = (u8) GET_RX_DESC_RX_MCS(pdesc); |
| 321 | stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc); |
| 322 | stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1); |
| 323 | stats->isampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1) |
| 324 | && (GET_RX_DESC_FAGGR(pdesc) == 1)); |
| 325 | stats->timestamp_low = GET_RX_DESC_TSFL(pdesc); |
| 326 | stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc); |
| 327 | rx_status->freq = hw->conf.channel->center_freq; |
| 328 | rx_status->band = hw->conf.channel->band; |
| 329 | if (GET_RX_DESC_CRC32(pdesc)) |
| 330 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; |
| 331 | if (!GET_RX_DESC_SWDEC(pdesc)) |
| 332 | rx_status->flag |= RX_FLAG_DECRYPTED; |
| 333 | if (GET_RX_DESC_BW(pdesc)) |
| 334 | rx_status->flag |= RX_FLAG_40MHZ; |
| 335 | if (GET_RX_DESC_RX_HT(pdesc)) |
| 336 | rx_status->flag |= RX_FLAG_HT; |
Johannes Berg | 6ebacbb | 2011-02-23 15:06:08 +0100 | [diff] [blame] | 337 | rx_status->flag |= RX_FLAG_MACTIME_MPDU; |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 338 | if (stats->decrypted) |
| 339 | rx_status->flag |= RX_FLAG_DECRYPTED; |
Larry Finger | 2b67e88 | 2011-08-22 16:50:16 -0500 | [diff] [blame] | 340 | rx_status->rate_idx = rtlwifi_rate_mapping(hw, |
| 341 | (bool)GET_RX_DESC_RX_HT(pdesc), |
| 342 | (u8)GET_RX_DESC_RX_MCS(pdesc), |
| 343 | (bool)GET_RX_DESC_PAGGR(pdesc)); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 344 | rx_status->mactime = GET_RX_DESC_TSFL(pdesc); |
Mike McCormack | e10542c | 2011-06-20 10:47:51 +0900 | [diff] [blame] | 345 | if (phystatus) { |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 346 | p_drvinfo = (struct rx_fwinfo_92c *)(pdesc + RTL_RX_DESC_SIZE); |
| 347 | rtl92c_translate_rx_signal_stuff(hw, skb, stats, pdesc, |
| 348 | p_drvinfo); |
| 349 | } |
| 350 | /*rx_status->qual = stats->signal; */ |
| 351 | rx_status->signal = stats->rssi + 10; |
| 352 | /*rx_status->noise = -stats->noise; */ |
| 353 | return true; |
| 354 | } |
| 355 | |
| 356 | #define RTL_RX_DRV_INFO_UNIT 8 |
| 357 | |
| 358 | static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb) |
| 359 | { |
| 360 | struct ieee80211_rx_status *rx_status = |
| 361 | (struct ieee80211_rx_status *)IEEE80211_SKB_RXCB(skb); |
| 362 | u32 skb_len, pkt_len, drvinfo_len; |
| 363 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 364 | u8 *rxdesc; |
| 365 | struct rtl_stats stats = { |
| 366 | .signal = 0, |
| 367 | .noise = -98, |
| 368 | .rate = 0, |
| 369 | }; |
| 370 | struct rx_fwinfo_92c *p_drvinfo; |
| 371 | bool bv; |
| 372 | __le16 fc; |
| 373 | struct ieee80211_hdr *hdr; |
| 374 | |
Joe Perches | 73f7436 | 2011-05-09 12:51:57 -0700 | [diff] [blame] | 375 | memset(rx_status, 0, sizeof(*rx_status)); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 376 | rxdesc = skb->data; |
| 377 | skb_len = skb->len; |
| 378 | drvinfo_len = (GET_RX_DESC_DRVINFO_SIZE(rxdesc) * RTL_RX_DRV_INFO_UNIT); |
| 379 | pkt_len = GET_RX_DESC_PKT_LEN(rxdesc); |
| 380 | /* TODO: Error recovery. drop this skb or something. */ |
| 381 | WARN_ON(skb_len < (pkt_len + RTL_RX_DESC_SIZE + drvinfo_len)); |
| 382 | stats.length = (u16) GET_RX_DESC_PKT_LEN(rxdesc); |
| 383 | stats.rx_drvinfo_size = (u8)GET_RX_DESC_DRVINFO_SIZE(rxdesc) * |
| 384 | RX_DRV_INFO_SIZE_UNIT; |
| 385 | stats.rx_bufshift = (u8) (GET_RX_DESC_SHIFT(rxdesc) & 0x03); |
| 386 | stats.icv = (u16) GET_RX_DESC_ICV(rxdesc); |
| 387 | stats.crc = (u16) GET_RX_DESC_CRC32(rxdesc); |
| 388 | stats.hwerror = (stats.crc | stats.icv); |
| 389 | stats.decrypted = !GET_RX_DESC_SWDEC(rxdesc); |
| 390 | stats.rate = (u8) GET_RX_DESC_RX_MCS(rxdesc); |
| 391 | stats.shortpreamble = (u16) GET_RX_DESC_SPLCP(rxdesc); |
| 392 | stats.isampdu = (bool) ((GET_RX_DESC_PAGGR(rxdesc) == 1) |
| 393 | && (GET_RX_DESC_FAGGR(rxdesc) == 1)); |
| 394 | stats.timestamp_low = GET_RX_DESC_TSFL(rxdesc); |
| 395 | stats.rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(rxdesc); |
| 396 | /* TODO: is center_freq changed when doing scan? */ |
| 397 | /* TODO: Shall we add protection or just skip those two step? */ |
| 398 | rx_status->freq = hw->conf.channel->center_freq; |
| 399 | rx_status->band = hw->conf.channel->band; |
| 400 | if (GET_RX_DESC_CRC32(rxdesc)) |
| 401 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; |
| 402 | if (!GET_RX_DESC_SWDEC(rxdesc)) |
| 403 | rx_status->flag |= RX_FLAG_DECRYPTED; |
| 404 | if (GET_RX_DESC_BW(rxdesc)) |
| 405 | rx_status->flag |= RX_FLAG_40MHZ; |
| 406 | if (GET_RX_DESC_RX_HT(rxdesc)) |
| 407 | rx_status->flag |= RX_FLAG_HT; |
| 408 | /* Data rate */ |
Larry Finger | 2b67e88 | 2011-08-22 16:50:16 -0500 | [diff] [blame] | 409 | rx_status->rate_idx = rtlwifi_rate_mapping(hw, |
| 410 | (bool)GET_RX_DESC_RX_HT(rxdesc), |
| 411 | (u8)GET_RX_DESC_RX_MCS(rxdesc), |
| 412 | (bool)GET_RX_DESC_PAGGR(rxdesc)); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 413 | /* There is a phy status after this rx descriptor. */ |
| 414 | if (GET_RX_DESC_PHY_STATUS(rxdesc)) { |
| 415 | p_drvinfo = (struct rx_fwinfo_92c *)(rxdesc + RTL_RX_DESC_SIZE); |
| 416 | rtl92c_translate_rx_signal_stuff(hw, skb, &stats, |
| 417 | (struct rx_desc_92c *)rxdesc, p_drvinfo); |
| 418 | } |
| 419 | skb_pull(skb, (drvinfo_len + RTL_RX_DESC_SIZE)); |
| 420 | hdr = (struct ieee80211_hdr *)(skb->data); |
| 421 | fc = hdr->frame_control; |
| 422 | bv = ieee80211_is_probe_resp(fc); |
| 423 | if (bv) |
| 424 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, |
Joe Perches | f30d750 | 2012-01-04 19:40:41 -0800 | [diff] [blame] | 425 | "Got probe response frame\n"); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 426 | if (ieee80211_is_beacon(fc)) |
Joe Perches | f30d750 | 2012-01-04 19:40:41 -0800 | [diff] [blame] | 427 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Got beacon frame\n"); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 428 | if (ieee80211_is_data(fc)) |
Joe Perches | f30d750 | 2012-01-04 19:40:41 -0800 | [diff] [blame] | 429 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Got data frame\n"); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 430 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, |
Joe Perches | f30d750 | 2012-01-04 19:40:41 -0800 | [diff] [blame] | 431 | "Fram: fc = 0x%X addr1 = 0x%02X:0x%02X:0x%02X:0x%02X:0x%02X:0x%02X\n", |
| 432 | fc, |
| 433 | (u32)hdr->addr1[0], (u32)hdr->addr1[1], |
| 434 | (u32)hdr->addr1[2], (u32)hdr->addr1[3], |
| 435 | (u32)hdr->addr1[4], (u32)hdr->addr1[5]); |
Joe Perches | 73f7436 | 2011-05-09 12:51:57 -0700 | [diff] [blame] | 436 | memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status)); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 437 | ieee80211_rx_irqsafe(hw, skb); |
| 438 | } |
| 439 | |
| 440 | void rtl8192cu_rx_hdl(struct ieee80211_hw *hw, struct sk_buff * skb) |
| 441 | { |
| 442 | _rtl_rx_process(hw, skb); |
| 443 | } |
| 444 | |
| 445 | void rtl8192c_rx_segregate_hdl( |
| 446 | struct ieee80211_hw *hw, |
| 447 | struct sk_buff *skb, |
| 448 | struct sk_buff_head *skb_list) |
| 449 | { |
| 450 | } |
| 451 | |
| 452 | /*---------------------------------------------------------------------- |
| 453 | * |
| 454 | * Tx handler |
| 455 | * |
| 456 | *---------------------------------------------------------------------- */ |
| 457 | void rtl8192c_tx_cleanup(struct ieee80211_hw *hw, struct sk_buff *skb) |
| 458 | { |
| 459 | } |
| 460 | |
| 461 | int rtl8192c_tx_post_hdl(struct ieee80211_hw *hw, struct urb *urb, |
| 462 | struct sk_buff *skb) |
| 463 | { |
| 464 | return 0; |
| 465 | } |
| 466 | |
| 467 | struct sk_buff *rtl8192c_tx_aggregate_hdl(struct ieee80211_hw *hw, |
| 468 | struct sk_buff_head *list) |
| 469 | { |
| 470 | return skb_dequeue(list); |
| 471 | } |
| 472 | |
| 473 | /*======================================== trx ===============================*/ |
| 474 | |
| 475 | static void _rtl_fill_usb_tx_desc(u8 *txdesc) |
| 476 | { |
| 477 | SET_TX_DESC_OWN(txdesc, 1); |
| 478 | SET_TX_DESC_LAST_SEG(txdesc, 1); |
| 479 | SET_TX_DESC_FIRST_SEG(txdesc, 1); |
| 480 | } |
| 481 | /** |
| 482 | * For HW recovery information |
| 483 | */ |
| 484 | static void _rtl_tx_desc_checksum(u8 *txdesc) |
| 485 | { |
| 486 | u16 *ptr = (u16 *)txdesc; |
| 487 | u16 checksum = 0; |
| 488 | u32 index; |
| 489 | |
| 490 | /* Clear first */ |
| 491 | SET_TX_DESC_TX_DESC_CHECKSUM(txdesc, 0); |
| 492 | for (index = 0; index < 16; index++) |
| 493 | checksum = checksum ^ (*(ptr + index)); |
Larry Finger | abfabc9 | 2011-11-17 12:14:44 -0600 | [diff] [blame] | 494 | SET_TX_DESC_TX_DESC_CHECKSUM(txdesc, cpu_to_le16(checksum)); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 495 | } |
| 496 | |
| 497 | void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, |
| 498 | struct ieee80211_hdr *hdr, u8 *pdesc_tx, |
| 499 | struct ieee80211_tx_info *info, struct sk_buff *skb, |
Chaoming_Li | 76c34f9 | 2011-04-25 12:54:05 -0500 | [diff] [blame] | 500 | u8 queue_index, |
| 501 | struct rtl_tcb_desc *tcb_desc) |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 502 | { |
| 503 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 504 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
| 505 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
| 506 | bool defaultadapter = true; |
Chaoming_Li | 76c34f9 | 2011-04-25 12:54:05 -0500 | [diff] [blame] | 507 | struct ieee80211_sta *sta = info->control.sta = info->control.sta; |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 508 | u8 *qc = ieee80211_get_qos_ctl(hdr); |
| 509 | u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; |
| 510 | u16 seq_number; |
| 511 | __le16 fc = hdr->frame_control; |
| 512 | u8 rate_flag = info->control.rates[0].flags; |
| 513 | u16 pktlen = skb->len; |
| 514 | enum rtl_desc_qsel fw_qsel = _rtl8192cu_mq_to_descq(hw, fc, |
| 515 | skb_get_queue_mapping(skb)); |
| 516 | u8 *txdesc; |
| 517 | |
| 518 | seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; |
Chaoming_Li | 76c34f9 | 2011-04-25 12:54:05 -0500 | [diff] [blame] | 519 | rtl_get_tcb_desc(hw, info, sta, skb, tcb_desc); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 520 | txdesc = (u8 *)skb_push(skb, RTL_TX_HEADER_SIZE); |
| 521 | memset(txdesc, 0, RTL_TX_HEADER_SIZE); |
| 522 | SET_TX_DESC_PKT_SIZE(txdesc, pktlen); |
| 523 | SET_TX_DESC_LINIP(txdesc, 0); |
| 524 | SET_TX_DESC_PKT_OFFSET(txdesc, RTL_DUMMY_OFFSET); |
| 525 | SET_TX_DESC_OFFSET(txdesc, RTL_TX_HEADER_SIZE); |
Chaoming_Li | 76c34f9 | 2011-04-25 12:54:05 -0500 | [diff] [blame] | 526 | SET_TX_DESC_TX_RATE(txdesc, tcb_desc->hw_rate); |
| 527 | if (tcb_desc->use_shortgi || tcb_desc->use_shortpreamble) |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 528 | SET_TX_DESC_DATA_SHORTGI(txdesc, 1); |
| 529 | if (mac->tids[tid].agg.agg_state == RTL_AGG_ON && |
| 530 | info->flags & IEEE80211_TX_CTL_AMPDU) { |
| 531 | SET_TX_DESC_AGG_ENABLE(txdesc, 1); |
| 532 | SET_TX_DESC_MAX_AGG_NUM(txdesc, 0x14); |
| 533 | } else { |
| 534 | SET_TX_DESC_AGG_BREAK(txdesc, 1); |
| 535 | } |
| 536 | SET_TX_DESC_SEQ(txdesc, seq_number); |
Chaoming_Li | 76c34f9 | 2011-04-25 12:54:05 -0500 | [diff] [blame] | 537 | SET_TX_DESC_RTS_ENABLE(txdesc, ((tcb_desc->rts_enable && |
| 538 | !tcb_desc->cts_enable) ? 1 : 0)); |
| 539 | SET_TX_DESC_HW_RTS_ENABLE(txdesc, ((tcb_desc->rts_enable || |
| 540 | tcb_desc->cts_enable) ? 1 : 0)); |
| 541 | SET_TX_DESC_CTS2SELF(txdesc, ((tcb_desc->cts_enable) ? 1 : 0)); |
| 542 | SET_TX_DESC_RTS_STBC(txdesc, ((tcb_desc->rts_stbc) ? 1 : 0)); |
| 543 | SET_TX_DESC_RTS_RATE(txdesc, tcb_desc->rts_rate); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 544 | SET_TX_DESC_RTS_BW(txdesc, 0); |
Chaoming_Li | 76c34f9 | 2011-04-25 12:54:05 -0500 | [diff] [blame] | 545 | SET_TX_DESC_RTS_SC(txdesc, tcb_desc->rts_sc); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 546 | SET_TX_DESC_RTS_SHORT(txdesc, |
Larry Finger | 2b67e88 | 2011-08-22 16:50:16 -0500 | [diff] [blame] | 547 | ((tcb_desc->rts_rate <= DESC92_RATE54M) ? |
Chaoming_Li | 76c34f9 | 2011-04-25 12:54:05 -0500 | [diff] [blame] | 548 | (tcb_desc->rts_use_shortpreamble ? 1 : 0) |
| 549 | : (tcb_desc->rts_use_shortgi ? 1 : 0))); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 550 | if (mac->bw_40) { |
George | 3401dc6 | 2011-09-03 10:58:47 -0500 | [diff] [blame] | 551 | if (rate_flag & IEEE80211_TX_RC_DUP_DATA) { |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 552 | SET_TX_DESC_DATA_BW(txdesc, 1); |
| 553 | SET_TX_DESC_DATA_SC(txdesc, 3); |
George | 3401dc6 | 2011-09-03 10:58:47 -0500 | [diff] [blame] | 554 | } else if(rate_flag & IEEE80211_TX_RC_40_MHZ_WIDTH){ |
| 555 | SET_TX_DESC_DATA_BW(txdesc, 1); |
| 556 | SET_TX_DESC_DATA_SC(txdesc, mac->cur_40_prime_sc); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 557 | } else { |
| 558 | SET_TX_DESC_DATA_BW(txdesc, 0); |
George | 3401dc6 | 2011-09-03 10:58:47 -0500 | [diff] [blame] | 559 | SET_TX_DESC_DATA_SC(txdesc, 0); |
| 560 | } |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 561 | } else { |
| 562 | SET_TX_DESC_DATA_BW(txdesc, 0); |
| 563 | SET_TX_DESC_DATA_SC(txdesc, 0); |
| 564 | } |
Alessio Igor Bogani | 701c2be | 2011-02-28 18:46:44 +0100 | [diff] [blame] | 565 | rcu_read_lock(); |
| 566 | sta = ieee80211_find_sta(mac->vif, mac->bssid); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 567 | if (sta) { |
| 568 | u8 ampdu_density = sta->ht_cap.ampdu_density; |
| 569 | SET_TX_DESC_AMPDU_DENSITY(txdesc, ampdu_density); |
| 570 | } |
Alessio Igor Bogani | 701c2be | 2011-02-28 18:46:44 +0100 | [diff] [blame] | 571 | rcu_read_unlock(); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 572 | if (info->control.hw_key) { |
| 573 | struct ieee80211_key_conf *keyconf = info->control.hw_key; |
| 574 | switch (keyconf->cipher) { |
| 575 | case WLAN_CIPHER_SUITE_WEP40: |
| 576 | case WLAN_CIPHER_SUITE_WEP104: |
| 577 | case WLAN_CIPHER_SUITE_TKIP: |
| 578 | SET_TX_DESC_SEC_TYPE(txdesc, 0x1); |
| 579 | break; |
| 580 | case WLAN_CIPHER_SUITE_CCMP: |
| 581 | SET_TX_DESC_SEC_TYPE(txdesc, 0x3); |
| 582 | break; |
| 583 | default: |
| 584 | SET_TX_DESC_SEC_TYPE(txdesc, 0x0); |
| 585 | break; |
| 586 | } |
| 587 | } |
| 588 | SET_TX_DESC_PKT_ID(txdesc, 0); |
| 589 | SET_TX_DESC_QUEUE_SEL(txdesc, fw_qsel); |
| 590 | SET_TX_DESC_DATA_RATE_FB_LIMIT(txdesc, 0x1F); |
| 591 | SET_TX_DESC_RTS_RATE_FB_LIMIT(txdesc, 0xF); |
| 592 | SET_TX_DESC_DISABLE_FB(txdesc, 0); |
Chaoming_Li | 76c34f9 | 2011-04-25 12:54:05 -0500 | [diff] [blame] | 593 | SET_TX_DESC_USE_RATE(txdesc, tcb_desc->use_driver_rate ? 1 : 0); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 594 | if (ieee80211_is_data_qos(fc)) { |
| 595 | if (mac->rdg_en) { |
| 596 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, |
Joe Perches | f30d750 | 2012-01-04 19:40:41 -0800 | [diff] [blame] | 597 | "Enable RDG function\n"); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 598 | SET_TX_DESC_RDG_ENABLE(txdesc, 1); |
| 599 | SET_TX_DESC_HTC(txdesc, 1); |
| 600 | } |
| 601 | } |
| 602 | if (rtlpriv->dm.useramask) { |
Chaoming_Li | 76c34f9 | 2011-04-25 12:54:05 -0500 | [diff] [blame] | 603 | SET_TX_DESC_RATE_ID(txdesc, tcb_desc->ratr_index); |
| 604 | SET_TX_DESC_MACID(txdesc, tcb_desc->mac_id); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 605 | } else { |
Chaoming_Li | 76c34f9 | 2011-04-25 12:54:05 -0500 | [diff] [blame] | 606 | SET_TX_DESC_RATE_ID(txdesc, 0xC + tcb_desc->ratr_index); |
| 607 | SET_TX_DESC_MACID(txdesc, tcb_desc->ratr_index); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 608 | } |
| 609 | if ((!ieee80211_is_data_qos(fc)) && ppsc->leisure_ps && |
| 610 | ppsc->fwctrl_lps) { |
| 611 | SET_TX_DESC_HWSEQ_EN(txdesc, 1); |
| 612 | SET_TX_DESC_PKT_ID(txdesc, 8); |
| 613 | if (!defaultadapter) |
| 614 | SET_TX_DESC_QOS(txdesc, 1); |
| 615 | } |
| 616 | if (ieee80211_has_morefrags(fc)) |
| 617 | SET_TX_DESC_MORE_FRAG(txdesc, 1); |
| 618 | if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || |
| 619 | is_broadcast_ether_addr(ieee80211_get_DA(hdr))) |
| 620 | SET_TX_DESC_BMC(txdesc, 1); |
| 621 | _rtl_fill_usb_tx_desc(txdesc); |
| 622 | _rtl_tx_desc_checksum(txdesc); |
Joe Perches | 4cd9f40 | 2012-01-04 19:40:44 -0800 | [diff] [blame] | 623 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "==>\n"); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 624 | } |
| 625 | |
| 626 | void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 * pDesc, |
| 627 | u32 buffer_len, bool bIsPsPoll) |
| 628 | { |
| 629 | /* Clear all status */ |
| 630 | memset(pDesc, 0, RTL_TX_HEADER_SIZE); |
| 631 | SET_TX_DESC_FIRST_SEG(pDesc, 1); /* bFirstSeg; */ |
| 632 | SET_TX_DESC_LAST_SEG(pDesc, 1); /* bLastSeg; */ |
| 633 | SET_TX_DESC_OFFSET(pDesc, RTL_TX_HEADER_SIZE); /* Offset = 32 */ |
| 634 | SET_TX_DESC_PKT_SIZE(pDesc, buffer_len); /* Buffer size + command hdr */ |
| 635 | SET_TX_DESC_QUEUE_SEL(pDesc, QSLT_MGNT); /* Fixed queue of Mgnt queue */ |
| 636 | /* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error |
| 637 | * vlaue by Hw. */ |
| 638 | if (bIsPsPoll) { |
| 639 | SET_TX_DESC_NAV_USE_HDR(pDesc, 1); |
| 640 | } else { |
| 641 | SET_TX_DESC_HWSEQ_EN(pDesc, 1); /* Hw set sequence number */ |
| 642 | SET_TX_DESC_PKT_ID(pDesc, 0x100); /* set bit3 to 1. */ |
| 643 | } |
| 644 | SET_TX_DESC_USE_RATE(pDesc, 1); /* use data rate which is set by Sw */ |
| 645 | SET_TX_DESC_OWN(pDesc, 1); |
Larry Finger | 2b67e88 | 2011-08-22 16:50:16 -0500 | [diff] [blame] | 646 | SET_TX_DESC_TX_RATE(pDesc, DESC92_RATE1M); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 647 | _rtl_tx_desc_checksum(pDesc); |
| 648 | } |
| 649 | |
| 650 | void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, |
| 651 | u8 *pdesc, bool firstseg, |
| 652 | bool lastseg, struct sk_buff *skb) |
| 653 | { |
| 654 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 655 | u8 fw_queue = QSLT_BEACON; |
| 656 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); |
| 657 | __le16 fc = hdr->frame_control; |
| 658 | |
Chaoming_Li | 76c34f9 | 2011-04-25 12:54:05 -0500 | [diff] [blame] | 659 | memset((void *)pdesc, 0, RTL_TX_HEADER_SIZE); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 660 | if (firstseg) |
| 661 | SET_TX_DESC_OFFSET(pdesc, RTL_TX_HEADER_SIZE); |
Larry Finger | 2b67e88 | 2011-08-22 16:50:16 -0500 | [diff] [blame] | 662 | SET_TX_DESC_TX_RATE(pdesc, DESC92_RATE1M); |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 663 | SET_TX_DESC_SEQ(pdesc, 0); |
| 664 | SET_TX_DESC_LINIP(pdesc, 0); |
| 665 | SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); |
| 666 | SET_TX_DESC_FIRST_SEG(pdesc, 1); |
| 667 | SET_TX_DESC_LAST_SEG(pdesc, 1); |
| 668 | SET_TX_DESC_RATE_ID(pdesc, 7); |
| 669 | SET_TX_DESC_MACID(pdesc, 0); |
| 670 | SET_TX_DESC_OWN(pdesc, 1); |
| 671 | SET_TX_DESC_PKT_SIZE((u8 *) pdesc, (u16) (skb->len)); |
| 672 | SET_TX_DESC_FIRST_SEG(pdesc, 1); |
| 673 | SET_TX_DESC_LAST_SEG(pdesc, 1); |
| 674 | SET_TX_DESC_OFFSET(pdesc, 0x20); |
| 675 | SET_TX_DESC_USE_RATE(pdesc, 1); |
| 676 | if (!ieee80211_is_data_qos(fc)) { |
| 677 | SET_TX_DESC_HWSEQ_EN(pdesc, 1); |
| 678 | SET_TX_DESC_PKT_ID(pdesc, 8); |
| 679 | } |
Joe Perches | af08687 | 2012-01-04 19:40:40 -0800 | [diff] [blame] | 680 | RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, "H2C Tx Cmd Content", |
George | 29d00a3 | 2011-02-19 16:29:47 -0600 | [diff] [blame] | 681 | pdesc, RTL_TX_DESC_SIZE); |
| 682 | } |
| 683 | |
| 684 | bool rtl92cu_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb) |
| 685 | { |
| 686 | return true; |
| 687 | } |