Extend iavf_configure_queues() to support more than 31 queues.
Virtchnl opcode used was already generic, but we have just not needed
more than one message before.

Add helper, iavf_max_vc_entries(), that determines how many entries we
could fit into virtchnl message (ending by flex array member). Will be
also used on another op later in this series.

Signed-off-by: Przemek Kitszel <[email protected]>
---
 .../net/ethernet/intel/iavf/iavf_virtchnl.c   | 55 +++++++++++++++----
 1 file changed, 45 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c 
b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
index a2f75bb4a74e..7a97fc76420f 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
@@ -8,6 +8,11 @@
 #include "iavf_ptp.h"
 #include "iavf_prototype.h"
 
+/* how many Flex Array Member entires do fit into VC message of type *ptr */
+#define iavf_max_vc_entries(ptr, flex_member) \
+       ((IAVF_MAX_AQ_BUF_SIZE - virtchnl_struct_size(ptr, flex_member, 1)) / \
+        sizeof(ptr->flex_member[0]) + 1)
+
 /**
  * iavf_send_pf_msg
  * @adapter: adapter structure
@@ -366,6 +371,14 @@ int iavf_get_vf_ptp_caps(struct iavf_adapter *adapter)
        return err;
 }
 
+static bool iavf_match_vc_op_cb(struct iavf_adapter *adapter, const void *data,
+                               enum virtchnl_ops recv_op)
+{
+       enum virtchnl_ops wanted_op = (enum virtchnl_ops)data;
+
+       return recv_op == wanted_op;
+}
+
 /**
  * iavf_configure_queues
  * @adapter: adapter structure
@@ -377,8 +390,9 @@ void iavf_configure_queues(struct iavf_adapter *adapter)
        struct virtchnl_vsi_queue_config_info *vqci;
        int pairs = adapter->num_active_queues;
        struct virtchnl_queue_pair_info *vqpi;
-       u32 i, max_frame;
        u8 rx_flags = 0;
+       u32 max_frame;
+       int max_pairs;
        size_t len;
 
        max_frame = LIBIE_MAX_RX_FRM_LEN(adapter->rx_rings->pp->p.offset);
@@ -390,22 +404,22 @@ void iavf_configure_queues(struct iavf_adapter *adapter)
                        adapter->current_op);
                return;
        }
-       adapter->current_op = VIRTCHNL_OP_CONFIG_VSI_QUEUES;
-       len = virtchnl_struct_size(vqci, qpair, pairs);
+
+       max_pairs = iavf_max_vc_entries(vqci, qpair);
+       len = virtchnl_struct_size(vqci, qpair, min(pairs, max_pairs));
        vqci = kzalloc(len, GFP_KERNEL);
        if (!vqci)
                return;
 
        if (iavf_ptp_cap_supported(adapter, VIRTCHNL_1588_PTP_CAP_RX_TSTAMP))
                rx_flags |= VIRTCHNL_PTP_RX_TSTAMP;
 
        vqci->vsi_id = adapter->vsi_res->vsi_id;
-       vqci->num_queue_pairs = pairs;
        vqpi = vqci->qpair;
-       /* Size check is not needed here - HW max is 16 queue pairs, and we
-        * can fit info for 31 of them into the AQ buffer before it overflows.
-        */
-       for (i = 0; i < pairs; i++) {
+
+       for (int i = 0, in_msg = 0; i < pairs; i++) {
+               const bool last = i + 1 == pairs;
+
                vqpi->txq.vsi_id = vqci->vsi_id;
                vqpi->txq.queue_id = i;
                vqpi->txq.ring_len = adapter->tx_rings[i].count;
@@ -423,11 +437,32 @@ void iavf_configure_queues(struct iavf_adapter *adapter)
                                                   NETIF_F_RXFCS);
                vqpi->rxq.flags = rx_flags;
                vqpi++;
+               in_msg++;
+               if (last || in_msg == max_pairs) {
+                       int err;
+
+                       adapter->current_op = VIRTCHNL_OP_CONFIG_VSI_QUEUES;
+                       vqci->num_queue_pairs = in_msg;
+
+                       iavf_send_pf_msg(adapter,
+                                        VIRTCHNL_OP_CONFIG_VSI_QUEUES,
+                                        (u8 *)vqci,
+                                        virtchnl_struct_size(vqci, qpair, 
in_msg));
+                       err = iavf_poll_virtchnl_response(adapter,
+                                                         iavf_match_vc_op_cb,
+                                                         (void 
*)VIRTCHNL_OP_CONFIG_VSI_QUEUES,
+                                                         1000);
+                       if (err)
+                               dev_warn(&adapter->pdev->dev,
+                                        "config queues poll failed, err: %d\n",
+                                        err);
+
+                       vqpi = vqci->qpair;
+                       in_msg = 0;
+               }
        }
 
        adapter->aq_required &= ~IAVF_FLAG_AQ_CONFIGURE_QUEUES;
-       iavf_send_pf_msg(adapter, VIRTCHNL_OP_CONFIG_VSI_QUEUES,
-                        (u8 *)vqci, len);
        kfree(vqci);
 }
 
-- 
2.39.3

Reply via email to