bnx2x: VF RSS support - PF side
[firefly-linux-kernel-4.4.55.git] / drivers / net / ethernet / broadcom / bnx2x / bnx2x_vfpf.c
index 2088063151d60ab72f59650ea36765acb8710291..a7e88a405a43fc6aadff3d9cc930fff290726c7a 100644 (file)
@@ -257,17 +257,23 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
 
                        /* humble our request */
                        req->resc_request.num_txqs =
-                               bp->acquire_resp.resc.num_txqs;
+                               min(req->resc_request.num_txqs,
+                                   bp->acquire_resp.resc.num_txqs);
                        req->resc_request.num_rxqs =
-                               bp->acquire_resp.resc.num_rxqs;
+                               min(req->resc_request.num_rxqs,
+                                   bp->acquire_resp.resc.num_rxqs);
                        req->resc_request.num_sbs =
-                               bp->acquire_resp.resc.num_sbs;
+                               min(req->resc_request.num_sbs,
+                                   bp->acquire_resp.resc.num_sbs);
                        req->resc_request.num_mac_filters =
-                               bp->acquire_resp.resc.num_mac_filters;
+                               min(req->resc_request.num_mac_filters,
+                                   bp->acquire_resp.resc.num_mac_filters);
                        req->resc_request.num_vlan_filters =
-                               bp->acquire_resp.resc.num_vlan_filters;
+                               min(req->resc_request.num_vlan_filters,
+                                   bp->acquire_resp.resc.num_vlan_filters);
                        req->resc_request.num_mc_filters =
-                               bp->acquire_resp.resc.num_mc_filters;
+                               min(req->resc_request.num_mc_filters,
+                                   bp->acquire_resp.resc.num_mc_filters);
 
                        /* Clear response buffer */
                        memset(&bp->vf2pf_mbox->resp, 0,
@@ -293,7 +299,7 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
        bp->common.flash_size = 0;
        bp->flags |=
                NO_WOL_FLAG | NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG | NO_FCOE_FLAG;
-       bp->igu_sb_cnt = 1;
+       bp->igu_sb_cnt = bp->acquire_resp.resc.num_sbs;
        bp->igu_base_sb = bp->acquire_resp.resc.hw_sbs[0].hw_sb_id;
        strlcpy(bp->fw_ver, bp->acquire_resp.pfdev_info.fw_ver,
                sizeof(bp->fw_ver));
@@ -452,6 +458,53 @@ free_irq:
        bnx2x_free_irq(bp);
 }
 
