From: Dave Ertman <david.m.ert...@intel.com>

Allow for forwarding of RDMA and VF virt channel messages. The driver will
forward messages from the RDMA driver to the VF via the vc_send operation
and invoke the peer's vc_receive() call when receiving a virt channel
message destined for the peer driver.

Signed-off-by: Dave Ertman <david.m.ert...@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.ngu...@intel.com>
Tested-by: Andrew Bowers <andrewx.bow...@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirs...@intel.com>
---
 drivers/net/ethernet/intel/ice/ice.h          |  1 +
 drivers/net/ethernet/intel/ice/ice_idc.c      | 34 +++++++++++++++++++
 .../net/ethernet/intel/ice/ice_virtchnl_pf.c  | 34 +++++++++++++++++++
 3 files changed, 69 insertions(+)

diff --git a/drivers/net/ethernet/intel/ice/ice.h 
b/drivers/net/ethernet/intel/ice/ice.h
index 6ad1894eca3f..0e45e080a41f 100644
--- a/drivers/net/ethernet/intel/ice/ice.h
+++ b/drivers/net/ethernet/intel/ice/ice.h
@@ -392,6 +392,7 @@ struct ice_pf {
        u32 msg_enable;
        u32 num_rdma_msix;      /* Total MSIX vectors for RDMA driver */
        u32 rdma_base_vector;
+       struct iidc_peer_dev *rdma_peer;
        u32 hw_csum_rx_error;
        u32 oicr_idx;           /* Other interrupt cause MSIX vector index */
        u32 num_avail_sw_msix;  /* remaining MSIX SW vectors left unclaimed */
diff --git a/drivers/net/ethernet/intel/ice/ice_idc.c 
b/drivers/net/ethernet/intel/ice/ice_idc.c
index 748e9134a113..d287728b3cc8 100644
--- a/drivers/net/ethernet/intel/ice/ice_idc.c
+++ b/drivers/net/ethernet/intel/ice/ice_idc.c
@@ -1071,6 +1071,38 @@ ice_peer_update_vsi_filter(struct iidc_peer_dev 
*peer_dev,
        return ret;
 }
 
+/**
+ * ice_peer_vc_send - send a virt channel message from RDMA peer
+ * @peer_dev: pointer to RDMA peer dev
+ * @vf_id: the absolute VF ID of recipient of message
+ * @msg: pointer to message contents
+ * @len: len of message
+ */
+static int
+ice_peer_vc_send(struct iidc_peer_dev *peer_dev, u32 vf_id, u8 *msg, u16 len)
+{
+       struct ice_pf *pf;
+       int err;
+
+       if (!ice_validate_peer_dev(peer_dev))
+               return -EINVAL;
+       if (!msg || !len)
+               return -ENOMEM;
+
+       pf = pci_get_drvdata(peer_dev->pdev);
+       if (vf_id >= pf->num_alloc_vfs || len > ICE_AQ_MAX_BUF_LEN)
+               return -EINVAL;
+
+       /* VIRTCHNL_OP_IWARP is being used for RoCEv2 msg also */
+       err = ice_aq_send_msg_to_vf(&pf->hw, vf_id, VIRTCHNL_OP_IWARP, 0, msg,
+                                   len, NULL);
+       if (err)
+               dev_err(ice_pf_to_dev(pf), "Unable to send RDMA msg to VF, 
error %d\n",
+                       err);
+
+       return err;
+}
+
 /* Initialize the ice_ops struct, which is used in 'ice_init_peer_devices' */
 static const struct iidc_ops ops = {
        .alloc_res                      = ice_peer_alloc_res,
@@ -1083,6 +1115,7 @@ static const struct iidc_ops ops = {
        .peer_register                  = ice_peer_register,
        .peer_unregister                = ice_peer_unregister,
        .update_vsi_filter              = ice_peer_update_vsi_filter,
+       .vc_send                        = ice_peer_vc_send,
 };
 
 /**
@@ -1264,6 +1297,7 @@ int ice_init_peer_devices(struct ice_pf *pf)
                switch (ice_peers[i].id) {
                case IIDC_PEER_RDMA_ID:
                        if (test_bit(ICE_FLAG_IWARP_ENA, pf->flags)) {
+                               pf->rdma_peer = peer_dev;
                                peer_dev->msix_count = pf->num_rdma_msix;
                                entry = &pf->msix_entries[pf->rdma_base_vector];
                        }
diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c 
b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c
index 07f3d4b456c7..95e39fef0a26 100644
--- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c
@@ -3170,6 +3170,37 @@ static int ice_vc_dis_vlan_stripping(struct ice_vf *vf)
                                     v_ret, NULL, 0);
 }
 
+/**
+ * ice_vc_rdma_msg - send msg to RDMA PF from VF
+ * @vf: pointer to VF info
+ * @msg: pointer to msg buffer
+ * @len: length of the message
+ *
+ * This function is called indirectly from the AQ clean function.
+ */
+static int ice_vc_rdma_msg(struct ice_vf *vf, u8 *msg, u16 len)
+{
+       struct iidc_peer_dev *rdma_peer;
+       int ret;
+
+       rdma_peer = vf->pf->rdma_peer;
+       if (!rdma_peer) {
+               pr_err("Invalid RDMA peer attempted to send message to peer\n");
+               return -EIO;
+       }
+
+       if (!rdma_peer->peer_ops || !rdma_peer->peer_ops->vc_receive) {
+               pr_err("Incomplete RMDA peer attempting to send msg\n");
+               return -EINVAL;
+       }
+
+       ret = rdma_peer->peer_ops->vc_receive(rdma_peer, vf->vf_id, msg, len);
+       if (ret)
+               pr_err("Failed to send message to RDMA peer, error %d\n", ret);
+
+       return ret;
+}
+
 /**
  * ice_vf_init_vlan_stripping - enable/disable VLAN stripping on initialization
  * @vf: VF to enable/disable VLAN stripping for on initialization
@@ -3304,6 +3335,9 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct 
ice_rq_event_info *event)
        case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING:
                err = ice_vc_dis_vlan_stripping(vf);
                break;
+       case VIRTCHNL_OP_IWARP:
+               err = ice_vc_rdma_msg(vf, msg, msglen);
+               break;
        case VIRTCHNL_OP_UNKNOWN:
        default:
                dev_err(dev, "Unsupported opcode %d from VF %d\n", v_opcode,
-- 
2.26.2

Reply via email to