crypto: cavium/nitrox - Enable interrups for PF in SR-IOV mode.

Enable the available interrupt vectors for PF in SR-IOV Mode.
Only single vector entry 192 is valid of PF. This is used to
notify any hardware errors and mailbox messages from VF(s).

Signed-off-by: Srikanth Jampala <Jampala.Srikanth@cavium.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
Srikanth, Jampala 2018-11-21 09:52:24 +00:00 committed by Herbert Xu
parent 4bede34c1a
commit 7a027b57f9
4 changed files with 142 additions and 10 deletions

View File

@ -103,6 +103,16 @@ struct nitrox_q_vector {
}; };
}; };
/**
* struct nitrox_iov - SR-IOV information
* @num_vfs: number of VF(s) enabled
* @msix: MSI-X for PF in SR-IOV case
*/
struct nitrox_iov {
int num_vfs;
struct msix_entry msix;
};
/* /*
* NITROX Device states * NITROX Device states
*/ */
@ -150,6 +160,9 @@ enum vf_mode {
* @ctx_pool: DMA pool for crypto context * @ctx_pool: DMA pool for crypto context
* @pkt_inq: Packet input rings * @pkt_inq: Packet input rings
* @qvec: MSI-X queue vectors information * @qvec: MSI-X queue vectors information
* @iov: SR-IOV informatin
* @num_vecs: number of MSI-X vectors
* @stats: request statistics
* @hw: hardware information * @hw: hardware information
* @debugfs_dir: debugfs directory * @debugfs_dir: debugfs directory
*/ */
@ -168,13 +181,13 @@ struct nitrox_device {
int node; int node;
u16 qlen; u16 qlen;
u16 nr_queues; u16 nr_queues;
int num_vfs;
enum vf_mode mode; enum vf_mode mode;
struct dma_pool *ctx_pool; struct dma_pool *ctx_pool;
struct nitrox_cmdq *pkt_inq; struct nitrox_cmdq *pkt_inq;
struct nitrox_q_vector *qvec; struct nitrox_q_vector *qvec;
struct nitrox_iov iov;
int num_vecs; int num_vecs;
struct nitrox_stats stats; struct nitrox_stats stats;

View File

@ -13,6 +13,7 @@
* - NPS packet ring, AQMQ ring and ZQMQ ring * - NPS packet ring, AQMQ ring and ZQMQ ring
*/ */
#define NR_RING_VECTORS 3 #define NR_RING_VECTORS 3
#define NR_NON_RING_VECTORS 1
/* base entry for packet ring/port */ /* base entry for packet ring/port */
#define PKT_RING_MSIX_BASE 0 #define PKT_RING_MSIX_BASE 0
#define NON_RING_MSIX_BASE 192 #define NON_RING_MSIX_BASE 192
@ -275,6 +276,7 @@ void nitrox_unregister_interrupts(struct nitrox_device *ndev)
qvec->valid = false; qvec->valid = false;
} }
kfree(ndev->qvec); kfree(ndev->qvec);
ndev->qvec = NULL;
pci_free_irq_vectors(pdev); pci_free_irq_vectors(pdev);
} }
@ -321,6 +323,7 @@ int nitrox_register_interrupts(struct nitrox_device *ndev)
if (qvec->ring >= ndev->nr_queues) if (qvec->ring >= ndev->nr_queues)
break; break;
qvec->cmdq = &ndev->pkt_inq[qvec->ring];
snprintf(qvec->name, IRQ_NAMESZ, "nitrox-pkt%d", qvec->ring); snprintf(qvec->name, IRQ_NAMESZ, "nitrox-pkt%d", qvec->ring);
/* get the vector number */ /* get the vector number */
vec = pci_irq_vector(pdev, i); vec = pci_irq_vector(pdev, i);
@ -335,13 +338,13 @@ int nitrox_register_interrupts(struct nitrox_device *ndev)
tasklet_init(&qvec->resp_tasklet, pkt_slc_resp_tasklet, tasklet_init(&qvec->resp_tasklet, pkt_slc_resp_tasklet,
(unsigned long)qvec); (unsigned long)qvec);
qvec->cmdq = &ndev->pkt_inq[qvec->ring];
qvec->valid = true; qvec->valid = true;
} }
/* request irqs for non ring vectors */ /* request irqs for non ring vectors */
i = NON_RING_MSIX_BASE; i = NON_RING_MSIX_BASE;
qvec = &ndev->qvec[i]; qvec = &ndev->qvec[i];
qvec->ndev = ndev;
snprintf(qvec->name, IRQ_NAMESZ, "nitrox-core-int%d", i); snprintf(qvec->name, IRQ_NAMESZ, "nitrox-core-int%d", i);
/* get the vector number */ /* get the vector number */
@ -356,7 +359,6 @@ int nitrox_register_interrupts(struct nitrox_device *ndev)
tasklet_init(&qvec->resp_tasklet, nps_core_int_tasklet, tasklet_init(&qvec->resp_tasklet, nps_core_int_tasklet,
(unsigned long)qvec); (unsigned long)qvec);
qvec->ndev = ndev;
qvec->valid = true; qvec->valid = true;
return 0; return 0;
@ -365,3 +367,81 @@ irq_fail:
nitrox_unregister_interrupts(ndev); nitrox_unregister_interrupts(ndev);
return ret; return ret;
} }
void nitrox_sriov_unregister_interrupts(struct nitrox_device *ndev)
{
struct pci_dev *pdev = ndev->pdev;
int i;
for (i = 0; i < ndev->num_vecs; i++) {
struct nitrox_q_vector *qvec;
int vec;
qvec = ndev->qvec + i;
if (!qvec->valid)
continue;
vec = ndev->iov.msix.vector;
irq_set_affinity_hint(vec, NULL);
free_irq(vec, qvec);
tasklet_disable(&qvec->resp_tasklet);
tasklet_kill(&qvec->resp_tasklet);
qvec->valid = false;
}
kfree(ndev->qvec);
ndev->qvec = NULL;
pci_disable_msix(pdev);
}
int nitrox_sriov_register_interupts(struct nitrox_device *ndev)
{
struct pci_dev *pdev = ndev->pdev;
struct nitrox_q_vector *qvec;
int vec, cpu;
int ret;
/**
* only non ring vectors i.e Entry 192 is available
* for PF in SR-IOV mode.
*/
ndev->iov.msix.entry = NON_RING_MSIX_BASE;
ret = pci_enable_msix_exact(pdev, &ndev->iov.msix, NR_NON_RING_VECTORS);
if (ret) {
dev_err(DEV(ndev), "failed to allocate nps-core-int%d\n",
NON_RING_MSIX_BASE);
return ret;
}
qvec = kcalloc(NR_NON_RING_VECTORS, sizeof(*qvec), GFP_KERNEL);
if (!qvec) {
pci_disable_msix(pdev);
return -ENOMEM;
}
qvec->ndev = ndev;
ndev->qvec = qvec;
ndev->num_vecs = NR_NON_RING_VECTORS;
snprintf(qvec->name, IRQ_NAMESZ, "nitrox-core-int%d",
NON_RING_MSIX_BASE);
vec = ndev->iov.msix.vector;
ret = request_irq(vec, nps_core_int_isr, 0, qvec->name, qvec);
if (ret) {
dev_err(DEV(ndev), "irq failed for nitrox-core-int%d\n",
NON_RING_MSIX_BASE);
goto iov_irq_fail;
}
cpu = num_online_cpus();
irq_set_affinity_hint(vec, get_cpu_mask(cpu));
tasklet_init(&qvec->resp_tasklet, nps_core_int_tasklet,
(unsigned long)qvec);
qvec->valid = true;
return 0;
iov_irq_fail:
nitrox_sriov_unregister_interrupts(ndev);
return ret;
}

