rtl8821ce_ops.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2016 - 2017 Realtek Corporation.
  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. *****************************************************************************/
  15. #define _HCI_OPS_OS_C_
  16. #include <drv_types.h> /* PADAPTER, basic_types.h and etc. */
  17. #include <hal_data.h> /* HAL_DATA_TYPE, GET_HAL_DATA() and etc. */
  18. #include <hal_intf.h> /* struct hal_ops */
  19. #include "../rtl8821c.h"
  20. #include "rtl8821ce.h"
  21. static void init_bd_ring_var(_adapter *padapter)
  22. {
  23. struct recv_priv *r_priv = &padapter->recvpriv;
  24. struct xmit_priv *t_priv = &padapter->xmitpriv;
  25. u8 i = 0;
  26. for (i = 0; i < HW_QUEUE_ENTRY; i++)
  27. t_priv->txringcount[i] = TX_BD_NUM_8821CE;
  28. /*
  29. * we just alloc 2 desc for beacon queue,
  30. * because we just need first desc in hw beacon.
  31. */
  32. t_priv->txringcount[BCN_QUEUE_INX] = TX_BD_NUM_8821CE_BCN;
  33. t_priv->txringcount[TXCMD_QUEUE_INX] = TX_BD_NUM_8821CE_CMD;
  34. /*
  35. * BE queue need more descriptor for performance consideration
  36. * or, No more tx desc will happen, and may cause mac80211 mem leakage.
  37. */
  38. r_priv->rxbuffersize = MAX_RECVBUF_SZ;
  39. r_priv->rxringcount = PCI_MAX_RX_COUNT;
  40. }
  41. static void rtl8821ce_reset_bd(_adapter *padapter)
  42. {
  43. _irqL irqL;
  44. struct xmit_priv *t_priv = &padapter->xmitpriv;
  45. struct recv_priv *r_priv = &padapter->recvpriv;
  46. struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
  47. struct xmit_buf *pxmitbuf = NULL;
  48. u8 *tx_bd, *rx_bd;
  49. int i, rx_queue_idx;
  50. dma_addr_t mapping;
  51. for (rx_queue_idx = 0; rx_queue_idx < 1; rx_queue_idx++) {
  52. if (r_priv->rx_ring[rx_queue_idx].buf_desc) {
  53. rx_bd = NULL;
  54. for (i = 0; i < r_priv->rxringcount; i++) {
  55. rx_bd = (u8 *)
  56. &r_priv->rx_ring[rx_queue_idx].buf_desc[i];
  57. }
  58. r_priv->rx_ring[rx_queue_idx].idx = 0;
  59. }
  60. }
  61. _enter_critical(&pdvobjpriv->irq_th_lock, &irqL);
  62. for (i = 0; i < PCI_MAX_TX_QUEUE_COUNT; i++) {
  63. if (t_priv->tx_ring[i].buf_desc) {
  64. struct rtw_tx_ring *ring = &t_priv->tx_ring[i];
  65. while (ring->qlen) {
  66. tx_bd = (u8 *)(&ring->buf_desc[ring->idx]);
  67. SET_TX_BD_OWN(tx_bd, 0);
  68. if (i != BCN_QUEUE_INX)
  69. ring->idx =
  70. (ring->idx + 1) % ring->entries;
  71. pxmitbuf = rtl8821ce_dequeue_xmitbuf(ring);
  72. if (pxmitbuf) {
  73. mapping = GET_TX_BD_PHYSICAL_ADDR0_LOW(tx_bd);
  74. #ifdef CONFIG_64BIT_DMA
  75. mapping |= (dma_addr_t)GET_TX_BD_PHYSICAL_ADDR0_HIGH(tx_bd) << 32;
  76. #endif
  77. #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0))
  78. pci_unmap_single(pdvobjpriv->ppcidev,
  79. mapping,
  80. pxmitbuf->len, PCI_DMA_TODEVICE);
  81. #else
  82. dma_unmap_single(&(pdvobjpriv->ppcidev)->dev,
  83. mapping,
  84. pxmitbuf->len, DMA_TO_DEVICE);
  85. #endif
  86. rtw_free_xmitbuf(t_priv, pxmitbuf);
  87. } else {
  88. RTW_INFO("%s(): qlen(%d) is not zero, but have xmitbuf in pending queue\n",
  89. __func__, ring->qlen);
  90. break;
  91. }
  92. }
  93. ring->idx = 0;
  94. }
  95. }
  96. _exit_critical(&pdvobjpriv->irq_th_lock, &irqL);
  97. }
  98. static void intf_chip_configure(PADAPTER padapter)
  99. {
  100. HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
  101. struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
  102. struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(pdvobjpriv);
  103. /* close ASPM for AMD defaultly */
  104. pdvobjpriv->const_amdpci_aspm = 0;
  105. /* ASPM PS mode. */
  106. /* 0 - Disable ASPM, 1 - Enable ASPM without Clock Req, */
  107. /* 2 - Enable ASPM with Clock Req, 3- Alwyas Enable ASPM with Clock Req, */
  108. /* 4- Always Enable ASPM without Clock Req. */
  109. /* set default to rtl8188ee:3 RTL8192E:2 */
  110. pdvobjpriv->const_pci_aspm = 0;
  111. /* Setting for PCI-E device */
  112. pdvobjpriv->const_devicepci_aspm_setting = 0x03;
  113. /* Setting for PCI-E bridge */
  114. pdvobjpriv->const_hostpci_aspm_setting = 0x03;
  115. /* In Hw/Sw Radio Off situation. */
  116. /* 0 - Default, 1 - From ASPM setting without low Mac Pwr, */
  117. /* 2 - From ASPM setting with low Mac Pwr, 3 - Bus D3 */
  118. /* set default to RTL8192CE:0 RTL8192SE:2 */
  119. pdvobjpriv->const_hwsw_rfoff_d3 = 0;
  120. /* This setting works for those device with backdoor ASPM setting such as EPHY setting. */
  121. /* 0: Not support ASPM, 1: Support ASPM, 2: According to chipset. */
  122. pdvobjpriv->const_support_pciaspm = 1;
  123. pwrpriv->reg_rfoff = 0;
  124. pwrpriv->rfoff_reason = 0;
  125. pHalData->bL1OffSupport = _FALSE;
  126. }
  127. /*
  128. * Description:
  129. * Collect all hardware information, fill "HAL_DATA_TYPE".
  130. * Sometimes this would be used to read MAC address.
  131. * This function will do
  132. * 1. Read Efuse/EEPROM to initialize
  133. * 2. Read registers to initialize
  134. * 3. Other vaiables initialization
  135. */
  136. static u8 read_adapter_info(PADAPTER padapter)
  137. {
  138. u8 ret = _FAIL;
  139. /*
  140. * 1. Read Efuse/EEPROM to initialize
  141. */
  142. if (rtl8821c_read_efuse(padapter) != _SUCCESS)
  143. goto exit;
  144. /*
  145. * 2. Read registers to initialize
  146. */
  147. /*
  148. * 3. Other Initialization
  149. */
  150. ret = _SUCCESS;
  151. exit:
  152. return ret;
  153. }
  154. static BOOLEAN rtl8821ce_InterruptRecognized(PADAPTER Adapter)
  155. {
  156. HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
  157. BOOLEAN bRecognized = _FALSE;
  158. /* 2013.11.18 Glayrainx suggests that turn off IMR and
  159. * restore after cleaning ISR.
  160. */
  161. rtw_write32(Adapter, REG_HIMR0, 0);
  162. rtw_write32(Adapter, REG_HIMR1, 0);
  163. rtw_write32(Adapter, REG_HIMR3, 0);
  164. pHalData->IntArray[0] = rtw_read32(Adapter, REG_HISR0);
  165. pHalData->IntArray[0] &= pHalData->IntrMask[0];
  166. rtw_write32(Adapter, REG_HISR0, pHalData->IntArray[0]);
  167. /* For HISR extension. Added by tynli. 2009.10.07. */
  168. pHalData->IntArray[1] = rtw_read32(Adapter, REG_HISR1);
  169. pHalData->IntArray[1] &= pHalData->IntrMask[1];
  170. rtw_write32(Adapter, REG_HISR1, pHalData->IntArray[1]);
  171. /* for H2C cmd queue */
  172. pHalData->IntArray[3] = rtw_read32(Adapter, REG_HISR3);
  173. pHalData->IntArray[3] &= pHalData->IntrMask[3];
  174. rtw_write32(Adapter, REG_HISR3, pHalData->IntArray[3]);
  175. if (((pHalData->IntArray[0]) & pHalData->IntrMask[0]) != 0 ||
  176. ((pHalData->IntArray[1]) & pHalData->IntrMask[1]) != 0)
  177. bRecognized = _TRUE;
  178. /* restore IMR */
  179. rtw_write32(Adapter, REG_HIMR0, pHalData->IntrMask[0] & 0xFFFFFFFF);
  180. rtw_write32(Adapter, REG_HIMR1, pHalData->IntrMask[1] & 0xFFFFFFFF);
  181. rtw_write32(Adapter, REG_HIMR3, pHalData->IntrMask[3] & 0xFFFFFFFF);
  182. return bRecognized;
  183. }
  184. static VOID DisableInterrupt8821ce(PADAPTER Adapter)
  185. {
  186. struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(Adapter);
  187. rtw_write32(Adapter, REG_HIMR0, 0x0);
  188. rtw_write32(Adapter, REG_HIMR1, 0x0);
  189. rtw_write32(Adapter, REG_HIMR3, 0x0);
  190. pdvobjpriv->irq_enabled = 0;
  191. }
  192. static VOID rtl8821ce_enable_interrupt(PADAPTER Adapter)
  193. {
  194. HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
  195. struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(Adapter);
  196. pdvobjpriv->irq_enabled = 1;
  197. rtw_write32(Adapter, REG_HIMR0, pHalData->IntrMask[0] & 0xFFFFFFFF);
  198. rtw_write32(Adapter, REG_HIMR1, pHalData->IntrMask[1] & 0xFFFFFFFF);
  199. rtw_write32(Adapter, REG_HIMR3, pHalData->IntrMask[3] & 0xFFFFFFFF);
  200. }
  201. static VOID rtl8821ce_clear_interrupt(PADAPTER Adapter)
  202. {
  203. u32 u32b;
  204. HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
  205. u32b = rtw_read32(Adapter, REG_HISR0_8821C);
  206. rtw_write32(Adapter, REG_HISR0_8821C, u32b);
  207. pHalData->IntArray[0] = 0;
  208. u32b = rtw_read32(Adapter, REG_HISR1_8821C);
  209. rtw_write32(Adapter, REG_HISR1_8821C, u32b);
  210. pHalData->IntArray[1] = 0;
  211. }
  212. static VOID rtl8821ce_disable_interrupt(PADAPTER Adapter)
  213. {
  214. struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(Adapter);
  215. rtw_write32(Adapter, REG_HIMR0, 0x0);
  216. rtw_write32(Adapter, REG_HIMR1, 0x0); /* by tynli */
  217. pdvobjpriv->irq_enabled = 0;
  218. }
  219. VOID UpdateInterruptMask8821CE(PADAPTER Adapter, u32 AddMSR, u32 AddMSR1,
  220. u32 RemoveMSR, u32 RemoveMSR1)
  221. {
  222. PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
  223. DisableInterrupt8821ce(Adapter);
  224. if (AddMSR)
  225. pHalData->IntrMask[0] |= AddMSR;
  226. if (AddMSR1)
  227. pHalData->IntrMask[1] |= AddMSR1;
  228. if (RemoveMSR)
  229. pHalData->IntrMask[0] &= (~RemoveMSR);
  230. if (RemoveMSR1)
  231. pHalData->IntrMask[1] &= (~RemoveMSR1);
  232. #if 0 /* TODO */
  233. if (RemoveMSR3)
  234. pHalData->IntrMask[3] &= (~RemoveMSR3);
  235. #endif
  236. rtl8821ce_enable_interrupt(Adapter);
  237. }
  238. static void rtl8821ce_bcn_handler(PADAPTER Adapter, u32 handled[])
  239. {
  240. PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
  241. if (pHalData->IntArray[0] & BIT_TXBCN0OK_MSK) {
  242. #ifdef CONFIG_BCN_ICF
  243. /* do nothing */
  244. #else
  245. /* Modify for MI temporary,
  246. * this processor cannot apply to multi-ap
  247. */
  248. PADAPTER bcn_adapter = rtw_mi_get_ap_adapter(Adapter);
  249. if (bcn_adapter->xmitpriv.beaconDMAing) {
  250. bcn_adapter->xmitpriv.beaconDMAing = _FAIL;
  251. rtl8821ce_tx_isr(Adapter, BCN_QUEUE_INX);
  252. }
  253. #endif /* CONFIG_BCN_ICF */
  254. handled[0] |= BIT_TXBCN0OK_MSK;
  255. }
  256. if (pHalData->IntArray[0] & BIT_TXBCN0ERR_MSK) {
  257. #ifdef CONFIG_BCN_ICF
  258. RTW_INFO("IMR_TXBCN0ERR isr!\n");
  259. #else /* !CONFIG_BCN_ICF */
  260. /* Modify for MI temporary,
  261. * this processor cannot apply to multi-ap
  262. */
  263. PADAPTER bcn_adapter = rtw_mi_get_ap_adapter(Adapter);
  264. if (bcn_adapter->xmitpriv.beaconDMAing) {
  265. bcn_adapter->xmitpriv.beaconDMAing = _FAIL;
  266. rtl8821ce_tx_isr(Adapter, BCN_QUEUE_INX);
  267. }
  268. #endif /* CONFIG_BCN_ICF */
  269. handled[0] |= BIT_TXBCN0ERR_MSK;
  270. }
  271. if (pHalData->IntArray[0] & BIT_BCNDERR0_MSK) {
  272. #ifdef CONFIG_BCN_ICF
  273. RTW_INFO("BIT_BCNDERR0_MSK isr!\n");
  274. #else /* !CONFIG_BCN_ICF */
  275. /* Release resource and re-transmit beacon to HW */
  276. struct tasklet_struct *bcn_tasklet;
  277. /* Modify for MI temporary,
  278. * this processor cannot apply to multi-ap
  279. */
  280. PADAPTER bcn_adapter = rtw_mi_get_ap_adapter(Adapter);
  281. rtl8821ce_tx_isr(Adapter, BCN_QUEUE_INX);
  282. bcn_adapter->mlmepriv.update_bcn = _TRUE;
  283. bcn_tasklet = &bcn_adapter->recvpriv.irq_prepare_beacon_tasklet;
  284. tasklet_hi_schedule(bcn_tasklet);
  285. #endif /* CONFIG_BCN_ICF */
  286. handled[0] |= BIT_BCNDERR0_MSK;
  287. }
  288. if (pHalData->IntArray[0] & BIT_BCNDMAINT0_MSK) {
  289. struct tasklet_struct *bcn_tasklet;
  290. /* Modify for MI temporary,
  291. * this processor cannot apply to multi-ap
  292. */
  293. PADAPTER bcn_adapter = rtw_mi_get_ap_adapter(Adapter);
  294. bcn_tasklet = &bcn_adapter->recvpriv.irq_prepare_beacon_tasklet;
  295. tasklet_hi_schedule(bcn_tasklet);
  296. handled[0] |= BIT_BCNDMAINT0_MSK;
  297. }
  298. }
  299. static void rtl8821ce_rx_handler(PADAPTER Adapter, u32 handled[])
  300. {
  301. PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
  302. if ((pHalData->IntArray[0] & (BIT_RXOK | BIT_RDU)) ||
  303. (pHalData->IntArray[1] & (BIT_FOVW | BIT_RXERR_INT))) {
  304. pHalData->IntrMask[0] &= (~(BIT_RXOK_MSK | BIT_RDU_MSK));
  305. pHalData->IntrMask[1] &= (~(BIT_FOVW_MSK | BIT_RXERR_MSK));
  306. rtw_write32(Adapter, REG_HIMR0, pHalData->IntrMask[0]);
  307. rtw_write32(Adapter, REG_HIMR1, pHalData->IntrMask[1]);
  308. tasklet_hi_schedule(&Adapter->recvpriv.recv_tasklet);
  309. handled[0] |= pHalData->IntArray[0] & (BIT_RXOK | BIT_RDU);
  310. handled[1] |= pHalData->IntArray[1] & (BIT_FOVW | BIT_RXERR_INT);
  311. }
  312. }
  313. static void rtl8821ce_tx_handler(PADAPTER Adapter, u32 events[], u32 handled[])
  314. {
  315. PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
  316. if (events[0] & BIT_MGTDOK_MSK) {
  317. rtl8821ce_tx_isr(Adapter, MGT_QUEUE_INX);
  318. handled[0] |= BIT_MGTDOK_MSK;
  319. }
  320. if (events[0] & BIT_HIGHDOK_MSK) {
  321. rtl8821ce_tx_isr(Adapter, HIGH_QUEUE_INX);
  322. handled[0] |= BIT_HIGHDOK_MSK;
  323. }
  324. if (events[0] & BIT_BKDOK_MSK) {
  325. rtl8821ce_tx_isr(Adapter, BK_QUEUE_INX);
  326. handled[0] |= BIT_BKDOK_MSK;
  327. }
  328. if (events[0] & BIT_BEDOK_MSK) {
  329. rtl8821ce_tx_isr(Adapter, BE_QUEUE_INX);
  330. handled[0] |= BIT_BEDOK_MSK;
  331. }
  332. if (events[0] & BIT_VIDOK_MSK) {
  333. rtl8821ce_tx_isr(Adapter, VI_QUEUE_INX);
  334. handled[0] |= BIT_VIDOK_MSK;
  335. }
  336. if (events[0] & BIT_VODOK_MSK) {
  337. rtl8821ce_tx_isr(Adapter, VO_QUEUE_INX);
  338. handled[0] |= BIT_VODOK_MSK;
  339. }
  340. }
  341. static void rtl8821ce_cmd_handler(PADAPTER Adapter, u32 handled[])
  342. {
  343. PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
  344. if (pHalData->IntArray[3] & BIT_SETH2CDOK_MASK) {
  345. rtl8821ce_tx_isr(Adapter, TXCMD_QUEUE_INX);
  346. handled[3] |= BIT_SETH2CDOK_MASK;
  347. }
  348. }
  349. static s32 rtl8821ce_interrupt(PADAPTER Adapter)
  350. {
  351. _irqL irqL;
  352. HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
  353. struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(Adapter);
  354. struct xmit_priv *t_priv = &Adapter->xmitpriv;
  355. int ret = _SUCCESS;
  356. u32 handled[4] = {0};
  357. _enter_critical(&pdvobjpriv->irq_th_lock, &irqL);
  358. /* read ISR: 4/8bytes */
  359. if (rtl8821ce_InterruptRecognized(Adapter) == _FALSE) {
  360. ret = _FAIL;
  361. goto done;
  362. }
  363. /* <1> beacon related */
  364. rtl8821ce_bcn_handler(Adapter, handled);
  365. /* <2> Rx related */
  366. rtl8821ce_rx_handler(Adapter, handled);
  367. /* <3> Tx related */
  368. rtl8821ce_tx_handler(Adapter, pHalData->IntArray, handled);
  369. if (pHalData->IntArray[1] & BIT_TXFOVW) {
  370. /*if (printk_ratelimit())*/
  371. RTW_WARN("[TXFOVW]\n");
  372. handled[1] |= BIT_TXFOVW;
  373. }
  374. if (pHalData->IntArray[1] & BIT_PRETXERR_HANDLE_ISR) {
  375. RTW_ERR("[PRE-TX HANG]\n");
  376. handled[1] |= BIT_PRETXERR_HANDLE_ISR;
  377. }
  378. /* <4> Cmd related */
  379. rtl8821ce_cmd_handler(Adapter, handled);
  380. #ifdef CONFIG_LPS_LCLK
  381. if (pHalData->IntArray[0] & BIT_CPWM) {
  382. struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(Adapter);
  383. _set_workitem(&(pwrpriv->cpwm_event));
  384. handled[0] |= BIT_CPWM;
  385. }
  386. #endif
  387. if ((pHalData->IntArray[0] & (~handled[0])) || (pHalData->IntArray[1] & (~handled[1])) || (pHalData->IntArray[3] & (~handled[3]))) {
  388. /*if (printk_ratelimit()) */
  389. {
  390. RTW_WARN("Unhandled ISR = %x, %x, %x\n",
  391. (pHalData->IntArray[0] & (~handled[0])),
  392. (pHalData->IntArray[1] & (~handled[1])),
  393. (pHalData->IntArray[3] & (~handled[3]))
  394. );
  395. }
  396. }
  397. done:
  398. _exit_critical(&pdvobjpriv->irq_th_lock, &irqL);
  399. return ret;
  400. }
  401. u32 rtl8821ce_init_bd(_adapter *padapter)
  402. {
  403. struct xmit_priv *t_priv = &padapter->xmitpriv;
  404. int i, ret = _SUCCESS;
  405. init_bd_ring_var(padapter);
  406. ret = rtl8821ce_init_rxbd_ring(padapter);
  407. if (ret == _FAIL)
  408. return ret;
  409. /* general process for other queue */
  410. for (i = 0; i < PCI_MAX_TX_QUEUE_COUNT; i++) {
  411. ret = rtl8821ce_init_txbd_ring(padapter, i,
  412. t_priv->txringcount[i]);
  413. if (ret == _FAIL)
  414. goto err_free_rings;
  415. }
  416. return ret;
  417. err_free_rings:
  418. rtl8821ce_free_rxbd_ring(padapter);
  419. for (i = 0; i < PCI_MAX_TX_QUEUE_COUNT; i++)
  420. if (t_priv->tx_ring[i].buf_desc)
  421. rtl8821ce_free_txbd_ring(padapter, i);
  422. return ret;
  423. }
  424. u32 rtl8821ce_free_bd(_adapter *padapter)
  425. {
  426. struct xmit_priv *t_priv = &padapter->xmitpriv;
  427. u32 i;
  428. /* free rxbd rings */
  429. rtl8821ce_free_rxbd_ring(padapter);
  430. /* free txbd rings */
  431. for (i = 0; i < HW_QUEUE_ENTRY; i++)
  432. rtl8821ce_free_txbd_ring(padapter, i);
  433. return _SUCCESS;
  434. }
  435. static u16
  436. hal_mdio_read_8821ce(PADAPTER Adapter, u8 Addr)
  437. {
  438. u2Byte ret = 0;
  439. u1Byte tmpU1b = 0, count = 0;
  440. rtw_write8(Adapter, REG_PCIE_MIX_CFG_8821C, Addr | BIT6);
  441. tmpU1b = rtw_read8(Adapter, REG_PCIE_MIX_CFG_8821C) & BIT6;
  442. count = 0;
  443. while (tmpU1b && count < 20) {
  444. rtw_udelay_os(10);
  445. tmpU1b = rtw_read8(Adapter, REG_PCIE_MIX_CFG_8821C) & BIT6;
  446. count++;
  447. }
  448. if (tmpU1b == 0)
  449. ret = rtw_read16(Adapter, REG_MDIO_V1_8821C);
  450. return ret;
  451. }
  452. static VOID
  453. hal_mdio_write_8821ce(PADAPTER Adapter, u8 Addr, u16 Data)
  454. {
  455. u1Byte tmpU1b = 0, count = 0;
  456. rtw_write16(Adapter, REG_MDIO_V1_8821C, Data);
  457. rtw_write8(Adapter, REG_PCIE_MIX_CFG_8821C, Addr | BIT5);
  458. tmpU1b = rtw_read8(Adapter, REG_PCIE_MIX_CFG_8821C) & BIT5;
  459. count = 0;
  460. while (tmpU1b && count < 20) {
  461. rtw_udelay_os(10);
  462. tmpU1b = rtw_read8(Adapter, REG_PCIE_MIX_CFG_8821C) & BIT5;
  463. count++;
  464. }
  465. }
  466. static void hal_dbi_write_8821ce(PADAPTER Adapter, u16 Addr, u8 Data)
  467. {
  468. u1Byte tmpU1b = 0, count = 0;
  469. u2Byte WriteAddr = 0, Remainder = Addr % 4;
  470. /* Write DBI 1Byte Data */
  471. WriteAddr = REG_DBI_WDATA_V1_8821C + Remainder;
  472. rtw_write8(Adapter, WriteAddr, Data);
  473. /* Write DBI 2Byte Address & Write Enable */
  474. WriteAddr = (Addr & 0xfffc) | (BIT0 << (Remainder + 12));
  475. rtw_write16(Adapter, REG_DBI_FLAG_V1_8821C, WriteAddr);
  476. /* Write DBI Write Flag */
  477. rtw_write8(Adapter, REG_DBI_FLAG_V1_8821C + 2, 0x1);
  478. tmpU1b = rtw_read8(Adapter, REG_DBI_FLAG_V1_8821C + 2);
  479. count = 0;
  480. while (tmpU1b && count < 20) {
  481. rtw_udelay_os(10);
  482. tmpU1b = rtw_read8(Adapter, REG_DBI_FLAG_V1_8821C + 2);
  483. count++;
  484. }
  485. }
  486. static u8 hal_dbi_read_8821ce(PADAPTER Adapter, u16 Addr)
  487. {
  488. u16 ReadAddr = Addr & 0xfffc;
  489. u8 ret = 0, tmpU1b = 0, count = 0;
  490. rtw_write16(Adapter, REG_DBI_FLAG_V1_8821C, ReadAddr);
  491. rtw_write8(Adapter, REG_DBI_FLAG_V1_8821C + 2, 0x2);
  492. tmpU1b = rtw_read8(Adapter, REG_DBI_FLAG_V1_8821C + 2);
  493. count = 0;
  494. while (tmpU1b && count < 20) {
  495. rtw_udelay_os(10);
  496. tmpU1b = rtw_read8(Adapter, REG_DBI_FLAG_V1_8821C + 2);
  497. count++;
  498. }
  499. if (tmpU1b == 0) {
  500. ReadAddr = REG_DBI_RDATA_V1_8821C + Addr % 4;
  501. ret = rtw_read8(Adapter, ReadAddr);
  502. }
  503. return ret;
  504. }
  505. /*
  506. * Description:
  507. * Query setting of specified variable.
  508. */
  509. static u8 gethaldefvar(PADAPTER padapter, HAL_DEF_VARIABLE eVariable, PVOID pValue)
  510. {
  511. HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
  512. u8 bResult = _SUCCESS;
  513. switch (eVariable) {
  514. case HAL_DEF_MAX_RECVBUF_SZ:
  515. *((u32 *)pValue) = MAX_RECVBUF_SZ;
  516. break;
  517. case HW_VAR_MAX_RX_AMPDU_FACTOR:
  518. *(HT_CAP_AMPDU_FACTOR *)pValue = MAX_AMPDU_FACTOR_64K;
  519. break;
  520. default:
  521. bResult = rtl8821c_gethaldefvar(padapter, eVariable, pValue);
  522. break;
  523. }
  524. return bResult;
  525. }
  526. /*
  527. * Description:
  528. * Change default setting of specified variable.
  529. */
  530. static u8 sethaldefvar(PADAPTER adapter, HAL_DEF_VARIABLE eVariable, void *pval)
  531. {
  532. PHAL_DATA_TYPE hal = GET_HAL_DATA(adapter);
  533. u8 bResult = _SUCCESS;
  534. switch (eVariable) {
  535. default:
  536. bResult = rtl8821c_sethaldefvar(adapter, eVariable, pval);
  537. break;
  538. }
  539. return bResult;
  540. }
  541. /*
  542. * If variable not handled here,
  543. * some variables will be processed in rtl8821c_sethwreg()
  544. */
  545. static u8 sethwreg(PADAPTER adapter, u8 variable, u8 *val)
  546. {
  547. PHAL_DATA_TYPE hal;
  548. u8 ret = _SUCCESS;
  549. u8 val8;
  550. hal = GET_HAL_DATA(adapter);
  551. switch (variable) {
  552. case HW_VAR_DBI:
  553. {
  554. u16 *pCmd;
  555. pCmd = (u16 *)val;
  556. hal_dbi_write_8821ce(adapter, pCmd[0], (u8)pCmd[1]);
  557. break;
  558. }
  559. case HW_VAR_MDIO:
  560. {
  561. u16 *pCmd;
  562. pCmd = (u16 *)val;
  563. hal_mdio_write_8821ce(adapter, (u8)pCmd[0], pCmd[1]);
  564. break;
  565. }
  566. #ifdef CONFIG_LPS_LCLK
  567. case HW_VAR_SET_RPWM:
  568. {
  569. u8 ps_state = *((u8 *)val);
  570. /* rpwm value only use BIT0(clock bit) ,BIT6(Ack bit), and BIT7(Toggle bit) for 88e. */
  571. /* BIT0 value - 1: 32k, 0:40MHz. */
  572. /* BIT6 value - 1: report cpwm value after success set, 0:do not report. */
  573. /* BIT7 value - Toggle bit change. */
  574. /* modify by Thomas. 2012/4/2. */
  575. ps_state = ps_state & 0xC1;
  576. /* RTW_INFO("##### Change RPWM value to = %x for switch clk #####\n",ps_state); */
  577. rtw_write8(adapter, REG_PCIE_HRPWM1_V1_8821C, ps_state);
  578. break;
  579. }
  580. #endif
  581. default:
  582. ret = rtl8821c_sethwreg(adapter, variable, val);
  583. break;
  584. }
  585. return ret;
  586. }
  587. /*
  588. * If variable not handled here,
  589. * some variables will be processed in GetHwReg8723B()
  590. */
  591. static void gethwreg(PADAPTER adapter, u8 variable, u8 *val)
  592. {
  593. PHAL_DATA_TYPE hal;
  594. hal = GET_HAL_DATA(adapter);
  595. switch (variable) {
  596. case HW_VAR_DBI:
  597. *val = hal_dbi_read_8821ce(adapter, *((u16 *)(val)));
  598. break;
  599. case HW_VAR_MDIO:
  600. *((u16 *)(val)) = hal_mdio_read_8821ce(adapter, *val);
  601. break;
  602. case HW_VAR_L1OFF_NIC_SUPPORT:
  603. {
  604. u8 l1off;
  605. l1off = hal_dbi_read_8821ce(adapter, 0x168);
  606. if (l1off & (BIT2|BIT3))
  607. *val = _TRUE;
  608. else
  609. *val = _FALSE;
  610. }
  611. break;
  612. case HW_VAR_L1OFF_CAPABILITY:
  613. {
  614. u8 l1off;
  615. l1off = hal_dbi_read_8821ce(adapter, 0x164);
  616. if (l1off & (BIT2|BIT3))
  617. *val = _TRUE;
  618. else
  619. *val = _FALSE;
  620. }
  621. break;
  622. #ifdef CONFIG_LPS_LCLK
  623. case HW_VAR_CPWM:
  624. *val = rtw_read8(adapter, REG_PCIE_HCPWM1_V1_8821C);
  625. break;
  626. #endif
  627. default:
  628. rtl8821c_gethwreg(adapter, variable, val);
  629. break;
  630. }
  631. }
  632. void rtl8821ce_set_hal_ops(PADAPTER padapter)
  633. {
  634. struct hal_ops *ops;
  635. int err;
  636. err = rtl8821ce_halmac_init_adapter(padapter);
  637. if (err) {
  638. RTW_INFO("%s: [ERROR]HALMAC initialize FAIL!\n", __func__);
  639. return;
  640. }
  641. rtl8821c_set_hal_ops(padapter);
  642. ops = &padapter->hal_func;
  643. ops->hal_init = rtl8821ce_hal_init;
  644. ops->hal_deinit = rtl8821ce_hal_deinit;
  645. ops->inirp_init = rtl8821ce_init_bd;
  646. ops->inirp_deinit = rtl8821ce_free_bd;
  647. ops->irp_reset = rtl8821ce_reset_bd;
  648. ops->init_xmit_priv = rtl8821ce_init_xmit_priv;
  649. ops->free_xmit_priv = rtl8821ce_free_xmit_priv;
  650. ops->init_recv_priv = rtl8821ce_init_recv_priv;
  651. ops->free_recv_priv = rtl8821ce_free_recv_priv;
  652. #ifdef CONFIG_RTW_SW_LED
  653. ops->InitSwLeds = rtl8821ce_InitSwLeds;
  654. ops->DeInitSwLeds = rtl8821ce_DeInitSwLeds;
  655. #endif
  656. ops->init_default_value = rtl8821ce_init_default_value;
  657. ops->intf_chip_configure = intf_chip_configure;
  658. ops->read_adapter_info = read_adapter_info;
  659. ops->enable_interrupt = rtl8821ce_enable_interrupt;
  660. ops->disable_interrupt = rtl8821ce_disable_interrupt;
  661. ops->interrupt_handler = rtl8821ce_interrupt;
  662. /*
  663. * ops->check_ips_status = check_ips_status;
  664. */
  665. ops->clear_interrupt = rtl8821ce_clear_interrupt;
  666. #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) ||\
  667. defined(CONFIG_PCI_HCI)
  668. /*
  669. * ops->clear_interrupt = clear_interrupt_all;
  670. */
  671. #endif
  672. ops->set_hw_reg_handler = sethwreg;
  673. ops->GetHwRegHandler = gethwreg;
  674. ops->get_hal_def_var_handler = gethaldefvar;
  675. ops->SetHalDefVarHandler = sethaldefvar;
  676. ops->hal_xmit = rtl8821ce_hal_xmit;
  677. ops->mgnt_xmit = rtl8821ce_mgnt_xmit;
  678. ops->hal_xmitframe_enqueue = rtl8821ce_hal_xmitframe_enqueue;
  679. #ifdef CONFIG_HOSTAPD_MLME
  680. ops->hostap_mgnt_xmit_entry = rtl8821ce_hostap_mgnt_xmit_entry;
  681. #endif
  682. #ifdef CONFIG_XMIT_THREAD_MODE
  683. /* TODO */
  684. ops->xmit_thread_handler = rtl8821ce_xmit_buf_handler;
  685. #endif
  686. ops->hal_set_l1ssbackdoor_handler = rtw_pci_aspm_config_l1off_general;
  687. }