drivers/s390/cio/qdio_setup.c

Source file repositories/reference/linux-study-clean/drivers/s390/cio/qdio_setup.c

File Facts

System
Linux kernel
Corpus path
drivers/s390/cio/qdio_setup.c
Extension
.c
Size
11483 bytes
Lines
445
Domain
Driver Families
Bucket
drivers/s390
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 (!buf[pos]) {
			qdio_free_buffers(buf, count);
			return -ENOMEM;
		}
	}
	for (pos = 0; pos < count; pos++)
		if (pos % QBUFF_PER_PAGE)
			buf[pos] = buf[pos - 1] + 1;
	return 0;
}
EXPORT_SYMBOL_GPL(qdio_alloc_buffers);

/**
 * qdio_reset_buffers() - reset qdio buffers
 * @buf: array of pointers to qdio buffers
 * @count: number of qdio buffers that will be zeroed
 */
void qdio_reset_buffers(struct qdio_buffer **buf, unsigned int count)
{
	int pos;

	for (pos = 0; pos < count; pos++)
		memset(buf[pos], 0, sizeof(struct qdio_buffer));
}
EXPORT_SYMBOL_GPL(qdio_reset_buffers);

static void __qdio_free_queues(struct qdio_q **queues, unsigned int count)
{
	struct qdio_q *q;
	unsigned int i;

	for (i = 0; i < count; i++) {
		q = queues[i];
		free_page((unsigned long)q->sl_page);
		kmem_cache_free(qdio_q_cache, q);
	}
}

void qdio_free_queues(struct qdio_irq *irq_ptr)
{
	__qdio_free_queues(irq_ptr->input_qs, irq_ptr->max_input_qs);
	irq_ptr->max_input_qs = 0;

	__qdio_free_queues(irq_ptr->output_qs, irq_ptr->max_output_qs);
	irq_ptr->max_output_qs = 0;
}

static int __qdio_allocate_qs(struct qdio_q **irq_ptr_qs, int nr_queues)
{
	struct qdio_q *q;
	int i;

	for (i = 0; i < nr_queues; i++) {
		q = kmem_cache_zalloc(qdio_q_cache, GFP_KERNEL);
		if (!q) {
			__qdio_free_queues(irq_ptr_qs, i);
			return -ENOMEM;
		}

		q->sl_page = (void *)__get_free_page(GFP_KERNEL);
		if (!q->sl_page) {
			kmem_cache_free(qdio_q_cache, q);
			__qdio_free_queues(irq_ptr_qs, i);
			return -ENOMEM;
		}
		q->slib = q->sl_page;
		/* As per architecture: SLIB is 2K bytes long, and SL 1K. */
		q->sl = (struct sl *)(q->slib + 1);

		irq_ptr_qs[i] = q;
	}
	return 0;
}

int qdio_allocate_qs(struct qdio_irq *irq_ptr, int nr_input_qs, int nr_output_qs)
{
	int rc;

	rc = __qdio_allocate_qs(irq_ptr->input_qs, nr_input_qs);
	if (rc)
		return rc;

	rc = __qdio_allocate_qs(irq_ptr->output_qs, nr_output_qs);
	if (rc) {
		__qdio_free_queues(irq_ptr->input_qs, nr_input_qs);
		return rc;
	}

	irq_ptr->max_input_qs = nr_input_qs;
	irq_ptr->max_output_qs = nr_output_qs;

Annotation

Implementation Notes