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:
Родитель
19c11c97c3
Коммит
cf718eaa8f
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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 */
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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 */
|
||||
|
|
Загрузка…
Ссылка в новой задаче