rtl8821ce_halmac.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2015 - 2016 Realtek Corporation. All rights reserved.
  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. *
  19. ******************************************************************************/
  20. #define _RTL8821CE_HALMAC_C_
  21. #include <drv_types.h> /* struct dvobj_priv and etc. */
  22. #include "../../hal_halmac.h"
  23. #include "rtl8821ce.h"
  24. static u8 pci_write_port_not_xmitframe(void *d, u32 size, u8 *pBuf)
  25. {
  26. struct dvobj_priv *pobj = (struct dvobj_priv *)d;
  27. struct pci_dev *pdev = pobj->ppcidev;
  28. PADAPTER padapter = dvobj_get_primary_adapter(pobj);
  29. u8 *txbd;
  30. u64 txbd_dma;
  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. /* map TX DESC buf_addr (including TX DESC + tx data) */
  36. mapping = pci_map_single(pdev, pBuf,
  37. size+TX_WIFI_INFO_SIZE, PCI_DMA_TODEVICE);
  38. /* Calculate page size.
  39. * Total buffer length including TX_WIFI_INFO and PacketLen
  40. */
  41. page_size_length =
  42. (size + TX_WIFI_INFO_SIZE) / HALMAC_TX_PAGE_SIZE_8821C;
  43. if (((size + TX_WIFI_INFO_SIZE) % HALMAC_TX_PAGE_SIZE_8821C) > 0)
  44. page_size_length++;
  45. txbd = pci_alloc_consistent(pdev,
  46. sizeof(struct tx_buf_desc), &txbd_dma);
  47. if (!txbd) {
  48. pci_unmap_single(pdev, mapping,
  49. size + TX_WIFI_INFO_SIZE, PCI_DMA_FROMDEVICE);
  50. return _FALSE;
  51. }
  52. /*
  53. * Reset all tx buffer desciprtor content
  54. * -- Reset first element
  55. */
  56. _rtw_memset(txbd, 0, sizeof(struct tx_buf_desc));
  57. /*
  58. * Fill buffer length of the first buffer,
  59. * For 8821ce, it is required that TX_WIFI_INFO is put in first segment,
  60. * and the size of the first segment cannot be larger than
  61. * TX_WIFI_INFO_SIZE.
  62. */
  63. SET_TX_BD_TX_BUFF_SIZE0(txbd, TX_WIFI_INFO_SIZE);
  64. SET_TX_BD_PSB(txbd, page_size_length);
  65. /* starting addr of TXDESC */
  66. SET_TX_BD_PHYSICAL_ADDR0_LOW(txbd, mapping);
  67. /*
  68. * It is assumed that in linux implementation, packet is coalesced
  69. * in only one buffer. Extension mode is not supported here
  70. */
  71. SET_TXBUFFER_DESC_LEN_WITH_OFFSET(txbd, 1, size);
  72. SET_TXBUFFER_DESC_ADD_LOW_WITH_OFFSET(txbd, 1,
  73. mapping + TX_WIFI_INFO_SIZE); /* pkt */
  74. /* Set BCN BD Reg */
  75. rtw_write32(padapter, REG_BCNQ_TXBD_DESA_8821C,
  76. txbd_dma & DMA_BIT_MASK(32));
  77. /* Need Comment */
  78. wmb();
  79. /* fill_txbd_own*/
  80. SET_TX_BD_OWN(txbd, 1);
  81. /* kick start */
  82. rtw_write8(padapter, REG_RX_RXBD_NUM + 1,
  83. rtw_read8(padapter, REG_RX_RXBD_NUM + 1) | BIT(4));
  84. udelay(100);
  85. pci_free_consistent(pdev, sizeof(*txbd), txbd, txbd_dma);
  86. pci_unmap_single(pdev, mapping,
  87. size + TX_WIFI_INFO_SIZE, PCI_DMA_FROMDEVICE);
  88. return ret;
  89. }
  90. static u8 pci_write_data_not_xmitframe(void *d, u8 *pBuf, u32 size, u8 qsel)
  91. {
  92. struct dvobj_priv *pobj = (struct dvobj_priv *)d;
  93. PADAPTER padapter = dvobj_get_primary_adapter(pobj);
  94. PHALMAC_ADAPTER halmac = dvobj_to_halmac((struct dvobj_priv *)d);
  95. PHALMAC_API api = HALMAC_GET_API(halmac);
  96. u8 desclen = 0;
  97. u8 *buf = NULL;
  98. u8 ret = _FALSE;
  99. if ((size + TXDESC_OFFSET) > MAX_CMDBUF_SZ) {
  100. RTW_INFO("%s: total buffer size(%d) > MAX_CMDBUF_SZ(%d)\n"
  101. , __func__, size + TXDESC_OFFSET, MAX_CMDBUF_SZ);
  102. return _FALSE;
  103. }
  104. desclen = HALMAC_TX_DESC_SIZE_8821C;
  105. buf = rtw_zmalloc(desclen + size);
  106. if (!buf) {
  107. RTW_INFO("%s: rtw_zmalloc for rsvd Fail\n", __func__);
  108. return _FALSE;
  109. }
  110. _rtw_memcpy(buf + desclen, pBuf, size);
  111. SET_TX_DESC_TXPKTSIZE_8821C(buf, size);
  112. SET_TX_DESC_OFFSET_8821C(buf, desclen);
  113. SET_TX_DESC_QSEL_8821C(buf, qsel);
  114. api->halmac_fill_txdesc_checksum(halmac, buf);
  115. ret = pci_write_port_not_xmitframe(d, size, buf);
  116. if (ret == _SUCCESS)
  117. ret = _TRUE;
  118. else
  119. ret = _FALSE;
  120. rtw_mfree(buf, desclen + size);
  121. return _TRUE;
  122. }
  123. static u8 pci_write_data_rsvd_page_xmitframe(void *d, u8 *pBuf, u32 size)
  124. {
  125. struct dvobj_priv *pobj = (struct dvobj_priv *)d;
  126. PADAPTER padapter = dvobj_get_primary_adapter(pobj);
  127. PHALMAC_ADAPTER halmac = dvobj_to_halmac((struct dvobj_priv *)d);
  128. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  129. struct xmit_frame *pcmdframe = NULL;
  130. struct pkt_attrib *pattrib = NULL;
  131. PHALMAC_API api = HALMAC_GET_API(halmac);
  132. u8 desclen = 0;
  133. u8 *txdesc = NULL;
  134. if (size + TXDESC_OFFSET > MAX_CMDBUF_SZ) {
  135. RTW_INFO("%s: total buffer size(%d) > MAX_CMDBUF_SZ(%d)\n"
  136. , __func__, size + TXDESC_OFFSET, MAX_CMDBUF_SZ);
  137. return _FALSE;
  138. }
  139. pcmdframe = rtw_alloc_cmdxmitframe(pxmitpriv);
  140. if (pcmdframe == NULL) {
  141. RTW_INFO("%s: alloc ReservedPagePacket fail!\n", __func__);
  142. return _FALSE;
  143. }
  144. desclen = HALMAC_TX_DESC_SIZE_8821C;
  145. txdesc = pcmdframe->buf_addr;
  146. _rtw_memcpy((txdesc + desclen), pBuf, size); /* shift desclen */
  147. /* update attribute */
  148. pattrib = &pcmdframe->attrib;
  149. update_mgntframe_attrib(padapter, pattrib);
  150. pattrib->qsel = QSLT_BEACON;
  151. pattrib->pktlen = size;
  152. pattrib->last_txcmdsz = size;
  153. dump_mgntframe(padapter, pcmdframe);
  154. return _TRUE;
  155. }
  156. static u8 pci_write_data_h2c_normal(void *d, u8 *pBuf, u32 size)
  157. {
  158. struct dvobj_priv *pobj = (struct dvobj_priv *)d;
  159. PADAPTER padapter = dvobj_get_primary_adapter(pobj);
  160. PHALMAC_ADAPTER halmac = dvobj_to_halmac((struct dvobj_priv *)d);
  161. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  162. struct xmit_frame *pcmdframe = NULL;
  163. struct pkt_attrib *pattrib = NULL;
  164. PHALMAC_API api;
  165. u32 desclen;
  166. u8 *buf;
  167. if (size + TXDESC_OFFSET > MAX_XMIT_EXTBUF_SZ) {
  168. RTW_INFO("%s: total buffer size(%d) > MAX_XMIT_EXTBUF_SZ(%d)\n"
  169. , __func__, size + TXDESC_OFFSET, MAX_XMIT_EXTBUF_SZ);
  170. return _FALSE;
  171. }
  172. pcmdframe = alloc_mgtxmitframe(pxmitpriv);
  173. if (pcmdframe == NULL) {
  174. RTW_INFO("%s: alloc ReservedPagePacket fail!\n", __func__);
  175. return _FALSE;
  176. }
  177. api = HALMAC_GET_API(halmac);
  178. desclen = HALMAC_TX_DESC_SIZE_8821C;
  179. buf = pcmdframe->buf_addr;
  180. _rtw_memcpy(buf + desclen, pBuf, size); /* shift desclen */
  181. SET_TX_DESC_TXPKTSIZE_8821C(buf, size);
  182. SET_TX_DESC_OFFSET_8821C(buf, 0);
  183. SET_TX_DESC_QSEL_8821C(buf, HALMAC_QUEUE_SELECT_CMD);
  184. SET_TX_DESC_TXDESC_CHECKSUM_8821C(buf, 0);
  185. api->halmac_fill_txdesc_checksum(halmac, buf);
  186. /* update attribute */
  187. pattrib = &pcmdframe->attrib;
  188. update_mgntframe_attrib(padapter, pattrib);
  189. pattrib->qsel = QSLT_CMD;
  190. pattrib->pktlen = size;
  191. pattrib->last_txcmdsz = size;
  192. /* fill tx desc in dump_mgntframe */
  193. dump_mgntframe(padapter, pcmdframe);
  194. return _TRUE;
  195. }
  196. static u8 pci_write_data_rsvd_page(void *d, u8 *pBuf, u32 size)
  197. {
  198. struct dvobj_priv *pobj = (struct dvobj_priv *)d;
  199. PADAPTER padapter = dvobj_get_primary_adapter(pobj);
  200. HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
  201. if (pHalData->not_xmitframe_fw_dl)
  202. return pci_write_data_not_xmitframe(d, pBuf, size, HALMAC_TXDESC_QSEL_BEACON);
  203. else
  204. return pci_write_data_rsvd_page_xmitframe(d, pBuf, size);
  205. }
  206. static u8 pci_write_data_h2c(void *d, u8 *pBuf, u32 size)
  207. {
  208. struct dvobj_priv *pobj = (struct dvobj_priv *)d;
  209. PADAPTER padapter = dvobj_get_primary_adapter(pobj);
  210. HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
  211. if (pHalData->not_xmitframe_fw_dl)
  212. return pci_write_data_not_xmitframe(d, pBuf, size, HALMAC_TXDESC_QSEL_H2C_CMD);
  213. else
  214. return pci_write_data_h2c_normal(d, pBuf, size);
  215. }
  216. int rtl8821ce_halmac_init_adapter(PADAPTER padapter)
  217. {
  218. struct dvobj_priv *d;
  219. PHALMAC_PLATFORM_API api;
  220. int err;
  221. d = adapter_to_dvobj(padapter);
  222. api = &rtw_halmac_platform_api;
  223. api->SEND_RSVD_PAGE = pci_write_data_rsvd_page;
  224. api->SEND_H2C_PKT = pci_write_data_h2c;
  225. err = rtw_halmac_init_adapter(d, api);
  226. return err;
  227. }