arch/s390/kvm/pci.c

Source file repositories/reference/linux-study-clean/arch/s390/kvm/pci.c

File Facts

System
Linux kernel
Corpus path
arch/s390/kvm/pci.c
Extension
.c
Size
15559 bytes
Lines
688
Domain
Architecture Layer
Bucket
arch/s390
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

if (npages < 1) {
			rc = -EIO;
			goto unpin1;
		}
		aisb_page = pages[0];
		pcount++;
	}

	/* Account for pinned pages, roll back on failure */
	if (account_mem(pcount))
		goto unpin2;

	/* AISB must be allocated before we can fill in GAITE */
	mutex_lock(&aift->aift_lock);
	bit = airq_iv_alloc_bit(aift->sbv);
	if (bit == -1UL)
		goto unlock;
	zdev->aisb = bit; /* store the summary bit number */
	zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA |
				    AIRQ_IV_BITLOCK |
				    AIRQ_IV_GUESTVEC,
				    phys_to_virt(fib->fmt0.aibv));

	spin_lock_irq(&aift->gait_lock);
	gaite = aift->gait + zdev->aisb;

	/* If assist not requested, host will get all alerts */
	if (assist)
		gaite->gisa = (u32)virt_to_phys(&kvm->arch.sie_page2->gisa);
	else
		gaite->gisa = 0;

	gaite->gisc = fib->fmt0.isc;
	gaite->count++;
	gaite->aisbo = fib->fmt0.aisbo;
	gaite->aisb = virt_to_phys(page_address(aisb_page) + (fib->fmt0.aisb &
							      ~PAGE_MASK));
	aift->kzdev[zdev->aisb] = zdev->kzdev;
	spin_unlock_irq(&aift->gait_lock);

	/* Update guest FIB for re-issue */
	fib->fmt0.aisbo = zdev->aisb & 63;
	fib->fmt0.aisb = virt_to_phys(aift->sbv->vector) + (zdev->aisb / 64) * 8;
	fib->fmt0.isc = gisc;

	/* Save some guest fib values in the host for later use */
	zdev->kzdev->fib.fmt0.isc = fib->fmt0.isc;
	zdev->kzdev->fib.fmt0.aibv = fib->fmt0.aibv;
	mutex_unlock(&aift->aift_lock);

	/* Issue the clp to setup the irq now */
	rc = kvm_zpci_set_airq(zdev);
	return rc;

unlock:
	mutex_unlock(&aift->aift_lock);
unpin2:
	if (fib->fmt0.sum == 1)
		unpin_user_page(aisb_page);
unpin1:
	unpin_user_page(aibv_page);
out:
	return rc;
}

static int kvm_s390_pci_aif_disable(struct zpci_dev *zdev, bool force)
{
	struct kvm_zdev *kzdev = zdev->kzdev;
	struct zpci_gaite *gaite;
	struct page *vpage = NULL, *spage = NULL;
	int rc, pcount = 0;
	u8 isc;

	if (zdev->gisa == 0)
		return -EINVAL;

	mutex_lock(&aift->aift_lock);

	/*
	 * If the clear fails due to an error, leave now unless we know this
	 * device is about to go away (force) -- In that case clear the GAITE
	 * regardless.
	 */
	rc = kvm_zpci_clear_airq(zdev);
	if (rc && !force)
		goto out;

	if (zdev->kzdev->fib.fmt0.aibv == 0)
		goto out;
	spin_lock_irq(&aift->gait_lock);

Annotation

Implementation Notes