[v4,13/27] common/octeontx2: add uplink message support

Message ID 20190622132417.32694-14-jerinj@marvell.com (mailing list archive)
State Accepted, archived
Delegated to: Thomas Monjalon
Headers
Series OCTEON TX2 common and mempool driver |

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/Intel-compilation fail Compilation issues

Commit Message

Jerin Jacob Kollanukkaran June 22, 2019, 1:24 p.m. UTC
  From: Nithin Dabilpuram <ndabilpuram@marvell.com>

The events like PHY link status change by AF or PHY configuration
change by PF would call for the uplink message.
The AF initiated uplink would land it in PF and PF would further
forward to VF(if it is intended for that specific VF)

The PF initiated uplink would be distributed to all active VFs.
This patch adds support for the same.

Signed-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com>
Signed-off-by: Harman Kalra <hkalra@marvell.com>
---
 drivers/common/octeontx2/otx2_dev.c | 243 +++++++++++++++++++++++++++-
 drivers/common/octeontx2/otx2_dev.h |  11 ++
 2 files changed, 252 insertions(+), 2 deletions(-)
  

Patch

diff --git a/drivers/common/octeontx2/otx2_dev.c b/drivers/common/octeontx2/otx2_dev.c
index c5f7d5078..09943855d 100644
--- a/drivers/common/octeontx2/otx2_dev.c
+++ b/drivers/common/octeontx2/otx2_dev.c
@@ -195,6 +195,57 @@  vf_pf_process_msgs(struct otx2_dev *dev, uint16_t vf)
 	return i;
 }
 
+static int
+vf_pf_process_up_msgs(struct otx2_dev *dev, uint16_t vf)
+{
+	struct otx2_mbox *mbox = &dev->mbox_vfpf_up;
+	struct otx2_mbox_dev *mdev = &mbox->dev[vf];
+	struct mbox_hdr *req_hdr;
+	struct mbox_msghdr *msg;
+	int msgs_acked = 0;
+	int offset;
+	uint16_t i;
+
+	req_hdr = (struct mbox_hdr *)((uintptr_t)mdev->mbase + mbox->rx_start);
+	if (req_hdr->num_msgs == 0)
+		return 0;
+
+	offset = mbox->rx_start + RTE_ALIGN(sizeof(*req_hdr), MBOX_MSG_ALIGN);
+
+	for (i = 0; i < req_hdr->num_msgs; i++) {
+		msg = (struct mbox_msghdr *)((uintptr_t)mdev->mbase + offset);
+
+		msgs_acked++;
+		/* RVU_PF_FUNC_S */
+		msg->pcifunc = otx2_pfvf_func(dev->pf, vf);
+
+		switch (msg->id) {
+		case MBOX_MSG_CGX_LINK_EVENT:
+			otx2_base_dbg("PF: Msg 0x%x (%s) fn:0x%x (pf:%d,vf:%d)",
+				      msg->id, otx2_mbox_id2name(msg->id),
+				      msg->pcifunc, otx2_get_pf(msg->pcifunc),
+				      otx2_get_vf(msg->pcifunc));
+			break;
+		case MBOX_MSG_CGX_PTP_RX_INFO:
+			otx2_base_dbg("PF: Msg 0x%x (%s) fn:0x%x (pf:%d,vf:%d)",
+				      msg->id, otx2_mbox_id2name(msg->id),
+				      msg->pcifunc, otx2_get_pf(msg->pcifunc),
+				      otx2_get_vf(msg->pcifunc));
+			break;
+		default:
+			otx2_err("Not handled UP msg 0x%x (%s) func:0x%x",
+				 msg->id, otx2_mbox_id2name(msg->id),
+				 msg->pcifunc);
+		}
+		offset = mbox->rx_start + msg->next_msgoff;
+	}
+	otx2_mbox_reset(mbox, vf);
+	mdev->msgs_acked = msgs_acked;
+	rte_wmb();
+
+	return i;
+}
+
 static void
 otx2_vf_pf_mbox_handle_msg(void *param)
 {
@@ -209,6 +260,8 @@  otx2_vf_pf_mbox_handle_msg(void *param)
 			otx2_base_dbg("Process vf:%d request (pf:%d, vf:%d)",
 				       vf, dev->pf, dev->vf);
 			vf_pf_process_msgs(dev, vf);
+			/* UP messages */
+			vf_pf_process_up_msgs(dev, vf);
 			dev->intr.bits[vf/max_bits] &= ~(BIT_ULL(vf%max_bits));
 		}
 	}
@@ -291,6 +344,185 @@  otx2_process_msgs(struct otx2_dev *dev, struct otx2_mbox *mbox)
 	rte_wmb();
 }
 
