diff options
Diffstat (limited to 'drivers/infiniband/hw/ocrdma/ocrdma_hw.c')
-rw-r--r-- | drivers/infiniband/hw/ocrdma/ocrdma_hw.c | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c index bce4adf342ce..e6463cb0f988 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c | |||
@@ -771,6 +771,10 @@ static void ocrdma_process_grp5_aync(struct ocrdma_dev *dev, | |||
771 | OCRDMA_AE_PVID_MCQE_TAG_MASK) >> | 771 | OCRDMA_AE_PVID_MCQE_TAG_MASK) >> |
772 | OCRDMA_AE_PVID_MCQE_TAG_SHIFT); | 772 | OCRDMA_AE_PVID_MCQE_TAG_SHIFT); |
773 | break; | 773 | break; |
774 | |||
775 | case OCRDMA_ASYNC_EVENT_COS_VALUE: | ||
776 | atomic_set(&dev->update_sl, 1); | ||
777 | break; | ||
774 | default: | 778 | default: |
775 | /* Not interested evts. */ | 779 | /* Not interested evts. */ |
776 | break; | 780 | break; |
@@ -2265,6 +2269,8 @@ static int ocrdma_set_av_params(struct ocrdma_qp *qp, | |||
2265 | 2269 | ||
2266 | if ((ah_attr->ah_flags & IB_AH_GRH) == 0) | 2270 | if ((ah_attr->ah_flags & IB_AH_GRH) == 0) |
2267 | return -EINVAL; | 2271 | return -EINVAL; |
2272 | if (atomic_cmpxchg(&qp->dev->update_sl, 1, 0)) | ||
2273 | ocrdma_init_service_level(qp->dev); | ||
2268 | cmd->params.tclass_sq_psn |= | 2274 | cmd->params.tclass_sq_psn |= |
2269 | (ah_attr->grh.traffic_class << OCRDMA_QP_PARAMS_TCLASS_SHIFT); | 2275 | (ah_attr->grh.traffic_class << OCRDMA_QP_PARAMS_TCLASS_SHIFT); |
2270 | cmd->params.rnt_rc_sl_fl |= | 2276 | cmd->params.rnt_rc_sl_fl |= |
@@ -2298,6 +2304,10 @@ static int ocrdma_set_av_params(struct ocrdma_qp *qp, | |||
2298 | cmd->params.vlan_dmac_b4_to_b5 |= | 2304 | cmd->params.vlan_dmac_b4_to_b5 |= |
2299 | vlan_id << OCRDMA_QP_PARAMS_VLAN_SHIFT; | 2305 | vlan_id << OCRDMA_QP_PARAMS_VLAN_SHIFT; |
2300 | cmd->flags |= OCRDMA_QP_PARA_VLAN_EN_VALID; | 2306 | cmd->flags |= OCRDMA_QP_PARA_VLAN_EN_VALID; |
2307 | /* override the sl with default priority if 0 */ | ||
2308 | cmd->params.rnt_rc_sl_fl |= | ||
2309 | (ah_attr->sl ? ah_attr->sl : | ||
2310 | qp->dev->sl) << OCRDMA_QP_PARAMS_SL_SHIFT; | ||
2301 | } | 2311 | } |
2302 | return 0; | 2312 | return 0; |
2303 | } | 2313 | } |
@@ -2605,6 +2615,168 @@ int ocrdma_mbx_destroy_srq(struct ocrdma_dev *dev, struct ocrdma_srq *srq) | |||
2605 | return status; | 2615 | return status; |
2606 | } | 2616 | } |
2607 | 2617 | ||
2618 | static int ocrdma_mbx_get_dcbx_config(struct ocrdma_dev *dev, u32 ptype, | ||
2619 | struct ocrdma_dcbx_cfg *dcbxcfg) | ||
2620 | { | ||
2621 | int status = 0; | ||
2622 | dma_addr_t pa; | ||
2623 | struct ocrdma_mqe cmd; | ||
2624 | |||
2625 | struct ocrdma_get_dcbx_cfg_req *req = NULL; | ||
2626 | struct ocrdma_get_dcbx_cfg_rsp *rsp = NULL; | ||
2627 | struct pci_dev *pdev = dev->nic_info.pdev; | ||
2628 | struct ocrdma_mqe_sge *mqe_sge = cmd.u.nonemb_req.sge; | ||
2629 | |||
2630 | memset(&cmd, 0, sizeof(struct ocrdma_mqe)); | ||
2631 | cmd.hdr.pyld_len = max_t (u32, sizeof(struct ocrdma_get_dcbx_cfg_rsp), | ||
2632 | sizeof(struct ocrdma_get_dcbx_cfg_req)); | ||
2633 | req = dma_alloc_coherent(&pdev->dev, cmd.hdr.pyld_len, &pa, GFP_KERNEL); | ||
2634 | if (!req) { | ||
2635 | status = -ENOMEM; | ||
2636 | goto mem_err; | ||
2637 | } | ||
2638 | |||
2639 | cmd.hdr.spcl_sge_cnt_emb |= (1 << OCRDMA_MQE_HDR_SGE_CNT_SHIFT) & | ||
2640 | OCRDMA_MQE_HDR_SGE_CNT_MASK; | ||
2641 | mqe_sge->pa_lo = (u32) (pa & 0xFFFFFFFFUL); | ||
2642 | mqe_sge->pa_hi = (u32) upper_32_bits(pa); | ||
2643 | mqe_sge->len = cmd.hdr.pyld_len; | ||
2644 | |||
2645 | memset(req, 0, sizeof(struct ocrdma_get_dcbx_cfg_req)); | ||
2646 | ocrdma_init_mch(&req->hdr, OCRDMA_CMD_GET_DCBX_CONFIG, | ||
2647 | OCRDMA_SUBSYS_DCBX, cmd.hdr.pyld_len); | ||
2648 | req->param_type = ptype; | ||
2649 | |||
2650 | status = ocrdma_mbx_cmd(dev, &cmd); | ||
2651 | if (status) | ||
2652 | goto mbx_err; | ||
2653 | |||
2654 | rsp = (struct ocrdma_get_dcbx_cfg_rsp *)req; | ||
2655 | ocrdma_le32_to_cpu(rsp, sizeof(struct ocrdma_get_dcbx_cfg_rsp)); | ||
2656 | memcpy(dcbxcfg, &rsp->cfg, sizeof(struct ocrdma_dcbx_cfg)); | ||
2657 | |||
2658 | mbx_err: | ||
2659 | dma_free_coherent(&pdev->dev, cmd.hdr.pyld_len, req, pa); | ||
2660 | mem_err: | ||
2661 | return status; | ||
2662 | } | ||
2663 | |||
2664 | #define OCRDMA_MAX_SERVICE_LEVEL_INDEX 0x08 | ||
2665 | #define OCRDMA_DEFAULT_SERVICE_LEVEL 0x05 | ||
2666 | |||
2667 | static int ocrdma_parse_dcbxcfg_rsp(struct ocrdma_dev *dev, int ptype, | ||
2668 | struct ocrdma_dcbx_cfg *dcbxcfg, | ||
2669 | u8 *srvc_lvl) | ||
2670 | { | ||
2671 | int status = -EINVAL, indx, slindx; | ||
2672 | int ventry_cnt; | ||
2673 | struct ocrdma_app_parameter *app_param; | ||
2674 | u8 valid, proto_sel; | ||
2675 | u8 app_prio, pfc_prio; | ||
2676 | u16 proto; | ||
2677 | |||
2678 | if (!(dcbxcfg->tcv_aev_opv_st & OCRDMA_DCBX_STATE_MASK)) { | ||
2679 | pr_info("%s ocrdma%d DCBX is disabled\n", | ||
2680 | dev_name(&dev->nic_info.pdev->dev), dev->id); | ||
2681 | goto out; | ||
2682 | } | ||
2683 | |||
2684 | if (!ocrdma_is_enabled_and_synced(dcbxcfg->pfc_state)) { | ||
2685 | pr_info("%s ocrdma%d priority flow control(%s) is %s%s\n", | ||
2686 | dev_name(&dev->nic_info.pdev->dev), dev->id, | ||
2687 | (ptype > 0 ? "operational" : "admin"), | ||
2688 | (dcbxcfg->pfc_state & OCRDMA_STATE_FLAG_ENABLED) ? | ||
2689 | "enabled" : "disabled", | ||
2690 | (dcbxcfg->pfc_state & OCRDMA_STATE_FLAG_SYNC) ? | ||
2691 | "" : ", not sync'ed"); | ||
2692 | goto out; | ||
2693 | } else { | ||
2694 | pr_info("%s ocrdma%d priority flow control is enabled and sync'ed\n", | ||
2695 | dev_name(&dev->nic_info.pdev->dev), dev->id); | ||
2696 | } | ||
2697 | |||
2698 | ventry_cnt = (dcbxcfg->tcv_aev_opv_st >> | ||
2699 | OCRDMA_DCBX_APP_ENTRY_SHIFT) | ||
2700 | & OCRDMA_DCBX_STATE_MASK; | ||
2701 | |||
2702 | for (indx = 0; indx < ventry_cnt; indx++) { | ||
2703 | app_param = &dcbxcfg->app_param[indx]; | ||
2704 | valid = (app_param->valid_proto_app >> | ||
2705 | OCRDMA_APP_PARAM_VALID_SHIFT) | ||
2706 | & OCRDMA_APP_PARAM_VALID_MASK; | ||
2707 | proto_sel = (app_param->valid_proto_app | ||
2708 | >> OCRDMA_APP_PARAM_PROTO_SEL_SHIFT) | ||
2709 | & OCRDMA_APP_PARAM_PROTO_SEL_MASK; | ||
2710 | proto = app_param->valid_proto_app & | ||
2711 | OCRDMA_APP_PARAM_APP_PROTO_MASK; | ||
2712 | |||
2713 | if ( | ||
2714 | valid && proto == OCRDMA_APP_PROTO_ROCE && | ||
2715 | proto_sel == OCRDMA_PROTO_SELECT_L2) { | ||
2716 | for (slindx = 0; slindx < | ||
2717 | OCRDMA_MAX_SERVICE_LEVEL_INDEX; slindx++) { | ||
2718 | app_prio = ocrdma_get_app_prio( | ||
2719 | (u8 *)app_param->app_prio, | ||
2720 | slindx); | ||
2721 | pfc_prio = ocrdma_get_pfc_prio( | ||
2722 | (u8 *)dcbxcfg->pfc_prio, | ||
2723 | slindx); | ||
2724 | |||
2725 | if (app_prio && pfc_prio) { | ||
2726 | *srvc_lvl = slindx; | ||
2727 | status = 0; | ||
2728 | goto out; | ||
2729 | } | ||
2730 | } | ||
2731 | if (slindx == OCRDMA_MAX_SERVICE_LEVEL_INDEX) { | ||
2732 | pr_info("%s ocrdma%d application priority not set for 0x%x protocol\n", | ||
2733 | dev_name(&dev->nic_info.pdev->dev), | ||
2734 | dev->id, proto); | ||
2735 | } | ||
2736 | } | ||
2737 | } | ||
2738 | |||
2739 | out: | ||
2740 | return status; | ||
2741 | } | ||
2742 | |||
2743 | void ocrdma_init_service_level(struct ocrdma_dev *dev) | ||
2744 | { | ||
2745 | int status = 0, indx; | ||
2746 | struct ocrdma_dcbx_cfg dcbxcfg; | ||
2747 | u8 srvc_lvl = OCRDMA_DEFAULT_SERVICE_LEVEL; | ||
2748 | int ptype = OCRDMA_PARAMETER_TYPE_OPER; | ||
2749 | |||
2750 | for (indx = 0; indx < 2; indx++) { | ||
2751 | status = ocrdma_mbx_get_dcbx_config(dev, ptype, &dcbxcfg); | ||
2752 | if (status) { | ||
2753 | pr_err("%s(): status=%d\n", __func__, status); | ||
2754 | ptype = OCRDMA_PARAMETER_TYPE_ADMIN; | ||
2755 | continue; | ||
2756 | } | ||
2757 | |||
2758 | status = ocrdma_parse_dcbxcfg_rsp(dev, ptype, | ||
2759 | &dcbxcfg, &srvc_lvl); | ||
2760 | if (status) { | ||
2761 | ptype = OCRDMA_PARAMETER_TYPE_ADMIN; | ||
2762 | continue; | ||
2763 | } | ||
2764 | |||
2765 | break; | ||
2766 | } | ||
2767 | |||
2768 | if (status) | ||
2769 | pr_info("%s ocrdma%d service level default\n", | ||
2770 | dev_name(&dev->nic_info.pdev->dev), dev->id); | ||
2771 | else | ||
2772 | pr_info("%s ocrdma%d service level %d\n", | ||
2773 | dev_name(&dev->nic_info.pdev->dev), dev->id, | ||
2774 | srvc_lvl); | ||
2775 | |||
2776 | dev->pfc_state = ocrdma_is_enabled_and_synced(dcbxcfg.pfc_state); | ||
2777 | dev->sl = srvc_lvl; | ||
2778 | } | ||
2779 | |||
2608 | int ocrdma_alloc_av(struct ocrdma_dev *dev, struct ocrdma_ah *ah) | 2780 | int ocrdma_alloc_av(struct ocrdma_dev *dev, struct ocrdma_ah *ah) |
2609 | { | 2781 | { |
2610 | int i; | 2782 | int i; |