cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

iosm_ipc_irq.c (2137B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2020-21 Intel Corporation.
      4 */
      5
      6#include "iosm_ipc_pcie.h"
      7#include "iosm_ipc_protocol.h"
      8
      9static void ipc_write_dbell_reg(struct iosm_pcie *ipc_pcie, int irq_n, u32 data)
     10{
     11	void __iomem *write_reg;
     12
     13	/* Select the first doorbell register, which is only currently needed
     14	 * by CP.
     15	 */
     16	write_reg = (void __iomem *)((u8 __iomem *)ipc_pcie->ipc_regs +
     17				     ipc_pcie->doorbell_write +
     18				     (irq_n * ipc_pcie->doorbell_reg_offset));
     19
     20	/* Fire the doorbell irq by writing data on the doorbell write pointer
     21	 * register.
     22	 */
     23	iowrite32(data, write_reg);
     24}
     25
     26void ipc_doorbell_fire(struct iosm_pcie *ipc_pcie, int irq_n, u32 data)
     27{
     28	ipc_write_dbell_reg(ipc_pcie, irq_n, data);
     29}
     30
     31/* Threaded Interrupt handler for MSI interrupts */
     32static irqreturn_t ipc_msi_interrupt(int irq, void *dev_id)
     33{
     34	struct iosm_pcie *ipc_pcie = dev_id;
     35	int instance = irq - ipc_pcie->pci->irq;
     36
     37	/* Shift the MSI irq actions to the IPC tasklet. IRQ_NONE means the
     38	 * irq was not from the IPC device or could not be served.
     39	 */
     40	if (instance >= ipc_pcie->nvec)
     41		return IRQ_NONE;
     42
     43	if (!test_bit(0, &ipc_pcie->suspend))
     44		ipc_imem_irq_process(ipc_pcie->imem, instance);
     45
     46	return IRQ_HANDLED;
     47}
     48
     49void ipc_release_irq(struct iosm_pcie *ipc_pcie)
     50{
     51	struct pci_dev *pdev = ipc_pcie->pci;
     52
     53	if (pdev->msi_enabled) {
     54		while (--ipc_pcie->nvec >= 0)
     55			free_irq(pdev->irq + ipc_pcie->nvec, ipc_pcie);
     56	}
     57	pci_free_irq_vectors(pdev);
     58}
     59
     60int ipc_acquire_irq(struct iosm_pcie *ipc_pcie)
     61{
     62	struct pci_dev *pdev = ipc_pcie->pci;
     63	int i, rc = -EINVAL;
     64
     65	ipc_pcie->nvec = pci_alloc_irq_vectors(pdev, IPC_MSI_VECTORS,
     66					       IPC_MSI_VECTORS, PCI_IRQ_MSI);
     67
     68	if (ipc_pcie->nvec < 0) {
     69		rc = ipc_pcie->nvec;
     70		goto error;
     71	}
     72
     73	if (!pdev->msi_enabled)
     74		goto error;
     75
     76	for (i = 0; i < ipc_pcie->nvec; ++i) {
     77		rc = request_threaded_irq(pdev->irq + i, NULL,
     78					  ipc_msi_interrupt, IRQF_ONESHOT,
     79					  KBUILD_MODNAME, ipc_pcie);
     80		if (rc) {
     81			dev_err(ipc_pcie->dev, "unable to grab IRQ, rc=%d", rc);
     82			ipc_pcie->nvec = i;
     83			ipc_release_irq(ipc_pcie);
     84			goto error;
     85		}
     86	}
     87
     88error:
     89	return rc;
     90}