+/* Copies the message received from AF and sends it to VF */
+static void
+pf_vf_mbox_send_up_msg(struct otx2_dev *dev, void *rec_msg)
+{
+	uint16_t max_bits = sizeof(dev->active_vfs[0]) * sizeof(uint64_t);
+	struct otx2_mbox *vf_mbox = &dev->mbox_vfpf_up;
+	struct msg_req *msg = rec_msg;
+	struct mbox_msghdr *vf_msg;
+	uint16_t vf;
+	size_t size;
+
+	size = RTE_ALIGN(otx2_mbox_id2size(msg->hdr.id), MBOX_MSG_ALIGN);
+	/* Send UP message to all VF's */
+	for (vf = 0; vf < vf_mbox->ndevs; vf++) {
+		/* VF active */
+		if (!(dev->active_vfs[vf / max_bits] & (BIT_ULL(vf))))
+			continue;
+
+		otx2_base_dbg("(%s) size: %zx to VF: %d",
+			      otx2_mbox_id2name(msg->hdr.id), size, vf);
+
+		/* Reserve PF/VF mbox message */
+		vf_msg = otx2_mbox_alloc_msg(vf_mbox, vf, size);
+		if (!vf_msg) {
+			otx2_err("Failed to alloc VF%d UP message", vf);
+			continue;
+		}
+		otx2_mbox_req_init(msg->hdr.id, vf_msg);
+
+		/*
+		 * Copy message from AF<->PF UP mbox
+		 * to PF<->VF UP mbox
+		 */
+		otx2_mbox_memcpy((uint8_t *)vf_msg +
+				 sizeof(struct mbox_msghdr), (uint8_t *)msg
+				 + sizeof(struct mbox_msghdr), size -
+				 sizeof(struct mbox_msghdr));
+
+		vf_msg->rc = msg->hdr.rc;
+		/* Set PF to be a sender */
+		vf_msg->pcifunc = dev->pf_func;
+
+		/* Send to VF */
+		otx2_mbox_msg_send(vf_mbox, vf);
+	}
+}
+
+static int
+otx2_mbox_up_handler_cgx_link_event(struct otx2_dev *dev,
+				    struct cgx_link_info_msg *msg,
+				    struct msg_rsp *rsp)
+{
+	struct cgx_link_user_info *linfo = &msg->link_info;
+
+	otx2_base_dbg("pf:%d/vf:%d NIC Link %s --> 0x%x (%s) from: pf:%d/vf:%d",
+		      otx2_get_pf(dev->pf_func), otx2_get_vf(dev->pf_func),
+		      linfo->link_up ? "UP" : "DOWN", msg->hdr.id,
+		      otx2_mbox_id2name(msg->hdr.id),
+		      otx2_get_pf(msg->hdr.pcifunc),
+		      otx2_get_vf(msg->hdr.pcifunc));
+
+	/* PF gets link notification from AF */
+	if (otx2_get_pf(msg->hdr.pcifunc) == 0) {
+		if (dev->ops && dev->ops->link_status_update)
+			dev->ops->link_status_update(dev, linfo);
+
+		/* Forward the same message as received from AF to VF */
+		pf_vf_mbox_send_up_msg(dev, msg);
+	} else {
+		/* VF gets link up notification */
+		if (dev->ops && dev->ops->link_status_update)
+			dev->ops->link_status_update(dev, linfo);
+	}
+
+	rsp->hdr.rc = 0;
+	return 0;
+}
+
+static int
+otx2_mbox_up_handler_cgx_ptp_rx_info(struct otx2_dev *dev,
+				     struct cgx_ptp_rx_info_msg *msg,
+				     struct msg_rsp *rsp)
+{
+	otx2_nix_dbg("pf:%d/vf:%d PTP mode %s --> 0x%x (%s) from: pf:%d/vf:%d",
+		 otx2_get_pf(dev->pf_func),
+		 otx2_get_vf(dev->pf_func),
+		 msg->ptp_en ? "ENABLED" : "DISABLED",
+		 msg->hdr.id, otx2_mbox_id2name(msg->hdr.id),
+		 otx2_get_pf(msg->hdr.pcifunc),
+		 otx2_get_vf(msg->hdr.pcifunc));
+
+	/* PF gets PTP notification from AF */
+	if (otx2_get_pf(msg->hdr.pcifunc) == 0) {
+		if (dev->ops && dev->ops->ptp_info_update)
+			dev->ops->ptp_info_update(dev, msg->ptp_en);
+
+		/* Forward the same message as received from AF to VF */
+		pf_vf_mbox_send_up_msg(dev, msg);
+	} else {
+		/* VF gets PTP notification */
+		if (dev->ops && dev->ops->ptp_info_update)
+			dev->ops->ptp_info_update(dev, msg->ptp_en);
+	}
+
+	rsp->hdr.rc = 0;
+	return 0;
+}
+
+static int
+mbox_process_msgs_up(struct otx2_dev *dev, struct mbox_msghdr *req)
+{
+	/* Check if valid, if not reply with a invalid msg */
+	if (req->sig != OTX2_MBOX_REQ_SIG)
+		return -EIO;
+
+	switch (req->id) {
+#define M(_name, _id, _fn_name, _req_type, _rsp_type)		\
+	case _id: {						\
+		struct _rsp_type *rsp;				\
+		int err;					\
+								\
+		rsp = (struct _rsp_type *)otx2_mbox_alloc_msg(	\
+			&dev->mbox_up, 0,			\
+			sizeof(struct _rsp_type));		\
+		if (!rsp)					\
+			return -ENOMEM;				\
+								\
+		rsp->hdr.id = _id;				\
+		rsp->hdr.sig = OTX2_MBOX_RSP_SIG;		\
+		rsp->hdr.pcifunc = dev->pf_func;		\
+		rsp->hdr.rc = 0;				\
+								\
+		err = otx2_mbox_up_handler_ ## _fn_name(	\
+			dev, (struct _req_type *)req, rsp);	\
+		return err;					\
+	}
+MBOX_UP_CGX_MESSAGES
+#undef M
+
+	default :
+		otx2_reply_invalid_msg(&dev->mbox_up, 0, 0, req->id);
+	}
+
+	return -ENODEV;
+}
+
+static void
+otx2_process_msgs_up(struct otx2_dev *dev, struct otx2_mbox *mbox)
+{
+	struct otx2_mbox_dev *mdev = &mbox->dev[0];
+	struct mbox_hdr *req_hdr;
+	struct mbox_msghdr *msg;
+	int i, err, offset;
+
+	req_hdr = (struct mbox_hdr *)((uintptr_t)mdev->mbase + mbox->rx_start);
+	if (req_hdr->num_msgs == 0)
+		return;
+
+	offset = mbox->rx_start + RTE_ALIGN(sizeof(*req_hdr), MBOX_MSG_ALIGN);
+	for (i = 0; i < req_hdr->num_msgs; i++) {
+		msg = (struct mbox_msghdr *)((uintptr_t)mdev->mbase + offset);
+
+		otx2_base_dbg("Message 0x%x (%s) pf:%d/vf:%d",
+				msg->id, otx2_mbox_id2name(msg->id),
+				otx2_get_pf(msg->pcifunc),
+				otx2_get_vf(msg->pcifunc));
+		err = mbox_process_msgs_up(dev, msg);
+		if (err)
+			otx2_err("Error %d handling 0x%x (%s)",
+				 err, msg->id, otx2_mbox_id2name(msg->id));
+		offset = mbox->rx_start + msg->next_msgoff;
+	}
+	/* Send mbox responses */
+	if (mdev->num_msgs) {
+		otx2_base_dbg("Reply num_msgs:%d", mdev->num_msgs);
+		otx2_mbox_msg_send(mbox, 0);
+	}
+}
+
 static void
 otx2_pf_vf_mbox_irq(void *param)
 {
@@ -303,10 +535,13 @@  otx2_pf_vf_mbox_irq(void *param)
 
 	otx2_write64(intr, dev->bar2 + RVU_VF_INT);
 	otx2_base_dbg("Irq 0x%" PRIx64 "(pf:%d,vf:%d)", intr, dev->pf, dev->vf);
-	if (intr)
+	if (intr) {
 		/* First process all configuration messages */
 		otx2_process_msgs(dev, dev->mbox);
 
+		/* Process Uplink messages */
+		otx2_process_msgs_up(dev, &dev->mbox_up);
+	}
 }
 
 static void
