bnx2x: VF RSS support - VF side
authorAriel Elior <ariele@broadcom.com>
Wed, 4 Sep 2013 11:09:22 +0000 (14:09 +0300)
committerDavid S. Miller <davem@davemloft.net>
Thu, 5 Sep 2013 16:44:31 +0000 (12:44 -0400)
In this patch capabilities are added to the Vf driver to request
multiple queues over the VF PF channel, and the logic for requesting
rss configuration for said queues.

Signed-off-by: Ariel Elior <ariele@broadcom.com>
Signed-off-by: Eilong Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c

index e7400d9..8d726f6 100644 (file)
@@ -1942,7 +1942,7 @@ static void bnx2x_set_rx_buf_size(struct bnx2x *bp)
        }
 }
 
-static int bnx2x_init_rss_pf(struct bnx2x *bp)
+static int bnx2x_init_rss(struct bnx2x *bp)
 {
        int i;
        u8 num_eth_queues = BNX2X_NUM_ETH_QUEUES(bp);
@@ -1966,8 +1966,8 @@ static int bnx2x_init_rss_pf(struct bnx2x *bp)
        return bnx2x_config_rss_eth(bp, bp->port.pmf || !CHIP_IS_E1x(bp));
 }
 
-int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
-                       bool config_hash)
+int bnx2x_rss(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
+             bool config_hash, bool enable)
 {
        struct bnx2x_config_rss_params params = {NULL};
 
@@ -1982,17 +1982,21 @@ int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
 
        __set_bit(RAMROD_COMP_WAIT, &params.ramrod_flags);
 
-       __set_bit(BNX2X_RSS_MODE_REGULAR, &params.rss_flags);
-
-       /* RSS configuration */
-       __set_bit(BNX2X_RSS_IPV4, &params.rss_flags);
-       __set_bit(BNX2X_RSS_IPV4_TCP, &params.rss_flags);
-       __set_bit(BNX2X_RSS_IPV6, &params.rss_flags);
-       __set_bit(BNX2X_RSS_IPV6_TCP, &params.rss_flags);
-       if (rss_obj->udp_rss_v4)
-               __set_bit(BNX2X_RSS_IPV4_UDP, &params.rss_flags);
-       if (rss_obj->udp_rss_v6)
-               __set_bit(BNX2X_RSS_IPV6_UDP, &params.rss_flags);
+       if (enable) {
+               __set_bit(BNX2X_RSS_MODE_REGULAR, &params.rss_flags);
+
+               /* RSS configuration */
+               __set_bit(BNX2X_RSS_IPV4, &params.rss_flags);
+               __set_bit(BNX2X_RSS_IPV4_TCP, &params.rss_flags);
+               __set_bit(BNX2X_RSS_IPV6, &params.rss_flags);
+               __set_bit(BNX2X_RSS_IPV6_TCP, &params.rss_flags);
+               if (rss_obj->udp_rss_v4)
+                       __set_bit(BNX2X_RSS_IPV4_UDP, &params.rss_flags);
+               if (rss_obj->udp_rss_v6)
+                       __set_bit(BNX2X_RSS_IPV6_UDP, &params.rss_flags);
+       } else {
+               __set_bit(BNX2X_RSS_MODE_DISABLED, &params.rss_flags);
+       }
 
        /* Hash bits */
        params.rss_result_mask = MULTI_MASK;
@@ -2001,11 +2005,14 @@ int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
 
        if (config_hash) {
                /* RSS keys */
-               prandom_bytes(params.rss_key, sizeof(params.rss_key));
+               prandom_bytes(params.rss_key, T_ETH_RSS_KEY * 4);
                __set_bit(BNX2X_RSS_SET_SRCH, &params.rss_flags);
        }
 
-       return bnx2x_config_rss(bp, &params);
+       if (IS_PF(bp))
+               return bnx2x_config_rss(bp, &params);
+       else
+               return bnx2x_vfpf_config_rss(bp, &params);
 }
 
 static int bnx2x_init_hw(struct bnx2x *bp, u32 load_code)
@@ -2645,38 +2652,32 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 
                /* initialize FW coalescing state machines in RAM */
                bnx2x_update_coalesce(bp);
+       }
 
-               /* setup the leading queue */
-               rc = bnx2x_setup_leading(bp);
-               if (rc) {
-                       BNX2X_ERR("Setup leading failed!\n");
-                       LOAD_ERROR_EXIT(bp, load_error3);
-               }
-
-               /* set up the rest of the queues */
-               for_each_nondefault_eth_queue(bp, i) {
-                       rc = bnx2x_setup_queue(bp, &bp->fp[i], 0);
-                       if (rc) {
-                               BNX2X_ERR("Queue setup failed\n");
-                               LOAD_ERROR_EXIT(bp, load_error3);
-                       }
-               }
+       /* setup the leading queue */
+       rc = bnx2x_setup_leading(bp);
+       if (rc) {
+               BNX2X_ERR("Setup leading failed!\n");
+               LOAD_ERROR_EXIT(bp, load_error3);
+       }
 
