rtl8821ce_halmac.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2016 - 2018 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 _RTL8821CE_HALMAC_C_
  16. #include <drv_types.h> /* struct dvobj_priv and etc. */
  17. #include "../../hal_halmac.h"
  18. #include "rtl8821ce.h"
  19. static u8 pci_write_port_not_xmitframe(void *d, u32 size, u8 *pBuf, u8 qsel)
  20. {
  21. struct dvobj_priv *pobj = (struct dvobj_priv *)d;
  22. struct pci_dev *pdev = pobj->ppcidev;
  23. PADAPTER padapter = dvobj_get_primary_adapter(pobj);
  24. u32 page_size = 0;
  25. u8 *txbd;
  26. #ifdef CONFIG_64BIT
  27. u64 txbd_dma;
  28. #else
  29. dma_addr_t txbd_dma;
  30. #endif
  31. u8 ret = _SUCCESS;
  32. dma_addr_t mapping;
  33. u16 seg_num = 2 << TX_BUFFER_SEG_NUM;
  34. u16 page_size_length = 0;
  35. #ifdef CONFIG_64BIT_DMA
  36. u16 tmp = rtw_read16(padapter, REG_RX_RXBD_NUM_8821C);
  37. /* using 64bit */
  38. rtw_write16(padapter, REG_RX_RXBD_NUM_8821C, tmp | 0x8000);
  39. #endif
  40. rtw_hal_get_def_var(padapter, HAL_DEF_TX_PAGE_SIZE, &page_size);
  41. /* map TX DESC buf_addr (including TX DESC + tx data) */
  42. mapping = pci_map_single(pdev, pBuf,
  43. size+TX_WIFI_INFO_SIZE, PCI_DMA_TODEVICE);
  44. /* Calculate page size.
  45. * Total buffer length including TX_WIFI_INFO and PacketLen
  46. */
  47. page_size_length =
  48. (size + TX_WIFI_INFO_SIZE) / page_size;
  49. if (((size + TX_WIFI_INFO_SIZE) % page_size) > 0)
  50. page_size_length++;
  51. txbd = pci_alloc_consistent(pdev,
  52. sizeof(struct tx_buf_desc), &txbd_dma);
  53. if (!txbd) {
  54. pci_unmap_single(pdev, mapping,
  55. size + TX_WIFI_INFO_SIZE, PCI_DMA_FROMDEVICE);
  56. return _FALSE;
  57. }
  58. if (qsel == HALMAC_TXDESC_QSEL_H2C_CMD) {
  59. rtw_write32(padapter, REG_H2CQ_TXBD_DESA_8821C,
  60. txbd_dma & DMA_BIT_MASK(32));
  61. #ifdef CONFIG_64BIT_DMA
  62. rtw_write32(padapter, REG_H2CQ_TXBD_DESA_8821C + 4,
  63. txbd_dma >> 32);
  64. #endif
  65. rtw_write32(padapter, REG_H2CQ_TXBD_NUM_8821C,
  66. 2 | ((RTL8821CE_SEG_NUM << 12) & 0x3000));
  67. } else {
  68. /* Set BCN BD Reg */
  69. rtw_write32(padapter, REG_BCNQ_TXBD_DESA_8821C,
  70. txbd_dma & DMA_BIT_MASK(32));
  71. #ifdef CONFIG_64BIT_DMA
  72. rtw_write32(padapter, REG_BCNQ_TXBD_DESA_8821C + 4,
  73. txbd_dma >> 32);
  74. #endif
  75. }
  76. /*
  77. * Reset all tx buffer desciprtor content
  78. * -- Reset first element
  79. */
  80. _rtw_memset(txbd, 0, sizeof(struct tx_buf_desc));
  81. /*
  82. * Fill buffer length of the first buffer,
  83. * For 8821ce, it is required that TX_WIFI_INFO is put in first segment,
  84. * and the size of the first segment cannot be larger than
  85. * TX_WIFI_INFO_SIZE.
  86. */
  87. SET_TX_BD_TX_BUFF_SIZE0(txbd, TX_WIFI_INFO_SIZE);
  88. SET_TX_BD_PSB(txbd, page_size_length);
  89. /* starting addr of TXDESC */
  90. SET_TX_BD_PHYSICAL_ADDR0_LOW(txbd, mapping);
  91. #ifdef CONFIG_64BIT_DMA
  92. SET_TX_BD_PHYSICAL_ADDR0_HIGH(txbd, mapping>>32);
  93. #endif
  94. /*
  95. * It is assumed that in linux implementation, packet is coalesced
  96. * in only one buffer. Extension mode is not supported here
  97. */
  98. SET_TXBUFFER_DESC_LEN_WITH_OFFSET(txbd, 1, size);
  99. SET_TXBUFFER_DESC_ADD_LOW_WITH_OFFSET(txbd, 1,
  100. mapping + TX_WIFI_INFO_SIZE); /* pkt */
  101. #ifdef CONFIG_64BIT_DMA
  102. SET_TXBUFFER_DESC_ADD_HIGH_WITH_OFFSET(txbd, 1,
  103. (mapping + TX_WIFI_INFO_SIZE) >> 32); /* pkt */
  104. #endif
  105. /* Need Comment */
  106. wmb();
  107. if (qsel == HALMAC_TXDESC_QSEL_H2C_CMD)
  108. rtw_write16(padapter, REG_H2CQ_TXBD_IDX, 1);
  109. else {
  110. /* fill_txbd_own*/
  111. SET_TX_BD_OWN(txbd, 1);
  112. /* kick start */
  113. rtw_write8(padapter, REG_RX_RXBD_NUM + 1,
  114. rtw_read8(padapter, REG_RX_RXBD_NUM + 1) | BIT(4));
  115. }
  116. udelay(100);
  117. pci_free_consistent(pdev, sizeof(struct tx_buf_desc), txbd, txbd_dma);
  118. pci_unmap_single(pdev, mapping,
  119. size + TX_WIFI_INFO_SIZE, PCI_DMA_FROMDEVICE);
  120. return ret;
  121. }
  122. static u8 pci_write_data_not_xmitframe(void *d, u8 *pBuf, u32 size, u8 qsel)
  123. {
  124. struct dvobj_priv *pobj = (struct dvobj_priv *)d;
  125. PADAPTER padapter = dvobj_get_primary_adapter(pobj);
  126. struct halmac_adapter *halmac = dvobj_to_halmac((struct dvobj_priv *)d);
  127. struct halmac_api *api = HALMAC_GET_API(halmac);
  128. u32 desclen = 0;
  129. u8 *buf = NULL;
  130. u8 ret = _FALSE;
  131. if ((size + TXDESC_OFFSET) > MAX_CMDBUF_SZ) {
  132. RTW_INFO("%s: total buffer size(%d) > MAX_CMDBUF_SZ(%d)\n"
  133. , __func__, size + TXDESC_OFFSET, MAX_CMDBUF_SZ);
  134. return _FALSE;
  135. }
  136. rtw_halmac_get_tx_desc_size(pobj, &desclen);
  137. buf = rtw_zmalloc(desclen + size);
  138. if (!buf) {
  139. RTW_INFO("%s: rtw_zmalloc for rsvd Fail\n", __func__);
  140. return _FALSE;
  141. }
  142. _rtw_memcpy(buf + desclen, pBuf, size);
  143. SET_TX_DESC_TXPKTSIZE_8821C(buf, size);
  144. /* TX_DESC is not included in the data,
  145. * driver needs to fill in the TX_DESC with qsel=h2c
  146. * Offset in TX_DESC should be set to 0.
  147. */
  148. if (qsel == HALMAC_TXDESC_QSEL_H2C_CMD)
  149. SET_TX_DESC_OFFSET_8821C(buf, 0);
  150. else
  151. SET_TX_DESC_OFFSET_8821C(buf, desclen);
  152. SET_TX_DESC_QSEL_8821C(buf, qsel);
  153. api->halmac_fill_txdesc_checksum(halmac, buf);
  154. ret = pci_write_port_not_xmitframe(d, size, buf, qsel);
  155. if (ret == _SUCCESS)
  156. ret = _TRUE;
  157. else
  158. ret = _FALSE;
  159. rtw_mfree(buf, desclen + size);
  160. return _TRUE;
  161. }
  162. static u8 pci_write_data_rsvd_page_xmitframe(void *d, u8 *pBuf, u32 size)
  163. {
  164. struct dvobj_priv *pobj = (struct dvobj_priv *)d;
  165. PADAPTER padapter = dvobj_get_primary_adapter(pobj);
  166. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  167. struct xmit_frame *pcmdframe = NULL;
  168. struct pkt_attrib *pattrib = NULL;
  169. u32 desclen = 0;
  170. struct rtw_tx_ring *ring = &pxmitpriv->tx_ring[BCN_QUEUE_INX];
  171. struct pci_dev *pdev = pobj->ppcidev;
  172. struct xmit_buf *pxmitbuf = NULL;
  173. u8 DLBcnCount = 0;
  174. u32 poll = 0;
  175. u8 *txbd;
  176. bool bcn_valid = _FALSE;
  177. u8 *txdesc = NULL;
  178. dma_addr_t mapping;
  179. if (size + TXDESC_OFFSET > MAX_CMDBUF_SZ) {
  180. RTW_INFO("%s: total buffer size(%d) > MAX_CMDBUF_SZ(%d)\n"
  181. , __func__, size + TXDESC_OFFSET, MAX_CMDBUF_SZ);
  182. return _FALSE;
  183. }
  184. pcmdframe = rtw_alloc_cmdxmitframe(pxmitpriv);
  185. if (pcmdframe == NULL) {
  186. RTW_INFO("%s: alloc ReservedPagePacket fail!\n", __func__);
  187. return _FALSE;
  188. }
  189. pxmitbuf = pcmdframe->pxmitbuf;
  190. rtw_halmac_get_tx_desc_size(pobj, &desclen);
  191. txdesc = pcmdframe->buf_addr;
  192. _rtw_memcpy((txdesc + desclen), pBuf, size); /* shift desclen */
  193. /* update attribute */
  194. pattrib = &pcmdframe->attrib;
  195. update_mgntframe_attrib(padapter, pattrib);
  196. pattrib->qsel = QSLT_BEACON;
  197. pattrib->pktlen = size;
  198. pattrib->last_txcmdsz = size;
  199. /* Clear beacon valid check bit. */
  200. rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
  201. dump_mgntframe(padapter, pcmdframe);
  202. DLBcnCount = 0;
  203. poll = 0;
  204. do {
  205. DLBcnCount++;
  206. do {
  207. rtw_yield_os();
  208. /* does rsvd page download OK. */
  209. rtw_hal_get_hwreg(padapter,
  210. HW_VAR_BCN_VALID,(u8 *)(&bcn_valid));
  211. poll++;
  212. } while (!bcn_valid && (poll % 10) != 0 && !RTW_CANNOT_RUN(padapter));
  213. } while (!bcn_valid && DLBcnCount <= 100 && !RTW_CANNOT_RUN(padapter));
  214. txbd = (u8 *)(&ring->buf_desc[0]);
  215. mapping = GET_TX_BD_PHYSICAL_ADDR0_LOW(txbd);
  216. #ifdef CONFIG_64BIT_DMA
  217. mapping |= (dma_addr_t)GET_TX_BD_PHYSICAL_ADDR0_HIGH(txbd) << 32;
  218. #endif
  219. /*To patch*/
  220. pci_unmap_single(pdev, mapping, pxmitbuf->len, PCI_DMA_TODEVICE);
  221. return _TRUE;
  222. }
  223. static u8 pci_write_data_h2c_normal(void *d, u8 *pBuf, u32 size)
  224. {
  225. struct dvobj_priv *pobj = (struct dvobj_priv *)d;
  226. PADAPTER padapter = dvobj_get_primary_adapter(pobj);
  227. struct halmac_adapter *halmac = dvobj_to_halmac((struct dvobj_priv *)d);
  228. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  229. struct xmit_frame *pcmdframe = NULL;
  230. struct pkt_attrib *pattrib = NULL;
  231. struct halmac_api *api;
  232. u32 desclen;
  233. u8 *buf;
  234. if (size + TXDESC_OFFSET > MAX_XMIT_EXTBUF_SZ) {
  235. RTW_INFO("%s: total buffer size(%d) > MAX_XMIT_EXTBUF_SZ(%d)\n"
  236. , __func__, size + TXDESC_OFFSET, MAX_XMIT_EXTBUF_SZ);
  237. return _FALSE;
  238. }
  239. pcmdframe = alloc_mgtxmitframe(pxmitpriv);
  240. if (pcmdframe == NULL) {
  241. RTW_INFO("%s: alloc ReservedPagePacket fail!\n", __func__);
  242. return _FALSE;
  243. }
  244. api = HALMAC_GET_API(halmac);
  245. rtw_halmac_get_tx_desc_size(pobj, &desclen);
  246. buf = pcmdframe->buf_addr;
  247. _rtw_memcpy(buf + desclen, pBuf, size); /* shift desclen */
  248. SET_TX_DESC_TXPKTSIZE_8821C(buf, size);
  249. SET_TX_DESC_OFFSET_8821C(buf, 0);
  250. SET_TX_DESC_QSEL_8821C(buf, HALMAC_TXDESC_QSEL_H2C_CMD);
  251. SET_TX_DESC_TXDESC_CHECKSUM_8821C(buf, 0);
  252. api->halmac_fill_txdesc_checksum(halmac, buf);
  253. /* update attribute */
  254. pattrib = &pcmdframe->attrib;
  255. update_mgntframe_attrib(padapter, pattrib);
  256. pattrib->qsel = QSLT_CMD;
  257. pattrib->pktlen = size;
  258. pattrib->last_txcmdsz = size;
  259. /* fill tx desc in dump_mgntframe */
  260. dump_mgntframe(padapter, pcmdframe);
  261. return _TRUE;
  262. }
  263. static u8 pci_write_data_rsvd_page(void *d, u8 *pBuf, u32 size)
  264. {
  265. struct dvobj_priv *pobj = (struct dvobj_priv *)d;
  266. PADAPTER padapter = dvobj_get_primary_adapter(pobj);
  267. HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
  268. u8 ret;
  269. if (pHalData->not_xmitframe_fw_dl)
  270. ret = pci_write_data_not_xmitframe(d, pBuf, size, HALMAC_TXDESC_QSEL_BEACON);
  271. else
  272. ret = pci_write_data_rsvd_page_xmitframe(d, pBuf, size);
  273. if (ret == _TRUE)
  274. return 1;
  275. return 0;
  276. }
  277. static u8 pci_write_data_h2c(void *d, u8 *pBuf, u32 size)
  278. {
  279. struct dvobj_priv *pobj = (struct dvobj_priv *)d;
  280. PADAPTER padapter = dvobj_get_primary_adapter(pobj);
  281. HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
  282. u8 ret;
  283. if (pHalData->not_xmitframe_fw_dl)
  284. ret = pci_write_data_not_xmitframe(d, pBuf, size, HALMAC_TXDESC_QSEL_H2C_CMD);
  285. else
  286. ret = pci_write_data_h2c_normal(d, pBuf, size);
  287. if (ret == _TRUE)
  288. return 1;
  289. return 0;
  290. }
  291. int rtl8821ce_halmac_init_adapter(PADAPTER padapter)
  292. {
  293. struct dvobj_priv *d;
  294. struct halmac_platform_api *api;
  295. int err;
  296. #ifdef CONFIG_64BIT_DMA
  297. if (adapter_to_dvobj(padapter)->bdma64)
  298. PlatformEnableDMA64(padapter);
  299. #endif
  300. d = adapter_to_dvobj(padapter);
  301. api = &rtw_halmac_platform_api;
  302. api->SEND_RSVD_PAGE = pci_write_data_rsvd_page;
  303. api->SEND_H2C_PKT = pci_write_data_h2c;
  304. err = rtw_halmac_init_adapter(d, api);
  305. return err;
  306. }