drivers/s390/crypto/vfio_ap_ops.c

Source file repositories/reference/linux-study-clean/drivers/s390/crypto/vfio_ap_ops.c

File Facts

System
Linux kernel
Corpus path
drivers/s390/crypto/vfio_ap_ops.c
Extension
.c
Size
83539 bytes
Lines
2870
Domain
Driver Families
Bucket
drivers/s390
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

test_bit_inv(AP_QID_QUEUE(apqn), matrix_mdev->matrix.aqm)) {
			if (matrix_mdev->kvm)
				mutex_lock(&matrix_mdev->kvm->lock);

			mutex_lock(&matrix_dev->mdevs_lock);

			return matrix_mdev;
		}
	}

	mutex_lock(&matrix_dev->mdevs_lock);

	return NULL;
}

/**
 * get_update_locks_for_queue: get the locks required to update the APCB of the
 *			       KVM guest to which the matrix mdev linked to a
 *			       vfio_ap_queue object is attached.
 *
 * @q: a pointer to a vfio_ap_queue object.
 *
 * The proper locking order is:
 * 1. q->matrix_dev->guests_lock: required to use the KVM pointer to update a
 *				  KVM guest's APCB.
 * 2. q->matrix_mdev->kvm->lock:  required to update a guest's APCB
 * 3. matrix_dev->mdevs_lock:	  required to access data stored in matrix_mdev
 *
 * Note: if @queue is not linked to an ap_matrix_mdev object, the KVM lock
 *	  will not be taken.
 */
static inline void get_update_locks_for_queue(struct vfio_ap_queue *q)
{
	mutex_lock(&matrix_dev->guests_lock);
	if (q->matrix_mdev && q->matrix_mdev->kvm)
		mutex_lock(&q->matrix_mdev->kvm->lock);
	mutex_lock(&matrix_dev->mdevs_lock);
}

/**
 * vfio_ap_mdev_get_queue - retrieve a queue with a specific APQN from a
 *			    hash table of queues assigned to a matrix mdev
 * @matrix_mdev: the matrix mdev
 * @apqn: The APQN of a queue device
 *
 * Return: the pointer to the vfio_ap_queue struct representing the queue or
 *	   NULL if the queue is not assigned to @matrix_mdev
 */
static struct vfio_ap_queue *vfio_ap_mdev_get_queue(
					struct ap_matrix_mdev *matrix_mdev,
					int apqn)
{
	struct vfio_ap_queue *q;

	hash_for_each_possible(matrix_mdev->qtable.queues, q, mdev_qnode,
			       apqn) {
		if (q && q->apqn == apqn)
			return q;
	}

	return NULL;
}

/**
 * vfio_ap_wait_for_irqclear - clears the IR bit or gives up after 5 tries
 * @apqn: The AP Queue number
 *
 * Checks the IRQ bit for the status of this APQN using ap_tapq.
 * Returns if the ap_tapq function succeeded and the bit is clear.
 * Returns if ap_tapq function failed with invalid, deconfigured or
 * checkstopped AP.
 * Otherwise retries up to 5 times after waiting 20ms.
 */
static void vfio_ap_wait_for_irqclear(int apqn)
{
	struct ap_queue_status status;
	int retry = 5;

	do {
		status = ap_tapq(apqn, NULL);
		switch (status.response_code) {
		case AP_RESPONSE_NORMAL:
		case AP_RESPONSE_RESET_IN_PROGRESS:
			if (!status.irq_enabled)
				return;
			fallthrough;
		case AP_RESPONSE_BUSY:
			msleep(20);
			break;
		case AP_RESPONSE_Q_NOT_AVAIL:

Annotation

Implementation Notes