-               /* setup rss */
-               rc = bnx2x_init_rss_pf(bp);
+       /* set up the rest of the queues */
+       for_each_nondefault_eth_queue(bp, i) {
+               if (IS_PF(bp))
+                       rc = bnx2x_setup_queue(bp, &bp->fp[i], false);
+               else /* VF */
+                       rc = bnx2x_vfpf_setup_q(bp, &bp->fp[i], false);
                if (rc) {
-                       BNX2X_ERR("PF RSS init failed\n");
+                       BNX2X_ERR("Queue %d setup failed\n", i);
                        LOAD_ERROR_EXIT(bp, load_error3);
                }
+       }
 
-       } else { /* vf */
-               for_each_eth_queue(bp, i) {
-                       rc = bnx2x_vfpf_setup_q(bp, i);
-                       if (rc) {
-                               BNX2X_ERR("Queue setup failed\n");
-                               LOAD_ERROR_EXIT(bp, load_error3);
-                       }
-               }
+       /* setup rss */
+       rc = bnx2x_init_rss(bp);
+       if (rc) {
+               BNX2X_ERR("PF RSS init failed\n");
+               LOAD_ERROR_EXIT(bp, load_error3);
        }
 
        /* Now when Clients are configured we are ready to work */
index affb764..da8fcaa 100644 (file)
@@ -105,9 +105,10 @@ void bnx2x_send_unload_done(struct bnx2x *bp, bool keep_link);
  * @rss_obj:           RSS object to use
  * @ind_table:         indirection table to configure
  * @config_hash:       re-configure RSS hash keys configuration
+ * @enable:            enabled or disabled configuration
  */
-int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
-                       bool config_hash);
+int bnx2x_rss(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
+             bool config_hash, bool enable);
 
 /**
  * bnx2x__init_func_obj - init function object
@@ -980,7 +981,7 @@ static inline int func_by_vn(struct bnx2x *bp, int vn)
 
 static inline int bnx2x_config_rss_eth(struct bnx2x *bp, bool config_hash)
 {
-       return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, config_hash);
+       return bnx2x_rss(bp, &bp->rss_conf_obj, config_hash, true);
 }
 
 /**
index c5f2251..2612e3c 100644 (file)
@@ -3281,14 +3281,14 @@ static int bnx2x_set_rss_flags(struct bnx2x *bp, struct ethtool_rxnfc *info)
                        DP(BNX2X_MSG_ETHTOOL,
                           "rss re-configured, UDP 4-tupple %s\n",
                           udp_rss_requested ? "enabled" : "disabled");
-                       return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, 0);
+                       return bnx2x_rss(bp, &bp->rss_conf_obj, false, true);
                } else if ((info->flow_type == UDP_V6_FLOW) &&
                           (bp->rss_conf_obj.udp_rss_v6 != udp_rss_requested)) {
                        bp->rss_conf_obj.udp_rss_v6 = udp_rss_requested;
                        DP(BNX2X_MSG_ETHTOOL,
                           "rss re-configured, UDP 4-tupple %s\n",
                           udp_rss_requested ? "enabled" : "disabled");
-                       return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, 0);
+                       return bnx2x_rss(bp, &bp->rss_conf_obj, false, true);
                }
                return 0;
 
index 5729aa7..c69990d 100644 (file)
@@ -8060,7 +8060,10 @@ int bnx2x_set_eth_mac(struct bnx2x *bp, bool set)
 
 int bnx2x_setup_leading(struct bnx2x *bp)
 {
-       return bnx2x_setup_queue(bp, &bp->fp[0], 1);
+       if (IS_PF(bp))
+               return bnx2x_setup_queue(bp, &bp->fp[0], true);
+       else /* VF */
+               return bnx2x_vfpf_setup_q(bp, &bp->fp[0], true);
 }
 
 /**
@@ -8074,8 +8077,10 @@ int bnx2x_set_int_mode(struct bnx2x *bp)
 {
        int rc = 0;
 
-       if (IS_VF(bp) && int_mode != BNX2X_INT_MODE_MSIX)
+       if (IS_VF(bp) && int_mode != BNX2X_INT_MODE_MSIX) {
+               BNX2X_ERR("VF not loaded since interrupt mode not msix\n");
                return -EINVAL;
+       }
 
        switch (int_mode) {
        case BNX2X_INT_MODE_MSIX:
@@ -11658,9 +11663,11 @@ static int bnx2x_init_bp(struct bnx2x *bp)
         * second status block for the L2 queue, and a third status block for
         * CNIC if supported.
         */
