drivers/infiniband/hw/cxgb4/qp.c

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

File Facts

System
Linux kernel
Corpus path
drivers/infiniband/hw/cxgb4/qp.c
Extension
.c
Size
77508 bytes
Lines
2839
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 (!wq->rq.qid) {
			ret = -ENOMEM;
			goto free_sq_qid;
		}
	}

	if (!user) {
		wq->sq.sw_sq = kzalloc_objs(*wq->sq.sw_sq, wq->sq.size);
		if (!wq->sq.sw_sq) {
			ret = -ENOMEM;
			goto free_rq_qid;//FIXME
		}

		if (need_rq) {
			wq->rq.sw_rq = kzalloc_objs(*wq->rq.sw_rq, wq->rq.size);
			if (!wq->rq.sw_rq) {
				ret = -ENOMEM;
				goto free_sw_sq;
			}
		}
	}

	if (need_rq) {
		/*
		 * RQT must be a power of 2 and at least 16 deep.
		 */
		wq->rq.rqt_size =
			roundup_pow_of_two(max_t(u16, wq->rq.size, 16));
		wq->rq.rqt_hwaddr = c4iw_rqtpool_alloc(rdev, wq->rq.rqt_size);
		if (!wq->rq.rqt_hwaddr) {
			ret = -ENOMEM;
			goto free_sw_rq;
		}
	}

	ret = alloc_sq(rdev, &wq->sq, user);
	if (ret)
		goto free_hwaddr;
	memset(wq->sq.queue, 0, wq->sq.memsize);
	dma_unmap_addr_set(&wq->sq, mapping, wq->sq.dma_addr);

	if (need_rq) {
		wq->rq.queue = dma_alloc_coherent(&rdev->lldi.pdev->dev,
						  wq->rq.memsize,
						  &wq->rq.dma_addr,
						  GFP_KERNEL);
		if (!wq->rq.queue) {
			ret = -ENOMEM;
			goto free_sq;
		}
		pr_debug("sq base va 0x%p pa 0x%llx rq base va 0x%p pa 0x%llx\n",
			 wq->sq.queue,
			 (unsigned long long)virt_to_phys(wq->sq.queue),
			 wq->rq.queue,
			 (unsigned long long)virt_to_phys(wq->rq.queue));
		dma_unmap_addr_set(&wq->rq, mapping, wq->rq.dma_addr);
	}

	wq->db = rdev->lldi.db_reg;

	wq->sq.bar2_va = c4iw_bar2_addrs(rdev, wq->sq.qid,
					 CXGB4_BAR2_QTYPE_EGRESS,
					 &wq->sq.bar2_qid,
					 user ? &wq->sq.bar2_pa : NULL);
	if (need_rq)
		wq->rq.bar2_va = c4iw_bar2_addrs(rdev, wq->rq.qid,
						 CXGB4_BAR2_QTYPE_EGRESS,
						 &wq->rq.bar2_qid,
						 user ? &wq->rq.bar2_pa : NULL);

	/*
	 * User mode must have bar2 access.
	 */
	if (user && (!wq->sq.bar2_pa || (need_rq && !wq->rq.bar2_pa))) {
		pr_warn("%s: sqid %u or rqid %u not in BAR2 range\n",
			pci_name(rdev->lldi.pdev), wq->sq.qid, wq->rq.qid);
		ret = -EINVAL;
		goto free_dma;
	}

	wq->rdev = rdev;
	wq->rq.msn = 1;

	/* build fw_ri_res_wr */
	wr_len = sizeof(*res_wr) + 2 * sizeof(*res);
	if (need_rq)
		wr_len += sizeof(*res);
	skb = alloc_skb(wr_len, GFP_KERNEL);
	if (!skb) {
		ret = -ENOMEM;

Annotation

Implementation Notes