Skip to content

Commit

Permalink
net: iosm: irq handling
Browse files Browse the repository at this point in the history
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.
90 changes: 90 additions & 0 deletions drivers/net/wwan/iosm/iosm_ipc_irq.c
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;
}
33 changes: 33 additions & 0 deletions drivers/net/wwan/iosm/iosm_ipc_irq.h
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

0 comments on commit 7f41ce0

Please sign in to comment.