crypto: cavium/nitrox - Enabled Mailbox support

Enabled the PF->VF Mailbox support. Mailbox message are interpreted
as {type, opcode, data}. Supported message types are REQ, ACK and NACK.

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-12-04 12:55:54 +00:00 committed by Herbert Xu
parent 19c11c97c3
commit cf718eaa8f
11 changed files with 441 additions and 54 deletions

View File

@ -6,7 +6,8 @@ n5pf-objs := nitrox_main.o \
nitrox_lib.o \
nitrox_hal.o \
nitrox_reqmgr.o \
nitrox_algs.o
nitrox_algs.o \
nitrox_mbx.o
n5pf-$(CONFIG_PCI_IOV) += nitrox_sriov.o
n5pf-$(CONFIG_DEBUG_FS) += nitrox_debugfs.o

View File

@ -54,7 +54,13 @@
#define NPS_STATS_PKT_DMA_WR_CNT 0x1000190
/* NPS packet registers */
#define NPS_PKT_INT 0x1040018
#define NPS_PKT_INT 0x1040018
#define NPS_PKT_MBOX_INT_LO 0x1040020
#define NPS_PKT_MBOX_INT_LO_ENA_W1C 0x1040030
#define NPS_PKT_MBOX_INT_LO_ENA_W1S 0x1040038
#define NPS_PKT_MBOX_INT_HI 0x1040040
#define NPS_PKT_MBOX_INT_HI_ENA_W1C 0x1040050
#define NPS_PKT_MBOX_INT_HI_ENA_W1S 0x1040058
#define NPS_PKT_IN_RERR_HI 0x1040108
#define NPS_PKT_IN_RERR_HI_ENA_W1S 0x1040120
#define NPS_PKT_IN_RERR_LO 0x1040128
@ -74,6 +80,10 @@
#define NPS_PKT_SLC_RERR_LO_ENA_W1S 0x1040240
#define NPS_PKT_SLC_ERR_TYPE 0x1040248
#define NPS_PKT_SLC_ERR_TYPE_ENA_W1S 0x1040260
/* Mailbox PF->VF PF Accessible Data registers */
#define NPS_PKT_MBOX_PF_VF_PFDATAX(_i) (0x1040800 + ((_i) * 0x8))
#define NPS_PKT_MBOX_VF_PF_PFDATAX(_i) (0x1040C00 + ((_i) * 0x8))
#define NPS_PKT_SLC_CTLX(_i) (0x10000 + ((_i) * 0x40000))
#define NPS_PKT_SLC_CNTSX(_i) (0x10008 + ((_i) * 0x40000))
#define NPS_PKT_SLC_INT_LEVELSX(_i) (0x10010 + ((_i) * 0x40000))

View File

@ -0,0 +1,22 @@
// SPDX-License-Identifier: GPL-2.0
#ifndef __NITROX_DEBUGFS_H
#define __NITROX_DEBUGFS_H
#include "nitrox_dev.h"
#ifdef CONFIG_DEBUG_FS
int nitrox_debugfs_init(struct nitrox_device *ndev);
void nitrox_debugfs_exit(struct nitrox_device *ndev);
#else
static inline int nitrox_debugfs_init(struct nitrox_device *ndev)
{
return 0;
}
static inline int nitrox_sriov_debugfs_init(struct nitrox_device *ndev)
{
return 0;
}
#endif /* !CONFIG_DEBUG_FS */
#endif /* __NITROX_DEBUGFS_H */

View File