View File

@ -6,5 +6,7 @@
int nitrox_register_interrupts(struct nitrox_device *ndev); int nitrox_register_interrupts(struct nitrox_device *ndev);
void nitrox_unregister_interrupts(struct nitrox_device *ndev); void nitrox_unregister_interrupts(struct nitrox_device *ndev);
int nitrox_sriov_register_interupts(struct nitrox_device *ndev);
void nitrox_sriov_unregister_interrupts(struct nitrox_device *ndev);
#endif /* __NITROX_ISR_H */ #endif /* __NITROX_ISR_H */

View File

@ -7,6 +7,10 @@
#include "nitrox_common.h" #include "nitrox_common.h"
#include "nitrox_isr.h" #include "nitrox_isr.h"
/**
* num_vfs_valid - validate VF count
* @num_vfs: number of VF(s)
*/
static inline bool num_vfs_valid(int num_vfs) static inline bool num_vfs_valid(int num_vfs)
{ {
bool valid = false; bool valid = false;
@ -48,7 +52,7 @@ static inline enum vf_mode num_vfs_to_mode(int num_vfs)
return mode; return mode;
} }
static void pf_sriov_cleanup(struct nitrox_device *ndev) static void nitrox_pf_cleanup(struct nitrox_device *ndev)
{ {
/* PF has no queues in SR-IOV mode */ /* PF has no queues in SR-IOV mode */
atomic_set(&ndev->state, __NDEV_NOT_READY); atomic_set(&ndev->state, __NDEV_NOT_READY);
@ -60,7 +64,11 @@ static void pf_sriov_cleanup(struct nitrox_device *ndev)
nitrox_common_sw_cleanup(ndev); nitrox_common_sw_cleanup(ndev);
} }
static int pf_sriov_init(struct nitrox_device *ndev) /**
* nitrox_pf_reinit - re-initialize PF resources once SR-IOV is disabled
* @ndev: NITROX device
*/
static int nitrox_pf_reinit(struct nitrox_device *ndev)
{ {
int err; int err;
@ -86,6 +94,18 @@ static int pf_sriov_init(struct nitrox_device *ndev)
return nitrox_crypto_register(); return nitrox_crypto_register();
} }
static int nitrox_sriov_init(struct nitrox_device *ndev)
{
/* register interrupts for PF in SR-IOV */
return nitrox_sriov_register_interupts(ndev);
}
static void nitrox_sriov_cleanup(struct nitrox_device *ndev)
{
/* unregister interrupts for PF in SR-IOV */
nitrox_sriov_unregister_interrupts(ndev);
}
static int nitrox_sriov_enable(struct pci_dev *pdev, int num_vfs) static int nitrox_sriov_enable(struct pci_dev *pdev, int num_vfs)
{ {
struct nitrox_device *ndev = pci_get_drvdata(pdev); struct nitrox_device *ndev = pci_get_drvdata(pdev);
@ -106,17 +126,31 @@ static int nitrox_sriov_enable(struct pci_dev *pdev, int num_vfs)
} }
dev_info(DEV(ndev), "Enabled VF(s) %d\n", num_vfs); dev_info(DEV(ndev), "Enabled VF(s) %d\n", num_vfs);
ndev->num_vfs = num_vfs; ndev->iov.num_vfs = num_vfs;
ndev->mode = num_vfs_to_mode(num_vfs); ndev->mode = num_vfs_to_mode(num_vfs);
/* set bit in flags */ /* set bit in flags */
set_bit(__NDEV_SRIOV_BIT, &ndev->flags); set_bit(__NDEV_SRIOV_BIT, &ndev->flags);
/* cleanup PF resources */ /* cleanup PF resources */
pf_sriov_cleanup(ndev); nitrox_pf_cleanup(ndev);
/* PF SR-IOV mode initialization */
err = nitrox_sriov_init(ndev);
if (err)
goto iov_fail;
config_nps_core_vfcfg_mode(ndev, ndev->mode); config_nps_core_vfcfg_mode(ndev, ndev->mode);
return num_vfs; return num_vfs;
iov_fail:
pci_disable_sriov(pdev);
/* clear bit in flags */
clear_bit(__NDEV_SRIOV_BIT, &ndev->flags);
ndev->iov.num_vfs = 0;
ndev->mode = __NDEV_MODE_PF;
/* reset back to working mode in PF */
nitrox_pf_reinit(ndev);
return err;
} }
static int nitrox_sriov_disable(struct pci_dev *pdev) static int nitrox_sriov_disable(struct pci_dev *pdev)
@ -134,12 +168,15 @@ static int nitrox_sriov_disable(struct pci_dev *pdev)
/* clear bit in flags */ /* clear bit in flags */
clear_bit(__NDEV_SRIOV_BIT, &ndev->flags); clear_bit(__NDEV_SRIOV_BIT, &ndev->flags);
ndev->num_vfs = 0; ndev->iov.num_vfs = 0;
ndev->mode = __NDEV_MODE_PF; ndev->mode = __NDEV_MODE_PF;
/* cleanup PF SR-IOV resources */
nitrox_sriov_cleanup(ndev);
config_nps_core_vfcfg_mode(ndev, ndev->mode); config_nps_core_vfcfg_mode(ndev, ndev->mode);
return pf_sriov_init(ndev); return nitrox_pf_reinit(ndev);
} }
int nitrox_sriov_configure(struct pci_dev *pdev, int num_vfs) int nitrox_sriov_configure(struct pci_dev *pdev, int num_vfs)