This patchset aims to add PF-VF mailbox support, its related
version support, and relevant control net support for immediate
functionalities such as firmware notifications to VF.
Changes:
V4:
- Included tag [1/4] in subject of first patch of series which was
lost in V3
V3: https://lore.kernel.org/all/[email protected]/
- Corrected error cleanup logic for PF-VF mbox setup
- Removed double inclusion of types.h header file in octep_pfvf_mbox.c
V2: https://lore.kernel.org/all/[email protected]/
- Removed unused variable in PATCH 1/4
V1: https://lore.kernel.org/all/[email protected]/
Shinas Rasheed (4):
octeon_ep: add PF-VF mailbox communication
octeon_ep: PF-VF mailbox version support
octeon_ep: control net framework to support VF offloads
octeon_ep: support firmware notifications for VFs
.../net/ethernet/marvell/octeon_ep/Makefile | 2 +-
.../marvell/octeon_ep/octep_cn9k_pf.c | 59 ++-
.../marvell/octeon_ep/octep_cnxk_pf.c | 49 +-
.../marvell/octeon_ep/octep_ctrl_mbox.h | 4 +-
.../marvell/octeon_ep/octep_ctrl_net.c | 6 +
.../ethernet/marvell/octeon_ep/octep_main.c | 84 +++-
.../ethernet/marvell/octeon_ep/octep_main.h | 46 +-
.../marvell/octeon_ep/octep_pfvf_mbox.c | 450 ++++++++++++++++++
.../marvell/octeon_ep/octep_pfvf_mbox.h | 167 +++++++
.../marvell/octeon_ep/octep_regs_cn9k_pf.h | 9 +
.../marvell/octeon_ep/octep_regs_cnxk_pf.h | 13 +
.../net/ethernet/marvell/octeon_ep/octep_tx.h | 24 +-
12 files changed, 864 insertions(+), 49 deletions(-)
create mode 100644 drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
create mode 100644 drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h
--
2.25.1
Add PF-VF mailbox initial version support
Signed-off-by: Shinas Rasheed <[email protected]>
---
V4:
- No changes
V3: https://lore.kernel.org/all/[email protected]/
- No changes
V2: https://lore.kernel.org/all/[email protected]/
- No changes
V1: https://lore.kernel.org/all/[email protected]/
.../net/ethernet/marvell/octeon_ep/octep_main.h | 1 +
.../ethernet/marvell/octeon_ep/octep_pfvf_mbox.c | 15 ++++++++++++---
.../ethernet/marvell/octeon_ep/octep_pfvf_mbox.h | 7 +++++--
3 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.h b/drivers/net/ethernet/marvell/octeon_ep/octep_main.h
index 3223bb6f95ea..fee59e0e0138 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.h
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.h
@@ -220,6 +220,7 @@ struct octep_iface_link_info {
/* The Octeon VF device specific info data structure.*/
struct octep_pfvf_info {
u8 mac_addr[ETH_ALEN];
+ u32 mbox_version;
};
/* The Octeon device specific private data structure.
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
index 43b40e91f7bf..baffe298a2a0 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
@@ -28,10 +28,18 @@ static void octep_pfvf_validate_version(struct octep_device *oct, u32 vf_id,
{
u32 vf_version = (u32)cmd.s_version.version;
- if (vf_version <= OCTEP_PFVF_MBOX_VERSION_V1)
- rsp->s_version.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
+ dev_dbg(&oct->pdev->dev, "VF id:%d VF version:%d PF version:%d\n",
+ vf_id, vf_version, OCTEP_PFVF_MBOX_VERSION_CURRENT);
+ if (vf_version < OCTEP_PFVF_MBOX_VERSION_CURRENT)
+ rsp->s_version.version = vf_version;
else
- rsp->s_version.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+ rsp->s_version.version = OCTEP_PFVF_MBOX_VERSION_CURRENT;
+
+ oct->vf_info[vf_id].mbox_version = rsp->s_version.version;
+ dev_dbg(&oct->pdev->dev, "VF id:%d negotiated VF version:%d\n",
+ vf_id, oct->vf_info[vf_id].mbox_version);
+
+ rsp->s_version.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
}
static void octep_pfvf_get_link_status(struct octep_device *oct, u32 vf_id,
@@ -167,6 +175,7 @@ int octep_setup_pfvf_mbox(struct octep_device *oct)
goto free_mbox;
memset(oct->mbox[ring], 0, sizeof(struct octep_mbox));
+ memset(&oct->vf_info[i], 0, sizeof(struct octep_pfvf_info));
mutex_init(&oct->mbox[ring]->lock);
INIT_WORK(&oct->mbox[ring]->wk.work, octep_pfvf_mbox_work);
oct->mbox[ring]->wk.ctxptr = oct->mbox[ring];
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h
index 34feeb559b0d..af4dcf5ef7f1 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h
@@ -13,11 +13,15 @@
#define OCTEON_SDP_16K_HW_FRS 16380UL
#define OCTEON_SDP_64K_HW_FRS 65531UL
+/* When a new command is implemented,PF Mbox version should be bumped.
+ */
enum octep_pfvf_mbox_version {
OCTEP_PFVF_MBOX_VERSION_V0,
OCTEP_PFVF_MBOX_VERSION_V1,
};
+#define OCTEP_PFVF_MBOX_VERSION_CURRENT OCTEP_PFVF_MBOX_VERSION_V1
+
enum octep_pfvf_mbox_opcode {
OCTEP_PFVF_MBOX_CMD_VERSION,
OCTEP_PFVF_MBOX_CMD_SET_MTU,
@@ -30,7 +34,7 @@ enum octep_pfvf_mbox_opcode {
OCTEP_PFVF_MBOX_CMD_GET_LINK_STATUS,
OCTEP_PFVF_MBOX_CMD_GET_MTU,
OCTEP_PFVF_MBOX_CMD_DEV_REMOVE,
- OCTEP_PFVF_MBOX_CMD_LAST,
+ OCTEP_PFVF_MBOX_CMD_MAX,
};
enum octep_pfvf_mbox_word_type {
@@ -79,7 +83,6 @@ enum octep_pfvf_link_autoneg {
#define OCTEP_PFVF_MBOX_TIMEOUT_MS 500
#define OCTEP_PFVF_MBOX_MAX_RETRIES 2
-#define OCTEP_PFVF_MBOX_VERSION 0
#define OCTEP_PFVF_MBOX_MAX_DATA_SIZE 6
#define OCTEP_PFVF_MBOX_MORE_FRAG_FLAG 1
#define OCTEP_PFVF_MBOX_WRITE_WAIT_TIME msecs_to_jiffies(1)
--
2.25.1
Notifications from firmware to vf has to pass through PF
control mbox and via PF-VF mailboxes. The notifications have to
be parsed out from the control mbox and passed to the
PF-VF mailbox in order to reach the corresponding VF.
Version compatibility should also be checked before messages
are passed to the mailboxes.
Signed-off-by: Shinas Rasheed <[email protected]>
---
V4:
- No changes
V3: https://lore.kernel.org/all/[email protected]/
- No changes
V2: https://lore.kernel.org/all/[email protected]/
- No changes
V1: https://lore.kernel.org/all/[email protected]/
.../marvell/octeon_ep/octep_ctrl_net.c | 6 ++
.../marvell/octeon_ep/octep_pfvf_mbox.c | 58 +++++++++++++++++++
.../marvell/octeon_ep/octep_pfvf_mbox.h | 2 +
3 files changed, 66 insertions(+)
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c
index 9dff2166dbb7..01b7be154c38 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c
@@ -13,6 +13,7 @@
#include "octep_config.h"
#include "octep_main.h"
#include "octep_ctrl_net.h"
+#include "octep_pfvf_mbox.h"
/* Control plane version */
#define OCTEP_CP_VERSION_CURRENT OCTEP_CP_VERSION(1, 0, 0)
@@ -329,6 +330,11 @@ static int process_mbox_notify(struct octep_device *oct,
octep_ctrl_net_f2h_cmd_versions[cmd] < OCTEP_CP_VERSION_CURRENT)
return -EOPNOTSUPP;
+ if (msg->hdr.s.is_vf) {
+ octep_pfvf_notify(oct, msg);
+ return 0;
+ }
+
switch (cmd) {
case OCTEP_CTRL_NET_F2H_CMD_LINK_STATUS:
if (netif_running(netdev)) {
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
index 57e0184840c2..387a07456f54 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
@@ -22,6 +22,15 @@
#include "octep_pfvf_mbox.h"
#include "octep_ctrl_net.h"
+/* When a new command is implemented, the below table should be updated
+ * with new command and it's version info.
+ */
+static u32 pfvf_cmd_versions[OCTEP_PFVF_MBOX_CMD_MAX] = {
+ [0 ... OCTEP_PFVF_MBOX_CMD_DEV_REMOVE] = OCTEP_PFVF_MBOX_VERSION_V1,
+ [OCTEP_PFVF_MBOX_CMD_GET_FW_INFO ... OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS] =
+ OCTEP_PFVF_MBOX_VERSION_V2
+};
+
static void octep_pfvf_validate_version(struct octep_device *oct, u32 vf_id,
union octep_pfvf_mbox_word cmd,
union octep_pfvf_mbox_word *rsp)
@@ -88,6 +97,34 @@ static void octep_pfvf_set_rx_state(struct octep_device *oct, u32 vf_id,
rsp->s_link_state.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
}
+static int octep_send_notification(struct octep_device *oct, u32 vf_id,
+ union octep_pfvf_mbox_word cmd)
+{
+ u32 max_rings_per_vf, vf_mbox_queue;
+ struct octep_mbox *mbox;
+
+ /* check if VF PF Mailbox is compatible for this notification */
+ if (pfvf_cmd_versions[cmd.s.opcode] > oct->vf_info[vf_id].mbox_version) {
+ dev_dbg(&oct->pdev->dev, "VF Mbox doesn't support Notification:%d on VF ver:%d\n",
+ cmd.s.opcode, oct->vf_info[vf_id].mbox_version);
+ return -EOPNOTSUPP;
+ }
+
+ max_rings_per_vf = CFG_GET_MAX_RPVF(oct->conf);
+ vf_mbox_queue = vf_id * max_rings_per_vf;
+ if (!oct->mbox[vf_mbox_queue]) {
+ dev_err(&oct->pdev->dev, "Notif obtained for bad mbox vf %d\n", vf_id);
+ return -EINVAL;
+ }
+ mbox = oct->mbox[vf_mbox_queue];
+
+ mutex_lock(&mbox->lock);
+ writeq(cmd.u64, mbox->pf_vf_data_reg);
+ mutex_unlock(&mbox->lock);
+
+ return 0;
+}
+
static void octep_pfvf_set_mtu(struct octep_device *oct, u32 vf_id,
union octep_pfvf_mbox_word cmd,
union octep_pfvf_mbox_word *rsp)
@@ -327,6 +364,27 @@ static void octep_pfvf_pf_get_data(struct octep_device *oct,
}
}
+void octep_pfvf_notify(struct octep_device *oct, struct octep_ctrl_mbox_msg *msg)
+{
+ union octep_pfvf_mbox_word notif = { 0 };
+ struct octep_ctrl_net_f2h_req *req;
+
+ req = (struct octep_ctrl_net_f2h_req *)msg->sg_list[0].msg;
+ switch (req->hdr.s.cmd) {
+ case OCTEP_CTRL_NET_F2H_CMD_LINK_STATUS:
+ notif.s_link_status.opcode = OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS;
+ notif.s_link_status.status = req->link.state;
+ break;
+ default:
+ pr_info("Unknown mbox notif for vf: %u\n",
+ req->hdr.s.cmd);
+ return;
+ }
+
+ notif.s.type = OCTEP_PFVF_MBOX_TYPE_CMD;
+ octep_send_notification(oct, msg->hdr.s.vf_idx, notif);
+}
+
void octep_pfvf_mbox_work(struct work_struct *work)
{
struct octep_pfvf_mbox_wk *wk = container_of(work, struct octep_pfvf_mbox_wk, work);
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h
index c18a9f26fc31..0dc6eead292a 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h
@@ -37,6 +37,7 @@ enum octep_pfvf_mbox_opcode {
OCTEP_PFVF_MBOX_CMD_DEV_REMOVE,
OCTEP_PFVF_MBOX_CMD_GET_FW_INFO,
OCTEP_PFVF_MBOX_CMD_SET_OFFLOADS,
+ OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS,
OCTEP_PFVF_MBOX_CMD_MAX,
};
@@ -162,4 +163,5 @@ union octep_pfvf_mbox_word {
void octep_pfvf_mbox_work(struct work_struct *work);
int octep_setup_pfvf_mbox(struct octep_device *oct);
void octep_delete_pfvf_mbox(struct octep_device *oct);
+void octep_pfvf_notify(struct octep_device *oct, struct octep_ctrl_mbox_msg *msg);
#endif
--
2.25.1
Inquire firmware on supported offloads, as well as convey offloads
enabled dynamically to firmware for the VFs. Implement control net API
to support the same.
Signed-off-by: Shinas Rasheed <[email protected]>
---
V4:
- No changes
V3: https://lore.kernel.org/all/[email protected]/
- No changes
V2: https://lore.kernel.org/all/[email protected]/
- No changes
V1: https://lore.kernel.org/all/[email protected]/
.../marvell/octeon_ep/octep_pfvf_mbox.c | 47 +++++++++++++++++++
.../marvell/octeon_ep/octep_pfvf_mbox.h | 21 ++++++++-
2 files changed, 67 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
index baffe298a2a0..57e0184840c2 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
@@ -159,6 +159,47 @@ static void octep_pfvf_dev_remove(struct octep_device *oct, u32 vf_id,
rsp->s.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
}
+static void octep_pfvf_get_fw_info(struct octep_device *oct, u32 vf_id,
+ union octep_pfvf_mbox_word cmd,
+ union octep_pfvf_mbox_word *rsp)
+{
+ struct octep_fw_info fw_info;
+ int err;
+
+ err = octep_ctrl_net_get_info(oct, vf_id, &fw_info);
+ if (err) {
+ rsp->s_fw_info.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+ dev_err(&oct->pdev->dev, "Get VF info failed via host control Mbox\n");
+ return;
+ }
+
+ rsp->s_fw_info.pkind = fw_info.pkind;
+ rsp->s_fw_info.fsz = fw_info.fsz;
+ rsp->s_fw_info.rx_ol_flags = fw_info.rx_ol_flags;
+ rsp->s_fw_info.tx_ol_flags = fw_info.tx_ol_flags;
+
+ rsp->s_fw_info.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
+}
+
+static void octep_pfvf_set_offloads(struct octep_device *oct, u32 vf_id,
+ union octep_pfvf_mbox_word cmd,
+ union octep_pfvf_mbox_word *rsp)
+{
+ struct octep_ctrl_net_offloads offloads = {
+ .rx_offloads = cmd.s_offloads.rx_ol_flags,
+ .tx_offloads = cmd.s_offloads.tx_ol_flags
+ };
+ int err;
+
+ err = octep_ctrl_net_set_offloads(oct, vf_id, &offloads, true);
+ if (err) {
+ rsp->s_offloads.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+ dev_err(&oct->pdev->dev, "Set VF offloads failed via host control Mbox\n");
+ return;
+ }
+ rsp->s_offloads.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
+}
+
int octep_setup_pfvf_mbox(struct octep_device *oct)
{
int i = 0, num_vfs = 0, rings_per_vf = 0;
@@ -335,6 +376,12 @@ void octep_pfvf_mbox_work(struct work_struct *work)
case OCTEP_PFVF_MBOX_CMD_DEV_REMOVE:
octep_pfvf_dev_remove(oct, vf_id, cmd, &rsp);
break;
+ case OCTEP_PFVF_MBOX_CMD_GET_FW_INFO:
+ octep_pfvf_get_fw_info(oct, vf_id, cmd, &rsp);
+ break;
+ case OCTEP_PFVF_MBOX_CMD_SET_OFFLOADS:
+ octep_pfvf_set_offloads(oct, vf_id, cmd, &rsp);
+ break;
default:
dev_err(&oct->pdev->dev, "PF-VF mailbox: invalid opcode %d\n", cmd.s.opcode);
rsp.s.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h
index af4dcf5ef7f1..c18a9f26fc31 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h
@@ -18,9 +18,10 @@
enum octep_pfvf_mbox_version {
OCTEP_PFVF_MBOX_VERSION_V0,
OCTEP_PFVF_MBOX_VERSION_V1,
+ OCTEP_PFVF_MBOX_VERSION_V2,
};
-#define OCTEP_PFVF_MBOX_VERSION_CURRENT OCTEP_PFVF_MBOX_VERSION_V1
+#define OCTEP_PFVF_MBOX_VERSION_CURRENT OCTEP_PFVF_MBOX_VERSION_V2
enum octep_pfvf_mbox_opcode {
OCTEP_PFVF_MBOX_CMD_VERSION,
@@ -34,6 +35,8 @@ enum octep_pfvf_mbox_opcode {
OCTEP_PFVF_MBOX_CMD_GET_LINK_STATUS,
OCTEP_PFVF_MBOX_CMD_GET_MTU,
OCTEP_PFVF_MBOX_CMD_DEV_REMOVE,
+ OCTEP_PFVF_MBOX_CMD_GET_FW_INFO,
+ OCTEP_PFVF_MBOX_CMD_SET_OFFLOADS,
OCTEP_PFVF_MBOX_CMD_MAX,
};
@@ -138,6 +141,22 @@ union octep_pfvf_mbox_word {
u64 status:1;
u64 rsvd:53;
} s_link_status;
+ struct {
+ u64 opcode:8;
+ u64 type:2;
+ u64 pkind:8;
+ u64 fsz:8;
+ u64 rx_ol_flags:16;
+ u64 tx_ol_flags:16;
+ u64 rsvd:6;
+ } s_fw_info;
+ struct {
+ u64 opcode:8;
+ u64 type:2;
+ u64 rsvd:22;
+ u64 rx_ol_flags:16;
+ u64 tx_ol_flags:16;
+ } s_offloads;
} __packed;
void octep_pfvf_mbox_work(struct work_struct *work);
--
2.25.1
Implement mailbox communication between PF and VFs.
PF-VF mailbox is used for all control commands from VF to PF and
asynchronous notification messages from PF to VF.
Signed-off-by: Shinas Rasheed <[email protected]>
---
V4:
- Include [1/4] in the subject for this patch, which was lost in V3
V3: https://lore.kernel.org/all/[email protected]/
- Corrected error cleanup logic for PF-VF mbox setup
- Removed double inclusion of types.h header file in octep_pfvf_mbox.c
V2: https://lore.kernel.org/all/[email protected]/
- Remove unused variable
V1: https://lore.kernel.org/all/[email protected]/
.../net/ethernet/marvell/octeon_ep/Makefile | 2 +-
.../marvell/octeon_ep/octep_cn9k_pf.c | 59 ++-
.../marvell/octeon_ep/octep_cnxk_pf.c | 46 ++-
.../marvell/octeon_ep/octep_ctrl_mbox.h | 4 +-
.../ethernet/marvell/octeon_ep/octep_main.c | 83 ++++-
.../ethernet/marvell/octeon_ep/octep_main.h | 45 ++-
.../marvell/octeon_ep/octep_pfvf_mbox.c | 335 ++++++++++++++++++
.../marvell/octeon_ep/octep_pfvf_mbox.h | 143 ++++++++
.../marvell/octeon_ep/octep_regs_cn9k_pf.h | 9 +
.../marvell/octeon_ep/octep_regs_cnxk_pf.h | 13 +
.../net/ethernet/marvell/octeon_ep/octep_tx.h | 24 +-
11 files changed, 714 insertions(+), 49 deletions(-)
create mode 100644 drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
create mode 100644 drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h
diff --git a/drivers/net/ethernet/marvell/octeon_ep/Makefile b/drivers/net/ethernet/marvell/octeon_ep/Makefile
index 02a4a21bc298..62162ed63f34 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/Makefile
+++ b/drivers/net/ethernet/marvell/octeon_ep/Makefile
@@ -7,4 +7,4 @@ obj-$(CONFIG_OCTEON_EP) += octeon_ep.o
octeon_ep-y := octep_main.o octep_cn9k_pf.o octep_tx.o octep_rx.o \
octep_ethtool.o octep_ctrl_mbox.o octep_ctrl_net.o \
- octep_cnxk_pf.o
+ octep_pfvf_mbox.o octep_cnxk_pf.o
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c b/drivers/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c
index 9209f1ec1b52..b5805969404f 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c
@@ -362,16 +362,55 @@ static void octep_setup_mbox_regs_cn93_pf(struct octep_device *oct, int q_no)
{
struct octep_mbox *mbox = oct->mbox[q_no];
- mbox->q_no = q_no;
-
- /* PF mbox interrupt reg */
- mbox->mbox_int_reg = oct->mmio[0].hw_addr + CN93_SDP_EPF_MBOX_RINT(0);
-
/* PF to VF DATA reg. PF writes into this reg */
- mbox->mbox_write_reg = oct->mmio[0].hw_addr + CN93_SDP_R_MBOX_PF_VF_DATA(q_no);
+ mbox->pf_vf_data_reg = oct->mmio[0].hw_addr + CN93_SDP_MBOX_PF_VF_DATA(q_no);
/* VF to PF DATA reg. PF reads from this reg */
- mbox->mbox_read_reg = oct->mmio[0].hw_addr + CN93_SDP_R_MBOX_VF_PF_DATA(q_no);
+ mbox->vf_pf_data_reg = oct->mmio[0].hw_addr + CN93_SDP_MBOX_VF_PF_DATA(q_no);
+}
+
+/* Poll for mailbox messages from VF */
+static void octep_poll_pfvf_mailbox(struct octep_device *oct)
+{
+ u32 vf, active_vfs, active_rings_per_vf, vf_mbox_queue;
+ u64 reg0, reg1;
+
+ reg0 = octep_read_csr64(oct, CN93_SDP_EPF_MBOX_RINT(0));
+ reg1 = octep_read_csr64(oct, CN93_SDP_EPF_MBOX_RINT(1));
+ if (reg0 || reg1) {
+ active_vfs = CFG_GET_ACTIVE_VFS(oct->conf);
+ active_rings_per_vf = CFG_GET_ACTIVE_RPVF(oct->conf);
+ for (vf = 0; vf < active_vfs; vf++) {
+ vf_mbox_queue = vf * active_rings_per_vf;
+
+ if (vf_mbox_queue < 64) {
+ if (!(reg0 & (0x1UL << vf_mbox_queue)))
+ continue;
+ } else {
+ if (!(reg1 & (0x1UL << (vf_mbox_queue - 64))))
+ continue;
+ }
+
+ if (!oct->mbox[vf_mbox_queue]) {
+ dev_err(&oct->pdev->dev, "bad mbox vf %d\n", vf);
+ continue;
+ }
+ schedule_work(&oct->mbox[vf_mbox_queue]->wk.work);
+ }
+ if (reg0)
+ octep_write_csr64(oct, CN93_SDP_EPF_MBOX_RINT(0), reg0);
+ if (reg1)
+ octep_write_csr64(oct, CN93_SDP_EPF_MBOX_RINT(1), reg1);
+ }
+}
+
+/* PF-VF mailbox interrupt handler */
+static irqreturn_t octep_pfvf_mbox_intr_handler_cn93_pf(void *dev)
+{
+ struct octep_device *oct = (struct octep_device *)dev;
+
+ octep_poll_pfvf_mailbox(oct);
+ return IRQ_HANDLED;
}
/* Poll OEI events like heartbeat */
@@ -403,6 +442,7 @@ static irqreturn_t octep_oei_intr_handler_cn93_pf(void *dev)
*/
static void octep_poll_non_ioq_interrupts_cn93_pf(struct octep_device *oct)
{
+ octep_poll_pfvf_mailbox(oct);
octep_poll_oei_cn93_pf(oct);
}
@@ -646,6 +686,8 @@ static void octep_enable_interrupts_cn93_pf(struct octep_device *oct)
octep_write_csr64(oct, CN93_SDP_EPF_MISC_RINT_ENA_W1S, intr_mask);
octep_write_csr64(oct, CN93_SDP_EPF_DMA_RINT_ENA_W1S, intr_mask);
+ octep_write_csr64(oct, CN93_SDP_EPF_MBOX_RINT_ENA_W1S(0), -1ULL);
+ octep_write_csr64(oct, CN93_SDP_EPF_MBOX_RINT_ENA_W1S(1), -1ULL);
octep_write_csr64(oct, CN93_SDP_EPF_DMA_VF_RINT_ENA_W1S(0), -1ULL);
octep_write_csr64(oct, CN93_SDP_EPF_PP_VF_RINT_ENA_W1S(0), -1ULL);
@@ -672,6 +714,8 @@ static void octep_disable_interrupts_cn93_pf(struct octep_device *oct)
octep_write_csr64(oct, CN93_SDP_EPF_MISC_RINT_ENA_W1C, intr_mask);
octep_write_csr64(oct, CN93_SDP_EPF_DMA_RINT_ENA_W1C, intr_mask);
+ octep_write_csr64(oct, CN93_SDP_EPF_MBOX_RINT_ENA_W1C(0), -1ULL);
+ octep_write_csr64(oct, CN93_SDP_EPF_MBOX_RINT_ENA_W1C(1), -1ULL);
octep_write_csr64(oct, CN93_SDP_EPF_DMA_VF_RINT_ENA_W1C(0), -1ULL);
octep_write_csr64(oct, CN93_SDP_EPF_PP_VF_RINT_ENA_W1C(0), -1ULL);
@@ -807,6 +851,7 @@ void octep_device_setup_cn93_pf(struct octep_device *oct)
oct->hw_ops.setup_oq_regs = octep_setup_oq_regs_cn93_pf;
oct->hw_ops.setup_mbox_regs = octep_setup_mbox_regs_cn93_pf;
+ oct->hw_ops.mbox_intr_handler = octep_pfvf_mbox_intr_handler_cn93_pf;
oct->hw_ops.oei_intr_handler = octep_oei_intr_handler_cn93_pf;
oct->hw_ops.ire_intr_handler = octep_ire_intr_handler_cn93_pf;
oct->hw_ops.ore_intr_handler = octep_ore_intr_handler_cn93_pf;
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_cnxk_pf.c b/drivers/net/ethernet/marvell/octeon_ep/octep_cnxk_pf.c
index 098a0c5c4d1c..5de0b5ecbc5f 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_cnxk_pf.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_cnxk_pf.c
@@ -392,16 +392,44 @@ static void octep_setup_mbox_regs_cnxk_pf(struct octep_device *oct, int q_no)
{
struct octep_mbox *mbox = oct->mbox[q_no];
- mbox->q_no = q_no;
-
- /* PF mbox interrupt reg */
- mbox->mbox_int_reg = oct->mmio[0].hw_addr + CNXK_SDP_EPF_MBOX_RINT(0);
-
/* PF to VF DATA reg. PF writes into this reg */
- mbox->mbox_write_reg = oct->mmio[0].hw_addr + CNXK_SDP_R_MBOX_PF_VF_DATA(q_no);
+ mbox->pf_vf_data_reg = oct->mmio[0].hw_addr + CNXK_SDP_MBOX_PF_VF_DATA(q_no);
/* VF to PF DATA reg. PF reads from this reg */
- mbox->mbox_read_reg = oct->mmio[0].hw_addr + CNXK_SDP_R_MBOX_VF_PF_DATA(q_no);
+ mbox->vf_pf_data_reg = oct->mmio[0].hw_addr + CNXK_SDP_MBOX_VF_PF_DATA(q_no);
+}
+
+static void octep_poll_pfvf_mailbox_cnxk_pf(struct octep_device *oct)
+{
+ u32 vf, active_vfs, active_rings_per_vf, vf_mbox_queue;
+ u64 reg0;
+
+ reg0 = octep_read_csr64(oct, CNXK_SDP_EPF_MBOX_RINT(0));
+ if (reg0) {
+ active_vfs = CFG_GET_ACTIVE_VFS(oct->conf);
+ active_rings_per_vf = CFG_GET_ACTIVE_RPVF(oct->conf);
+ for (vf = 0; vf < active_vfs; vf++) {
+ vf_mbox_queue = vf * active_rings_per_vf;
+ if (!(reg0 & (0x1UL << vf_mbox_queue)))
+ continue;
+
+ if (!oct->mbox[vf_mbox_queue]) {
+ dev_err(&oct->pdev->dev, "bad mbox vf %d\n", vf);
+ continue;
+ }
+ schedule_work(&oct->mbox[vf_mbox_queue]->wk.work);
+ }
+ if (reg0)
+ octep_write_csr64(oct, CNXK_SDP_EPF_MBOX_RINT(0), reg0);
+ }
+}
+
+static irqreturn_t octep_pfvf_mbox_intr_handler_cnxk_pf(void *dev)
+{
+ struct octep_device *oct = (struct octep_device *)dev;
+
+ octep_poll_pfvf_mailbox_cnxk_pf(oct);
+ return IRQ_HANDLED;
}
/* Poll OEI events like heartbeat */
@@ -435,6 +463,7 @@ static irqreturn_t octep_oei_intr_handler_cnxk_pf(void *dev)
*/
static void octep_poll_non_ioq_interrupts_cnxk_pf(struct octep_device *oct)
{
+ octep_poll_pfvf_mailbox_cnxk_pf(oct);
octep_poll_oei_cnxk_pf(oct);
}
@@ -682,6 +711,7 @@ static void octep_enable_interrupts_cnxk_pf(struct octep_device *oct)
octep_write_csr64(oct, CNXK_SDP_EPF_MISC_RINT_ENA_W1S, intr_mask);
octep_write_csr64(oct, CNXK_SDP_EPF_DMA_RINT_ENA_W1S, intr_mask);
+ octep_write_csr64(oct, CNXK_SDP_EPF_MBOX_RINT_ENA_W1S(0), -1ULL);
octep_write_csr64(oct, CNXK_SDP_EPF_DMA_VF_RINT_ENA_W1S(0), -1ULL);
octep_write_csr64(oct, CNXK_SDP_EPF_PP_VF_RINT_ENA_W1S(0), -1ULL);
@@ -708,6 +738,7 @@ static void octep_disable_interrupts_cnxk_pf(struct octep_device *oct)
octep_write_csr64(oct, CNXK_SDP_EPF_MISC_RINT_ENA_W1C, intr_mask);
octep_write_csr64(oct, CNXK_SDP_EPF_DMA_RINT_ENA_W1C, intr_mask);
+ octep_write_csr64(oct, CNXK_SDP_EPF_MBOX_RINT_ENA_W1C(0), -1ULL);
octep_write_csr64(oct, CNXK_SDP_EPF_DMA_VF_RINT_ENA_W1C(0), -1ULL);
octep_write_csr64(oct, CNXK_SDP_EPF_PP_VF_RINT_ENA_W1C(0), -1ULL);
@@ -843,6 +874,7 @@ void octep_device_setup_cnxk_pf(struct octep_device *oct)
oct->hw_ops.setup_oq_regs = octep_setup_oq_regs_cnxk_pf;
oct->hw_ops.setup_mbox_regs = octep_setup_mbox_regs_cnxk_pf;
+ oct->hw_ops.mbox_intr_handler = octep_pfvf_mbox_intr_handler_cnxk_pf;
oct->hw_ops.oei_intr_handler = octep_oei_intr_handler_cnxk_pf;
oct->hw_ops.ire_intr_handler = octep_ire_intr_handler_cnxk_pf;
oct->hw_ops.ore_intr_handler = octep_ore_intr_handler_cnxk_pf;
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.h b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.h
index 7f8135788efc..6da32d40f926 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.h
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.h
@@ -16,10 +16,12 @@
* |reserved (4 bytes) |
* |-------------------------------------------|
* |host version (8 bytes) |
+ * | low 32 bits |
* |host status (8 bytes) |
* |host reserved (104 bytes) |
* |-------------------------------------------|
- * |fw version (8 bytes) |
+ * |fw version's (8 bytes) |
+ * | min=high 32 bits, max=low 32 bits |
* |fw status (8 bytes) |
* |fw reserved (104 bytes) |
* |===========================================|
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
index bbfc06581e77..4ebf4b68d629 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
@@ -16,6 +16,7 @@
#include "octep_config.h"
#include "octep_main.h"
#include "octep_ctrl_net.h"
+#include "octep_pfvf_mbox.h"
#define OCTEP_INTR_POLL_TIME_MSECS 100
struct workqueue_struct *octep_wq;
@@ -159,6 +160,21 @@ static void octep_disable_msix(struct octep_device *oct)
dev_info(&oct->pdev->dev, "Disabled MSI-X\n");
}
+/**
+ * octep_mbox_intr_handler() - common handler for pfvf mbox interrupts.
+ *
+ * @irq: Interrupt number.
+ * @data: interrupt data.
+ *
+ * this is common handler for pfvf mbox interrupts.
+ */
+static irqreturn_t octep_mbox_intr_handler(int irq, void *data)
+{
+ struct octep_device *oct = data;
+
+ return oct->hw_ops.mbox_intr_handler(oct);
+}
+
/**
* octep_oei_intr_handler() - common handler for output endpoint interrupts.
*
@@ -362,8 +378,12 @@ static int octep_request_irqs(struct octep_device *oct)
snprintf(irq_name, OCTEP_MSIX_NAME_SIZE,
"%s-%s", netdev->name, non_ioq_msix_names[i]);
- if (!strncmp(non_ioq_msix_names[i], "epf_oei_rint",
- strlen("epf_oei_rint"))) {
+ if (!strncmp(non_ioq_msix_names[i], "epf_mbox_rint", strlen("epf_mbox_rint"))) {
+ ret = request_irq(msix_entry->vector,
+ octep_mbox_intr_handler, 0,
+ irq_name, oct);
+ } else if (!strncmp(non_ioq_msix_names[i], "epf_oei_rint",
+ strlen("epf_oei_rint"))) {
ret = request_irq(msix_entry->vector,
octep_oei_intr_handler, 0,
irq_name, oct);
@@ -1315,6 +1335,7 @@ static void octep_device_cleanup(struct octep_device *oct)
oct->mbox[i] = NULL;
}
+ octep_delete_pfvf_mbox(oct);
octep_ctrl_net_uninit(oct);
cancel_delayed_work_sync(&oct->hb_task);
@@ -1411,6 +1432,12 @@ static int octep_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_octep_config;
}
+ err = octep_setup_pfvf_mbox(octep_dev);
+ if (err) {
+ dev_err(&pdev->dev, "PF-VF mailbox setup failed\n");
+ goto register_dev_err;
+ }
+
octep_ctrl_net_get_info(octep_dev, OCTEP_CTRL_NET_INVALID_VFID,
&octep_dev->conf->fw_info);
dev_info(&octep_dev->pdev->dev, "Heartbeat interval %u msecs Heartbeat miss count %u\n",
@@ -1482,6 +1509,21 @@ static int octep_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return err;
}
+static int octep_sriov_disable(struct octep_device *oct)
+{
+ struct pci_dev *pdev = oct->pdev;
+
+ if (pci_vfs_assigned(oct->pdev)) {
+ dev_warn(&pdev->dev, "Can't disable SRIOV while VFs are assigned\n");
+ return -EPERM;
+ }
+
+ pci_disable_sriov(pdev);
+ CFG_GET_ACTIVE_VFS(oct->conf) = 0;
+
+ return 0;
+}
+
/**
* octep_remove() - Remove Octeon PCI device from driver control.
*
@@ -1499,6 +1541,7 @@ static void octep_remove(struct pci_dev *pdev)
return;
netdev = oct->netdev;
+ octep_sriov_disable(oct);
if (netdev->reg_state == NETREG_REGISTERED)
unregister_netdev(netdev);
@@ -1509,11 +1552,47 @@ static void octep_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
}
+static int octep_sriov_enable(struct octep_device *oct, int num_vfs)
+{
+ struct pci_dev *pdev = oct->pdev;
+ int err;
+
+ CFG_GET_ACTIVE_VFS(oct->conf) = num_vfs;
+ err = pci_enable_sriov(pdev, num_vfs);
+ if (err) {
+ dev_warn(&pdev->dev, "Failed to enable SRIOV err=%d\n", err);
+ CFG_GET_ACTIVE_VFS(oct->conf) = 0;
+ return err;
+ }
+
+ return num_vfs;
+}
+
+static int octep_sriov_configure(struct pci_dev *pdev, int num_vfs)
+{
+ struct octep_device *oct = pci_get_drvdata(pdev);
+ int max_nvfs;
+
+ if (num_vfs == 0)
+ return octep_sriov_disable(oct);
+
+ max_nvfs = CFG_GET_MAX_VFS(oct->conf);
+
+ if (num_vfs > max_nvfs) {
+ dev_err(&pdev->dev, "Invalid VF count Max supported VFs = %d\n",
+ max_nvfs);
+ return -EINVAL;
+ }
+
+ return octep_sriov_enable(oct, num_vfs);
+}
+
static struct pci_driver octep_driver = {
.name = OCTEP_DRV_NAME,
.id_table = octep_pci_id_tbl,
.probe = octep_probe,
.remove = octep_remove,
+ .sriov_configure = octep_sriov_configure,
};
/**
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.h b/drivers/net/ethernet/marvell/octeon_ep/octep_main.h
index 2cb93d425744..3223bb6f95ea 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.h
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.h
@@ -80,6 +80,7 @@ struct octep_hw_ops {
void (*setup_oq_regs)(struct octep_device *oct, int q);
void (*setup_mbox_regs)(struct octep_device *oct, int mbox);
+ irqreturn_t (*mbox_intr_handler)(void *ioq_vector);
irqreturn_t (*oei_intr_handler)(void *ioq_vector);
irqreturn_t (*ire_intr_handler)(void *ioq_vector);
irqreturn_t (*ore_intr_handler)(void *ioq_vector);
@@ -118,28 +119,27 @@ struct octep_mbox_data {
u64 *data;
};
+#define MAX_VF_PF_MBOX_DATA_SIZE 384
+/* wrappers around work structs */
+struct octep_pfvf_mbox_wk {
+ struct work_struct work;
+ void *ctxptr;
+ u64 ctxul;
+};
+
/* Octeon device mailbox */
struct octep_mbox {
- /* A spinlock to protect access to this q_mbox. */
- spinlock_t lock;
-
- u32 q_no;
- u32 state;
-
- /* SLI_MAC_PF_MBOX_INT for PF, SLI_PKT_MBOX_INT for VF. */
- u8 __iomem *mbox_int_reg;
-
- /* SLI_PKT_PF_VF_MBOX_SIG(0) for PF,
- * SLI_PKT_PF_VF_MBOX_SIG(1) for VF.
- */
- u8 __iomem *mbox_write_reg;
-
- /* SLI_PKT_PF_VF_MBOX_SIG(1) for PF,
- * SLI_PKT_PF_VF_MBOX_SIG(0) for VF.
- */
- u8 __iomem *mbox_read_reg;
-
+ /* A mutex to protect access to this q_mbox. */
+ struct mutex lock;
+ u32 vf_id;
+ u32 config_data_index;
+ u32 message_len;
+ u8 __iomem *pf_vf_data_reg;
+ u8 __iomem *vf_pf_data_reg;
+ struct octep_pfvf_mbox_wk wk;
+ struct octep_device *oct;
struct octep_mbox_data mbox_data;
+ u8 config_data[MAX_VF_PF_MBOX_DATA_SIZE];
};
/* Tx/Rx queue vector per interrupt. */
@@ -217,6 +217,11 @@ struct octep_iface_link_info {
u8 oper_up;
};
+/* The Octeon VF device specific info data structure.*/
+struct octep_pfvf_info {
+ u8 mac_addr[ETH_ALEN];
+};
+
/* The Octeon device specific private data structure.
* Each Octeon device has this structure to represent all its components.
*/
@@ -282,6 +287,8 @@ struct octep_device {
/* Mailbox to talk to VFs */
struct octep_mbox *mbox[OCTEP_MAX_VF];
+ /* VFs info */
+ struct octep_pfvf_info vf_info[OCTEP_MAX_VF];
/* Work entry to handle Tx timeout */
struct work_struct tx_timeout_task;
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
new file mode 100644
index 000000000000..0557c138060f
--- /dev/null
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
@@ -0,0 +1,335 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Marvell Octeon EP (EndPoint) Ethernet Driver
+ *
+ * Copyright (C) 2020 Marvell.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mutex.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include <linux/sched/signal.h>
+#include <linux/io.h>
+#include <linux/pci.h>
+#include <linux/etherdevice.h>
+
+#include "octep_config.h"
+#include "octep_main.h"
+#include "octep_pfvf_mbox.h"
+#include "octep_ctrl_net.h"
+
+static void octep_pfvf_validate_version(struct octep_device *oct, u32 vf_id,
+ union octep_pfvf_mbox_word cmd,
+ union octep_pfvf_mbox_word *rsp)
+{
+ u32 vf_version = (u32)cmd.s_version.version;
+
+ if (vf_version <= OCTEP_PFVF_MBOX_VERSION_V1)
+ rsp->s_version.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
+ else
+ rsp->s_version.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+}
+
+static void octep_pfvf_get_link_status(struct octep_device *oct, u32 vf_id,
+ union octep_pfvf_mbox_word cmd,
+ union octep_pfvf_mbox_word *rsp)
+{
+ int status;
+
+ status = octep_ctrl_net_get_link_status(oct, vf_id);
+ if (status < 0) {
+ rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+ dev_err(&oct->pdev->dev, "Get VF link status failed via host control Mbox\n");
+ return;
+ }
+ rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
+ rsp->s_link_status.status = status;
+}
+
+static void octep_pfvf_set_link_status(struct octep_device *oct, u32 vf_id,
+ union octep_pfvf_mbox_word cmd,
+ union octep_pfvf_mbox_word *rsp)
+{
+ int err;
+
+ err = octep_ctrl_net_set_link_status(oct, vf_id, cmd.s_link_status.status, true);
+ if (err) {
+ rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+ dev_err(&oct->pdev->dev, "Set VF link status failed via host control Mbox\n");
+ return;
+ }
+ rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
+}
+
+static void octep_pfvf_set_rx_state(struct octep_device *oct, u32 vf_id,
+ union octep_pfvf_mbox_word cmd,
+ union octep_pfvf_mbox_word *rsp)
+{
+ int err;
+
+ err = octep_ctrl_net_set_rx_state(oct, vf_id, cmd.s_link_state.state, true);
+ if (err) {
+ rsp->s_link_state.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+ dev_err(&oct->pdev->dev, "Set VF Rx link state failed via host control Mbox\n");
+ return;
+ }
+ rsp->s_link_state.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
+}
+
+static void octep_pfvf_set_mtu(struct octep_device *oct, u32 vf_id,
+ union octep_pfvf_mbox_word cmd,
+ union octep_pfvf_mbox_word *rsp)
+{
+ int err;
+
+ err = octep_ctrl_net_set_mtu(oct, vf_id, cmd.s_set_mtu.mtu, true);
+ if (err) {
+ rsp->s_set_mtu.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+ dev_err(&oct->pdev->dev, "Set VF MTU failed via host control Mbox\n");
+ return;
+ }
+ rsp->s_set_mtu.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
+}
+
+static void octep_pfvf_get_mtu(struct octep_device *oct, u32 vf_id,
+ union octep_pfvf_mbox_word cmd,
+ union octep_pfvf_mbox_word *rsp)
+{
+ int max_rx_pktlen = oct->netdev->max_mtu + (ETH_HLEN + ETH_FCS_LEN);
+
+ rsp->s_set_mtu.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
+ rsp->s_get_mtu.mtu = max_rx_pktlen;
+}
+
+static void octep_pfvf_set_mac_addr(struct octep_device *oct, u32 vf_id,
+ union octep_pfvf_mbox_word cmd,
+ union octep_pfvf_mbox_word *rsp)
+{
+ int err;
+
+ err = octep_ctrl_net_set_mac_addr(oct, vf_id, cmd.s_set_mac.mac_addr, true);
+ if (err) {
+ rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+ dev_err(&oct->pdev->dev, "Set VF MAC address failed via host control Mbox\n");
+ return;
+ }
+ rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
+}
+
+static void octep_pfvf_get_mac_addr(struct octep_device *oct, u32 vf_id,
+ union octep_pfvf_mbox_word cmd,
+ union octep_pfvf_mbox_word *rsp)
+{
+ int err;
+
+ err = octep_ctrl_net_get_mac_addr(oct, vf_id, rsp->s_set_mac.mac_addr);
+ if (err) {
+ rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+ dev_err(&oct->pdev->dev, "Get VF MAC address failed via host control Mbox\n");
+ return;
+ }
+ rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
+}
+
+static void octep_pfvf_dev_remove(struct octep_device *oct, u32 vf_id,
+ union octep_pfvf_mbox_word cmd,
+ union octep_pfvf_mbox_word *rsp)
+{
+ int err;
+
+ err = octep_ctrl_net_dev_remove(oct, vf_id);
+ if (err) {
+ rsp->s.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+ dev_err(&oct->pdev->dev, "Failed to acknowledge fw of vf %d removal\n",
+ vf_id);
+ return;
+ }
+ rsp->s.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
+}
+
+int octep_setup_pfvf_mbox(struct octep_device *oct)
+{
+ int i = 0, num_vfs = 0, rings_per_vf = 0;
+ int ring = 0;
+
+ num_vfs = oct->conf->sriov_cfg.active_vfs;
+ rings_per_vf = oct->conf->sriov_cfg.max_rings_per_vf;
+
+ for (i = 0; i < num_vfs; i++) {
+ ring = rings_per_vf * i;
+ oct->mbox[ring] = vzalloc(sizeof(*oct->mbox[ring]));
+
+ if (!oct->mbox[ring])
+ goto free_mbox;
+
+ memset(oct->mbox[ring], 0, sizeof(struct octep_mbox));
+ mutex_init(&oct->mbox[ring]->lock);
+ INIT_WORK(&oct->mbox[ring]->wk.work, octep_pfvf_mbox_work);
+ oct->mbox[ring]->wk.ctxptr = oct->mbox[ring];
+ oct->mbox[ring]->oct = oct;
+ oct->mbox[ring]->vf_id = i;
+ oct->hw_ops.setup_mbox_regs(oct, ring);
+ }
+ return 0;
+
+free_mbox:
+ while (i) {
+ i--;
+ ring = rings_per_vf * i;
+ cancel_work_sync(&oct->mbox[ring]->wk.work);
+ mutex_destroy(&oct->mbox[ring]->lock);
+ vfree(oct->mbox[ring]);
+ oct->mbox[ring] = NULL;
+ }
+ return -ENOMEM;
+}
+
+void octep_delete_pfvf_mbox(struct octep_device *oct)
+{
+ int rings_per_vf = oct->conf->sriov_cfg.max_rings_per_vf;
+ int num_vfs = oct->conf->sriov_cfg.active_vfs;
+ int i = 0, ring = 0, vf_srn = 0;
+
+ for (i = 0; i < num_vfs; i++) {
+ ring = vf_srn + rings_per_vf * i;
+ if (!oct->mbox[ring])
+ continue;
+
+ if (work_pending(&oct->mbox[ring]->wk.work))
+ cancel_work_sync(&oct->mbox[ring]->wk.work);
+
+ mutex_destroy(&oct->mbox[ring]->lock);
+ vfree(oct->mbox[ring]);
+ oct->mbox[ring] = NULL;
+ }
+}
+
+static void octep_pfvf_pf_get_data(struct octep_device *oct,
+ struct octep_mbox *mbox, int vf_id,
+ union octep_pfvf_mbox_word cmd,
+ union octep_pfvf_mbox_word *rsp)
+{
+ int length = 0;
+ int i = 0;
+ int err;
+ struct octep_iface_link_info link_info;
+ struct octep_iface_rx_stats rx_stats;
+ struct octep_iface_tx_stats tx_stats;
+
+ rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
+
+ if (cmd.s_data.frag != OCTEP_PFVF_MBOX_MORE_FRAG_FLAG) {
+ mbox->config_data_index = 0;
+ memset(mbox->config_data, 0, MAX_VF_PF_MBOX_DATA_SIZE);
+ /* Based on the OPCODE CMD the PF driver
+ * specific API should be called to fetch
+ * the requested data
+ */
+ switch (cmd.s.opcode) {
+ case OCTEP_PFVF_MBOX_CMD_GET_LINK_INFO:
+ memset(&link_info, 0, sizeof(link_info));
+ err = octep_ctrl_net_get_link_info(oct, vf_id, &link_info);
+ if (!err) {
+ mbox->message_len = sizeof(link_info);
+ *((int32_t *)rsp->s_data.data) = mbox->message_len;
+ memcpy(mbox->config_data, (u8 *)&link_info, sizeof(link_info));
+ } else {
+ rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+ return;
+ }
+ break;
+ case OCTEP_PFVF_MBOX_CMD_GET_STATS:
+ memset(&rx_stats, 0, sizeof(rx_stats));
+ memset(&tx_stats, 0, sizeof(tx_stats));
+ err = octep_ctrl_net_get_if_stats(oct, vf_id, &rx_stats, &tx_stats);
+ if (!err) {
+ mbox->message_len = sizeof(rx_stats) + sizeof(tx_stats);
+ *((int32_t *)rsp->s_data.data) = mbox->message_len;
+ memcpy(mbox->config_data, (u8 *)&rx_stats, sizeof(rx_stats));
+ memcpy(mbox->config_data + sizeof(rx_stats), (u8 *)&tx_stats,
+ sizeof(tx_stats));
+
+ } else {
+ rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+ return;
+ }
+ break;
+ }
+ *((int32_t *)rsp->s_data.data) = mbox->message_len;
+ return;
+ }
+
+ if (mbox->message_len > OCTEP_PFVF_MBOX_MAX_DATA_SIZE)
+ length = OCTEP_PFVF_MBOX_MAX_DATA_SIZE;
+ else
+ length = mbox->message_len;
+
+ mbox->message_len -= length;
+
+ for (i = 0; i < length; i++) {
+ rsp->s_data.data[i] =
+ mbox->config_data[mbox->config_data_index];
+ mbox->config_data_index++;
+ }
+}
+
+void octep_pfvf_mbox_work(struct work_struct *work)
+{
+ struct octep_pfvf_mbox_wk *wk = container_of(work, struct octep_pfvf_mbox_wk, work);
+ union octep_pfvf_mbox_word cmd = { 0 };
+ union octep_pfvf_mbox_word rsp = { 0 };
+ struct octep_mbox *mbox = NULL;
+ struct octep_device *oct = NULL;
+ int vf_id;
+
+ mbox = (struct octep_mbox *)wk->ctxptr;
+ oct = (struct octep_device *)mbox->oct;
+ vf_id = mbox->vf_id;
+
+ mutex_lock(&mbox->lock);
+ cmd.u64 = readq(mbox->vf_pf_data_reg);
+ rsp.u64 = 0;
+
+ switch (cmd.s.opcode) {
+ case OCTEP_PFVF_MBOX_CMD_VERSION:
+ octep_pfvf_validate_version(oct, vf_id, cmd, &rsp);
+ break;
+ case OCTEP_PFVF_MBOX_CMD_GET_LINK_STATUS:
+ octep_pfvf_get_link_status(oct, vf_id, cmd, &rsp);
+ break;
+ case OCTEP_PFVF_MBOX_CMD_SET_LINK_STATUS:
+ octep_pfvf_set_link_status(oct, vf_id, cmd, &rsp);
+ break;
+ case OCTEP_PFVF_MBOX_CMD_SET_RX_STATE:
+ octep_pfvf_set_rx_state(oct, vf_id, cmd, &rsp);
+ break;
+ case OCTEP_PFVF_MBOX_CMD_SET_MTU:
+ octep_pfvf_set_mtu(oct, vf_id, cmd, &rsp);
+ break;
+ case OCTEP_PFVF_MBOX_CMD_SET_MAC_ADDR:
+ octep_pfvf_set_mac_addr(oct, vf_id, cmd, &rsp);
+ break;
+ case OCTEP_PFVF_MBOX_CMD_GET_MAC_ADDR:
+ octep_pfvf_get_mac_addr(oct, vf_id, cmd, &rsp);
+ break;
+ case OCTEP_PFVF_MBOX_CMD_GET_LINK_INFO:
+ case OCTEP_PFVF_MBOX_CMD_GET_STATS:
+ octep_pfvf_pf_get_data(oct, mbox, vf_id, cmd, &rsp);
+ break;
+ case OCTEP_PFVF_MBOX_CMD_GET_MTU:
+ octep_pfvf_get_mtu(oct, vf_id, cmd, &rsp);
+ break;
+ case OCTEP_PFVF_MBOX_CMD_DEV_REMOVE:
+ octep_pfvf_dev_remove(oct, vf_id, cmd, &rsp);
+ break;
+ default:
+ dev_err(&oct->pdev->dev, "PF-VF mailbox: invalid opcode %d\n", cmd.s.opcode);
+ rsp.s.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+ break;
+ }
+ writeq(rsp.u64, mbox->vf_pf_data_reg);
+ mutex_unlock(&mbox->lock);
+}
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h
new file mode 100644
index 000000000000..34feeb559b0d
--- /dev/null
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h
@@ -0,0 +1,143 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Marvell Octeon EP (EndPoint) Ethernet Driver
+ *
+ * Copyright (C) 2020 Marvell.
+ *
+ */
+
+#ifndef _OCTEP_PFVF_MBOX_H_
+#define _OCTEP_PFVF_MBOX_H_
+
+/* VF flags */
+#define OCTEON_PFVF_FLAG_MAC_SET_BY_PF BIT_ULL(0) /* PF has set VF MAC address */
+#define OCTEON_SDP_16K_HW_FRS 16380UL
+#define OCTEON_SDP_64K_HW_FRS 65531UL
+
+enum octep_pfvf_mbox_version {
+ OCTEP_PFVF_MBOX_VERSION_V0,
+ OCTEP_PFVF_MBOX_VERSION_V1,
+};
+
+enum octep_pfvf_mbox_opcode {
+ OCTEP_PFVF_MBOX_CMD_VERSION,
+ OCTEP_PFVF_MBOX_CMD_SET_MTU,
+ OCTEP_PFVF_MBOX_CMD_SET_MAC_ADDR,
+ OCTEP_PFVF_MBOX_CMD_GET_MAC_ADDR,
+ OCTEP_PFVF_MBOX_CMD_GET_LINK_INFO,
+ OCTEP_PFVF_MBOX_CMD_GET_STATS,
+ OCTEP_PFVF_MBOX_CMD_SET_RX_STATE,
+ OCTEP_PFVF_MBOX_CMD_SET_LINK_STATUS,
+ OCTEP_PFVF_MBOX_CMD_GET_LINK_STATUS,
+ OCTEP_PFVF_MBOX_CMD_GET_MTU,
+ OCTEP_PFVF_MBOX_CMD_DEV_REMOVE,
+ OCTEP_PFVF_MBOX_CMD_LAST,
+};
+
+enum octep_pfvf_mbox_word_type {
+ OCTEP_PFVF_MBOX_TYPE_CMD,
+ OCTEP_PFVF_MBOX_TYPE_RSP_ACK,
+ OCTEP_PFVF_MBOX_TYPE_RSP_NACK,
+};
+
+enum octep_pfvf_mbox_cmd_status {
+ OCTEP_PFVF_MBOX_CMD_STATUS_NOT_SETUP = 1,
+ OCTEP_PFVF_MBOX_CMD_STATUS_TIMEDOUT = 2,
+ OCTEP_PFVF_MBOX_CMD_STATUS_NACK = 3,
+ OCTEP_PFVF_MBOX_CMD_STATUS_BUSY = 4
+};
+
+enum octep_pfvf_mbox_state {
+ OCTEP_PFVF_MBOX_STATE_IDLE = 0,
+ OCTEP_PFVF_MBOX_STATE_BUSY = 1,
+};
+
+enum octep_pfvf_link_status {
+ OCTEP_PFVF_LINK_STATUS_DOWN,
+ OCTEP_PFVF_LINK_STATUS_UP,
+};
+
+enum octep_pfvf_link_speed {
+ OCTEP_PFVF_LINK_SPEED_NONE,
+ OCTEP_PFVF_LINK_SPEED_1000,
+ OCTEP_PFVF_LINK_SPEED_10000,
+ OCTEP_PFVF_LINK_SPEED_25000,
+ OCTEP_PFVF_LINK_SPEED_40000,
+ OCTEP_PFVF_LINK_SPEED_50000,
+ OCTEP_PFVF_LINK_SPEED_100000,
+ OCTEP_PFVF_LINK_SPEED_LAST,
+};
+
+enum octep_pfvf_link_duplex {
+ OCTEP_PFVF_LINK_HALF_DUPLEX,
+ OCTEP_PFVF_LINK_FULL_DUPLEX,
+};
+
+enum octep_pfvf_link_autoneg {
+ OCTEP_PFVF_LINK_AUTONEG,
+ OCTEP_PFVF_LINK_FIXED,
+};
+
+#define OCTEP_PFVF_MBOX_TIMEOUT_MS 500
+#define OCTEP_PFVF_MBOX_MAX_RETRIES 2
+#define OCTEP_PFVF_MBOX_VERSION 0
+#define OCTEP_PFVF_MBOX_MAX_DATA_SIZE 6
+#define OCTEP_PFVF_MBOX_MORE_FRAG_FLAG 1
+#define OCTEP_PFVF_MBOX_WRITE_WAIT_TIME msecs_to_jiffies(1)
+
+union octep_pfvf_mbox_word {
+ u64 u64;
+ struct {
+ u64 opcode:8;
+ u64 type:2;
+ u64 rsvd:6;
+ u64 data:48;
+ } s;
+ struct {
+ u64 opcode:8;
+ u64 type:2;
+ u64 frag:1;
+ u64 rsvd:5;
+ u8 data[6];
+ } s_data;
+ struct {
+ u64 opcode:8;
+ u64 type:2;
+ u64 rsvd:6;
+ u64 version:48;
+ } s_version;
+ struct {
+ u64 opcode:8;
+ u64 type:2;
+ u64 rsvd:6;
+ u8 mac_addr[6];
+ } s_set_mac;
+ struct {
+ u64 opcode:8;
+ u64 type:2;
+ u64 rsvd:6;
+ u64 mtu:48;
+ } s_set_mtu;
+ struct {
+ u64 opcode:8;
+ u64 type:2;
+ u64 rsvd:6;
+ u64 mtu:48;
+ } s_get_mtu;
+ struct {
+ u64 opcode:8;
+ u64 type:2;
+ u64 state:1;
+ u64 rsvd:53;
+ } s_link_state;
+ struct {
+ u64 opcode:8;
+ u64 type:2;
+ u64 status:1;
+ u64 rsvd:53;
+ } s_link_status;
+} __packed;
+
+void octep_pfvf_mbox_work(struct work_struct *work);
+int octep_setup_pfvf_mbox(struct octep_device *oct);
+void octep_delete_pfvf_mbox(struct octep_device *oct);
+#endif
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cn9k_pf.h b/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cn9k_pf.h
index 2e20a39d89af..ca473502d7a0 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cn9k_pf.h
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cn9k_pf.h
@@ -208,6 +208,9 @@
#define CN93_SDP_R_MBOX_PF_VF_INT_START 0x10220
#define CN93_SDP_R_MBOX_VF_PF_DATA_START 0x10230
+#define CN93_SDP_MBOX_VF_PF_DATA_START 0x24000
+#define CN93_SDP_MBOX_PF_VF_DATA_START 0x22000
+
#define CN93_SDP_R_MBOX_PF_VF_DATA(ring) \
(CN93_SDP_R_MBOX_PF_VF_DATA_START + ((ring) * CN93_RING_OFFSET))
@@ -217,6 +220,12 @@
#define CN93_SDP_R_MBOX_VF_PF_DATA(ring) \
(CN93_SDP_R_MBOX_VF_PF_DATA_START + ((ring) * CN93_RING_OFFSET))
+#define CN93_SDP_MBOX_VF_PF_DATA(ring) \
+ (CN93_SDP_MBOX_VF_PF_DATA_START + ((ring) * CN93_EPVF_RING_OFFSET))
+
+#define CN93_SDP_MBOX_PF_VF_DATA(ring) \
+ (CN93_SDP_MBOX_PF_VF_DATA_START + ((ring) * CN93_EPVF_RING_OFFSET))
+
/* ##################### Interrupt Registers ########################## */
#define CN93_SDP_R_ERR_TYPE_START 0x10400
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cnxk_pf.h b/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cnxk_pf.h
index ea677f760ef0..e637d7c8224d 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cnxk_pf.h
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cnxk_pf.h
@@ -183,6 +183,7 @@
#define CNXK_SDP_R_OUT_INT_MDRT_CTL1_START 0x103A0
#define CNXK_SDP_R_OUT_INT_MDRT_DBG_START 0x103C0
+#define CNXK_SDP_R_MBOX_ISM_START 0x10500
#define CNXK_SDP_R_OUT_CNTS_ISM_START 0x10510
#define CNXK_SDP_R_IN_CNTS_ISM_START 0x10520
@@ -204,6 +205,9 @@
#define CNXK_SDP_R_OUT_INT_MDRT_DBG(ring) \
(CNXK_SDP_R_OUT_INT_MDRT_DBG_START + ((ring) * CNXK_RING_OFFSET))
+#define CNXK_SDP_R_MBOX_ISM(ring) \
+ (CNXK_SDP_R_MBOX_ISM_START + ((ring) * CNXK_RING_OFFSET))
+
#define CNXK_SDP_R_OUT_CNTS_ISM(ring) \
(CNXK_SDP_R_OUT_CNTS_ISM_START + ((ring) * CNXK_RING_OFFSET))
@@ -222,6 +226,9 @@
#define CNXK_SDP_R_MBOX_PF_VF_INT_START 0x10220
#define CNXK_SDP_R_MBOX_VF_PF_DATA_START 0x10230
+#define CNXK_SDP_MBOX_VF_PF_DATA_START 0x24000
+#define CNXK_SDP_MBOX_PF_VF_DATA_START 0x22000
+
#define CNXK_SDP_R_MBOX_PF_VF_DATA(ring) \
(CNXK_SDP_R_MBOX_PF_VF_DATA_START + ((ring) * CNXK_RING_OFFSET))
@@ -231,6 +238,12 @@
#define CNXK_SDP_R_MBOX_VF_PF_DATA(ring) \
(CNXK_SDP_R_MBOX_VF_PF_DATA_START + ((ring) * CNXK_RING_OFFSET))
+#define CNXK_SDP_MBOX_VF_PF_DATA(ring) \
+ (CNXK_SDP_MBOX_VF_PF_DATA_START + ((ring) * CNXK_EPVF_RING_OFFSET))
+
+#define CNXK_SDP_MBOX_PF_VF_DATA(ring) \
+ (CNXK_SDP_MBOX_PF_VF_DATA_START + ((ring) * CNXK_EPVF_RING_OFFSET))
+
/* ##################### Interrupt Registers ########################## */
#define CNXK_SDP_R_ERR_TYPE_START 0x10400
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_tx.h b/drivers/net/ethernet/marvell/octeon_ep/octep_tx.h
index 059fa921069f..875a2c34091f 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_tx.h
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_tx.h
@@ -61,6 +61,18 @@ struct octep_tx_buffer {
/* Hardware interface Tx statistics */
struct octep_iface_tx_stats {
+ /* Total frames sent on the interface */
+ u64 pkts;
+
+ /* Total octets sent on the interface */
+ u64 octs;
+
+ /* Packets sent to a broadcast DMAC */
+ u64 bcst;
+
+ /* Packets sent to the multicast DMAC */
+ u64 mcst;
+
/* Packets dropped due to excessive collisions */
u64 xscol;
@@ -77,12 +89,6 @@ struct octep_iface_tx_stats {
*/
u64 scol;
- /* Total octets sent on the interface */
- u64 octs;
-
- /* Total frames sent on the interface */
- u64 pkts;
-
/* Packets sent with an octet count < 64 */
u64 hist_lt64;
@@ -107,12 +113,6 @@ struct octep_iface_tx_stats {
/* Packets sent with an octet count of > 1518 */
u64 hist_gt1518;
- /* Packets sent to a broadcast DMAC */
- u64 bcst;
-
- /* Packets sent to the multicast DMAC */
- u64 mcst;
-
/* Packets sent that experienced a transmit underflow and were
* truncated
*/
--
2.25.1
A few nit comments
在 2023/12/13 11:58, Shinas Rasheed 写道:
> Implement mailbox communication between PF and VFs.
> PF-VF mailbox is used for all control commands from VF to PF and
> asynchronous notification messages from PF to VF.
>
> Signed-off-by: Shinas Rasheed <[email protected]>
> ---
> V4:
> - Include [1/4] in the subject for this patch, which was lost in V3
>
> V3: https://lore.kernel.org/all/[email protected]/
> - Corrected error cleanup logic for PF-VF mbox setup
> - Removed double inclusion of types.h header file in octep_pfvf_mbox.c
>
> V2: https://lore.kernel.org/all/[email protected]/
> - Remove unused variable
>
> V1: https://lore.kernel.org/all/[email protected]/
>
> .../net/ethernet/marvell/octeon_ep/Makefile | 2 +-
> .../marvell/octeon_ep/octep_cn9k_pf.c | 59 ++-
> .../marvell/octeon_ep/octep_cnxk_pf.c | 46 ++-
> .../marvell/octeon_ep/octep_ctrl_mbox.h | 4 +-
> .../ethernet/marvell/octeon_ep/octep_main.c | 83 ++++-
> .../ethernet/marvell/octeon_ep/octep_main.h | 45 ++-
> .../marvell/octeon_ep/octep_pfvf_mbox.c | 335 ++++++++++++++++++
> .../marvell/octeon_ep/octep_pfvf_mbox.h | 143 ++++++++
> .../marvell/octeon_ep/octep_regs_cn9k_pf.h | 9 +
> .../marvell/octeon_ep/octep_regs_cnxk_pf.h | 13 +
> .../net/ethernet/marvell/octeon_ep/octep_tx.h | 24 +-
> 11 files changed, 714 insertions(+), 49 deletions(-)
> create mode 100644 drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
> create mode 100644 drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h
>
> diff --git a/drivers/net/ethernet/marvell/octeon_ep/Makefile b/drivers/net/ethernet/marvell/octeon_ep/Makefile
> index 02a4a21bc298..62162ed63f34 100644
> --- a/drivers/net/ethernet/marvell/octeon_ep/Makefile
> +++ b/drivers/net/ethernet/marvell/octeon_ep/Makefile
> @@ -7,4 +7,4 @@ obj-$(CONFIG_OCTEON_EP) += octeon_ep.o
>
> octeon_ep-y := octep_main.o octep_cn9k_pf.o octep_tx.o octep_rx.o \
> octep_ethtool.o octep_ctrl_mbox.o octep_ctrl_net.o \
> - octep_cnxk_pf.o
> + octep_pfvf_mbox.o octep_cnxk_pf.o
> diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c b/drivers/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c
> index 9209f1ec1b52..b5805969404f 100644
> --- a/drivers/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c
> +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c
> @@ -362,16 +362,55 @@ static void octep_setup_mbox_regs_cn93_pf(struct octep_device *oct, int q_no)
> {
> struct octep_mbox *mbox = oct->mbox[q_no];
>
> - mbox->q_no = q_no;
> -
> - /* PF mbox interrupt reg */
> - mbox->mbox_int_reg = oct->mmio[0].hw_addr + CN93_SDP_EPF_MBOX_RINT(0);
> -
> /* PF to VF DATA reg. PF writes into this reg */
> - mbox->mbox_write_reg = oct->mmio[0].hw_addr + CN93_SDP_R_MBOX_PF_VF_DATA(q_no);
> + mbox->pf_vf_data_reg = oct->mmio[0].hw_addr + CN93_SDP_MBOX_PF_VF_DATA(q_no);
>
> /* VF to PF DATA reg. PF reads from this reg */
> - mbox->mbox_read_reg = oct->mmio[0].hw_addr + CN93_SDP_R_MBOX_VF_PF_DATA(q_no);
> + mbox->vf_pf_data_reg = oct->mmio[0].hw_addr + CN93_SDP_MBOX_VF_PF_DATA(q_no);
> +}
> +
> +/* Poll for mailbox messages from VF */
> +static void octep_poll_pfvf_mailbox(struct octep_device *oct)
> +{
> + u32 vf, active_vfs, active_rings_per_vf, vf_mbox_queue;
> + u64 reg0, reg1;
> +
> + reg0 = octep_read_csr64(oct, CN93_SDP_EPF_MBOX_RINT(0));
> + reg1 = octep_read_csr64(oct, CN93_SDP_EPF_MBOX_RINT(1));
> + if (reg0 || reg1) {
> + active_vfs = CFG_GET_ACTIVE_VFS(oct->conf);
> + active_rings_per_vf = CFG_GET_ACTIVE_RPVF(oct->conf);
> + for (vf = 0; vf < active_vfs; vf++) {
> + vf_mbox_queue = vf * active_rings_per_vf;
> +
> + if (vf_mbox_queue < 64) {
> + if (!(reg0 & (0x1UL << vf_mbox_queue)))
> + continue;
> + } else {
> + if (!(reg1 & (0x1UL << (vf_mbox_queue - 64))))
> + continue;
> + }
> +
> + if (!oct->mbox[vf_mbox_queue]) {
> + dev_err(&oct->pdev->dev, "bad mbox vf %d\n", vf);
> + continue;
> + }
> + schedule_work(&oct->mbox[vf_mbox_queue]->wk.work);
> + }
> + if (reg0)
> + octep_write_csr64(oct, CN93_SDP_EPF_MBOX_RINT(0), reg0);
> + if (reg1)
> + octep_write_csr64(oct, CN93_SDP_EPF_MBOX_RINT(1), reg1);
> + }
> +}
> +
> +/* PF-VF mailbox interrupt handler */
> +static irqreturn_t octep_pfvf_mbox_intr_handler_cn93_pf(void *dev)
> +{
> + struct octep_device *oct = (struct octep_device *)dev;
> +
> + octep_poll_pfvf_mailbox(oct);
> + return IRQ_HANDLED;
> }
>
> /* Poll OEI events like heartbeat */
> @@ -403,6 +442,7 @@ static irqreturn_t octep_oei_intr_handler_cn93_pf(void *dev)
> */
> static void octep_poll_non_ioq_interrupts_cn93_pf(struct octep_device *oct)
> {
> + octep_poll_pfvf_mailbox(oct);
> octep_poll_oei_cn93_pf(oct);
> }
>
> @@ -646,6 +686,8 @@ static void octep_enable_interrupts_cn93_pf(struct octep_device *oct)
>
> octep_write_csr64(oct, CN93_SDP_EPF_MISC_RINT_ENA_W1S, intr_mask);
> octep_write_csr64(oct, CN93_SDP_EPF_DMA_RINT_ENA_W1S, intr_mask);
> + octep_write_csr64(oct, CN93_SDP_EPF_MBOX_RINT_ENA_W1S(0), -1ULL);
> + octep_write_csr64(oct, CN93_SDP_EPF_MBOX_RINT_ENA_W1S(1), -1ULL);
>
> octep_write_csr64(oct, CN93_SDP_EPF_DMA_VF_RINT_ENA_W1S(0), -1ULL);
> octep_write_csr64(oct, CN93_SDP_EPF_PP_VF_RINT_ENA_W1S(0), -1ULL);
> @@ -672,6 +714,8 @@ static void octep_disable_interrupts_cn93_pf(struct octep_device *oct)
>
> octep_write_csr64(oct, CN93_SDP_EPF_MISC_RINT_ENA_W1C, intr_mask);
> octep_write_csr64(oct, CN93_SDP_EPF_DMA_RINT_ENA_W1C, intr_mask);
> + octep_write_csr64(oct, CN93_SDP_EPF_MBOX_RINT_ENA_W1C(0), -1ULL);
> + octep_write_csr64(oct, CN93_SDP_EPF_MBOX_RINT_ENA_W1C(1), -1ULL);
>
> octep_write_csr64(oct, CN93_SDP_EPF_DMA_VF_RINT_ENA_W1C(0), -1ULL);
> octep_write_csr64(oct, CN93_SDP_EPF_PP_VF_RINT_ENA_W1C(0), -1ULL);
> @@ -807,6 +851,7 @@ void octep_device_setup_cn93_pf(struct octep_device *oct)
> oct->hw_ops.setup_oq_regs = octep_setup_oq_regs_cn93_pf;
> oct->hw_ops.setup_mbox_regs = octep_setup_mbox_regs_cn93_pf;
>
> + oct->hw_ops.mbox_intr_handler = octep_pfvf_mbox_intr_handler_cn93_pf;
> oct->hw_ops.oei_intr_handler = octep_oei_intr_handler_cn93_pf;
> oct->hw_ops.ire_intr_handler = octep_ire_intr_handler_cn93_pf;
> oct->hw_ops.ore_intr_handler = octep_ore_intr_handler_cn93_pf;
> diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_cnxk_pf.c b/drivers/net/ethernet/marvell/octeon_ep/octep_cnxk_pf.c
> index 098a0c5c4d1c..5de0b5ecbc5f 100644
> --- a/drivers/net/ethernet/marvell/octeon_ep/octep_cnxk_pf.c
> +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_cnxk_pf.c
> @@ -392,16 +392,44 @@ static void octep_setup_mbox_regs_cnxk_pf(struct octep_device *oct, int q_no)
> {
> struct octep_mbox *mbox = oct->mbox[q_no];
>
> - mbox->q_no = q_no;
> -
> - /* PF mbox interrupt reg */
> - mbox->mbox_int_reg = oct->mmio[0].hw_addr + CNXK_SDP_EPF_MBOX_RINT(0);
> -
> /* PF to VF DATA reg. PF writes into this reg */
> - mbox->mbox_write_reg = oct->mmio[0].hw_addr + CNXK_SDP_R_MBOX_PF_VF_DATA(q_no);
> + mbox->pf_vf_data_reg = oct->mmio[0].hw_addr + CNXK_SDP_MBOX_PF_VF_DATA(q_no);
>
> /* VF to PF DATA reg. PF reads from this reg */
> - mbox->mbox_read_reg = oct->mmio[0].hw_addr + CNXK_SDP_R_MBOX_VF_PF_DATA(q_no);
> + mbox->vf_pf_data_reg = oct->mmio[0].hw_addr + CNXK_SDP_MBOX_VF_PF_DATA(q_no);
> +}
> +
> +static void octep_poll_pfvf_mailbox_cnxk_pf(struct octep_device *oct)
> +{
> + u32 vf, active_vfs, active_rings_per_vf, vf_mbox_queue;
> + u64 reg0;
> +
> + reg0 = octep_read_csr64(oct, CNXK_SDP_EPF_MBOX_RINT(0));
> + if (reg0) {
> + active_vfs = CFG_GET_ACTIVE_VFS(oct->conf);
> + active_rings_per_vf = CFG_GET_ACTIVE_RPVF(oct->conf);
> + for (vf = 0; vf < active_vfs; vf++) {
> + vf_mbox_queue = vf * active_rings_per_vf;
> + if (!(reg0 & (0x1UL << vf_mbox_queue)))
> + continue;
> +
> + if (!oct->mbox[vf_mbox_queue]) {
> + dev_err(&oct->pdev->dev, "bad mbox vf %d\n", vf);
> + continue;
> + }
> + schedule_work(&oct->mbox[vf_mbox_queue]->wk.work);
> + }
> + if (reg0)
the checking of reg0 here seems unnecessary.
> + octep_write_csr64(oct, CNXK_SDP_EPF_MBOX_RINT(0), reg0);
> + }
> +}
> +
> +static irqreturn_t octep_pfvf_mbox_intr_handler_cnxk_pf(void *dev)
> +{
> + struct octep_device *oct = (struct octep_device *)dev;
> +
> + octep_poll_pfvf_mailbox_cnxk_pf(oct);
> + return IRQ_HANDLED;
> }
...
> +#include <linux/types.h>
> +#include <linux/errno.h>
> +#include <linux/string.h>
> +#include <linux/mutex.h>
> +#include <linux/jiffies.h>
> +#include <linux/sched.h>
> +#include <linux/sched/signal.h>
> +#include <linux/io.h>
> +#include <linux/pci.h>
> +#include <linux/etherdevice.h>
> +
> +#include "octep_config.h"
> +#include "octep_main.h"
> +#include "octep_pfvf_mbox.h"
> +#include "octep_ctrl_net.h"
> +
> +static void octep_pfvf_validate_version(struct octep_device *oct, u32 vf_id,
redundant space before "u32 vf_id"
> + union octep_pfvf_mbox_word cmd,
> + union octep_pfvf_mbox_word *rsp)
> +{
> + u32 vf_version = (u32)cmd.s_version.version;
> +
> + if (vf_version <= OCTEP_PFVF_MBOX_VERSION_V1)
> + rsp->s_version.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
> + else
> + rsp->s_version.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
> +}
...
> +static void octep_pfvf_dev_remove(struct octep_device *oct, u32 vf_id,
> + union octep_pfvf_mbox_word cmd,
> + union octep_pfvf_mbox_word *rsp)
> +{
> + int err;
> +
> + err = octep_ctrl_net_dev_remove(oct, vf_id);
> + if (err) {
> + rsp->s.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
> + dev_err(&oct->pdev->dev, "Failed to acknowledge fw of vf %d removal\n",
> + vf_id);
> + return;
> + }
> + rsp->s.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
> +}
> +
> +int octep_setup_pfvf_mbox(struct octep_device *oct)
> +{
> + int i = 0, num_vfs = 0, rings_per_vf = 0;
looks unnecessary initialiazation here.
> + int ring = 0;
> +
> + num_vfs = oct->conf->sriov_cfg.active_vfs;
> + rings_per_vf = oct->conf->sriov_cfg.max_rings_per_vf;
> +
> + for (i = 0; i < num_vfs; i++) {
> + ring = rings_per_vf * i;
redundant space after 'ring'? also exist at other places.
> + oct->mbox[ring] = vzalloc(sizeof(*oct->mbox[ring]));
> +
> + if (!oct->mbox[ring])
> + goto free_mbox;
> +
> + memset(oct->mbox[ring], 0, sizeof(struct octep_mbox));
> + mutex_init(&oct->mbox[ring]->lock);
> + INIT_WORK(&oct->mbox[ring]->wk.work, octep_pfvf_mbox_work);
> + oct->mbox[ring]->wk.ctxptr = oct->mbox[ring];
> + oct->mbox[ring]->oct = oct;
> + oct->mbox[ring]->vf_id = i;
> + oct->hw_ops.setup_mbox_regs(oct, ring);
> + }
> + return 0;
> +
> +free_mbox:
> + while (i) {
> + i--;
> + ring = rings_per_vf * i;
> + cancel_work_sync(&oct->mbox[ring]->wk.work);
> + mutex_destroy(&oct->mbox[ring]->lock);
> + vfree(oct->mbox[ring]);
> + oct->mbox[ring] = NULL;
> + }
> + return -ENOMEM;
> +}
> +
> +void octep_delete_pfvf_mbox(struct octep_device *oct)
> +{
> + int rings_per_vf = oct->conf->sriov_cfg.max_rings_per_vf;
> + int num_vfs = oct->conf->sriov_cfg.active_vfs;
> + int i = 0, ring = 0, vf_srn = 0;
> +
> + for (i = 0; i < num_vfs; i++) {
> + ring = vf_srn + rings_per_vf * i;
> + if (!oct->mbox[ring])
> + continue;
> +
> + if (work_pending(&oct->mbox[ring]->wk.work))
> + cancel_work_sync(&oct->mbox[ring]->wk.work);
> +
> + mutex_destroy(&oct->mbox[ring]->lock);
> + vfree(oct->mbox[ring]);
> + oct->mbox[ring] = NULL;
> + }
> +}
> +
> +static void octep_pfvf_pf_get_data(struct octep_device *oct,
> + struct octep_mbox *mbox, int vf_id,
> + union octep_pfvf_mbox_word cmd,
> + union octep_pfvf_mbox_word *rsp)
> +{
> + int length = 0;
> + int i = 0;
> + int err;
> + struct octep_iface_link_info link_info;
> + struct octep_iface_rx_stats rx_stats;
> + struct octep_iface_tx_stats tx_stats;
Variables should be placed with Revert-Chris Tree sequency
...
在 2023/12/13 11:58, Shinas Rasheed 写道:
> Add PF-VF mailbox initial version support
>
> Signed-off-by: Shinas Rasheed <[email protected]>
> ---
> V4:
> - No changes
>
> V3: https://lore.kernel.org/all/[email protected]/
> - No changes
>
> V2: https://lore.kernel.org/all/[email protected]/
> - No changes
>
> V1: https://lore.kernel.org/all/[email protected]/
>
> .../net/ethernet/marvell/octeon_ep/octep_main.h | 1 +
> .../ethernet/marvell/octeon_ep/octep_pfvf_mbox.c | 15 ++++++++++++---
> .../ethernet/marvell/octeon_ep/octep_pfvf_mbox.h | 7 +++++--
> 3 files changed, 18 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.h b/drivers/net/ethernet/marvell/octeon_ep/octep_main.h
> index 3223bb6f95ea..fee59e0e0138 100644
> --- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.h
> +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.h
> @@ -220,6 +220,7 @@ struct octep_iface_link_info {
> /* The Octeon VF device specific info data structure.*/
> struct octep_pfvf_info {
> u8 mac_addr[ETH_ALEN];
> + u32 mbox_version;
> };
>
> /* The Octeon device specific private data structure.
> diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
> index 43b40e91f7bf..baffe298a2a0 100644
> --- a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
> +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
> @@ -28,10 +28,18 @@ static void octep_pfvf_validate_version(struct octep_device *oct, u32 vf_id,
> {
> u32 vf_version = (u32)cmd.s_version.version;
>
> - if (vf_version <= OCTEP_PFVF_MBOX_VERSION_V1)
> - rsp->s_version.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
> + dev_dbg(&oct->pdev->dev, "VF id:%d VF version:%d PF version:%d\n",
> + vf_id, vf_version, OCTEP_PFVF_MBOX_VERSION_CURRENT);
> + if (vf_version < OCTEP_PFVF_MBOX_VERSION_CURRENT)
> + rsp->s_version.version = vf_version;
> else
> - rsp->s_version.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
> + rsp->s_version.version = OCTEP_PFVF_MBOX_VERSION_CURRENT;
> +
> + oct->vf_info[vf_id].mbox_version = rsp->s_version.version;
> + dev_dbg(&oct->pdev->dev, "VF id:%d negotiated VF version:%d\n",
> + vf_id, oct->vf_info[vf_id].mbox_version);
> +
> + rsp->s_version.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
> }
>
> static void octep_pfvf_get_link_status(struct octep_device *oct, u32 vf_id,
> @@ -167,6 +175,7 @@ int octep_setup_pfvf_mbox(struct octep_device *oct)
> goto free_mbox;
>
> memset(oct->mbox[ring], 0, sizeof(struct octep_mbox));
> + memset(&oct->vf_info[i], 0, sizeof(struct octep_pfvf_info));
> mutex_init(&oct->mbox[ring]->lock);
> INIT_WORK(&oct->mbox[ring]->wk.work, octep_pfvf_mbox_work);
> oct->mbox[ring]->wk.ctxptr = oct->mbox[ring];
> diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h
> index 34feeb559b0d..af4dcf5ef7f1 100644
> --- a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h
> +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h
> @@ -13,11 +13,15 @@
> #define OCTEON_SDP_16K_HW_FRS 16380UL
> #define OCTEON_SDP_64K_HW_FRS 65531UL
>
> +/* When a new command is implemented,PF Mbox version should be bumped.
> + */
> enum octep_pfvf_mbox_version {
> OCTEP_PFVF_MBOX_VERSION_V0,
> OCTEP_PFVF_MBOX_VERSION_V1,
> };
>
> +#define OCTEP_PFVF_MBOX_VERSION_CURRENT OCTEP_PFVF_MBOX_VERSION_V1
> +
> enum octep_pfvf_mbox_opcode {
> OCTEP_PFVF_MBOX_CMD_VERSION,
> OCTEP_PFVF_MBOX_CMD_SET_MTU,
> @@ -30,7 +34,7 @@ enum octep_pfvf_mbox_opcode {
> OCTEP_PFVF_MBOX_CMD_GET_LINK_STATUS,
> OCTEP_PFVF_MBOX_CMD_GET_MTU,
> OCTEP_PFVF_MBOX_CMD_DEV_REMOVE,
> - OCTEP_PFVF_MBOX_CMD_LAST,
> + OCTEP_PFVF_MBOX_CMD_MAX,
> };
This change is unrelative with
this enum is introduced in the first patch, why not directly rename it
in the first one?
>
> enum octep_pfvf_mbox_word_type {
> @@ -79,7 +83,6 @@ enum octep_pfvf_link_autoneg {
>
> #define OCTEP_PFVF_MBOX_TIMEOUT_MS 500
> #define OCTEP_PFVF_MBOX_MAX_RETRIES 2
> -#define OCTEP_PFVF_MBOX_VERSION 0
Similar here, you introduce it in first patch, and no place used, then
remove it int the second one.
Maybe you can reorganize this patchset ?
> #define OCTEP_PFVF_MBOX_MAX_DATA_SIZE 6
> #define OCTEP_PFVF_MBOX_MORE_FRAG_FLAG 1
> #define OCTEP_PFVF_MBOX_WRITE_WAIT_TIME msecs_to_jiffies(1)
Hi Shenijan
> > +#define OCTEP_PFVF_MBOX_VERSION_CURRENT
> OCTEP_PFVF_MBOX_VERSION_V1
> > +
> > enum octep_pfvf_mbox_opcode {
> > OCTEP_PFVF_MBOX_CMD_VERSION,
> > OCTEP_PFVF_MBOX_CMD_SET_MTU,
> > @@ -30,7 +34,7 @@ enum octep_pfvf_mbox_opcode {
> > OCTEP_PFVF_MBOX_CMD_GET_LINK_STATUS,
> > OCTEP_PFVF_MBOX_CMD_GET_MTU,
> > OCTEP_PFVF_MBOX_CMD_DEV_REMOVE,
> > - OCTEP_PFVF_MBOX_CMD_LAST,
> > + OCTEP_PFVF_MBOX_CMD_MAX,
> > };
> This change is unrelative with
> this enum is introduced in the first patch, why not directly rename it
> in the first one?
That is correct. These changes were ported from our original development release internal repos in order
to also reflect the development history, but I think this particular detail can be avoided by fixing it
in the original patch as it doesn't seem too relevant. I can do that in the next patchset.
> >
> > enum octep_pfvf_mbox_word_type {
> > @@ -79,7 +83,6 @@ enum octep_pfvf_link_autoneg {
> >
> > #define OCTEP_PFVF_MBOX_TIMEOUT_MS 500
> > #define OCTEP_PFVF_MBOX_MAX_RETRIES 2
> > -#define OCTEP_PFVF_MBOX_VERSION 0
> Similar here, you introduce it in first patch, and no place used, then
> remove it int the second one.
> Maybe you can reorganize this patchset ?
>
> > #define OCTEP_PFVF_MBOX_MAX_DATA_SIZE 6
> > #define OCTEP_PFVF_MBOX_MORE_FRAG_FLAG 1
> > #define OCTEP_PFVF_MBOX_WRITE_WAIT_TIME msecs_to_jiffies(1)