-       if (CNIC_SUPPORT(bp))
+       if (IS_VF(bp))
+               bp->min_msix_vec_cnt = 1;
+       else if (CNIC_SUPPORT(bp))
                bp->min_msix_vec_cnt = 3;
-       else
+       else /* PF w/o cnic */
                bp->min_msix_vec_cnt = 2;
        BNX2X_DEV_INFO("bp->min_msix_vec_cnt %d", bp->min_msix_vec_cnt);
 
@@ -12571,8 +12578,7 @@ static int bnx2x_set_qm_cid_count(struct bnx2x *bp)
  * @dev:       pci device
  *
  */
-static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev,
-                                    int cnic_cnt, bool is_vf)
+static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev, int cnic_cnt)
 {
        int index;
        u16 control = 0;
@@ -12598,7 +12604,7 @@ static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev,
 
        index = control & PCI_MSIX_FLAGS_QSIZE;
 
-       return is_vf ? index + 1 : index;
+       return index;
 }
 
 static int set_max_cos_est(int chip_id)
@@ -12678,10 +12684,13 @@ static int bnx2x_init_one(struct pci_dev *pdev,
        is_vf = set_is_vf(ent->driver_data);
        cnic_cnt = is_vf ? 0 : 1;
 
-       max_non_def_sbs = bnx2x_get_num_non_def_sbs(pdev, cnic_cnt, is_vf);
+       max_non_def_sbs = bnx2x_get_num_non_def_sbs(pdev, cnic_cnt);
+
+       /* add another SB for VF as it has no default SB */
+       max_non_def_sbs += is_vf ? 1 : 0;
 
        /* Maximum number of RSS queues: one IGU SB goes to CNIC */
-       rss_count = is_vf ? 1 : max_non_def_sbs - cnic_cnt;
+       rss_count = max_non_def_sbs - cnic_cnt;
 
        if (rss_count < 1)
                return -EINVAL;
index 8e9847f..2a8c1dc 100644 (file)
@@ -746,9 +746,12 @@ int bnx2x_vfpf_release(struct bnx2x *bp);
 int bnx2x_vfpf_release(struct bnx2x *bp);
 int bnx2x_vfpf_init(struct bnx2x *bp);
 void bnx2x_vfpf_close_vf(struct bnx2x *bp);
-int bnx2x_vfpf_setup_q(struct bnx2x *bp, int fp_idx);
+int bnx2x_vfpf_setup_q(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+                      bool is_leading);
 int bnx2x_vfpf_teardown_queue(struct bnx2x *bp, int qidx);
 int bnx2x_vfpf_config_mac(struct bnx2x *bp, u8 *addr, u8 vf_qid, bool set);
+int bnx2x_vfpf_config_rss(struct bnx2x *bp,
+                         struct bnx2x_config_rss_params *params);
 int bnx2x_vfpf_set_mcast(struct net_device *dev);
 int bnx2x_vfpf_storm_rx_mode(struct bnx2x *bp);
 
@@ -809,7 +812,7 @@ static inline int bnx2x_vfpf_acquire(struct bnx2x *bp,
 static inline int bnx2x_vfpf_release(struct bnx2x *bp) {return 0; }
 static inline int bnx2x_vfpf_init(struct bnx2x *bp) {return 0; }
 static inline void bnx2x_vfpf_close_vf(struct bnx2x *bp) {}
-static inline int bnx2x_vfpf_setup_q(struct bnx2x *bp, int fp_idx) {return 0; }
+static inline int bnx2x_vfpf_setup_q(struct bnx2x *bp, struct bnx2x_fastpath *fp, bool is_leading) {return 0; }
 static inline int bnx2x_vfpf_teardown_queue(struct bnx2x *bp, int qidx) {return 0; }
 static inline int bnx2x_vfpf_config_mac(struct bnx2x *bp, u8 *addr,
                                        u8 vf_qid, bool set) {return 0; }
index a7e88a4..6cfb887 100644 (file)
@@ -379,6 +379,8 @@ int bnx2x_vfpf_init(struct bnx2x *bp)
        req->stats_addr = bp->fw_stats_data_mapping +
                          offsetof(struct bnx2x_fw_stats_data, queue_stats);
 
+       req->stats_stride = sizeof(struct per_queue_stats);
+
        /* add list termination tlv */
        bnx2x_add_tlv(bp, req, req->first_tlv.tl.length, CHANNEL_TLV_LIST_END,
                      sizeof(struct channel_list_end_tlv));
@@ -506,11 +508,12 @@ static void bnx2x_leading_vfq_init(struct bnx2x *bp, struct bnx2x_virtf *vf,
 }
 
 /* ask the pf to open a queue for the vf */
-int bnx2x_vfpf_setup_q(struct bnx2x *bp, int fp_idx)
+int bnx2x_vfpf_setup_q(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+                      bool is_leading)
 {
        struct vfpf_setup_q_tlv *req = &bp->vf2pf_mbox->req.setup_q;
        struct pfvf_general_resp_tlv *resp = &bp->vf2pf_mbox->resp.general_resp;
-       struct bnx2x_fastpath *fp = &bp->fp[fp_idx];
+       u8 fp_idx = fp->index;
        u16 tpa_agg_size = 0, flags = 0;
        int rc;
 
@@ -526,6 +529,9 @@ int bnx2x_vfpf_setup_q(struct bnx2x *bp, int fp_idx)
                tpa_agg_size = TPA_AGG_SIZE;
        }
 
+       if (is_leading)
+               flags |= VFPF_QUEUE_FLG_LEADING_RSS;
+
        /* calculate queue flags */
        flags |= VFPF_QUEUE_FLG_STATS;
        flags |= VFPF_QUEUE_FLG_CACHE_ALIGN;
@@ -699,6 +705,71 @@ out:
        return 0;
 }
 
+/* request pf to config rss table for vf queues*/
+int bnx2x_vfpf_config_rss(struct bnx2x *bp,
+                         struct bnx2x_config_rss_params *params)
+{
+       struct pfvf_general_resp_tlv *resp = &bp->vf2pf_mbox->resp.general_resp;
+       struct vfpf_rss_tlv *req = &bp->vf2pf_mbox->req.update_rss;
+       int rc = 0;
+
+       /* clear mailbox and prep first tlv */
+       bnx2x_vfpf_prep(bp, &req->first_tlv, CHANNEL_TLV_UPDATE_RSS,
+                       sizeof(*req));
+
+       /* add list termination tlv */
+       bnx2x_add_tlv(bp, req, req->first_tlv.tl.length, CHANNEL_TLV_LIST_END,
+                     sizeof(struct channel_list_end_tlv));
+
+       memcpy(req->ind_table, params->ind_table, T_ETH_INDIRECTION_TABLE_SIZE);
+       memcpy(req->rss_key, params->rss_key, sizeof(params->rss_key));
+       req->ind_table_size = T_ETH_INDIRECTION_TABLE_SIZE;
+       req->rss_key_size = T_ETH_RSS_KEY;
+       req->rss_result_mask = params->rss_result_mask;
+
+       /* flags handled individually for backward/forward compatability */
+       if (params->rss_flags & (1 << BNX2X_RSS_MODE_DISABLED))
+               req->rss_flags |= VFPF_RSS_MODE_DISABLED;
+       if (params->rss_flags & (1 << BNX2X_RSS_MODE_REGULAR))
+               req->rss_flags |= VFPF_RSS_MODE_REGULAR;
+       if (params->rss_flags & (1 << BNX2X_RSS_SET_SRCH))
+               req->rss_flags |= VFPF_RSS_SET_SRCH;
+       if (params->rss_flags & (1 << BNX2X_RSS_IPV4))
+               req->rss_flags |= VFPF_RSS_IPV4;
+       if (params->rss_flags & (1 << BNX2X_RSS_IPV4_TCP))
+               req->rss_flags |= VFPF_RSS_IPV4_TCP;
+       if (params->rss_flags & (1 << BNX2X_RSS_IPV4_UDP))
+               req->rss_flags |= VFPF_RSS_IPV4_UDP;
+       if (params->rss_flags & (1 << BNX2X_RSS_IPV6))
+               req->rss_flags |= VFPF_RSS_IPV6;
+       if (params->rss_flags & (1 << BNX2X_RSS_IPV6_TCP))
+               req->rss_flags |= VFPF_RSS_IPV6_TCP;
+       if (params->rss_flags & (1 << BNX2X_RSS_IPV6_UDP))
+               req->rss_flags |= VFPF_RSS_IPV6_UDP;
+
+       DP(BNX2X_MSG_IOV, "rss flags %x\n", req->rss_flags);
+
+       /* output tlvs list */
+       bnx2x_dp_tlv_list(bp, req);
+
+       /* send message to pf */
+       rc = bnx2x_send_msg2pf(bp, &resp->hdr.status, bp->vf2pf_mbox_mapping);
+       if (rc) {
+               BNX2X_ERR("failed to send message to pf. rc was %d\n", rc);
+               goto out;
+       }
+
+       if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
+               BNX2X_ERR("failed to send rss message to PF over Vf PF channel %d\n",
+                         resp->hdr.status);
+               rc = -EINVAL;
+       }
+out:
+       bnx2x_vfpf_finalize(bp, &req->first_tlv);
+
+       return 0;
+}
+
 int bnx2x_vfpf_set_mcast(struct net_device *dev)
 {
        struct bnx2x *bp = netdev_priv(dev);