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 коммит произвёл Herbert Xu
Родитель 19c11c97c3
Коммит cf718eaa8f
11 изменённых файлов: 441 добавлений и 54 удалений

Просмотреть файл

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

Просмотреть файл

@ -54,7 +54,13 @@
#define NPS_STATS_PKT_DMA_WR_CNT 0x1000190 #define NPS_STATS_PKT_DMA_WR_CNT 0x1000190
/* NPS packet registers */ /* 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 0x1040108
#define NPS_PKT_IN_RERR_HI_ENA_W1S 0x1040120 #define NPS_PKT_IN_RERR_HI_ENA_W1S 0x1040120
#define NPS_PKT_IN_RERR_LO 0x1040128 #define NPS_PKT_IN_RERR_LO 0x1040128
@ -74,6 +80,10 @@
#define NPS_PKT_SLC_RERR_LO_ENA_W1S 0x1040240 #define NPS_PKT_SLC_RERR_LO_ENA_W1S 0x1040240
#define NPS_PKT_SLC_ERR_TYPE 0x1040248 #define NPS_PKT_SLC_ERR_TYPE 0x1040248
#define NPS_PKT_SLC_ERR_TYPE_ENA_W1S 0x1040260 #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_CTLX(_i) (0x10000 + ((_i) * 0x40000))
#define NPS_PKT_SLC_CNTSX(_i) (0x10008 + ((_i) * 0x40000)) #define NPS_PKT_SLC_CNTSX(_i) (0x10008 + ((_i) * 0x40000))
#define NPS_PKT_SLC_INT_LEVELSX(_i) (0x10010 + ((_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> #include <linux/if.h>
#define VERSION_LEN 32 #define VERSION_LEN 32
/* Maximum queues in PF mode */
#define MAX_PF_QUEUES 64
/** /**
* struct nitrox_cmdq - NITROX command queue * 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 * struct nitrox_iov - SR-IOV information
* @num_vfs: number of VF(s) enabled * @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 { struct nitrox_iov {
int num_vfs; int num_vfs;
int max_vf_queues;
struct nitrox_vfdev *vfdev;
struct workqueue_struct *pf2vf_wq;
struct msix_entry msix; struct msix_entry msix;
}; };
@ -226,17 +273,9 @@ static inline bool nitrox_ready(struct nitrox_device *ndev)
return atomic_read(&ndev->state) == __NDEV_READY; return atomic_read(&ndev->state) == __NDEV_READY;
} }
#ifdef CONFIG_DEBUG_FS static inline bool nitrox_vfdev_ready(struct nitrox_vfdev *vfdev)
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; return atomic_read(&vfdev->state) == __NDEV_READY;
} }
static inline void nitrox_debugfs_exit(struct nitrox_device *ndev)
{ }
#endif
#endif /* __NITROX_DEV_H */ #endif /* __NITROX_DEV_H */

Просмотреть файл

