drivers/infiniband/ulp/iser/iser_memory.c

Source file repositories/reference/linux-study-clean/drivers/infiniband/ulp/iser/iser_memory.c

File Facts

System
Linux kernel
Corpus path
drivers/infiniband/ulp/iser/iser_memory.c
Extension
.c
Size
11327 bytes
Lines
392
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 (unlikely(pdata->dma_nents == 0)) {
			iser_err("protection dma_map_sg failed!!!\n");
			goto out_unmap;
		}
	}

	return 0;

out_unmap:
	ib_dma_unmap_sg(dev, data->sg, data->size, dma_dir);
	return -EINVAL;
}


void iser_dma_unmap_task_data(struct iscsi_iser_task *iser_task,
			      enum iser_data_dir iser_dir,
			      enum dma_data_direction dma_dir)
{
	struct iser_data_buf *data = &iser_task->data[iser_dir];
	struct ib_device *dev;

	dev = iser_task->iser_conn->ib_conn.device->ib_device;
	ib_dma_unmap_sg(dev, data->sg, data->size, dma_dir);

	if (scsi_prot_sg_count(iser_task->sc)) {
		struct iser_data_buf *pdata = &iser_task->prot[iser_dir];

		ib_dma_unmap_sg(dev, pdata->sg, pdata->size, dma_dir);
	}
}

static int iser_reg_dma(struct iser_device *device, struct iser_data_buf *mem,
			struct iser_mem_reg *reg)
{
	struct scatterlist *sg = mem->sg;

	reg->sge.lkey = device->pd->local_dma_lkey;
	/*
	 * FIXME: rework the registration code path to differentiate
	 * rkey/lkey use cases
	 */

	if (device->pd->flags & IB_PD_UNSAFE_GLOBAL_RKEY)
		reg->rkey = device->pd->unsafe_global_rkey;
	else
		reg->rkey = 0;
	reg->sge.addr = sg_dma_address(&sg[0]);
	reg->sge.length = sg_dma_len(&sg[0]);

	iser_dbg("Single DMA entry: lkey=0x%x, rkey=0x%x, addr=0x%llx,"
		 " length=0x%x\n", reg->sge.lkey, reg->rkey,
		 reg->sge.addr, reg->sge.length);

	return 0;
}

void iser_unreg_mem_fastreg(struct iscsi_iser_task *iser_task,
			    enum iser_data_dir cmd_dir)
{
	struct iser_mem_reg *reg = &iser_task->rdma_reg[cmd_dir];
	struct iser_fr_desc *desc;
	struct ib_mr_status mr_status;

	desc = reg->desc;
	if (!desc)
		return;

	/*
	 * The signature MR cannot be invalidated and reused without checking.
	 * libiscsi calls the check_protection transport handler only if
	 * SCSI-Response is received. And the signature MR is not checked if
	 * the task is completed for some other reason like a timeout or error
	 * handling. That's why we must check the signature MR here before
	 * putting it to the free pool.
	 */
	if (unlikely(desc->sig_protected)) {
		desc->sig_protected = false;
		ib_check_mr_status(desc->rsc.sig_mr, IB_MR_CHECK_SIG_STATUS,
				   &mr_status);
	}
	iser_reg_desc_put_fr(&iser_task->iser_conn->ib_conn, reg->desc);
	reg->desc = NULL;
}

static void iser_set_dif_domain(struct scsi_cmnd *sc,
				struct ib_sig_domain *domain)
{
	domain->sig_type = IB_SIG_TYPE_T10_DIF;
	domain->sig.dif.pi_interval = scsi_prot_interval(sc);
	domain->sig.dif.ref_tag = t10_pi_ref_tag(scsi_cmd_to_rq(sc));

Annotation

Implementation Notes