drivers/infiniband/hw/cxgb4/mem.c

Source file repositories/reference/linux-study-clean/drivers/infiniband/hw/cxgb4/mem.c

File Facts

System
Linux kernel
Corpus path
drivers/infiniband/hw/cxgb4/mem.c
Extension
.c
Size
19919 bytes
Lines
744
Domain
Driver Families
Bucket
drivers/infiniband
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 (!skb) {
			skb = alloc_skb(wr_len, GFP_KERNEL | __GFP_NOFAIL);
			if (!skb)
				return -ENOMEM;
		}
		set_wr_txq(skb, CPL_PRIORITY_CONTROL, 0);

		req = __skb_put_zero(skb, wr_len);
		INIT_ULPTX_WR(req, wr_len, 0, 0);

		if (i == (num_wqe-1)) {
			req->wr.wr_hi = cpu_to_be32(FW_WR_OP_V(FW_ULPTX_WR) |
						    FW_WR_COMPL_F);
			req->wr.wr_lo = (__force __be64)(unsigned long)wr_waitp;
		} else
			req->wr.wr_hi = cpu_to_be32(FW_WR_OP_V(FW_ULPTX_WR));
		req->wr.wr_mid = cpu_to_be32(
				       FW_WR_LEN16_V(DIV_ROUND_UP(wr_len, 16)));

		req->cmd = cmd;
		req->dlen = cpu_to_be32(ULP_MEMIO_DATA_LEN_V(
				DIV_ROUND_UP(copy_len, T4_ULPTX_MIN_IO)));
		req->len16 = cpu_to_be32(DIV_ROUND_UP(wr_len-sizeof(req->wr),
						      16));
		req->lock_addr = cpu_to_be32(ULP_MEMIO_ADDR_V(addr + i * 3));

		sc = (struct ulptx_idata *)(req + 1);
		sc->cmd_more = cpu_to_be32(ULPTX_CMD_V(ULP_TX_SC_IMM));
		sc->len = cpu_to_be32(roundup(copy_len, T4_ULPTX_MIN_IO));

		to_dp = (u8 *)(sc + 1);
		from_dp = (u8 *)data + i * C4IW_MAX_INLINE_SIZE;
		if (data)
			memcpy(to_dp, from_dp, copy_len);
		else
			memset(to_dp, 0, copy_len);
		if (copy_len % T4_ULPTX_MIN_IO)
			memset(to_dp + copy_len, 0, T4_ULPTX_MIN_IO -
			       (copy_len % T4_ULPTX_MIN_IO));
		if (i == (num_wqe-1))
			ret = c4iw_ref_send_wait(rdev, skb, wr_waitp, 0, 0,
						 __func__);
		else
			ret = c4iw_ofld_send(rdev, skb);
		if (ret)
			break;
		skb = NULL;
		len -= C4IW_MAX_INLINE_SIZE;
	}

	return ret;
}

static int _c4iw_write_mem_dma(struct c4iw_rdev *rdev, u32 addr, u32 len,
			       void *data, struct sk_buff *skb,
			       struct c4iw_wr_wait *wr_waitp)
{
	u32 remain = len;
	u32 dmalen;
	int ret = 0;
	dma_addr_t daddr;
	dma_addr_t save;

	daddr = dma_map_single(&rdev->lldi.pdev->dev, data, len, DMA_TO_DEVICE);
	if (dma_mapping_error(&rdev->lldi.pdev->dev, daddr))
		return -1;
	save = daddr;

	while (remain > inline_threshold) {
		if (remain < T4_ULPTX_MAX_DMA) {
			if (remain & ~T4_ULPTX_MIN_IO)
				dmalen = remain & ~(T4_ULPTX_MIN_IO-1);
			else
				dmalen = remain;
		} else
			dmalen = T4_ULPTX_MAX_DMA;
		remain -= dmalen;
		ret = _c4iw_write_mem_dma_aligned(rdev, addr, dmalen, daddr,
						 skb, remain ? NULL : wr_waitp);
		if (ret)
			goto out;
		addr += dmalen >> 5;
		data += dmalen;
		daddr += dmalen;
	}
	if (remain)
		ret = _c4iw_write_mem_inline(rdev, addr, remain, data, skb,
					     wr_waitp);
out:
	dma_unmap_single(&rdev->lldi.pdev->dev, save, len, DMA_TO_DEVICE);

Annotation

Implementation Notes