File Index
Files and directories
Sign in
FILE

t7xx_hif_dpmaif_rx.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c C
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2021, MediaTek Inc.
   4 * Copyright (c) 2021-2022, Intel Corporation.
   5 *
   6 * Authors:
   7 *  Amir Hanania <amir.hanania@intel.com>
   8 *  Haijun Liu <haijun.liu@mediatek.com>
   9 *  Eliot Lee <eliot.lee@intel.com>
  10 *  Moises Veleta <moises.veleta@intel.com>
  11 *  Ricardo Martinez <ricardo.martinez@linux.intel.com>
  12 *
  13 * Contributors:
  14 *  Andy Shevchenko <andriy.shevchenko@linux.intel.com>
  15 *  Chiranjeevi Rapolu <chiranjeevi.rapolu@intel.com>
  16 *  Sreehari Kancharla <sreehari.kancharla@intel.com>
  17 */
  18
  19#include <linux/atomic.h>
  20#include <linux/bitfield.h>
  21#include <linux/bitops.h>
  22#include <linux/device.h>
  23#include <linux/dma-direction.h>
  24#include <linux/dma-mapping.h>
  25#include <linux/gfp.h>
  26#include <linux/err.h>
  27#include <linux/iopoll.h>
  28#include <linux/jiffies.h>
  29#include <linux/kernel.h>
  30#include <linux/kthread.h>
  31#include <linux/list.h>
  32#include <linux/minmax.h>
  33#include <linux/mm.h>
  34#include <linux/netdevice.h>
  35#include <linux/pm_runtime.h>
  36#include <linux/sched.h>
  37#include <linux/skbuff.h>
  38#include <linux/slab.h>
  39#include <linux/spinlock.h>
  40#include <linux/string.h>
  41#include <linux/types.h>
  42#include <linux/wait.h>
  43#include <linux/workqueue.h>
  44#include <net/gro.h>
  45
  46#include "t7xx_dpmaif.h"
  47#include "t7xx_hif_dpmaif.h"
  48#include "t7xx_hif_dpmaif_rx.h"
  49#include "t7xx_netdev.h"
  50#include "t7xx_pci.h"
  51
  52#define DPMAIF_BAT_COUNT		8192
  53#define DPMAIF_FRG_COUNT		4814
  54#define DPMAIF_PIT_COUNT		(DPMAIF_BAT_COUNT * 2)
  55
  56#define DPMAIF_BAT_CNT_THRESHOLD	30
  57#define DPMAIF_PIT_CNT_THRESHOLD	60
  58#define DPMAIF_RX_PUSH_THRESHOLD_MASK	GENMASK(2, 0)
  59#define DPMAIF_NOTIFY_RELEASE_COUNT	128
  60#define DPMAIF_POLL_PIT_TIME_US		20
  61#define DPMAIF_POLL_PIT_MAX_TIME_US	2000
  62#define DPMAIF_WQ_TIME_LIMIT_MS		2
  63#define DPMAIF_CS_RESULT_PASS		0
  64
  65/* Packet type */
  66#define DES_PT_PD			0
  67#define DES_PT_MSG			1
  68/* Buffer type */
  69#define PKT_BUF_FRAG			1
  70
  71static unsigned int t7xx_normal_pit_bid(const struct dpmaif_pit *pit_info)
  72{
  73	u32 value;
  74
  75	value = FIELD_GET(PD_PIT_H_BID, le32_to_cpu(pit_info->pd.footer));
  76	value <<= 13;
  77	value += FIELD_GET(PD_PIT_BUFFER_ID, le32_to_cpu(pit_info->header));
  78	return value;
  79}
  80
  81static int t7xx_dpmaif_update_bat_wr_idx(struct dpmaif_ctrl *dpmaif_ctrl,
  82					 const unsigned int q_num, const unsigned int bat_cnt)
  83{
  84	struct dpmaif_rx_queue *rxq = &dpmaif_ctrl->rxq[q_num];
  85	struct dpmaif_bat_request *bat_req = rxq->bat_req;
  86	unsigned int old_rl_idx, new_wr_idx, old_wr_idx;
  87
  88	if (!rxq->que_started) {
  89		dev_err(dpmaif_ctrl->dev, "RX queue %d has not been started\n", rxq->index);
  90		return -EINVAL;
  91	}
  92
  93	old_rl_idx = bat_req->bat_release_rd_idx;
  94	old_wr_idx = bat_req->bat_wr_idx;
  95	new_wr_idx = old_wr_idx + bat_cnt;
  96
  97	if (old_rl_idx > old_wr_idx && new_wr_idx >= old_rl_idx)
  98		goto err_flow;
  99
 100	if (new_wr_idx >= bat_req->bat_size_cnt) {
 101		new_wr_idx -= bat_req->bat_size_cnt;
 102		if (new_wr_idx >= old_rl_idx)
 103			goto err_flow;
 104	}
 105
 106	bat_req->bat_wr_idx = new_wr_idx;
 107	return 0;
 108
 109err_flow:
 110	dev_err(dpmaif_ctrl->dev, "RX BAT flow check fail\n");
 111	return -EINVAL;
 112}
 113
 114static bool t7xx_alloc_and_map_skb_info(const struct dpmaif_ctrl *dpmaif_ctrl,
 115					const unsigned int size, struct dpmaif_bat_skb *cur_skb)
 116{
 117	dma_addr_t data_bus_addr;
 118	struct sk_buff *skb;
 119
 120	skb = __dev_alloc_skb(size, GFP_KERNEL);
 121	if (!skb)
 122		return false;
 123
 124	data_bus_addr = dma_map_single(dpmaif_ctrl->dev, skb->data, size, DMA_FROM_DEVICE);
 125	if (dma_mapping_error(dpmaif_ctrl->dev, data_bus_addr)) {
 126		dev_err_ratelimited(dpmaif_ctrl->dev, "DMA mapping error\n");
 127		dev_kfree_skb_any(skb);
 128		return false;
 129	}
 130
 131	cur_skb->skb = skb;
 132	cur_skb->data_bus_addr = data_bus_addr;
 133	cur_skb->data_len = size;
 134
 135	return true;
 136}
 137
 138static void t7xx_unmap_bat_skb(struct device *dev, struct dpmaif_bat_skb *bat_skb_base,
 139			       unsigned int index)
 140{
 141	struct dpmaif_bat_skb *bat_skb = bat_skb_base + index;
 142
 143	if (bat_skb->skb) {
 144		dma_unmap_single(dev, bat_skb->data_bus_addr, bat_skb->data_len, DMA_FROM_DEVICE);
 145		dev_kfree_skb(bat_skb->skb);
 146		bat_skb->skb = NULL;
 147	}
 148}
 149
 150/**
 151 * t7xx_dpmaif_rx_buf_alloc() - Allocate buffers for the BAT ring.
 152 * @dpmaif_ctrl: Pointer to DPMAIF context structure.
 153 * @bat_req: Pointer to BAT request structure.
 154 * @q_num: Queue number.
 155 * @buf_cnt: Number of buffers to allocate.
 156 * @initial: Indicates if the ring is being populated for the first time.
 157 *
 158 * Allocate skb and store the start address of the data buffer into the BAT ring.
 159 * If this is not the initial call, notify the HW about the new entries.
 160 *
 161 * Return:
 162 * * 0		- Success.
 163 * * -ERROR	- Error code.
 164 */
 165int t7xx_dpmaif_rx_buf_alloc(struct dpmaif_ctrl *dpmaif_ctrl,
 166			     const struct dpmaif_bat_request *bat_req,
 167			     const unsigned int q_num, const unsigned int buf_cnt,
 168			     const bool initial)
 169{
 170	unsigned int i, bat_cnt, bat_max_cnt, bat_start_idx;
 171	int ret;
 172
 173	if (!buf_cnt || buf_cnt > bat_req->bat_size_cnt)
 174		return -EINVAL;
 175
 176	/* Check BAT buffer space */
 177	bat_max_cnt = bat_req->bat_size_cnt;
 178
 179	bat_cnt = t7xx_ring_buf_rd_wr_count(bat_max_cnt, bat_req->bat_release_rd_idx,
 180					    bat_req->bat_wr_idx, DPMAIF_WRITE);
 181	if (buf_cnt > bat_cnt)
 182		return -ENOMEM;
 183
 184	bat_start_idx = bat_req->bat_wr_idx;
 185
 186	for (i = 0; i < buf_cnt; i++) {
 187		unsigned int cur_bat_idx = bat_start_idx + i;
 188		struct dpmaif_bat_skb *cur_skb;
 189		struct dpmaif_bat *cur_bat;
 190
 191		if (cur_bat_idx >= bat_max_cnt)
 192			cur_bat_idx -= bat_max_cnt;
 193
 194		cur_skb = (struct dpmaif_bat_skb *)bat_req->bat_skb + cur_bat_idx;
 195		if (!cur_skb->skb &&
 196		    !t7xx_alloc_and_map_skb_info(dpmaif_ctrl, bat_req->pkt_buf_sz, cur_skb))
 197			break;
 198
 199		cur_bat = (struct dpmaif_bat *)bat_req->bat_base + cur_bat_idx;
 200		cur_bat->buffer_addr_ext = upper_32_bits(cur_skb->data_bus_addr);
 201		cur_bat->p_buffer_addr = lower_32_bits(cur_skb->data_bus_addr);
 202	}
 203
 204	if (!i)
 205		return -ENOMEM;
 206
 207	ret = t7xx_dpmaif_update_bat_wr_idx(dpmaif_ctrl, q_num, i);
 208	if (ret)
 209		goto err_unmap_skbs;
 210
 211	if (!initial) {
 212		unsigned int hw_wr_idx;
 213
 214		ret = t7xx_dpmaif_dl_snd_hw_bat_cnt(&dpmaif_ctrl->hw_info, i);
 215		if (ret)
 216			goto err_unmap_skbs;
 217
 218		hw_wr_idx = t7xx_dpmaif_dl_get_bat_wr_idx(&dpmaif_ctrl->hw_info,
 219							  DPF_RX_QNO_DFT);
 220		if (hw_wr_idx != bat_req->bat_wr_idx) {
 221			ret = -EFAULT;
 222			dev_err(dpmaif_ctrl->dev, "Write index mismatch in RX ring\n");
 223			goto err_unmap_skbs;
 224		}
 225	}
 226
 227	return 0;
 228
 229err_unmap_skbs:
 230	while (i--)
 231		t7xx_unmap_bat_skb(dpmaif_ctrl->dev, bat_req->bat_skb, i);
 232
 233	return ret;
 234}
 235
 236static int t7xx_dpmaifq_release_pit_entry(struct dpmaif_rx_queue *rxq,
 237					  const unsigned int rel_entry_num)
 238{
 239	struct dpmaif_hw_info *hw_info = &rxq->dpmaif_ctrl->hw_info;
 240	unsigned int old_rel_idx, new_rel_idx, hw_wr_idx;
 241	int ret;
 242
 243	if (!rxq->que_started)
 244		return 0;
 245
 246	if (rel_entry_num >= rxq->pit_size_cnt) {
 247		dev_err(rxq->dpmaif_ctrl->dev, "Invalid PIT release index\n");
 248		return -EINVAL;
 249	}
 250
 251	old_rel_idx = rxq->pit_release_rd_idx;
 252	new_rel_idx = old_rel_idx + rel_entry_num;
 253	hw_wr_idx = rxq->pit_wr_idx;
 254	if (hw_wr_idx < old_rel_idx && new_rel_idx >= rxq->pit_size_cnt)
 255		new_rel_idx -= rxq->pit_size_cnt;
 256
 257	ret = t7xx_dpmaif_dlq_add_pit_remain_cnt(hw_info, rxq->index, rel_entry_num);
 258	if (ret) {
 259		dev_err(rxq->dpmaif_ctrl->dev, "PIT release failure: %d\n", ret);
 260		return ret;
 261	}
 262
 263	rxq->pit_release_rd_idx = new_rel_idx;
 264	return 0;
 265}
 266
 267static void t7xx_dpmaif_set_bat_mask(struct dpmaif_bat_request *bat_req, unsigned int idx)
 268{
 269	unsigned long flags;
 270
 271	spin_lock_irqsave(&bat_req->mask_lock, flags);
 272	set_bit(idx, bat_req->bat_bitmap);
 273	spin_unlock_irqrestore(&bat_req->mask_lock, flags);
 274}
 275
 276static int t7xx_frag_bat_cur_bid_check(struct dpmaif_rx_queue *rxq,
 277				       const unsigned int cur_bid)
 278{
 279	struct dpmaif_bat_request *bat_frag = rxq->bat_frag;
 280	struct dpmaif_bat_page *bat_page;
 281
 282	if (cur_bid >= DPMAIF_FRG_COUNT)
 283		return -EINVAL;
 284
 285	bat_page = bat_frag->bat_skb + cur_bid;
 286	if (!bat_page->page)
 287		return -EINVAL;
 288
 289	return 0;
 290}
 291
 292static void t7xx_unmap_bat_page(struct device *dev, struct dpmaif_bat_page *bat_page_base,
 293				unsigned int index)
 294{
 295	struct dpmaif_bat_page *bat_page = bat_page_base + index;
 296
 297	if (bat_page->page) {
 298		dma_unmap_page(dev, bat_page->data_bus_addr, bat_page->data_len, DMA_FROM_DEVICE);
 299		put_page(bat_page->page);
 300		bat_page->page = NULL;
 301	}
 302}
 303
 304/**
 305 * t7xx_dpmaif_rx_frag_alloc() - Allocates buffers for the Fragment BAT ring.
 306 * @dpmaif_ctrl: Pointer to DPMAIF context structure.
 307 * @bat_req: Pointer to BAT request structure.
 308 * @buf_cnt: Number of buffers to allocate.
 309 * @initial: Indicates if the ring is being populated for the first time.
 310 *
 311 * Fragment BAT is used when the received packet does not fit in a normal BAT entry.
 312 * This function allocates a page fragment and stores the start address of the page
 313 * into the Fragment BAT ring.
 314 * If this is not the initial call, notify the HW about the new entries.
 315 *
 316 * Return:
 317 * * 0		- Success.
 318 * * -ERROR	- Error code.
 319 */
 320int t7xx_dpmaif_rx_frag_alloc(struct dpmaif_ctrl *dpmaif_ctrl, struct dpmaif_bat_request *bat_req,
 321			      const unsigned int buf_cnt, const bool initial)
 322{
 323	unsigned int buf_space, cur_bat_idx = bat_req->bat_wr_idx;
 324	struct dpmaif_bat_page *bat_skb = bat_req->bat_skb;
 325	int ret = 0, i;
 326
 327	if (!buf_cnt || buf_cnt > bat_req->bat_size_cnt)
 328		return -EINVAL;
 329
 330	buf_space = t7xx_ring_buf_rd_wr_count(bat_req->bat_size_cnt,
 331					      bat_req->bat_release_rd_idx, bat_req->bat_wr_idx,
 332					      DPMAIF_WRITE);
 333	if (buf_cnt > buf_space) {
 334		dev_err(dpmaif_ctrl->dev,
 335			"Requested more buffers than the space available in RX frag ring\n");
 336		return -EINVAL;
 337	}
 338
 339	for (i = 0; i < buf_cnt; i++) {
 340		struct dpmaif_bat_page *cur_page = bat_skb + cur_bat_idx;
 341		struct dpmaif_bat *cur_bat;
 342		dma_addr_t data_base_addr;
 343
 344		if (!cur_page->page) {
 345			unsigned long offset;
 346			struct page *page;
 347			void *data;
 348
 349			data = netdev_alloc_frag(bat_req->pkt_buf_sz);
 350			if (!data)
 351				break;
 352
 353			page = virt_to_head_page(data);
 354			offset = data - page_address(page);
 355
 356			data_base_addr = dma_map_page(dpmaif_ctrl->dev, page, offset,
 357						      bat_req->pkt_buf_sz, DMA_FROM_DEVICE);
 358			if (dma_mapping_error(dpmaif_ctrl->dev, data_base_addr)) {
 359				put_page(virt_to_head_page(data));
 360				dev_err(dpmaif_ctrl->dev, "DMA mapping fail\n");
 361				break;
 362			}
 363
 364			cur_page->page = page;
 365			cur_page->data_bus_addr = data_base_addr;
 366			cur_page->offset = offset;
 367			cur_page->data_len = bat_req->pkt_buf_sz;
 368		}
 369
 370		data_base_addr = cur_page->data_bus_addr;
 371		cur_bat = (struct dpmaif_bat *)bat_req->bat_base + cur_bat_idx;
 372		cur_bat->buffer_addr_ext = upper_32_bits(data_base_addr);
 373		cur_bat->p_buffer_addr = lower_32_bits(data_base_addr);
 374		cur_bat_idx = t7xx_ring_buf_get_next_wr_idx(bat_req->bat_size_cnt, cur_bat_idx);
 375	}
 376
 377	bat_req->bat_wr_idx = cur_bat_idx;
 378
 379	if (!initial)
 380		t7xx_dpmaif_dl_snd_hw_frg_cnt(&dpmaif_ctrl->hw_info, i);
 381
 382	if (i < buf_cnt) {
 383		ret = -ENOMEM;
 384		if (initial) {
 385			while (--i > 0)
 386				t7xx_unmap_bat_page(dpmaif_ctrl->dev, bat_req->bat_skb, i);
 387		}
 388	}
 389
 390	return ret;
 391}
 392
 393static int t7xx_dpmaif_set_frag_to_skb(const struct dpmaif_rx_queue *rxq,
 394				       const struct dpmaif_pit *pkt_info,
 395				       struct sk_buff *skb)
 396{
 397	unsigned long long data_bus_addr, data_base_addr;
 398	struct skb_shared_info *shinfo = skb_shinfo(skb);
 399	struct device *dev = rxq->dpmaif_ctrl->dev;
 400	struct dpmaif_bat_page *page_info;
 401	unsigned int data_len;
 402	int data_offset;
 403
 404	page_info = rxq->bat_frag->bat_skb;
 405	page_info += t7xx_normal_pit_bid(pkt_info);
 406
 407	if (!page_info->page)
 408		return -EINVAL;
 409
 410	if (shinfo->nr_frags >= MAX_SKB_FRAGS)
 411		return -EINVAL;
 412
 413	dma_unmap_page(dev, page_info->data_bus_addr, page_info->data_len, DMA_FROM_DEVICE);
 414
 415	data_bus_addr = le32_to_cpu(pkt_info->pd.data_addr_h);
 416	data_bus_addr = (data_bus_addr << 32) + le32_to_cpu(pkt_info->pd.data_addr_l);
 417	data_base_addr = page_info->data_bus_addr;
 418	data_offset = data_bus_addr - data_base_addr;
 419	data_offset += page_info->offset;
 420	data_len = FIELD_GET(PD_PIT_DATA_LEN, le32_to_cpu(pkt_info->header));
 421	skb_add_rx_frag(skb, shinfo->nr_frags, page_info->page,
 422			data_offset, data_len, page_info->data_len);
 423
 424	page_info->page = NULL;
 425	page_info->offset = 0;
 426	page_info->data_len = 0;
 427	return 0;
 428}
 429
 430static int t7xx_dpmaif_get_frag(struct dpmaif_rx_queue *rxq,
 431				const struct dpmaif_pit *pkt_info,
 432				const struct dpmaif_cur_rx_skb_info *skb_info)
 433{
 434	unsigned int cur_bid = t7xx_normal_pit_bid(pkt_info);
 435	int ret;
 436
 437	ret = t7xx_frag_bat_cur_bid_check(rxq, cur_bid);
 438	if (ret < 0)
 439		return ret;
 440
 441	ret = t7xx_dpmaif_set_frag_to_skb(rxq, pkt_info, skb_info->cur_skb);
 442	if (ret < 0) {
 443		dev_err(rxq->dpmaif_ctrl->dev, "Failed to set frag data to skb: %d\n", ret);
 444		return ret;
 445	}
 446
 447	t7xx_dpmaif_set_bat_mask(rxq->bat_frag, cur_bid);
 448	return 0;
 449}
 450
 451static int t7xx_bat_cur_bid_check(struct dpmaif_rx_queue *rxq, const unsigned int cur_bid)
 452{
 453	struct dpmaif_bat_skb *bat_skb = rxq->bat_req->bat_skb;
 454
 455	bat_skb += cur_bid;
 456	if (cur_bid >= DPMAIF_BAT_COUNT || !bat_skb->skb)
 457		return -EINVAL;
 458
 459	return 0;
 460}
 461
 462static int t7xx_dpmaif_read_pit_seq(const struct dpmaif_pit *pit)
 463{
 464	return FIELD_GET(PD_PIT_PIT_SEQ, le32_to_cpu(pit->pd.footer));
 465}
 466
 467static int t7xx_dpmaif_check_pit_seq(struct dpmaif_rx_queue *rxq,
 468				     const struct dpmaif_pit *pit)
 469{
 470	unsigned int cur_pit_seq, expect_pit_seq = rxq->expect_pit_seq;
 471
 472	if (read_poll_timeout_atomic(t7xx_dpmaif_read_pit_seq, cur_pit_seq,
 473				     cur_pit_seq == expect_pit_seq, DPMAIF_POLL_PIT_TIME_US,
 474				     DPMAIF_POLL_PIT_MAX_TIME_US, false, pit))
 475		return -EFAULT;
 476
 477	rxq->expect_pit_seq++;
 478	if (rxq->expect_pit_seq >= DPMAIF_DL_PIT_SEQ_VALUE)
 479		rxq->expect_pit_seq = 0;
 480
 481	return 0;
 482}
 483
 484static unsigned int t7xx_dpmaif_avail_pkt_bat_cnt(struct dpmaif_bat_request *bat_req)
 485{
 486	unsigned int zero_index;
 487	unsigned long flags;
 488
 489	spin_lock_irqsave(&bat_req->mask_lock, flags);
 490
 491	zero_index = find_next_zero_bit(bat_req->bat_bitmap, bat_req->bat_size_cnt,
 492					bat_req->bat_release_rd_idx);
 493
 494	if (zero_index < bat_req->bat_size_cnt) {
 495		spin_unlock_irqrestore(&bat_req->mask_lock, flags);
 496		return zero_index - bat_req->bat_release_rd_idx;
 497	}
 498
 499	/* limiting the search till bat_release_rd_idx */
 500	zero_index = find_first_zero_bit(bat_req->bat_bitmap, bat_req->bat_release_rd_idx);
 501	spin_unlock_irqrestore(&bat_req->mask_lock, flags);
 502	return bat_req->bat_size_cnt - bat_req->bat_release_rd_idx + zero_index;
 503}
 504
 505static int t7xx_dpmaif_release_bat_entry(const struct dpmaif_rx_queue *rxq,
 506					 const unsigned int rel_entry_num,
 507					 const enum bat_type buf_type)
 508{
 509	struct dpmaif_hw_info *hw_info = &rxq->dpmaif_ctrl->hw_info;
 510	unsigned int old_rel_idx, new_rel_idx, hw_rd_idx, i;
 511	struct dpmaif_bat_request *bat;
 512	unsigned long flags;
 513
 514	if (!rxq->que_started || !rel_entry_num)
 515		return -EINVAL;
 516
 517	if (buf_type == BAT_TYPE_FRAG) {
 518		bat = rxq->bat_frag;
 519		hw_rd_idx = t7xx_dpmaif_dl_get_frg_rd_idx(hw_info, rxq->index);
 520	} else {
 521		bat = rxq->bat_req;
 522		hw_rd_idx = t7xx_dpmaif_dl_get_bat_rd_idx(hw_info, rxq->index);
 523	}
 524
 525	if (rel_entry_num >= bat->bat_size_cnt)
 526		return -EINVAL;
 527
 528	old_rel_idx = bat->bat_release_rd_idx;
 529	new_rel_idx = old_rel_idx + rel_entry_num;
 530
 531	/* Do not need to release if the queue is empty */
 532	if (bat->bat_wr_idx == old_rel_idx)
 533		return 0;
 534
 535	if (hw_rd_idx >= old_rel_idx) {
 536		if (new_rel_idx > hw_rd_idx)
 537			return -EINVAL;
 538	}
 539
 540	if (new_rel_idx >= bat->bat_size_cnt) {
 541		new_rel_idx -= bat->bat_size_cnt;
 542		if (new_rel_idx > hw_rd_idx)
 543			return -EINVAL;
 544	}
 545
 546	spin_lock_irqsave(&bat->mask_lock, flags);
 547	for (i = 0; i < rel_entry_num; i++) {
 548		unsigned int index = bat->bat_release_rd_idx + i;
 549
 550		if (index >= bat->bat_size_cnt)
 551			index -= bat->bat_size_cnt;
 552
 553		clear_bit(index, bat->bat_bitmap);
 554	}
 555	spin_unlock_irqrestore(&bat->mask_lock, flags);
 556
 557	bat->bat_release_rd_idx = new_rel_idx;
 558	return rel_entry_num;
 559}
 560
 561static int t7xx_dpmaif_pit_release_and_add(struct dpmaif_rx_queue *rxq)
 562{
 563	int ret;
 564
 565	if (rxq->pit_remain_release_cnt < DPMAIF_PIT_CNT_THRESHOLD)
 566		return 0;
 567
 568	ret = t7xx_dpmaifq_release_pit_entry(rxq, rxq->pit_remain_release_cnt);
 569	if (ret)
 570		return ret;
 571
 572	rxq->pit_remain_release_cnt = 0;
 573	return 0;
 574}
 575
 576static int t7xx_dpmaif_bat_release_and_add(const struct dpmaif_rx_queue *rxq)
 577{
 578	unsigned int bid_cnt;
 579	int ret;
 580
 581	bid_cnt = t7xx_dpmaif_avail_pkt_bat_cnt(rxq->bat_req);
 582	if (bid_cnt < DPMAIF_BAT_CNT_THRESHOLD)
 583		return 0;
 584
 585	ret = t7xx_dpmaif_release_bat_entry(rxq, bid_cnt, BAT_TYPE_NORMAL);
 586	if (ret <= 0) {
 587		dev_err(rxq->dpmaif_ctrl->dev, "Release PKT BAT failed: %d\n", ret);
 588		return ret;
 589	}
 590
 591	ret = t7xx_dpmaif_rx_buf_alloc(rxq->dpmaif_ctrl, rxq->bat_req, rxq->index, bid_cnt, false);
 592	if (ret < 0)
 593		dev_err(rxq->dpmaif_ctrl->dev, "Allocate new RX buffer failed: %d\n", ret);
 594
 595	return ret;
 596}
 597
 598static int t7xx_dpmaif_frag_bat_release_and_add(const struct dpmaif_rx_queue *rxq)
 599{
 600	unsigned int bid_cnt;
 601	int ret;
 602
 603	bid_cnt = t7xx_dpmaif_avail_pkt_bat_cnt(rxq->bat_frag);
 604	if (bid_cnt < DPMAIF_BAT_CNT_THRESHOLD)
 605		return 0;
 606
 607	ret = t7xx_dpmaif_release_bat_entry(rxq, bid_cnt, BAT_TYPE_FRAG);
 608	if (ret <= 0) {
 609		dev_err(rxq->dpmaif_ctrl->dev, "Release BAT entry failed: %d\n", ret);
 610		return ret;
 611	}
 612
 613	return t7xx_dpmaif_rx_frag_alloc(rxq->dpmaif_ctrl, rxq->bat_frag, bid_cnt, false);
 614}
 615
 616static void t7xx_dpmaif_parse_msg_pit(const struct dpmaif_rx_queue *rxq,
 617				      const struct dpmaif_pit *msg_pit,
 618				      struct dpmaif_cur_rx_skb_info *skb_info)
 619{
 620	int header = le32_to_cpu(msg_pit->header);
 621
 622	skb_info->cur_chn_idx = FIELD_GET(MSG_PIT_CHANNEL_ID, header);
 623	skb_info->check_sum = FIELD_GET(MSG_PIT_CHECKSUM, header);
 624	skb_info->pit_dp = FIELD_GET(MSG_PIT_DP, header);
 625	skb_info->pkt_type = FIELD_GET(MSG_PIT_IP, le32_to_cpu(msg_pit->msg.params_3));
 626}
 627
 628static int t7xx_dpmaif_set_data_to_skb(const struct dpmaif_rx_queue *rxq,
 629				       const struct dpmaif_pit *pkt_info,
 630				       struct dpmaif_cur_rx_skb_info *skb_info)
 631{
 632	unsigned long long data_bus_addr, data_base_addr;
 633	struct device *dev = rxq->dpmaif_ctrl->dev;
 634	struct dpmaif_bat_skb *bat_skb;
 635	unsigned int data_len;
 636	struct sk_buff *skb;
 637	int data_offset;
 638
 639	bat_skb = rxq->bat_req->bat_skb;
 640	bat_skb += t7xx_normal_pit_bid(pkt_info);
 641	dma_unmap_single(dev, bat_skb->data_bus_addr, bat_skb->data_len, DMA_FROM_DEVICE);
 642
 643	data_bus_addr = le32_to_cpu(pkt_info->pd.data_addr_h);
 644	data_bus_addr = (data_bus_addr << 32) + le32_to_cpu(pkt_info->pd.data_addr_l);
 645	data_base_addr = bat_skb->data_bus_addr;
 646	data_offset = data_bus_addr - data_base_addr;
 647	data_len = FIELD_GET(PD_PIT_DATA_LEN, le32_to_cpu(pkt_info->header));
 648	skb = bat_skb->skb;
 649	skb->len = 0;
 650	skb_reset_tail_pointer(skb);
 651	skb_reserve(skb, data_offset);
 652
 653	if (skb->tail + data_len > skb->end) {
 654		dev_err(dev, "No buffer space available\n");
 655		return -ENOBUFS;
 656	}
 657
 658	skb_put(skb, data_len);
 659	skb_info->cur_skb = skb;
 660	bat_skb->skb = NULL;
 661	return 0;
 662}
 663
 664static int t7xx_dpmaif_get_rx_pkt(struct dpmaif_rx_queue *rxq,
 665				  const struct dpmaif_pit *pkt_info,
 666				  struct dpmaif_cur_rx_skb_info *skb_info)
 667{
 668	unsigned int cur_bid = t7xx_normal_pit_bid(pkt_info);
 669	int ret;
 670
 671	ret = t7xx_bat_cur_bid_check(rxq, cur_bid);
 672	if (ret < 0)
 673		return ret;
 674
 675	ret = t7xx_dpmaif_set_data_to_skb(rxq, pkt_info, skb_info);
 676	if (ret < 0) {
 677		dev_err(rxq->dpmaif_ctrl->dev, "RX set data to skb failed: %d\n", ret);
 678		return ret;
 679	}
 680
 681	t7xx_dpmaif_set_bat_mask(rxq->bat_req, cur_bid);
 682	return 0;
 683}
 684
 685static int t7xx_dpmaifq_rx_notify_hw(struct dpmaif_rx_queue *rxq)
 686{
 687	struct dpmaif_ctrl *dpmaif_ctrl = rxq->dpmaif_ctrl;
 688	int ret;
 689
 690	queue_work(dpmaif_ctrl->bat_release_wq, &dpmaif_ctrl->bat_release_work);
 691
 692	ret = t7xx_dpmaif_pit_release_and_add(rxq);
 693	if (ret < 0)
 694		dev_err(dpmaif_ctrl->dev, "RXQ%u update PIT failed: %d\n", rxq->index, ret);
 695
 696	return ret;
 697}
 698
 699static void t7xx_dpmaif_rx_skb(struct dpmaif_rx_queue *rxq,
 700			       struct dpmaif_cur_rx_skb_info *skb_info)
 701{
 702	struct dpmaif_ctrl *dpmaif_ctrl = rxq->dpmaif_ctrl;
 703	struct sk_buff *skb = skb_info->cur_skb;
 704	struct t7xx_skb_cb *skb_cb;
 705	u8 netif_id;
 706
 707	skb_info->cur_skb = NULL;
 708
 709	if (skb_info->pit_dp) {
 710		dev_kfree_skb_any(skb);
 711		return;
 712	}
 713
 714	skb->ip_summed = skb_info->check_sum == DPMAIF_CS_RESULT_PASS ? CHECKSUM_UNNECESSARY :
 715									CHECKSUM_NONE;
 716	netif_id = FIELD_GET(NETIF_MASK, skb_info->cur_chn_idx);
 717	skb_cb = T7XX_SKB_CB(skb);
 718	skb_cb->netif_idx = netif_id;
 719	skb_cb->rx_pkt_type = skb_info->pkt_type;
 720	dpmaif_ctrl->callbacks->recv_skb(dpmaif_ctrl->t7xx_dev->ccmni_ctlb, skb, &rxq->napi);
 721}
 722
 723static int t7xx_dpmaif_rx_start(struct dpmaif_rx_queue *rxq, const unsigned int pit_cnt,
 724				const unsigned int budget, int *once_more)
 725{
 726	unsigned int cur_pit, pit_len, rx_cnt, recv_skb_cnt = 0;
 727	struct device *dev = rxq->dpmaif_ctrl->dev;
 728	struct dpmaif_cur_rx_skb_info *skb_info;
 729	int ret = 0;
 730
 731	pit_len = rxq->pit_size_cnt;
 732	skb_info = &rxq->rx_data_info;
 733	cur_pit = rxq->pit_rd_idx;
 734
 735	for (rx_cnt = 0; rx_cnt < pit_cnt; rx_cnt++) {
 736		struct dpmaif_pit *pkt_info;
 737		u32 val;
 738
 739		if (!skb_info->msg_pit_received && recv_skb_cnt >= budget)
 740			break;
 741
 742		pkt_info = (struct dpmaif_pit *)rxq->pit_base + cur_pit;
 743		if (t7xx_dpmaif_check_pit_seq(rxq, pkt_info)) {
 744			dev_err_ratelimited(dev, "RXQ%u checks PIT SEQ fail\n", rxq->index);
 745			*once_more = 1;
 746			return recv_skb_cnt;
 747		}
 748
 749		val = FIELD_GET(PD_PIT_PACKET_TYPE, le32_to_cpu(pkt_info->header));
 750		if (val == DES_PT_MSG) {
 751			if (skb_info->msg_pit_received)
 752				dev_err(dev, "RXQ%u received repeated PIT\n", rxq->index);
 753
 754			skb_info->msg_pit_received = true;
 755			t7xx_dpmaif_parse_msg_pit(rxq, pkt_info, skb_info);
 756		} else { /* DES_PT_PD */
 757			val = FIELD_GET(PD_PIT_BUFFER_TYPE, le32_to_cpu(pkt_info->header));
 758			if (val != PKT_BUF_FRAG)
 759				ret = t7xx_dpmaif_get_rx_pkt(rxq, pkt_info, skb_info);
 760			else if (!skb_info->cur_skb)
 761				ret = -EINVAL;
 762			else
 763				ret = t7xx_dpmaif_get_frag(rxq, pkt_info, skb_info);
 764
 765			if (ret < 0) {
 766				skb_info->err_payload = 1;
 767				dev_err_ratelimited(dev, "RXQ%u error payload\n", rxq->index);
 768			}
 769
 770			val = FIELD_GET(PD_PIT_CONT, le32_to_cpu(pkt_info->header));
 771			if (!val) {
 772				if (!skb_info->err_payload) {
 773					t7xx_dpmaif_rx_skb(rxq, skb_info);
 774				} else if (skb_info->cur_skb) {
 775					dev_kfree_skb_any(skb_info->cur_skb);
 776					skb_info->cur_skb = NULL;
 777				}
 778
 779				memset(skb_info, 0, sizeof(*skb_info));
 780				recv_skb_cnt++;
 781			}
 782		}
 783
 784		cur_pit = t7xx_ring_buf_get_next_wr_idx(pit_len, cur_pit);
 785		rxq->pit_rd_idx = cur_pit;
 786		rxq->pit_remain_release_cnt++;
 787
 788		if (rx_cnt > 0 && !(rx_cnt % DPMAIF_NOTIFY_RELEASE_COUNT)) {
 789			ret = t7xx_dpmaifq_rx_notify_hw(rxq);
 790			if (ret < 0)
 791				break;
 792		}
 793	}
 794
 795	if (!ret)
 796		ret = t7xx_dpmaifq_rx_notify_hw(rxq);
 797
 798	if (ret)
 799		return ret;
 800
 801	return recv_skb_cnt;
 802}
 803
 804static unsigned int t7xx_dpmaifq_poll_pit(struct dpmaif_rx_queue *rxq)
 805{
 806	unsigned int hw_wr_idx, pit_cnt;
 807
 808	if (!rxq->que_started)
 809		return 0;
 810
 811	hw_wr_idx = t7xx_dpmaif_dl_dlq_pit_get_wr_idx(&rxq->dpmaif_ctrl->hw_info, rxq->index);
 812	pit_cnt = t7xx_ring_buf_rd_wr_count(rxq->pit_size_cnt, rxq->pit_rd_idx, hw_wr_idx,
 813					    DPMAIF_READ);
 814	rxq->pit_wr_idx = hw_wr_idx;
 815	return pit_cnt;
 816}
 817
 818static int t7xx_dpmaif_napi_rx_data_collect(struct dpmaif_ctrl *dpmaif_ctrl,
 819					    const unsigned int q_num,
 820					    const unsigned int budget, int *once_more)
 821{
 822	struct dpmaif_rx_queue *rxq = &dpmaif_ctrl->rxq[q_num];
 823	unsigned int cnt;
 824	int ret = 0;
 825
 826	cnt = t7xx_dpmaifq_poll_pit(rxq);
 827	if (!cnt)
 828		return ret;
 829
 830	ret = t7xx_dpmaif_rx_start(rxq, cnt, budget, once_more);
 831	if (ret < 0)
 832		dev_err(dpmaif_ctrl->dev, "dlq%u rx ERR:%d\n", rxq->index, ret);
 833
 834	return ret;
 835}
 836
 837int t7xx_dpmaif_napi_rx_poll(struct napi_struct *napi, const int budget)
 838{
 839	struct dpmaif_rx_queue *rxq = container_of(napi, struct dpmaif_rx_queue, napi);
 840	struct t7xx_pci_dev *t7xx_dev = rxq->dpmaif_ctrl->t7xx_dev;
 841	int ret, once_more = 0, work_done = 0;
 842
 843	atomic_set(&rxq->rx_processing, 1);
 844	/* Ensure rx_processing is changed to 1 before actually begin RX flow */
 845	smp_mb();
 846
 847	if (!rxq->que_started) {
 848		atomic_set(&rxq->rx_processing, 0);
 849		pm_runtime_put_autosuspend(rxq->dpmaif_ctrl->dev);
 850		dev_err(rxq->dpmaif_ctrl->dev, "Work RXQ: %d has not been started\n", rxq->index);
 851		return work_done;
 852	}
 853
 854	if (!rxq->sleep_lock_pending)
 855		t7xx_pci_disable_sleep(t7xx_dev);
 856
 857	ret = try_wait_for_completion(&t7xx_dev->sleep_lock_acquire);
 858	if (!ret) {
 859		napi_complete_done(napi, work_done);
 860		rxq->sleep_lock_pending = true;
 861		napi_schedule(napi);
 862		return work_done;
 863	}
 864
 865	rxq->sleep_lock_pending = false;
 866	while (work_done < budget) {
 867		int each_budget = budget - work_done;
 868		int rx_cnt = t7xx_dpmaif_napi_rx_data_collect(rxq->dpmaif_ctrl, rxq->index,
 869							      each_budget, &once_more);
 870		if (rx_cnt > 0)
 871			work_done += rx_cnt;
 872		else
 873			break;
 874	}
 875
 876	if (once_more) {
 877		napi_gro_flush(napi, false);
 878		work_done = budget;
 879		t7xx_dpmaif_clr_ip_busy_sts(&rxq->dpmaif_ctrl->hw_info);
 880	} else if (work_done < budget) {
 881		napi_complete_done(napi, work_done);
 882		t7xx_dpmaif_clr_ip_busy_sts(&rxq->dpmaif_ctrl->hw_info);
 883		t7xx_dpmaif_dlq_unmask_rx_done(&rxq->dpmaif_ctrl->hw_info, rxq->index);
 884		t7xx_pci_enable_sleep(rxq->dpmaif_ctrl->t7xx_dev);
 885		pm_runtime_put_autosuspend(rxq->dpmaif_ctrl->dev);
 886		atomic_set(&rxq->rx_processing, 0);
 887	} else {
 888		t7xx_dpmaif_clr_ip_busy_sts(&rxq->dpmaif_ctrl->hw_info);
 889	}
 890
 891	return work_done;
 892}
 893
 894void t7xx_dpmaif_irq_rx_done(struct dpmaif_ctrl *dpmaif_ctrl, const unsigned int que_mask)
 895{
 896	struct dpmaif_rx_queue *rxq;
 897	struct dpmaif_ctrl *ctrl;
 898	int qno, ret;
 899
 900	qno = ffs(que_mask) - 1;
 901	if (qno < 0 || qno > DPMAIF_RXQ_NUM - 1) {
 902		dev_err(dpmaif_ctrl->dev, "Invalid RXQ number: %u\n", qno);
 903		return;
 904	}
 905
 906	rxq = &dpmaif_ctrl->rxq[qno];
 907	ctrl = rxq->dpmaif_ctrl;
 908	/* We need to make sure that the modem has been resumed before
 909	 * calling napi. This can't be done inside the polling function
 910	 * as we could be blocked waiting for device to be resumed,
 911	 * which can't be done from softirq context the poll function
 912	 * is running in.
 913	 */
 914	ret = pm_runtime_resume_and_get(ctrl->dev);
 915	if (ret < 0 && ret != -EACCES) {
 916		dev_err(ctrl->dev, "Failed to resume device: %d\n", ret);
 917		return;
 918	}
 919	napi_schedule(&rxq->napi);
 920}
 921
 922static void t7xx_dpmaif_base_free(const struct dpmaif_ctrl *dpmaif_ctrl,
 923				  const struct dpmaif_bat_request *bat_req)
 924{
 925	if (bat_req->bat_base)
 926		dma_free_coherent(dpmaif_ctrl->dev,
 927				  bat_req->bat_size_cnt * sizeof(struct dpmaif_bat),
 928				  bat_req->bat_base, bat_req->bat_bus_addr);
 929}
 930
 931/**
 932 * t7xx_dpmaif_bat_alloc() - Allocate the BAT ring buffer.
 933 * @dpmaif_ctrl: Pointer to DPMAIF context structure.
 934 * @bat_req: Pointer to BAT request structure.
 935 * @buf_type: BAT ring type.
 936 *
 937 * This function allocates the BAT ring buffer shared with the HW device, also allocates
 938 * a buffer used to store information about the BAT skbs for further release.
 939 *
 940 * Return:
 941 * * 0		- Success.
 942 * * -ERROR	- Error code.
 943 */
 944int t7xx_dpmaif_bat_alloc(const struct dpmaif_ctrl *dpmaif_ctrl, struct dpmaif_bat_request *bat_req,
 945			  const enum bat_type buf_type)
 946{
 947	int sw_buf_size;
 948
 949	if (buf_type == BAT_TYPE_FRAG) {
 950		sw_buf_size = sizeof(struct dpmaif_bat_page);
 951		bat_req->bat_size_cnt = DPMAIF_FRG_COUNT;
 952		bat_req->pkt_buf_sz = DPMAIF_HW_FRG_PKTBUF;
 953	} else {
 954		sw_buf_size = sizeof(struct dpmaif_bat_skb);
 955		bat_req->bat_size_cnt = DPMAIF_BAT_COUNT;
 956		bat_req->pkt_buf_sz = DPMAIF_HW_BAT_PKTBUF;
 957	}
 958
 959	bat_req->type = buf_type;
 960	bat_req->bat_wr_idx = 0;
 961	bat_req->bat_release_rd_idx = 0;
 962
 963	bat_req->bat_base = dma_alloc_coherent(dpmaif_ctrl->dev,
 964					       bat_req->bat_size_cnt * sizeof(struct dpmaif_bat),
 965					       &bat_req->bat_bus_addr, GFP_KERNEL | __GFP_ZERO);
 966	if (!bat_req->bat_base)
 967		return -ENOMEM;
 968
 969	/* For AP SW to record skb information */
 970	bat_req->bat_skb = devm_kzalloc(dpmaif_ctrl->dev, bat_req->bat_size_cnt * sw_buf_size,
 971					GFP_KERNEL);
 972	if (!bat_req->bat_skb)
 973		goto err_free_dma_mem;
 974
 975	bat_req->bat_bitmap = bitmap_zalloc(bat_req->bat_size_cnt, GFP_KERNEL);
 976	if (!bat_req->bat_bitmap)
 977		goto err_free_dma_mem;
 978
 979	spin_lock_init(&bat_req->mask_lock);
 980	atomic_set(&bat_req->refcnt, 0);
 981	return 0;
 982
 983err_free_dma_mem:
 984	t7xx_dpmaif_base_free(dpmaif_ctrl, bat_req);
 985
 986	return -ENOMEM;
 987}
 988
 989void t7xx_dpmaif_bat_free(const struct dpmaif_ctrl *dpmaif_ctrl, struct dpmaif_bat_request *bat_req)
 990{
 991	if (!bat_req || !atomic_dec_and_test(&bat_req->refcnt))
 992		return;
 993
 994	bitmap_free(bat_req->bat_bitmap);
 995	bat_req->bat_bitmap = NULL;
 996
 997	if (bat_req->bat_skb) {
 998		unsigned int i;
 999
1000		for (i = 0; i < bat_req->bat_size_cnt; i++) {
1001			if (bat_req->type == BAT_TYPE_FRAG)
1002				t7xx_unmap_bat_page(dpmaif_ctrl->dev, bat_req->bat_skb, i);
1003			else
1004				t7xx_unmap_bat_skb(dpmaif_ctrl->dev, bat_req->bat_skb, i);
1005		}
1006	}
1007
1008	t7xx_dpmaif_base_free(dpmaif_ctrl, bat_req);
1009}
1010
1011static int t7xx_dpmaif_rx_alloc(struct dpmaif_rx_queue *rxq)
1012{
1013	rxq->pit_size_cnt = DPMAIF_PIT_COUNT;
1014	rxq->pit_rd_idx = 0;
1015	rxq->pit_wr_idx = 0;
1016	rxq->pit_release_rd_idx = 0;
1017	rxq->expect_pit_seq = 0;
1018	rxq->pit_remain_release_cnt = 0;
1019	memset(&rxq->rx_data_info, 0, sizeof(rxq->rx_data_info));
1020
1021	rxq->pit_base = dma_alloc_coherent(rxq->dpmaif_ctrl->dev,
1022					   rxq->pit_size_cnt * sizeof(struct dpmaif_pit),
1023					   &rxq->pit_bus_addr, GFP_KERNEL | __GFP_ZERO);
1024	if (!rxq->pit_base)
1025		return -ENOMEM;
1026
1027	rxq->bat_req = &rxq->dpmaif_ctrl->bat_req;
1028	atomic_inc(&rxq->bat_req->refcnt);
1029
1030	rxq->bat_frag = &rxq->dpmaif_ctrl->bat_frag;
1031	atomic_inc(&rxq->bat_frag->refcnt);
1032	return 0;
1033}
1034
1035static void t7xx_dpmaif_rx_buf_free(const struct dpmaif_rx_queue *rxq)
1036{
1037	if (!rxq->dpmaif_ctrl)
1038		return;
1039
1040	t7xx_dpmaif_bat_free(rxq->dpmaif_ctrl, rxq->bat_req);
1041	t7xx_dpmaif_bat_free(rxq->dpmaif_ctrl, rxq->bat_frag);
1042
1043	if (rxq->pit_base)
1044		dma_free_coherent(rxq->dpmaif_ctrl->dev,
1045				  rxq->pit_size_cnt * sizeof(struct dpmaif_pit),
1046				  rxq->pit_base, rxq->pit_bus_addr);
1047}
1048
1049int t7xx_dpmaif_rxq_init(struct dpmaif_rx_queue *queue)
1050{
1051	int ret;
1052
1053	ret = t7xx_dpmaif_rx_alloc(queue);
1054	if (ret < 0)
1055		dev_err(queue->dpmaif_ctrl->dev, "Failed to allocate RX buffers: %d\n", ret);
1056
1057	return ret;
1058}
1059
1060void t7xx_dpmaif_rxq_free(struct dpmaif_rx_queue *queue)
1061{
1062	t7xx_dpmaif_rx_buf_free(queue);
1063}
1064
1065static void t7xx_dpmaif_bat_release_work(struct work_struct *work)
1066{
1067	struct dpmaif_ctrl *dpmaif_ctrl = container_of(work, struct dpmaif_ctrl, bat_release_work);
1068	struct dpmaif_rx_queue *rxq;
1069	int ret;
1070
1071	ret = pm_runtime_resume_and_get(dpmaif_ctrl->dev);
1072	if (ret < 0 && ret != -EACCES)
1073		return;
1074
1075	t7xx_pci_disable_sleep(dpmaif_ctrl->t7xx_dev);
1076
1077	/* ALL RXQ use one BAT table, so choose DPF_RX_QNO_DFT */
1078	rxq = &dpmaif_ctrl->rxq[DPF_RX_QNO_DFT];
1079	if (t7xx_pci_sleep_disable_complete(dpmaif_ctrl->t7xx_dev)) {
1080		t7xx_dpmaif_bat_release_and_add(rxq);
1081		t7xx_dpmaif_frag_bat_release_and_add(rxq);
1082	}
1083
1084	t7xx_pci_enable_sleep(dpmaif_ctrl->t7xx_dev);
1085	pm_runtime_put_autosuspend(dpmaif_ctrl->dev);
1086}
1087
1088int t7xx_dpmaif_bat_rel_wq_alloc(struct dpmaif_ctrl *dpmaif_ctrl)
1089{
1090	dpmaif_ctrl->bat_release_wq = alloc_workqueue("dpmaif_bat_release_work_queue",
1091						      WQ_MEM_RECLAIM | WQ_PERCPU,
1092						      1);
1093	if (!dpmaif_ctrl->bat_release_wq)
1094		return -ENOMEM;
1095
1096	INIT_WORK(&dpmaif_ctrl->bat_release_work, t7xx_dpmaif_bat_release_work);
1097	return 0;
1098}
1099
1100void t7xx_dpmaif_bat_wq_rel(struct dpmaif_ctrl *dpmaif_ctrl)
1101{
1102	flush_work(&dpmaif_ctrl->bat_release_work);
1103
1104	if (dpmaif_ctrl->bat_release_wq) {
1105		destroy_workqueue(dpmaif_ctrl->bat_release_wq);
1106		dpmaif_ctrl->bat_release_wq = NULL;
1107	}
1108}
1109
1110/**
1111 * t7xx_dpmaif_rx_stop() - Suspend RX flow.
1112 * @dpmaif_ctrl: Pointer to data path control struct dpmaif_ctrl.
1113 *
1114 * Wait for all the RX work to finish executing and mark the RX queue as paused.
1115 */
1116void t7xx_dpmaif_rx_stop(struct dpmaif_ctrl *dpmaif_ctrl)
1117{
1118	unsigned int i;
1119
1120	for (i = 0; i < DPMAIF_RXQ_NUM; i++) {
1121		struct dpmaif_rx_queue *rxq = &dpmaif_ctrl->rxq[i];
1122		int timeout, value;
1123
1124		timeout = readx_poll_timeout_atomic(atomic_read, &rxq->rx_processing, value,
1125						    !value, 0, DPMAIF_CHECK_INIT_TIMEOUT_US);
1126		if (timeout)
1127			dev_err(dpmaif_ctrl->dev, "Stop RX SW failed\n");
1128
1129		/* Ensure RX processing has stopped before we set rxq->que_started to false */
1130		smp_mb();
1131		rxq->que_started = false;
1132	}
1133}
1134
1135static void t7xx_dpmaif_stop_rxq(struct dpmaif_rx_queue *rxq)
1136{
1137	int cnt, j = 0;
1138
1139	rxq->que_started = false;
1140
1141	do {
1142		cnt = t7xx_ring_buf_rd_wr_count(rxq->pit_size_cnt, rxq->pit_rd_idx,
1143						rxq->pit_wr_idx, DPMAIF_READ);
1144
1145		if (++j >= DPMAIF_MAX_CHECK_COUNT) {
1146			dev_err(rxq->dpmaif_ctrl->dev, "Stop RX SW failed, %d\n", cnt);
1147			break;
1148		}
1149	} while (cnt);
1150
1151	memset(rxq->pit_base, 0, rxq->pit_size_cnt * sizeof(struct dpmaif_pit));
1152	memset(rxq->bat_req->bat_base, 0, rxq->bat_req->bat_size_cnt * sizeof(struct dpmaif_bat));
1153	bitmap_zero(rxq->bat_req->bat_bitmap, rxq->bat_req->bat_size_cnt);
1154	memset(&rxq->rx_data_info, 0, sizeof(rxq->rx_data_info));
1155
1156	rxq->pit_rd_idx = 0;
1157	rxq->pit_wr_idx = 0;
1158	rxq->pit_release_rd_idx = 0;
1159	rxq->expect_pit_seq = 0;
1160	rxq->pit_remain_release_cnt = 0;
1161	rxq->bat_req->bat_release_rd_idx = 0;
1162	rxq->bat_req->bat_wr_idx = 0;
1163	rxq->bat_frag->bat_release_rd_idx = 0;
1164	rxq->bat_frag->bat_wr_idx = 0;
1165}
1166
1167void t7xx_dpmaif_rx_clear(struct dpmaif_ctrl *dpmaif_ctrl)
1168{
1169	int i;
1170
1171	for (i = 0; i < DPMAIF_RXQ_NUM; i++)
1172		t7xx_dpmaif_stop_rxq(&dpmaif_ctrl->rxq[i]);
1173}
~/ Read-only file preview.