@ -5,10 +5,11 @@
#include "nitrox_csr.h" #include "nitrox_csr.h"
#define PLL_REF_CLK 50 #define PLL_REF_CLK 50
#define MAX_CSR_RETRIES 10
/** /**
* emu_enable_cores - Enable EMU cluster cores. * emu_enable_cores - Enable EMU cluster cores.
* @ndev: N5 device * @ndev: NITROX device
*/ */
static void emu_enable_cores(struct nitrox_device *ndev) 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. * nitrox_config_emu_unit - configure EMU unit.
* @ndev: N5 device * @ndev: NITROX device
*/ */
void nitrox_config_emu_unit(struct nitrox_device *ndev) 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) 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_ctl pkt_in_ctl;
union nps_pkt_in_instr_baoff_dbell pkt_in_dbell;
union nps_pkt_in_done_cnts pkt_in_cnts; union nps_pkt_in_done_cnts pkt_in_cnts;
int max_retries = MAX_CSR_RETRIES;
u64 offset; u64 offset;
/* step 1: disable the ring, clear enable bit */
offset = NPS_PKT_IN_INSTR_CTLX(ring); offset = NPS_PKT_IN_INSTR_CTLX(ring);
/* disable the ring */
pkt_in_ctl.value = nitrox_read_csr(ndev, offset); pkt_in_ctl.value = nitrox_read_csr(ndev, offset);
pkt_in_ctl.s.enb = 0; pkt_in_ctl.s.enb = 0;
nitrox_write_csr(ndev, offset, pkt_in_ctl.value); 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 { do {
pkt_in_ctl.value = nitrox_read_csr(ndev, offset); 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 */ /* step 3: clear done 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 */
offset = NPS_PKT_IN_DONE_CNTSX(ring); offset = NPS_PKT_IN_DONE_CNTSX(ring);
pkt_in_cnts.value = nitrox_read_csr(ndev, offset); pkt_in_cnts.value = nitrox_read_csr(ndev, offset);
nitrox_write_csr(ndev, offset, pkt_in_cnts.value); 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) void enable_pkt_input_ring(struct nitrox_device *ndev, int ring)
{ {
union nps_pkt_in_instr_ctl pkt_in_ctl; union nps_pkt_in_instr_ctl pkt_in_ctl;
int max_retries = MAX_CSR_RETRIES;
u64 offset; u64 offset;
/* 64-byte instruction size */ /* 64-byte instruction size */
@ -107,12 +106,15 @@ void enable_pkt_input_ring(struct nitrox_device *ndev, int ring)
/* wait for set [ENB] */ /* wait for set [ENB] */
do { do {
pkt_in_ctl.value = nitrox_read_csr(ndev, offset); 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 * 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) 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++) { for (i = 0; i < ndev->nr_queues; i++) {
struct nitrox_cmdq *cmdq = &ndev->pkt_inq[i]; struct nitrox_cmdq *cmdq = &ndev->pkt_inq[i];
union nps_pkt_in_instr_rsize pkt_in_rsize; union nps_pkt_in_instr_rsize pkt_in_rsize;
union nps_pkt_in_instr_baoff_dbell pkt_in_dbell;
u64 offset; u64 offset;
reset_pkt_input_ring(ndev, i); 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. * size and interrupt threshold.
*/ */
offset = NPS_PKT_IN_INSTR_BADDRX(i); 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); offset = NPS_PKT_IN_INT_LEVELSX(i);
nitrox_write_csr(ndev, offset, 0xffffffff); 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); 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_ctl pkt_slc_ctl;
union nps_pkt_slc_cnts pkt_slc_cnts; union nps_pkt_slc_cnts pkt_slc_cnts;
int max_retries = MAX_CSR_RETRIES;
u64 offset; u64 offset;
/* disable slc port */ /* step 1: disable slc port */
offset = NPS_PKT_SLC_CTLX(port); offset = NPS_PKT_SLC_CTLX(port);
pkt_slc_ctl.value = nitrox_read_csr(ndev, offset); pkt_slc_ctl.value = nitrox_read_csr(ndev, offset);
pkt_slc_ctl.s.enb = 0; pkt_slc_ctl.s.enb = 0;
nitrox_write_csr(ndev, offset, pkt_slc_ctl.value); nitrox_write_csr(ndev, offset, pkt_slc_ctl.value);
usleep_range(100, 150);
/* step 2 */
usleep_range(100, 150);
/* wait to clear [ENB] */ /* wait to clear [ENB] */
do { do {
pkt_slc_ctl.value = nitrox_read_csr(ndev, offset); 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); offset = NPS_PKT_SLC_CNTSX(port);
pkt_slc_cnts.value = nitrox_read_csr(ndev, offset); pkt_slc_cnts.value = nitrox_read_csr(ndev, offset);
nitrox_write_csr(ndev, offset, pkt_slc_cnts.value); 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) void enable_pkt_solicit_port(struct nitrox_device *ndev, int port)
{ {
union nps_pkt_slc_ctl pkt_slc_ctl; union nps_pkt_slc_ctl pkt_slc_ctl;
int max_retries = MAX_CSR_RETRIES;
u64 offset; u64 offset;
offset = NPS_PKT_SLC_CTLX(port); offset = NPS_PKT_SLC_CTLX(port);
pkt_slc_ctl.value = 0; pkt_slc_ctl.value = 0;
pkt_slc_ctl.s.enb = 1; pkt_slc_ctl.s.enb = 1;
/* /*
* 8 trailing 0x00 bytes will be added * 8 trailing 0x00 bytes will be added
* to the end of the outgoing packet. * 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] */ /* wait to set [ENB] */
do { do {
pkt_slc_ctl.value = nitrox_read_csr(ndev, offset); 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, static void config_pkt_solicit_port(struct nitrox_device *ndev, int port)
int port)
{ {
union nps_pkt_slc_int_levels pkt_slc_int; union nps_pkt_slc_int_levels pkt_slc_int;
u64 offset; u64 offset;
reset_pkt_solicit_port(ndev, port); reset_pkt_solicit_port(ndev, port);
/* step 4: configure interrupt levels */
offset = NPS_PKT_SLC_INT_LEVELSX(port); offset = NPS_PKT_SLC_INT_LEVELSX(port);
pkt_slc_int.value = 0; pkt_slc_int.value = 0;
/* time interrupt threshold */ /* time interrupt threshold */
pkt_slc_int.s.timet = 0x3fffff; pkt_slc_int.s.timet = 0x3fffff;
nitrox_write_csr(ndev, offset, pkt_slc_int.value); nitrox_write_csr(ndev, offset, pkt_slc_int.value);
/* enable the solicit port */
enable_pkt_solicit_port(ndev, port); enable_pkt_solicit_port(ndev, port);
} }
@ -216,12 +237,12 @@ void nitrox_config_pkt_solicit_ports(struct nitrox_device *ndev)
int i; int i;
for (i = 0; i < ndev->nr_queues; 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 * enable_nps_interrupts - enable NPS interrutps
* @ndev: N5 device. * @ndev: NITROX device.
* *
* This includes NPS core, packet in and slc interrupts. * 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 * nitrox_config_rand_unit - enable NITROX random number unit
* @ndev: N5 device * @ndev: NITROX device
*/ */
void nitrox_config_rand_unit(struct nitrox_device *ndev) 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_ctl lbc_ctl;
union lbc_inval_status lbc_stat; union lbc_inval_status lbc_stat;
int max_retries = MAX_CSR_RETRIES;
u64 offset; u64 offset;
/* invalidate LBC */ /* invalidate LBC */
@ -370,10 +392,12 @@ void invalidate_lbc(struct nitrox_device *ndev)
nitrox_write_csr(ndev, offset, lbc_ctl.value); nitrox_write_csr(ndev, offset, lbc_ctl.value);
offset = LBC_INVAL_STATUS; offset = LBC_INVAL_STATUS;
do { do {
lbc_stat.value = nitrox_read_csr(ndev, offset); 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) void nitrox_config_lbc_unit(struct nitrox_device *ndev)
@ -467,3 +491,31 @@ void nitrox_get_hwinfo(struct nitrox_device *ndev)
/* copy partname */ /* copy partname */
strncpy(ndev->hw.partname, name, sizeof(ndev->hw.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 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 config_nps_core_vfcfg_mode(struct nitrox_device *ndev, enum vf_mode mode);
void nitrox_get_hwinfo(struct nitrox_device *ndev); 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 */ #endif /* __NITROX_HAL_H */

Просмотреть файл

@ -7,6 +7,7 @@
#include "nitrox_csr.h" #include "nitrox_csr.h"
#include "nitrox_common.h" #include "nitrox_common.h"
#include "nitrox_hal.h" #include "nitrox_hal.h"
#include "nitrox_mbx.h"
/** /**
* One vector for each type of ring * 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) 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; union nps_core_int_active core_int;
core_int.value = nitrox_read_csr(ndev, NPS_CORE_INT_ACTIVE); 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) if (core_int.s.bmi)
clear_bmi_err_intr(ndev); 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 */ /* If more work callback the ISR, set resend */
core_int.s.resend = 1; core_int.s.resend = 1;
nitrox_write_csr(ndev, NPS_CORE_INT_ACTIVE, core_int.value); nitrox_write_csr(ndev, NPS_CORE_INT_ACTIVE, core_int.value);

Просмотреть файл

@ -1,6 +1,5 @@
#include <linux/aer.h> #include <linux/aer.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/debugfs.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/module.h> #include <linux/module.h>
@ -13,9 +12,9 @@
#include "nitrox_csr.h" #include "nitrox_csr.h"
#include "nitrox_hal.h" #include "nitrox_hal.h"
#include "nitrox_isr.h" #include "nitrox_isr.h"
#include "nitrox_debugfs.h"
#define CNN55XX_DEV_ID 0x12 #define CNN55XX_DEV_ID 0x12
#define MAX_PF_QUEUES 64
#define UCODE_HLEN 48 #define UCODE_HLEN 48
#define SE_GROUP 0 #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_hal.h"
#include "nitrox_common.h" #include "nitrox_common.h"
#include "nitrox_isr.h" #include "nitrox_isr.h"
#include "nitrox_mbx.h"
/** /**
* num_vfs_valid - validate VF count * num_vfs_valid - validate VF count
@ -52,6 +53,31 @@ static inline enum vf_mode num_vfs_to_mode(int num_vfs)
return mode; 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) 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 */
@ -94,16 +120,31 @@ static int nitrox_pf_reinit(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) static void nitrox_sriov_cleanup(struct nitrox_device *ndev)
{ {
/* unregister interrupts for PF in SR-IOV */ /* unregister interrupts for PF in SR-IOV */
nitrox_sriov_unregister_interrupts(ndev); 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) 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); 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->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 in flags */
set_bit(__NDEV_SRIOV_BIT, &ndev->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); clear_bit(__NDEV_SRIOV_BIT, &ndev->flags);
ndev->iov.num_vfs = 0; ndev->iov.num_vfs = 0;
ndev->iov.max_vf_queues = 0;
ndev->mode = __NDEV_MODE_PF; ndev->mode = __NDEV_MODE_PF;
/* cleanup PF SR-IOV resources */ /* cleanup PF SR-IOV resources */