@ -8,6 +8,8 @@
#include <linux/if.h>
#define VERSION_LEN 32
/* Maximum queues in PF mode */
#define MAX_PF_QUEUES 64
/**
* struct nitrox_cmdq - NITROX command queue
@ -103,13 +105,58 @@ struct nitrox_q_vector {
};
};
/**
* mbox_msg - Mailbox message data
* @type: message type
* @opcode: message opcode
* @data: message data
*/
union mbox_msg {
u64 value;
struct {
u64 type: 2;
u64 opcode: 6;
u64 data: 58;
};
struct {
u64 type: 2;
u64 opcode: 6;
u64 chipid: 8;
u64 vfid: 8;
} id;
};
/**
* nitrox_vfdev - NITROX VF device instance in PF
* @state: VF device state
* @vfno: VF number
* @nr_queues: number of queues enabled in VF
* @ring: ring to communicate with VF
* @msg: Mailbox message data from VF
* @mbx_resp: Mailbox counters
*/
struct nitrox_vfdev {
atomic_t state;
int vfno;
int nr_queues;
int ring;
union mbox_msg msg;
atomic64_t mbx_resp;
};
/**
* struct nitrox_iov - SR-IOV information
* @num_vfs: number of VF(s) enabled
* @msix: MSI-X for PF in SR-IOV case
* @max_vf_queues: Maximum number of queues allowed for VF
* @vfdev: VF(s) devices
* @pf2vf_wq: workqueue for PF2VF communication
* @msix: MSI-X entry for PF in SR-IOV case
*/
struct nitrox_iov {
int num_vfs;
int max_vf_queues;
struct nitrox_vfdev *vfdev;
struct workqueue_struct *pf2vf_wq;
struct msix_entry msix;
};
@ -226,17 +273,9 @@ static inline bool nitrox_ready(struct nitrox_device *ndev)
return atomic_read(&ndev->state) == __NDEV_READY;
}
#ifdef CONFIG_DEBUG_FS
int nitrox_debugfs_init(struct nitrox_device *ndev);
void nitrox_debugfs_exit(struct nitrox_device *ndev);
#else
static inline int nitrox_debugfs_init(struct nitrox_device *ndev)
static inline bool nitrox_vfdev_ready(struct nitrox_vfdev *vfdev)
{
return 0;
return atomic_read(&vfdev->state) == __NDEV_READY;
}
static inline void nitrox_debugfs_exit(struct nitrox_device *ndev)
{ }
#endif
#endif /* __NITROX_DEV_H */

View File

