-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
1) Request interrupt vector, frees allocated resource. 2) Registers IRQ handler. Signed-off-by: M Chetan Kumar <m.chetan.kumar@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
- Loading branch information
M Chetan Kumar
authored and
David S. Miller
committed
Jun 13, 2021
1 parent
7e98d78
commit 7f41ce0
Showing
2 changed files
with
123 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// SPDX-License-Identifier: GPL-2.0-only | ||
/* | ||
* Copyright (C) 2020-21 Intel Corporation. | ||
*/ | ||
|
||
#include "iosm_ipc_pcie.h" | ||
#include "iosm_ipc_protocol.h" | ||
|
||
static void ipc_write_dbell_reg(struct iosm_pcie *ipc_pcie, int irq_n, u32 data) | ||
{ | ||
void __iomem *write_reg; | ||
|
||
/* Select the first doorbell register, which is only currently needed | ||
* by CP. | ||
*/ | ||
write_reg = (void __iomem *)((u8 __iomem *)ipc_pcie->ipc_regs + | ||
ipc_pcie->doorbell_write + | ||
(irq_n * ipc_pcie->doorbell_reg_offset)); | ||
|
||
/* Fire the doorbell irq by writing data on the doorbell write pointer | ||
* register. | ||
*/ | ||
iowrite32(data, write_reg); | ||
} | ||
|
||
void ipc_doorbell_fire(struct iosm_pcie *ipc_pcie, int irq_n, u32 data) | ||
{ | ||
ipc_write_dbell_reg(ipc_pcie, irq_n, data); | ||
} | ||
|
||
/* Threaded Interrupt handler for MSI interrupts */ | ||
static irqreturn_t ipc_msi_interrupt(int irq, void *dev_id) | ||
{ | ||
struct iosm_pcie *ipc_pcie = dev_id; | ||
int instance = irq - ipc_pcie->pci->irq; | ||
|
||
/* Shift the MSI irq actions to the IPC tasklet. IRQ_NONE means the | ||
* irq was not from the IPC device or could not be served. | ||
*/ | ||
if (instance >= ipc_pcie->nvec) | ||
return IRQ_NONE; | ||
|
||
if (!test_bit(0, &ipc_pcie->suspend)) | ||
ipc_imem_irq_process(ipc_pcie->imem, instance); | ||
|
||
return IRQ_HANDLED; | ||
} | ||
|
||
void ipc_release_irq(struct iosm_pcie *ipc_pcie) | ||
{ | ||
struct pci_dev *pdev = ipc_pcie->pci; | ||
|
||
if (pdev->msi_enabled) { | ||
while (--ipc_pcie->nvec >= 0) | ||
free_irq(pdev->irq + ipc_pcie->nvec, ipc_pcie); | ||
} | ||
pci_free_irq_vectors(pdev); | ||
} | ||
|
||
int ipc_acquire_irq(struct iosm_pcie *ipc_pcie) | ||
{ | ||
struct pci_dev *pdev = ipc_pcie->pci; | ||
int i, rc = -EINVAL; | ||
|
||
ipc_pcie->nvec = pci_alloc_irq_vectors(pdev, IPC_MSI_VECTORS, | ||
IPC_MSI_VECTORS, PCI_IRQ_MSI); | ||
|
||
if (ipc_pcie->nvec < 0) { | ||
rc = ipc_pcie->nvec; | ||
goto error; | ||
} | ||
|
||
if (!pdev->msi_enabled) | ||
goto error; | ||
|
||
for (i = 0; i < ipc_pcie->nvec; ++i) { | ||
rc = request_threaded_irq(pdev->irq + i, NULL, | ||
ipc_msi_interrupt, IRQF_ONESHOT, | ||
KBUILD_MODNAME, ipc_pcie); | ||
if (rc) { | ||
dev_err(ipc_pcie->dev, "unable to grab IRQ, rc=%d", rc); | ||
ipc_pcie->nvec = i; | ||
ipc_release_irq(ipc_pcie); | ||
goto error; | ||
} | ||
} | ||
|
||
error: | ||
return rc; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/* SPDX-License-Identifier: GPL-2.0-only | ||
* | ||
* Copyright (C) 2020-21 Intel Corporation. | ||
*/ | ||
|
||
#ifndef IOSM_IPC_IRQ_H | ||
#define IOSM_IPC_IRQ_H | ||
|
||
struct iosm_pcie; | ||
|
||
/** | ||
* ipc_doorbell_fire - fire doorbell to CP | ||
* @ipc_pcie: Pointer to iosm_pcie | ||
* @irq_n: Doorbell type | ||
* @data: ipc state | ||
*/ | ||
void ipc_doorbell_fire(struct iosm_pcie *ipc_pcie, int irq_n, u32 data); | ||
|
||
/** | ||
* ipc_release_irq - Release the IRQ handler. | ||
* @ipc_pcie: Pointer to iosm_pcie struct | ||
*/ | ||
void ipc_release_irq(struct iosm_pcie *ipc_pcie); | ||
|
||
/** | ||
* ipc_acquire_irq - acquire IRQ & register IRQ handler. | ||
* @ipc_pcie: Pointer to iosm_pcie struct | ||
* | ||
* Return: 0 on success and failure value on error | ||
*/ | ||
int ipc_acquire_irq(struct iosm_pcie *ipc_pcie); | ||
|
||
#endif |