1ef454717SKhoronzhuk, Ivan /* 2ef454717SKhoronzhuk, Ivan * Multicore Navigator driver for TI Keystone 2 devices. 3ef454717SKhoronzhuk, Ivan * 4ef454717SKhoronzhuk, Ivan * (C) Copyright 2012-2014 5ef454717SKhoronzhuk, Ivan * Texas Instruments Incorporated, <www.ti.com> 6ef454717SKhoronzhuk, Ivan * 7ef454717SKhoronzhuk, Ivan * SPDX-License-Identifier: GPL-2.0+ 8ef454717SKhoronzhuk, Ivan */ 9ef454717SKhoronzhuk, Ivan #include <common.h> 10ef454717SKhoronzhuk, Ivan #include <asm/io.h> 11ef454717SKhoronzhuk, Ivan #include <asm/ti-common/keystone_nav.h> 12ef454717SKhoronzhuk, Ivan 13ef454717SKhoronzhuk, Ivan struct qm_config qm_memmap = { 14ef454717SKhoronzhuk, Ivan .stat_cfg = CONFIG_KSNAV_QM_QUEUE_STATUS_BASE, 15ef454717SKhoronzhuk, Ivan .queue = (void *)CONFIG_KSNAV_QM_MANAGER_QUEUES_BASE, 16ef454717SKhoronzhuk, Ivan .mngr_vbusm = CONFIG_KSNAV_QM_BASE_ADDRESS, 17ef454717SKhoronzhuk, Ivan .i_lram = CONFIG_KSNAV_QM_LINK_RAM_BASE, 18ef454717SKhoronzhuk, Ivan .proxy = (void *)CONFIG_KSNAV_QM_MANAGER_Q_PROXY_BASE, 19ef454717SKhoronzhuk, Ivan .status_ram = CONFIG_KSNAV_QM_STATUS_RAM_BASE, 20ef454717SKhoronzhuk, Ivan .mngr_cfg = (void *)CONFIG_KSNAV_QM_CONF_BASE, 21ef454717SKhoronzhuk, Ivan .intd_cfg = CONFIG_KSNAV_QM_INTD_CONF_BASE, 22ef454717SKhoronzhuk, Ivan .desc_mem = (void *)CONFIG_KSNAV_QM_DESC_SETUP_BASE, 23ef454717SKhoronzhuk, Ivan .region_num = CONFIG_KSNAV_QM_REGION_NUM, 24ef454717SKhoronzhuk, Ivan .pdsp_cmd = CONFIG_KSNAV_QM_PDSP1_CMD_BASE, 25ef454717SKhoronzhuk, Ivan .pdsp_ctl = CONFIG_KSNAV_QM_PDSP1_CTRL_BASE, 26ef454717SKhoronzhuk, Ivan .pdsp_iram = CONFIG_KSNAV_QM_PDSP1_IRAM_BASE, 27ef454717SKhoronzhuk, Ivan .qpool_num = CONFIG_KSNAV_QM_QPOOL_NUM, 28ef454717SKhoronzhuk, Ivan }; 29ef454717SKhoronzhuk, Ivan 30ef454717SKhoronzhuk, Ivan /* 31ef454717SKhoronzhuk, Ivan * We are going to use only one type of descriptors - host packet 32ef454717SKhoronzhuk, Ivan * descriptors. We staticaly allocate memory for them here 33ef454717SKhoronzhuk, Ivan */ 34ef454717SKhoronzhuk, Ivan struct qm_host_desc desc_pool[HDESC_NUM] __aligned(sizeof(struct qm_host_desc)); 35ef454717SKhoronzhuk, Ivan 36ef454717SKhoronzhuk, Ivan static struct qm_config *qm_cfg; 37ef454717SKhoronzhuk, Ivan 38ef454717SKhoronzhuk, Ivan inline int num_of_desc_to_reg(int num_descr) 39ef454717SKhoronzhuk, Ivan { 40ef454717SKhoronzhuk, Ivan int j, num; 41ef454717SKhoronzhuk, Ivan 42ef454717SKhoronzhuk, Ivan for (j = 0, num = 32; j < 15; j++, num *= 2) { 43ef454717SKhoronzhuk, Ivan if (num_descr <= num) 44ef454717SKhoronzhuk, Ivan return j; 45ef454717SKhoronzhuk, Ivan } 46ef454717SKhoronzhuk, Ivan 47ef454717SKhoronzhuk, Ivan return 15; 48ef454717SKhoronzhuk, Ivan } 49ef454717SKhoronzhuk, Ivan 50ef454717SKhoronzhuk, Ivan int _qm_init(struct qm_config *cfg) 51ef454717SKhoronzhuk, Ivan { 52ef454717SKhoronzhuk, Ivan u32 j; 53ef454717SKhoronzhuk, Ivan 54ef454717SKhoronzhuk, Ivan qm_cfg = cfg; 55ef454717SKhoronzhuk, Ivan 56ef454717SKhoronzhuk, Ivan qm_cfg->mngr_cfg->link_ram_base0 = qm_cfg->i_lram; 57*bc3003b9SVitaly Andrianov qm_cfg->mngr_cfg->link_ram_size0 = HDESC_NUM * 8 - 1; 58ef454717SKhoronzhuk, Ivan qm_cfg->mngr_cfg->link_ram_base1 = 0; 59ef454717SKhoronzhuk, Ivan qm_cfg->mngr_cfg->link_ram_size1 = 0; 60ef454717SKhoronzhuk, Ivan qm_cfg->mngr_cfg->link_ram_base2 = 0; 61ef454717SKhoronzhuk, Ivan 62ef454717SKhoronzhuk, Ivan qm_cfg->desc_mem[0].base_addr = (u32)desc_pool; 63ef454717SKhoronzhuk, Ivan qm_cfg->desc_mem[0].start_idx = 0; 64ef454717SKhoronzhuk, Ivan qm_cfg->desc_mem[0].desc_reg_size = 65ef454717SKhoronzhuk, Ivan (((sizeof(struct qm_host_desc) >> 4) - 1) << 16) | 66ef454717SKhoronzhuk, Ivan num_of_desc_to_reg(HDESC_NUM); 67ef454717SKhoronzhuk, Ivan 68ef454717SKhoronzhuk, Ivan memset(desc_pool, 0, sizeof(desc_pool)); 69ef454717SKhoronzhuk, Ivan for (j = 0; j < HDESC_NUM; j++) 70ef454717SKhoronzhuk, Ivan qm_push(&desc_pool[j], qm_cfg->qpool_num); 71ef454717SKhoronzhuk, Ivan 72ef454717SKhoronzhuk, Ivan return QM_OK; 73ef454717SKhoronzhuk, Ivan } 74ef454717SKhoronzhuk, Ivan 75ef454717SKhoronzhuk, Ivan int qm_init(void) 76ef454717SKhoronzhuk, Ivan { 77ef454717SKhoronzhuk, Ivan return _qm_init(&qm_memmap); 78ef454717SKhoronzhuk, Ivan } 79ef454717SKhoronzhuk, Ivan 80ef454717SKhoronzhuk, Ivan void qm_close(void) 81ef454717SKhoronzhuk, Ivan { 82ef454717SKhoronzhuk, Ivan u32 j; 83ef454717SKhoronzhuk, Ivan 84ef454717SKhoronzhuk, Ivan queue_close(qm_cfg->qpool_num); 85ef454717SKhoronzhuk, Ivan 86ef454717SKhoronzhuk, Ivan qm_cfg->mngr_cfg->link_ram_base0 = 0; 87ef454717SKhoronzhuk, Ivan qm_cfg->mngr_cfg->link_ram_size0 = 0; 88ef454717SKhoronzhuk, Ivan qm_cfg->mngr_cfg->link_ram_base1 = 0; 89ef454717SKhoronzhuk, Ivan qm_cfg->mngr_cfg->link_ram_size1 = 0; 90ef454717SKhoronzhuk, Ivan qm_cfg->mngr_cfg->link_ram_base2 = 0; 91ef454717SKhoronzhuk, Ivan 92ef454717SKhoronzhuk, Ivan for (j = 0; j < qm_cfg->region_num; j++) { 93ef454717SKhoronzhuk, Ivan qm_cfg->desc_mem[j].base_addr = 0; 94ef454717SKhoronzhuk, Ivan qm_cfg->desc_mem[j].start_idx = 0; 95ef454717SKhoronzhuk, Ivan qm_cfg->desc_mem[j].desc_reg_size = 0; 96ef454717SKhoronzhuk, Ivan } 97ef454717SKhoronzhuk, Ivan 98ef454717SKhoronzhuk, Ivan qm_cfg = NULL; 99ef454717SKhoronzhuk, Ivan } 100ef454717SKhoronzhuk, Ivan 101ef454717SKhoronzhuk, Ivan void qm_push(struct qm_host_desc *hd, u32 qnum) 102ef454717SKhoronzhuk, Ivan { 103ef454717SKhoronzhuk, Ivan u32 regd; 104ef454717SKhoronzhuk, Ivan 105ef454717SKhoronzhuk, Ivan cpu_to_bus((u32 *)hd, sizeof(struct qm_host_desc)/4); 106ef454717SKhoronzhuk, Ivan regd = (u32)hd | ((sizeof(struct qm_host_desc) >> 4) - 1); 107ef454717SKhoronzhuk, Ivan writel(regd, &qm_cfg->queue[qnum].ptr_size_thresh); 108ef454717SKhoronzhuk, Ivan } 109ef454717SKhoronzhuk, Ivan 110ef454717SKhoronzhuk, Ivan void qm_buff_push(struct qm_host_desc *hd, u32 qnum, 111ef454717SKhoronzhuk, Ivan void *buff_ptr, u32 buff_len) 112ef454717SKhoronzhuk, Ivan { 113ef454717SKhoronzhuk, Ivan hd->orig_buff_len = buff_len; 114ef454717SKhoronzhuk, Ivan hd->buff_len = buff_len; 115ef454717SKhoronzhuk, Ivan hd->orig_buff_ptr = (u32)buff_ptr; 116ef454717SKhoronzhuk, Ivan hd->buff_ptr = (u32)buff_ptr; 117ef454717SKhoronzhuk, Ivan qm_push(hd, qnum); 118ef454717SKhoronzhuk, Ivan } 119ef454717SKhoronzhuk, Ivan 120ef454717SKhoronzhuk, Ivan struct qm_host_desc *qm_pop(u32 qnum) 121ef454717SKhoronzhuk, Ivan { 122ef454717SKhoronzhuk, Ivan u32 uhd; 123ef454717SKhoronzhuk, Ivan 124ef454717SKhoronzhuk, Ivan uhd = readl(&qm_cfg->queue[qnum].ptr_size_thresh) & ~0xf; 125ef454717SKhoronzhuk, Ivan if (uhd) 126ef454717SKhoronzhuk, Ivan cpu_to_bus((u32 *)uhd, sizeof(struct qm_host_desc)/4); 127ef454717SKhoronzhuk, Ivan 128ef454717SKhoronzhuk, Ivan return (struct qm_host_desc *)uhd; 129ef454717SKhoronzhuk, Ivan } 130ef454717SKhoronzhuk, Ivan 131ef454717SKhoronzhuk, Ivan struct qm_host_desc *qm_pop_from_free_pool(void) 132ef454717SKhoronzhuk, Ivan { 133ef454717SKhoronzhuk, Ivan return qm_pop(qm_cfg->qpool_num); 134ef454717SKhoronzhuk, Ivan } 135ef454717SKhoronzhuk, Ivan 136ef454717SKhoronzhuk, Ivan void queue_close(u32 qnum) 137ef454717SKhoronzhuk, Ivan { 138ef454717SKhoronzhuk, Ivan struct qm_host_desc *hd; 139ef454717SKhoronzhuk, Ivan 140ef454717SKhoronzhuk, Ivan while ((hd = qm_pop(qnum))) 141ef454717SKhoronzhuk, Ivan ; 142ef454717SKhoronzhuk, Ivan } 143ef454717SKhoronzhuk, Ivan 144ef454717SKhoronzhuk, Ivan /** 145ef454717SKhoronzhuk, Ivan * DMA API 146ef454717SKhoronzhuk, Ivan */ 147ef454717SKhoronzhuk, Ivan 1489ea9021aSKhoronzhuk, Ivan static int ksnav_rx_disable(struct pktdma_cfg *pktdma) 149ef454717SKhoronzhuk, Ivan { 150ef454717SKhoronzhuk, Ivan u32 j, v, k; 151ef454717SKhoronzhuk, Ivan 1529ea9021aSKhoronzhuk, Ivan for (j = 0; j < pktdma->rx_ch_num; j++) { 1539ea9021aSKhoronzhuk, Ivan v = readl(&pktdma->rx_ch[j].cfg_a); 154ef454717SKhoronzhuk, Ivan if (!(v & CPDMA_CHAN_A_ENABLE)) 155ef454717SKhoronzhuk, Ivan continue; 156ef454717SKhoronzhuk, Ivan 1579ea9021aSKhoronzhuk, Ivan writel(v | CPDMA_CHAN_A_TDOWN, &pktdma->rx_ch[j].cfg_a); 158ef454717SKhoronzhuk, Ivan for (k = 0; k < TDOWN_TIMEOUT_COUNT; k++) { 159ef454717SKhoronzhuk, Ivan udelay(100); 1609ea9021aSKhoronzhuk, Ivan v = readl(&pktdma->rx_ch[j].cfg_a); 161ef454717SKhoronzhuk, Ivan if (!(v & CPDMA_CHAN_A_ENABLE)) 162ef454717SKhoronzhuk, Ivan continue; 163ef454717SKhoronzhuk, Ivan } 164ef454717SKhoronzhuk, Ivan /* TODO: teardown error on if TDOWN_TIMEOUT_COUNT is reached */ 165ef454717SKhoronzhuk, Ivan } 166ef454717SKhoronzhuk, Ivan 167ef454717SKhoronzhuk, Ivan /* Clear all of the flow registers */ 1689ea9021aSKhoronzhuk, Ivan for (j = 0; j < pktdma->rx_flow_num; j++) { 1699ea9021aSKhoronzhuk, Ivan writel(0, &pktdma->rx_flows[j].control); 1709ea9021aSKhoronzhuk, Ivan writel(0, &pktdma->rx_flows[j].tags); 1719ea9021aSKhoronzhuk, Ivan writel(0, &pktdma->rx_flows[j].tag_sel); 1729ea9021aSKhoronzhuk, Ivan writel(0, &pktdma->rx_flows[j].fdq_sel[0]); 1739ea9021aSKhoronzhuk, Ivan writel(0, &pktdma->rx_flows[j].fdq_sel[1]); 1749ea9021aSKhoronzhuk, Ivan writel(0, &pktdma->rx_flows[j].thresh[0]); 1759ea9021aSKhoronzhuk, Ivan writel(0, &pktdma->rx_flows[j].thresh[1]); 1769ea9021aSKhoronzhuk, Ivan writel(0, &pktdma->rx_flows[j].thresh[2]); 177ef454717SKhoronzhuk, Ivan } 178ef454717SKhoronzhuk, Ivan 179ef454717SKhoronzhuk, Ivan return QM_OK; 180ef454717SKhoronzhuk, Ivan } 181ef454717SKhoronzhuk, Ivan 1829ea9021aSKhoronzhuk, Ivan static int ksnav_tx_disable(struct pktdma_cfg *pktdma) 183ef454717SKhoronzhuk, Ivan { 184ef454717SKhoronzhuk, Ivan u32 j, v, k; 185ef454717SKhoronzhuk, Ivan 1869ea9021aSKhoronzhuk, Ivan for (j = 0; j < pktdma->tx_ch_num; j++) { 1879ea9021aSKhoronzhuk, Ivan v = readl(&pktdma->tx_ch[j].cfg_a); 188ef454717SKhoronzhuk, Ivan if (!(v & CPDMA_CHAN_A_ENABLE)) 189ef454717SKhoronzhuk, Ivan continue; 190ef454717SKhoronzhuk, Ivan 1919ea9021aSKhoronzhuk, Ivan writel(v | CPDMA_CHAN_A_TDOWN, &pktdma->tx_ch[j].cfg_a); 192ef454717SKhoronzhuk, Ivan for (k = 0; k < TDOWN_TIMEOUT_COUNT; k++) { 193ef454717SKhoronzhuk, Ivan udelay(100); 1949ea9021aSKhoronzhuk, Ivan v = readl(&pktdma->tx_ch[j].cfg_a); 195ef454717SKhoronzhuk, Ivan if (!(v & CPDMA_CHAN_A_ENABLE)) 196ef454717SKhoronzhuk, Ivan continue; 197ef454717SKhoronzhuk, Ivan } 198ef454717SKhoronzhuk, Ivan /* TODO: teardown error on if TDOWN_TIMEOUT_COUNT is reached */ 199ef454717SKhoronzhuk, Ivan } 200ef454717SKhoronzhuk, Ivan 201ef454717SKhoronzhuk, Ivan return QM_OK; 202ef454717SKhoronzhuk, Ivan } 203ef454717SKhoronzhuk, Ivan 2049ea9021aSKhoronzhuk, Ivan int ksnav_init(struct pktdma_cfg *pktdma, struct rx_buff_desc *rx_buffers) 205ef454717SKhoronzhuk, Ivan { 206ef454717SKhoronzhuk, Ivan u32 j, v; 207ef454717SKhoronzhuk, Ivan struct qm_host_desc *hd; 208ef454717SKhoronzhuk, Ivan u8 *rx_ptr; 209ef454717SKhoronzhuk, Ivan 2109ea9021aSKhoronzhuk, Ivan if (pktdma == NULL || rx_buffers == NULL || 211ef454717SKhoronzhuk, Ivan rx_buffers->buff_ptr == NULL || qm_cfg == NULL) 212ef454717SKhoronzhuk, Ivan return QM_ERR; 213ef454717SKhoronzhuk, Ivan 2149ea9021aSKhoronzhuk, Ivan pktdma->rx_flow = rx_buffers->rx_flow; 215ef454717SKhoronzhuk, Ivan 216ef454717SKhoronzhuk, Ivan /* init rx queue */ 217ef454717SKhoronzhuk, Ivan rx_ptr = rx_buffers->buff_ptr; 218ef454717SKhoronzhuk, Ivan 219ef454717SKhoronzhuk, Ivan for (j = 0; j < rx_buffers->num_buffs; j++) { 220ef454717SKhoronzhuk, Ivan hd = qm_pop(qm_cfg->qpool_num); 221ef454717SKhoronzhuk, Ivan if (hd == NULL) 222ef454717SKhoronzhuk, Ivan return QM_ERR; 223ef454717SKhoronzhuk, Ivan 2249ea9021aSKhoronzhuk, Ivan qm_buff_push(hd, pktdma->rx_free_q, 225ef454717SKhoronzhuk, Ivan rx_ptr, rx_buffers->buff_len); 226ef454717SKhoronzhuk, Ivan 227ef454717SKhoronzhuk, Ivan rx_ptr += rx_buffers->buff_len; 228ef454717SKhoronzhuk, Ivan } 229ef454717SKhoronzhuk, Ivan 2309ea9021aSKhoronzhuk, Ivan ksnav_rx_disable(pktdma); 231ef454717SKhoronzhuk, Ivan 232ef454717SKhoronzhuk, Ivan /* configure rx channels */ 2339ea9021aSKhoronzhuk, Ivan v = CPDMA_REG_VAL_MAKE_RX_FLOW_A(1, 1, 0, 0, 0, 0, 0, pktdma->rx_rcv_q); 2349ea9021aSKhoronzhuk, Ivan writel(v, &pktdma->rx_flows[pktdma->rx_flow].control); 2359ea9021aSKhoronzhuk, Ivan writel(0, &pktdma->rx_flows[pktdma->rx_flow].tags); 2369ea9021aSKhoronzhuk, Ivan writel(0, &pktdma->rx_flows[pktdma->rx_flow].tag_sel); 237ef454717SKhoronzhuk, Ivan 2389ea9021aSKhoronzhuk, Ivan v = CPDMA_REG_VAL_MAKE_RX_FLOW_D(0, pktdma->rx_free_q, 0, 2399ea9021aSKhoronzhuk, Ivan pktdma->rx_free_q); 240ef454717SKhoronzhuk, Ivan 2419ea9021aSKhoronzhuk, Ivan writel(v, &pktdma->rx_flows[pktdma->rx_flow].fdq_sel[0]); 2429ea9021aSKhoronzhuk, Ivan writel(v, &pktdma->rx_flows[pktdma->rx_flow].fdq_sel[1]); 2439ea9021aSKhoronzhuk, Ivan writel(0, &pktdma->rx_flows[pktdma->rx_flow].thresh[0]); 2449ea9021aSKhoronzhuk, Ivan writel(0, &pktdma->rx_flows[pktdma->rx_flow].thresh[1]); 2459ea9021aSKhoronzhuk, Ivan writel(0, &pktdma->rx_flows[pktdma->rx_flow].thresh[2]); 246ef454717SKhoronzhuk, Ivan 2479ea9021aSKhoronzhuk, Ivan for (j = 0; j < pktdma->rx_ch_num; j++) 2489ea9021aSKhoronzhuk, Ivan writel(CPDMA_CHAN_A_ENABLE, &pktdma->rx_ch[j].cfg_a); 249ef454717SKhoronzhuk, Ivan 250ef454717SKhoronzhuk, Ivan /* configure tx channels */ 251ef454717SKhoronzhuk, Ivan /* Disable loopback in the tx direction */ 2529ea9021aSKhoronzhuk, Ivan writel(0, &pktdma->global->emulation_control); 253ef454717SKhoronzhuk, Ivan 254ef454717SKhoronzhuk, Ivan /* Set QM base address, only for K2x devices */ 2559ea9021aSKhoronzhuk, Ivan writel(CONFIG_KSNAV_QM_BASE_ADDRESS, &pktdma->global->qm_base_addr[0]); 256ef454717SKhoronzhuk, Ivan 257ef454717SKhoronzhuk, Ivan /* Enable all channels. The current state isn't important */ 2589ea9021aSKhoronzhuk, Ivan for (j = 0; j < pktdma->tx_ch_num; j++) { 2599ea9021aSKhoronzhuk, Ivan writel(0, &pktdma->tx_ch[j].cfg_b); 2609ea9021aSKhoronzhuk, Ivan writel(CPDMA_CHAN_A_ENABLE, &pktdma->tx_ch[j].cfg_a); 261ef454717SKhoronzhuk, Ivan } 262ef454717SKhoronzhuk, Ivan 263ef454717SKhoronzhuk, Ivan return QM_OK; 264ef454717SKhoronzhuk, Ivan } 265ef454717SKhoronzhuk, Ivan 2669ea9021aSKhoronzhuk, Ivan int ksnav_close(struct pktdma_cfg *pktdma) 267ef454717SKhoronzhuk, Ivan { 2689ea9021aSKhoronzhuk, Ivan if (!pktdma) 269ef454717SKhoronzhuk, Ivan return QM_ERR; 270ef454717SKhoronzhuk, Ivan 2719ea9021aSKhoronzhuk, Ivan ksnav_tx_disable(pktdma); 2729ea9021aSKhoronzhuk, Ivan ksnav_rx_disable(pktdma); 273ef454717SKhoronzhuk, Ivan 2749ea9021aSKhoronzhuk, Ivan queue_close(pktdma->rx_free_q); 2759ea9021aSKhoronzhuk, Ivan queue_close(pktdma->rx_rcv_q); 2769ea9021aSKhoronzhuk, Ivan queue_close(pktdma->tx_snd_q); 277ef454717SKhoronzhuk, Ivan 278ef454717SKhoronzhuk, Ivan return QM_OK; 279ef454717SKhoronzhuk, Ivan } 280ef454717SKhoronzhuk, Ivan 2819ea9021aSKhoronzhuk, Ivan int ksnav_send(struct pktdma_cfg *pktdma, u32 *pkt, int num_bytes, u32 swinfo2) 282ef454717SKhoronzhuk, Ivan { 283ef454717SKhoronzhuk, Ivan struct qm_host_desc *hd; 284ef454717SKhoronzhuk, Ivan 285ef454717SKhoronzhuk, Ivan hd = qm_pop(qm_cfg->qpool_num); 286ef454717SKhoronzhuk, Ivan if (hd == NULL) 287ef454717SKhoronzhuk, Ivan return QM_ERR; 288ef454717SKhoronzhuk, Ivan 289ef454717SKhoronzhuk, Ivan hd->desc_info = num_bytes; 290ef454717SKhoronzhuk, Ivan hd->swinfo[2] = swinfo2; 291ef454717SKhoronzhuk, Ivan hd->packet_info = qm_cfg->qpool_num; 292ef454717SKhoronzhuk, Ivan 2939ea9021aSKhoronzhuk, Ivan qm_buff_push(hd, pktdma->tx_snd_q, pkt, num_bytes); 294ef454717SKhoronzhuk, Ivan 295ef454717SKhoronzhuk, Ivan return QM_OK; 296ef454717SKhoronzhuk, Ivan } 297ef454717SKhoronzhuk, Ivan 2989ea9021aSKhoronzhuk, Ivan void *ksnav_recv(struct pktdma_cfg *pktdma, u32 **pkt, int *num_bytes) 299ef454717SKhoronzhuk, Ivan { 300ef454717SKhoronzhuk, Ivan struct qm_host_desc *hd; 301ef454717SKhoronzhuk, Ivan 3029ea9021aSKhoronzhuk, Ivan hd = qm_pop(pktdma->rx_rcv_q); 303ef454717SKhoronzhuk, Ivan if (!hd) 304ef454717SKhoronzhuk, Ivan return NULL; 305ef454717SKhoronzhuk, Ivan 306ef454717SKhoronzhuk, Ivan *pkt = (u32 *)hd->buff_ptr; 307ef454717SKhoronzhuk, Ivan *num_bytes = hd->desc_info & 0x3fffff; 308ef454717SKhoronzhuk, Ivan 309ef454717SKhoronzhuk, Ivan return hd; 310ef454717SKhoronzhuk, Ivan } 311ef454717SKhoronzhuk, Ivan 3129ea9021aSKhoronzhuk, Ivan void ksnav_release_rxhd(struct pktdma_cfg *pktdma, void *hd) 313ef454717SKhoronzhuk, Ivan { 314ef454717SKhoronzhuk, Ivan struct qm_host_desc *_hd = (struct qm_host_desc *)hd; 315ef454717SKhoronzhuk, Ivan 316ef454717SKhoronzhuk, Ivan _hd->buff_len = _hd->orig_buff_len; 317ef454717SKhoronzhuk, Ivan _hd->buff_ptr = _hd->orig_buff_ptr; 318ef454717SKhoronzhuk, Ivan 3199ea9021aSKhoronzhuk, Ivan qm_push(_hd, pktdma->rx_free_q); 320ef454717SKhoronzhuk, Ivan } 321