@ -5,10 +5,11 @@
#include "nitrox_csr.h"
#define PLL_REF_CLK 50
#define MAX_CSR_RETRIES 10
/**
* emu_enable_cores - Enable EMU cluster cores.
* @ndev: N5 device
* @ndev: NITROX device
*/
static void emu_enable_cores(struct nitrox_device *ndev)
{
@ -33,7 +34,7 @@ static void emu_enable_cores(struct nitrox_device *ndev)
/**
* nitrox_config_emu_unit - configure EMU unit.
* @ndev: N5 device
* @ndev: NITROX device
*/
void nitrox_config_emu_unit(struct nitrox_device *ndev)
{
@ -63,29 +64,26 @@ void nitrox_config_emu_unit(struct nitrox_device *ndev)
static void reset_pkt_input_ring(struct nitrox_device *ndev, int ring)
{
union nps_pkt_in_instr_ctl pkt_in_ctl;
union nps_pkt_in_instr_baoff_dbell pkt_in_dbell;
union nps_pkt_in_done_cnts pkt_in_cnts;
int max_retries = MAX_CSR_RETRIES;
u64 offset;
/* step 1: disable the ring, clear enable bit */
offset = NPS_PKT_IN_INSTR_CTLX(ring);
/* disable the ring */
pkt_in_ctl.value = nitrox_read_csr(ndev, offset);
pkt_in_ctl.s.enb = 0;
nitrox_write_csr(ndev, offset, pkt_in_ctl.value);
usleep_range(100, 150);
/* wait to clear [ENB] */
/* step 2: wait to clear [ENB] */
usleep_range(100, 150);
do {
pkt_in_ctl.value = nitrox_read_csr(ndev, offset);
} while (pkt_in_ctl.s.enb);
if (!pkt_in_ctl.s.enb)
break;
udelay(50);
} while (max_retries--);
/* clear off door bell counts */
offset = NPS_PKT_IN_INSTR_BAOFF_DBELLX(ring);
pkt_in_dbell.value = 0;
pkt_in_dbell.s.dbell = 0xffffffff;
nitrox_write_csr(ndev, offset, pkt_in_dbell.value);
/* clear done counts */
/* step 3: clear done counts */
offset = NPS_PKT_IN_DONE_CNTSX(ring);
pkt_in_cnts.value = nitrox_read_csr(ndev, offset);
nitrox_write_csr(ndev, offset, pkt_in_cnts.value);
@ -95,6 +93,7 @@ static void reset_pkt_input_ring(struct nitrox_device *ndev, int ring)
void enable_pkt_input_ring(struct nitrox_device *ndev, int ring)
{
union nps_pkt_in_instr_ctl pkt_in_ctl;
int max_retries = MAX_CSR_RETRIES;
u64 offset;
/* 64-byte instruction size */
@ -107,12 +106,15 @@ void enable_pkt_input_ring(struct nitrox_device *ndev, int ring)
/* wait for set [ENB] */
do {
pkt_in_ctl.value = nitrox_read_csr(ndev, offset);
} while (!pkt_in_ctl.s.enb);
if (pkt_in_ctl.s.enb)
break;
udelay(50);
} while (max_retries--);
}
/**
* nitrox_config_pkt_input_rings - configure Packet Input Rings
* @ndev: N5 device
* @ndev: NITROX device
*/
void nitrox_config_pkt_input_rings(struct nitrox_device *ndev)
{
@ -121,11 +123,14 @@ void nitrox_config_pkt_input_rings(struct nitrox_device *ndev)
for (i = 0; i < ndev->nr_queues; i++) {
struct nitrox_cmdq *cmdq = &ndev->pkt_inq[i];
union nps_pkt_in_instr_rsize pkt_in_rsize;
union nps_pkt_in_instr_baoff_dbell pkt_in_dbell;
u64 offset;
reset_pkt_input_ring(ndev, i);
/* configure ring base address 16-byte aligned,
/**
* step 4:
* configure ring base address 16-byte aligned,
* size and interrupt threshold.
*/
offset = NPS_PKT_IN_INSTR_BADDRX(i);
@ -141,6 +146,13 @@ void nitrox_config_pkt_input_rings(struct nitrox_device *ndev)
offset = NPS_PKT_IN_INT_LEVELSX(i);
nitrox_write_csr(ndev, offset, 0xffffffff);
/* step 5: clear off door bell counts */
offset = NPS_PKT_IN_INSTR_BAOFF_DBELLX(i);
pkt_in_dbell.value = 0;
pkt_in_dbell.s.dbell = 0xffffffff;
nitrox_write_csr(ndev, offset, pkt_in_dbell.value);
/* enable the ring */
enable_pkt_input_ring(ndev, i);
}
}
@ -149,21 +161,26 @@ static void reset_pkt_solicit_port(struct nitrox_device *ndev, int port)
{
union nps_pkt_slc_ctl pkt_slc_ctl;
union nps_pkt_slc_cnts pkt_slc_cnts;
int max_retries = MAX_CSR_RETRIES;
u64 offset;
/* disable slc port */
/* step 1: disable slc port */
offset = NPS_PKT_SLC_CTLX(port);
pkt_slc_ctl.value = nitrox_read_csr(ndev, offset);
pkt_slc_ctl.s.enb = 0;
nitrox_write_csr(ndev, offset, pkt_slc_ctl.value);
usleep_range(100, 150);
/* step 2 */
usleep_range(100, 150);
/* wait to clear [ENB] */
do {
pkt_slc_ctl.value = nitrox_read_csr(ndev, offset);
} while (pkt_slc_ctl.s.enb);
if (!pkt_slc_ctl.s.enb)
break;
udelay(50);
} while (max_retries--);
/* clear slc counters */
/* step 3: clear slc counters */
offset = NPS_PKT_SLC_CNTSX(port);
pkt_slc_cnts.value = nitrox_read_csr(ndev, offset);
nitrox_write_csr(ndev, offset, pkt_slc_cnts.value);
@ -173,12 +190,12 @@ static void reset_pkt_solicit_port(struct nitrox_device *ndev, int port)
void enable_pkt_solicit_port(struct nitrox_device *ndev, int port)
{
union nps_pkt_slc_ctl pkt_slc_ctl;
int max_retries = MAX_CSR_RETRIES;
u64 offset;
offset = NPS_PKT_SLC_CTLX(port);
pkt_slc_ctl.value = 0;
pkt_slc_ctl.s.enb = 1;
/*
* 8 trailing 0x00 bytes will be added
* to the end of the outgoing packet.
@ -191,23 +208,27 @@ void enable_pkt_solicit_port(struct nitrox_device *ndev, int port)
/* wait to set [ENB] */
do {
pkt_slc_ctl.value = nitrox_read_csr(ndev, offset);
} while (!pkt_slc_ctl.s.enb);
if (pkt_slc_ctl.s.enb)
break;
udelay(50);
} while (max_retries--);
}
static void config_single_pkt_solicit_port(struct nitrox_device *ndev,
int port)
static void config_pkt_solicit_port(struct nitrox_device *ndev, int port)
{
union nps_pkt_slc_int_levels pkt_slc_int;
u64 offset;
reset_pkt_solicit_port(ndev, port);
/* step 4: configure interrupt levels */
offset = NPS_PKT_SLC_INT_LEVELSX(port);
pkt_slc_int.value = 0;
/* time interrupt threshold */
pkt_slc_int.s.timet = 0x3fffff;
nitrox_write_csr(ndev, offset, pkt_slc_int.value);
/* enable the solicit port */
enable_pkt_solicit_port(ndev, port);
}
@ -216,12 +237,12 @@ void nitrox_config_pkt_solicit_ports(struct nitrox_device *ndev)
int i;
for (i = 0; i < ndev->nr_queues; i++)
config_single_pkt_solicit_port(ndev, i);
config_pkt_solicit_port(ndev, i);
}
/**
* enable_nps_interrupts - enable NPS interrutps
* @ndev: N5 device.
* @ndev: NITROX device.
*
* This includes NPS core, packet in and slc interrupts.
*/
@ -284,8 +305,8 @@ void nitrox_config_pom_unit(struct nitrox_device *ndev)
}
/**
* nitrox_config_rand_unit - enable N5 random number unit
* @ndev: N5 device
* nitrox_config_rand_unit - enable NITROX random number unit
* @ndev: NITROX device
*/
void nitrox_config_rand_unit(struct nitrox_device *ndev)
{
@ -361,6 +382,7 @@ void invalidate_lbc(struct nitrox_device *ndev)
{
union lbc_inval_ctl lbc_ctl;
union lbc_inval_status lbc_stat;
int max_retries = MAX_CSR_RETRIES;
u64 offset;
/* invalidate LBC */
@ -370,10 +392,12 @@ void invalidate_lbc(struct nitrox_device *ndev)
nitrox_write_csr(ndev, offset, lbc_ctl.value);
offset = LBC_INVAL_STATUS;
do {
lbc_stat.value = nitrox_read_csr(ndev, offset);
} while (!lbc_stat.s.done);
if (lbc_stat.s.done)
break;
udelay(50);
} while (max_retries--);
}
void nitrox_config_lbc_unit(struct nitrox_device *ndev)
@ -467,3 +491,31 @@ void nitrox_get_hwinfo(struct nitrox_device *ndev)
/* copy partname */
strncpy(ndev->hw.partname, name, sizeof(ndev->hw.partname));
}
void enable_pf2vf_mbox_interrupts(struct nitrox_device *ndev)
{
u64 value = ~0ULL;
u64 reg_addr;
/* Mailbox interrupt low enable set register */
reg_addr = NPS_PKT_MBOX_INT_LO_ENA_W1S;
nitrox_write_csr(ndev, reg_addr, value);
/* Mailbox interrupt high enable set register */
reg_addr = NPS_PKT_MBOX_INT_HI_ENA_W1S;
nitrox_write_csr(ndev, reg_addr, value);
}
void disable_pf2vf_mbox_interrupts(struct nitrox_device *ndev)
{
u64 value = ~0ULL;
u64 reg_addr;
/* Mailbox interrupt low enable clear register */
reg_addr = NPS_PKT_MBOX_INT_LO_ENA_W1C;
nitrox_write_csr(ndev, reg_addr, value);
/* Mailbox interrupt high enable clear register */
reg_addr = NPS_PKT_MBOX_INT_HI_ENA_W1C;
nitrox_write_csr(ndev, reg_addr, value);
}