@@ -322,9 +557,13 @@  otx2_af_pf_mbox_irq(void *param)
 	otx2_write64(intr, dev->bar2 + RVU_PF_INT);
 
 	otx2_base_dbg("Irq 0x%" PRIx64 "(pf:%d,vf:%d)", intr, dev->pf, dev->vf);
-	if (intr)
+	if (intr) {
 		/* First process all configuration messages */
 		otx2_process_msgs(dev, dev->mbox);
+
+		/* Process Uplink messages */
+		otx2_process_msgs_up(dev, &dev->mbox_up);
+	}
 }
 
 static int
diff --git a/drivers/common/octeontx2/otx2_dev.h b/drivers/common/octeontx2/otx2_dev.h
index 70104dfa2..8fa5f32d2 100644
--- a/drivers/common/octeontx2/otx2_dev.h
+++ b/drivers/common/octeontx2/otx2_dev.h
@@ -23,6 +23,17 @@ 
 
 struct otx2_dev;
 
+/* Link status callback */
+typedef void (*otx2_link_status_t)(struct otx2_dev *dev,
+				   struct cgx_link_user_info *link);
+/* PTP info callback */
+typedef int (*otx2_ptp_info_t)(struct otx2_dev *dev, bool ptp_en);
+
+struct otx2_dev_ops {
+	otx2_link_status_t link_status_update;
+	otx2_ptp_info_t ptp_info_update;
+};
+
 #define OTX2_DEV					\
 	int node __rte_cache_aligned;			\
 	uint16_t pf;					\