drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c

Source file repositories/reference/linux-study-clean/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c
Extension
.c
Size
32927 bytes
Lines
1174
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (hw_wr_idx != bat_req->bat_wr_idx) {
			ret = -EFAULT;
			dev_err(dpmaif_ctrl->dev, "Write index mismatch in RX ring\n");
			goto err_unmap_skbs;
		}
	}

	return 0;

err_unmap_skbs:
	while (i--)
		t7xx_unmap_bat_skb(dpmaif_ctrl->dev, bat_req->bat_skb, i);

	return ret;
}

static int t7xx_dpmaifq_release_pit_entry(struct dpmaif_rx_queue *rxq,
					  const unsigned int rel_entry_num)
{
	struct dpmaif_hw_info *hw_info = &rxq->dpmaif_ctrl->hw_info;
	unsigned int old_rel_idx, new_rel_idx, hw_wr_idx;
	int ret;

	if (!rxq->que_started)
		return 0;

	if (rel_entry_num >= rxq->pit_size_cnt) {
		dev_err(rxq->dpmaif_ctrl->dev, "Invalid PIT release index\n");
		return -EINVAL;
	}

	old_rel_idx = rxq->pit_release_rd_idx;
	new_rel_idx = old_rel_idx + rel_entry_num;
	hw_wr_idx = rxq->pit_wr_idx;
	if (hw_wr_idx < old_rel_idx && new_rel_idx >= rxq->pit_size_cnt)
		new_rel_idx -= rxq->pit_size_cnt;

	ret = t7xx_dpmaif_dlq_add_pit_remain_cnt(hw_info, rxq->index, rel_entry_num);
	if (ret) {
		dev_err(rxq->dpmaif_ctrl->dev, "PIT release failure: %d\n", ret);
		return ret;
	}

	rxq->pit_release_rd_idx = new_rel_idx;
	return 0;
}

static void t7xx_dpmaif_set_bat_mask(struct dpmaif_bat_request *bat_req, unsigned int idx)
{
	unsigned long flags;

	spin_lock_irqsave(&bat_req->mask_lock, flags);
	set_bit(idx, bat_req->bat_bitmap);
	spin_unlock_irqrestore(&bat_req->mask_lock, flags);
}

static int t7xx_frag_bat_cur_bid_check(struct dpmaif_rx_queue *rxq,
				       const unsigned int cur_bid)
{
	struct dpmaif_bat_request *bat_frag = rxq->bat_frag;
	struct dpmaif_bat_page *bat_page;

	if (cur_bid >= DPMAIF_FRG_COUNT)
		return -EINVAL;

	bat_page = bat_frag->bat_skb + cur_bid;
	if (!bat_page->page)
		return -EINVAL;

	return 0;
}

static void t7xx_unmap_bat_page(struct device *dev, struct dpmaif_bat_page *bat_page_base,
				unsigned int index)
{
	struct dpmaif_bat_page *bat_page = bat_page_base + index;

	if (bat_page->page) {
		dma_unmap_page(dev, bat_page->data_bus_addr, bat_page->data_len, DMA_FROM_DEVICE);
		put_page(bat_page->page);
		bat_page->page = NULL;
	}
}

/**
 * t7xx_dpmaif_rx_frag_alloc() - Allocates buffers for the Fragment BAT ring.
 * @dpmaif_ctrl: Pointer to DPMAIF context structure.
 * @bat_req: Pointer to BAT request structure.
 * @buf_cnt: Number of buffers to allocate.
 * @initial: Indicates if the ring is being populated for the first time.

Annotation

Implementation Notes