View File

@ -19,5 +19,7 @@ void enable_pkt_input_ring(struct nitrox_device *ndev, int ring);
void enable_pkt_solicit_port(struct nitrox_device *ndev, int port);
void config_nps_core_vfcfg_mode(struct nitrox_device *ndev, enum vf_mode mode);
void nitrox_get_hwinfo(struct nitrox_device *ndev);
void enable_pf2vf_mbox_interrupts(struct nitrox_device *ndev);
void disable_pf2vf_mbox_interrupts(struct nitrox_device *ndev);
#endif /* __NITROX_HAL_H */

View File

@ -7,6 +7,7 @@
#include "nitrox_csr.h"
#include "nitrox_common.h"
#include "nitrox_hal.h"
#include "nitrox_mbx.h"
/**
* One vector for each type of ring
@ -220,7 +221,8 @@ static void nps_core_int_tasklet(unsigned long data)
*/
static irqreturn_t nps_core_int_isr(int irq, void *data)
{
struct nitrox_device *ndev = data;
struct nitrox_q_vector *qvec = data;
struct nitrox_device *ndev = qvec->ndev;
union nps_core_int_active core_int;
core_int.value = nitrox_read_csr(ndev, NPS_CORE_INT_ACTIVE);
@ -246,6 +248,10 @@ static irqreturn_t nps_core_int_isr(int irq, void *data)
if (core_int.s.bmi)
clear_bmi_err_intr(ndev);
/* Mailbox interrupt */
if (core_int.s.mbox)
nitrox_pf2vf_mbox_handler(ndev);
/* If more work callback the ISR, set resend */
core_int.s.resend = 1;
nitrox_write_csr(ndev, NPS_CORE_INT_ACTIVE, core_int.value);

View File

@ -1,6 +1,5 @@
#include <linux/aer.h>
#include <linux/delay.h>
#include <linux/debugfs.h>
#include <linux/firmware.h>
#include <linux/list.h>
#include <linux/module.h>
@ -13,9 +12,9 @@
#include "nitrox_csr.h"
#include "nitrox_hal.h"
#include "nitrox_isr.h"
#include "nitrox_debugfs.h"
#define CNN55XX_DEV_ID 0x12
#define MAX_PF_QUEUES 64
#define UCODE_HLEN 48
#define SE_GROUP 0

View File

@ -0,0 +1,204 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/workqueue.h>
#include "nitrox_csr.h"
#include "nitrox_hal.h"
#include "nitrox_dev.h"
#define RING_TO_VFNO(_x, _y) ((_x) / (_y))
/**
* mbx_msg_type - Mailbox message types
*/
enum mbx_msg_type {
MBX_MSG_TYPE_NOP,
MBX_MSG_TYPE_REQ,
MBX_MSG_TYPE_ACK,
MBX_MSG_TYPE_NACK,
};
/**
* mbx_msg_opcode - Mailbox message opcodes
*/
enum mbx_msg_opcode {
MSG_OP_VF_MODE = 1,
MSG_OP_VF_UP,
MSG_OP_VF_DOWN,
MSG_OP_CHIPID_VFID,
};
struct pf2vf_work {
struct nitrox_vfdev *vfdev;
struct nitrox_device *ndev;
struct work_struct pf2vf_resp;
};
static inline u64 pf2vf_read_mbox(struct nitrox_device *ndev, int ring)
{
u64 reg_addr;
reg_addr = NPS_PKT_MBOX_VF_PF_PFDATAX(ring);
return nitrox_read_csr(ndev, reg_addr);
}
static inline void pf2vf_write_mbox(struct nitrox_device *ndev, u64 value,
int ring)
{
u64 reg_addr;
reg_addr = NPS_PKT_MBOX_PF_VF_PFDATAX(ring);
nitrox_write_csr(ndev, reg_addr, value);
}
static void pf2vf_send_response(struct nitrox_device *ndev,
struct nitrox_vfdev *vfdev)
{
union mbox_msg msg;
msg.value = vfdev->msg.value;
switch (vfdev->msg.opcode) {
case MSG_OP_VF_MODE:
msg.data = ndev->mode;
break;
case MSG_OP_VF_UP:
vfdev->nr_queues = vfdev->msg.data;
atomic_set(&vfdev->state, __NDEV_READY);
break;
case MSG_OP_CHIPID_VFID:
msg.id.chipid = ndev->idx;
msg.id.vfid = vfdev->vfno;
break;
case MSG_OP_VF_DOWN:
vfdev->nr_queues = 0;
atomic_set(&vfdev->state, __NDEV_NOT_READY);
break;
default:
msg.type = MBX_MSG_TYPE_NOP;
break;
}
if (msg.type == MBX_MSG_TYPE_NOP)
return;
/* send ACK to VF */
msg.type = MBX_MSG_TYPE_ACK;
pf2vf_write_mbox(ndev, msg.value, vfdev->ring);
vfdev->msg.value = 0;
atomic64_inc(&vfdev->mbx_resp);
}
static void pf2vf_resp_handler(struct work_struct *work)
{
struct pf2vf_work *pf2vf_resp = container_of(work, struct pf2vf_work,
pf2vf_resp);
struct nitrox_vfdev *vfdev = pf2vf_resp->vfdev;
struct nitrox_device *ndev = pf2vf_resp->ndev;
switch (vfdev->msg.type) {
case MBX_MSG_TYPE_REQ:
/* process the request from VF */
pf2vf_send_response(ndev, vfdev);
break;
case MBX_MSG_TYPE_ACK:
case MBX_MSG_TYPE_NACK:
break;
};
kfree(pf2vf_resp);
}
void nitrox_pf2vf_mbox_handler(struct nitrox_device *ndev)
{
struct nitrox_vfdev *vfdev;
struct pf2vf_work *pfwork;
u64 value, reg_addr;
u32 i;
int vfno;
/* loop for VF(0..63) */
reg_addr = NPS_PKT_MBOX_INT_LO;
value = nitrox_read_csr(ndev, reg_addr);
for_each_set_bit(i, (const unsigned long *)&value, BITS_PER_LONG) {
/* get the vfno from ring */
vfno = RING_TO_VFNO(i, ndev->iov.max_vf_queues);
vfdev = ndev->iov.vfdev + vfno;
vfdev->ring = i;
/* fill the vf mailbox data */
vfdev->msg.value = pf2vf_read_mbox(ndev, vfdev->ring);
pfwork = kzalloc(sizeof(*pfwork), GFP_ATOMIC);
if (!pfwork)
continue;
pfwork->vfdev = vfdev;
pfwork->ndev = ndev;
INIT_WORK(&pfwork->pf2vf_resp, pf2vf_resp_handler);
queue_work(ndev->iov.pf2vf_wq, &pfwork->pf2vf_resp);
/* clear the corresponding vf bit */
nitrox_write_csr(ndev, reg_addr, BIT_ULL(i));
}
/* loop for VF(64..127) */
reg_addr = NPS_PKT_MBOX_INT_HI;
value = nitrox_read_csr(ndev, reg_addr);
for_each_set_bit(i, (const unsigned long *)&value, BITS_PER_LONG) {
/* get the vfno from ring */
vfno = RING_TO_VFNO(i + 64, ndev->iov.max_vf_queues);
vfdev = ndev->iov.vfdev + vfno;
vfdev->ring = (i + 64);
/* fill the vf mailbox data */
vfdev->msg.value = pf2vf_read_mbox(ndev, vfdev->ring);
pfwork = kzalloc(sizeof(*pfwork), GFP_ATOMIC);
if (!pfwork)
continue;
pfwork->vfdev = vfdev;
pfwork->ndev = ndev;
INIT_WORK(&pfwork->pf2vf_resp, pf2vf_resp_handler);
queue_work(ndev->iov.pf2vf_wq, &pfwork->pf2vf_resp);
/* clear the corresponding vf bit */
nitrox_write_csr(ndev, reg_addr, BIT_ULL(i));
}
}
int nitrox_mbox_init(struct nitrox_device *ndev)
{
struct nitrox_vfdev *vfdev;
int i;
ndev->iov.vfdev = kcalloc(ndev->iov.num_vfs,
sizeof(struct nitrox_vfdev), GFP_KERNEL);
if (!ndev->iov.vfdev)
return -ENOMEM;
for (i = 0; i < ndev->iov.num_vfs; i++) {
vfdev = ndev->iov.vfdev + i;
vfdev->vfno = i;
}
/* allocate pf2vf response workqueue */
ndev->iov.pf2vf_wq = alloc_workqueue("nitrox_pf2vf", 0, 0);
if (!ndev->iov.pf2vf_wq) {
kfree(ndev->iov.vfdev);
return -ENOMEM;
}
/* enable pf2vf mailbox interrupts */
enable_pf2vf_mbox_interrupts(ndev);
return 0;
}
void nitrox_mbox_cleanup(struct nitrox_device *ndev)
{
/* disable pf2vf mailbox interrupts */
disable_pf2vf_mbox_interrupts(ndev);
/* destroy workqueue */
if (ndev->iov.pf2vf_wq)
destroy_workqueue(ndev->iov.pf2vf_wq);
kfree(ndev->iov.vfdev);
ndev->iov.pf2vf_wq = NULL;
ndev->iov.vfdev = NULL;
}

View File

@ -0,0 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
#ifndef __NITROX_MBX_H
#define __NITROX_MBX_H
int nitrox_mbox_init(struct nitrox_device *ndev);
void nitrox_mbox_cleanup(struct nitrox_device *ndev);
void nitrox_pf2vf_mbox_handler(struct nitrox_device *ndev);
#endif /* __NITROX_MBX_H */

View File

@ -6,6 +6,7 @@
#include "nitrox_hal.h"
#include "nitrox_common.h"
#include "nitrox_isr.h"
#include "nitrox_mbx.h"
/**
* num_vfs_valid - validate VF count
@ -52,6 +53,31 @@ static inline enum vf_mode num_vfs_to_mode(int num_vfs)
return mode;
}
static inline int vf_mode_to_nr_queues(enum vf_mode mode)
{
int nr_queues = 0;
switch (mode) {
case __NDEV_MODE_PF:
nr_queues = MAX_PF_QUEUES;
break;
case __NDEV_MODE_VF16:
nr_queues = 8;
break;
case __NDEV_MODE_VF32:
nr_queues = 4;
break;
case __NDEV_MODE_VF64:
nr_queues = 2;
break;
case __NDEV_MODE_VF128:
nr_queues = 1;
break;
}
return nr_queues;
}
static void nitrox_pf_cleanup(struct nitrox_device *ndev)
{
/* PF has no queues in SR-IOV mode */
@ -94,16 +120,31 @@ static int nitrox_pf_reinit(struct nitrox_device *ndev)
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);
nitrox_mbox_cleanup(ndev);
}
static int nitrox_sriov_init(struct nitrox_device *ndev)
{
int ret;
/* register interrupts for PF in SR-IOV */
ret = nitrox_sriov_register_interupts(ndev);
if (ret)
return ret;
ret = nitrox_mbox_init(ndev);
if (ret)
goto sriov_init_fail;
return 0;
sriov_init_fail:
nitrox_sriov_cleanup(ndev);
return ret;
}
static int nitrox_sriov_enable(struct pci_dev *pdev, int num_vfs)
@ -126,8 +167,9 @@ static int nitrox_sriov_enable(struct pci_dev *pdev, int num_vfs)
}
dev_info(DEV(ndev), "Enabled VF(s) %d\n", num_vfs);
ndev->iov.num_vfs = num_vfs;
ndev->mode = num_vfs_to_mode(num_vfs);
ndev->iov.num_vfs = num_vfs;
ndev->iov.max_vf_queues = vf_mode_to_nr_queues(ndev->mode);
/* set bit in flags */
set_bit(__NDEV_SRIOV_BIT, &ndev->flags);
@ -169,6 +211,7 @@ static int nitrox_sriov_disable(struct pci_dev *pdev)
clear_bit(__NDEV_SRIOV_BIT, &ndev->flags);
ndev->iov.num_vfs = 0;
ndev->iov.max_vf_queues = 0;
ndev->mode = __NDEV_MODE_PF;
/* cleanup PF SR-IOV resources */