drivers/scsi/ibmvscsi_tgt/libsrp.c

Source file repositories/reference/linux-study-clean/drivers/scsi/ibmvscsi_tgt/libsrp.c

File Facts

System
Linux kernel
Corpus path
drivers/scsi/ibmvscsi_tgt/libsrp.c
Extension
.c
Size
10099 bytes
Lines
421
Domain
Driver Families
Bucket
drivers/scsi
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 (ring[i]->buf) {
			dma_free_coherent(dev, size, ring[i]->buf,
					  ring[i]->dma);
		}
		kfree(ring[i]);
	}
	kfree(ring);

	return NULL;
}

static void srp_ring_free(struct device *dev, struct srp_buf **ring,
			  size_t max, size_t size)
{
	int i;

	for (i = 0; i < max; i++) {
		dma_free_coherent(dev, size, ring[i]->buf, ring[i]->dma);
		kfree(ring[i]);
	}
	kfree(ring);
}

int srp_target_alloc(struct srp_target *target, struct device *dev,
		     size_t nr, size_t iu_size)
{
	int err;

	spin_lock_init(&target->lock);

	target->dev = dev;

	target->srp_iu_size = iu_size;
	target->rx_ring_size = nr;
	target->rx_ring = srp_ring_alloc(target->dev, nr, iu_size);
	if (!target->rx_ring)
		return -ENOMEM;
	err = srp_iu_pool_alloc(&target->iu_queue, nr, target->rx_ring);
	if (err)
		goto free_ring;

	dev_set_drvdata(target->dev, target);
	return 0;

free_ring:
	srp_ring_free(target->dev, target->rx_ring, nr, iu_size);
	return -ENOMEM;
}

void srp_target_free(struct srp_target *target)
{
	dev_set_drvdata(target->dev, NULL);
	srp_ring_free(target->dev, target->rx_ring, target->rx_ring_size,
		      target->srp_iu_size);
	srp_iu_pool_free(&target->iu_queue);
}

struct iu_entry *srp_iu_get(struct srp_target *target)
{
	struct iu_entry *iue = NULL;

	if (kfifo_out_locked(&target->iu_queue.queue, (void *)&iue,
			     sizeof(void *),
			     &target->iu_queue.lock) != sizeof(void *)) {
		WARN_ONCE(1, "unexpected fifo state");
		return NULL;
	}
	if (!iue)
		return iue;
	iue->target = target;
	iue->flags = 0;
	return iue;
}

void srp_iu_put(struct iu_entry *iue)
{
	kfifo_in_locked(&iue->target->iu_queue.queue, (void *)&iue,
			sizeof(void *), &iue->target->iu_queue.lock);
}

static int srp_direct_data(struct ibmvscsis_cmd *cmd, struct srp_direct_buf *md,
			   enum dma_data_direction dir, srp_rdma_t rdma_io,
			   int dma_map, int ext_desc)
{
	struct iu_entry *iue = NULL;
	struct scatterlist *sg = NULL;
	int err, nsg = 0, len;

	if (dma_map) {
		iue = cmd->iue;

Annotation

Implementation Notes