+static void bnx2x_leading_vfq_init(struct bnx2x *bp, struct bnx2x_virtf *vf,
+                                  struct bnx2x_vf_queue *q)
+{
+       u8 cl_id = vfq_cl_id(vf, q);
+       u8 func_id = FW_VF_HANDLE(vf->abs_vfid);
+
+       /* mac */
+       bnx2x_init_mac_obj(bp, &q->mac_obj,
+                          cl_id, q->cid, func_id,
+                          bnx2x_vf_sp(bp, vf, mac_rdata),
+                          bnx2x_vf_sp_map(bp, vf, mac_rdata),
+                          BNX2X_FILTER_MAC_PENDING,
+                          &vf->filter_state,
+                          BNX2X_OBJ_TYPE_RX_TX,
+                          &bp->macs_pool);
+       /* vlan */
+       bnx2x_init_vlan_obj(bp, &q->vlan_obj,
+                           cl_id, q->cid, func_id,
+                           bnx2x_vf_sp(bp, vf, vlan_rdata),
+                           bnx2x_vf_sp_map(bp, vf, vlan_rdata),
+                           BNX2X_FILTER_VLAN_PENDING,
+                           &vf->filter_state,
+                           BNX2X_OBJ_TYPE_RX_TX,
+                           &bp->vlans_pool);
+
+       /* mcast */
+       bnx2x_init_mcast_obj(bp, &vf->mcast_obj, cl_id,
+                            q->cid, func_id, func_id,
+                            bnx2x_vf_sp(bp, vf, mcast_rdata),
+                            bnx2x_vf_sp_map(bp, vf, mcast_rdata),
+                            BNX2X_FILTER_MCAST_PENDING,
+                            &vf->filter_state,
+                            BNX2X_OBJ_TYPE_RX_TX);
+
+       /* rss */
+       bnx2x_init_rss_config_obj(bp, &vf->rss_conf_obj, cl_id, q->cid,
+                                 func_id, func_id,
+                                 bnx2x_vf_sp(bp, vf, rss_rdata),
+                                 bnx2x_vf_sp_map(bp, vf, rss_rdata),
+                                 BNX2X_FILTER_RSS_CONF_PENDING,
+                                 &vf->filter_state,
+                                 BNX2X_OBJ_TYPE_RX_TX);
+
+       vf->leading_rss = cl_id;
+       q->is_leading = true;
+}
+
 /* ask the pf to open a queue for the vf */
 int bnx2x_vfpf_setup_q(struct bnx2x *bp, int fp_idx)
 {
@@ -948,7 +1001,7 @@ static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf,
 
        /* fill in pfdev info */
        resp->pfdev_info.chip_num = bp->common.chip_id;
-       resp->pfdev_info.db_size = (1 << BNX2X_DB_SHIFT);
+       resp->pfdev_info.db_size = bp->db_size;
        resp->pfdev_info.indices_per_sb = HC_SB_MAX_INDICES_E2;
        resp->pfdev_info.pf_cap = (PFVF_CAP_RSS |
                                   /* PFVF_CAP_DHC |*/ PFVF_CAP_TPA);
@@ -1054,8 +1107,13 @@ static void bnx2x_vf_mbx_init_vf(struct bnx2x *bp, struct bnx2x_virtf *vf,
        /* record ghost addresses from vf message */
        vf->spq_map = init->spq_addr;
        vf->fw_stat_map = init->stats_addr;
+       vf->stats_stride = init->stats_stride;
        vf->op_rc = bnx2x_vf_init(bp, vf, (dma_addr_t *)init->sb_addr);
 
+       /* set VF multiqueue statistics collection mode */
+       if (init->flags & VFPF_INIT_FLG_STATS_COALESCE)
+               vf->cfg_flags |= VF_CFG_STATS_COALESCE;
+
        /* response */
        bnx2x_vf_mbx_resp(bp, vf);
 }
@@ -1080,6 +1138,8 @@ static void bnx2x_vf_mbx_set_q_flags(struct bnx2x *bp, u32 mbx_q_flags,
                __set_bit(BNX2X_Q_FLG_HC, sp_q_flags);
        if (mbx_q_flags & VFPF_QUEUE_FLG_DHC)
                __set_bit(BNX2X_Q_FLG_DHC, sp_q_flags);
+       if (mbx_q_flags & VFPF_QUEUE_FLG_LEADING_RSS)
+               __set_bit(BNX2X_Q_FLG_LEADING_RSS, sp_q_flags);
 
        /* outer vlan removal is set according to PF's multi function mode */
        if (IS_MF_SD(bp))
@@ -1113,6 +1173,9 @@ static void bnx2x_vf_mbx_setup_q(struct bnx2x *bp, struct bnx2x_virtf *vf,
                struct bnx2x_queue_init_params *init_p;
                struct bnx2x_queue_setup_params *setup_p;
 
+               if (bnx2x_vfq_is_leading(q))
+                       bnx2x_leading_vfq_init(bp, vf, q);
+
                /* re-init the VF operation context */
                memset(&vf->op_params.qctor, 0 , sizeof(vf->op_params.qctor));
                setup_p = &vf->op_params.qctor.prep_qsetup;
@@ -1552,6 +1615,68 @@ static void bnx2x_vf_mbx_release_vf(struct bnx2x *bp, struct bnx2x_virtf *vf,
                bnx2x_vf_mbx_resp(bp, vf);
 }
 
+static void bnx2x_vf_mbx_update_rss(struct bnx2x *bp, struct bnx2x_virtf *vf,
+                                   struct bnx2x_vf_mbx *mbx)
+{
+       struct bnx2x_vfop_cmd cmd = {
+               .done = bnx2x_vf_mbx_resp,
+               .block = false,
+       };
+       struct bnx2x_config_rss_params *vf_op_params = &vf->op_params.rss;
+       struct vfpf_rss_tlv *rss_tlv = &mbx->msg->req.update_rss;
+
+       if (rss_tlv->ind_table_size != T_ETH_INDIRECTION_TABLE_SIZE ||
+           rss_tlv->rss_key_size != T_ETH_RSS_KEY) {
+               BNX2X_ERR("failing rss configuration of vf %d due to size mismatch\n",
+                         vf->index);
+               vf->op_rc = -EINVAL;
+               goto mbx_resp;
+       }
+
+       /* set vfop params according to rss tlv */
+       memcpy(vf_op_params->ind_table, rss_tlv->ind_table,
+              T_ETH_INDIRECTION_TABLE_SIZE);
+       memcpy(vf_op_params->rss_key, rss_tlv->rss_key,
+              sizeof(rss_tlv->rss_key));
+       vf_op_params->rss_obj = &vf->rss_conf_obj;
+       vf_op_params->rss_result_mask = rss_tlv->rss_result_mask;
+
+       /* flags handled individually for backward/forward compatability */
+       if (rss_tlv->rss_flags & VFPF_RSS_MODE_DISABLED)
+               __set_bit(BNX2X_RSS_MODE_DISABLED, &vf_op_params->rss_flags);
+       if (rss_tlv->rss_flags & VFPF_RSS_MODE_REGULAR)
+               __set_bit(BNX2X_RSS_MODE_REGULAR, &vf_op_params->rss_flags);
+       if (rss_tlv->rss_flags & VFPF_RSS_SET_SRCH)
+               __set_bit(BNX2X_RSS_SET_SRCH, &vf_op_params->rss_flags);
+       if (rss_tlv->rss_flags & VFPF_RSS_IPV4)
+               __set_bit(BNX2X_RSS_IPV4, &vf_op_params->rss_flags);
+       if (rss_tlv->rss_flags & VFPF_RSS_IPV4_TCP)
+               __set_bit(BNX2X_RSS_IPV4_TCP, &vf_op_params->rss_flags);
+       if (rss_tlv->rss_flags & VFPF_RSS_IPV4_UDP)
+               __set_bit(BNX2X_RSS_IPV4_UDP, &vf_op_params->rss_flags);
+       if (rss_tlv->rss_flags & VFPF_RSS_IPV6)
+               __set_bit(BNX2X_RSS_IPV6, &vf_op_params->rss_flags);
+       if (rss_tlv->rss_flags & VFPF_RSS_IPV6_TCP)
+               __set_bit(BNX2X_RSS_IPV6_TCP, &vf_op_params->rss_flags);
+       if (rss_tlv->rss_flags & VFPF_RSS_IPV6_UDP)
+               __set_bit(BNX2X_RSS_IPV6_UDP, &vf_op_params->rss_flags);
+
+       if ((!(rss_tlv->rss_flags & VFPF_RSS_IPV4_TCP) &&
+            rss_tlv->rss_flags & VFPF_RSS_IPV4_UDP) ||
+           (!(rss_tlv->rss_flags & VFPF_RSS_IPV6_TCP) &&
+            rss_tlv->rss_flags & VFPF_RSS_IPV6_UDP)) {
+               BNX2X_ERR("about to hit a FW assert. aborting...\n");
+               vf->op_rc = -EINVAL;
+               goto mbx_resp;
+       }
+
+       vf->op_rc = bnx2x_vfop_rss_cmd(bp, vf, &cmd);
+
+mbx_resp:
+       if (vf->op_rc)
+               bnx2x_vf_mbx_resp(bp, vf);
+}
+
 /* dispatch request */
 static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf,
                                  struct bnx2x_vf_mbx *mbx)
@@ -1588,6 +1713,9 @@ static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf,
                case CHANNEL_TLV_RELEASE:
                        bnx2x_vf_mbx_release_vf(bp, vf, mbx);
                        break;
+               case CHANNEL_TLV_UPDATE_RSS:
+                       bnx2x_vf_mbx_update_rss(bp, vf, mbx);
+                       break;
                }
 
        } else {
@@ -1607,7 +1735,7 @@ static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf,
                /* test whether we can respond to the VF (do we have an address
                 * for it?)
                 */
-               if (vf->state == VF_ACQUIRED) {
+               if (vf->state == VF_ACQUIRED || vf->state == VF_ENABLED) {
                        /* mbx_resp uses the op_rc of the VF */
                        vf->op_rc = PFVF_STATUS_NOT_SUPPORTED;