1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2017 Huawei Technologies Co., Ltd 3 */ 4 5 #include "hinic_compat.h" 6 #include "hinic_pmd_hwdev.h" 7 #include "hinic_pmd_hwif.h" 8 #include "hinic_pmd_mgmt.h" 9 #include "hinic_pmd_eqs.h" 10 #include "hinic_pmd_cfg.h" 11 #include "hinic_pmd_mbox.h" 12 13 bool hinic_support_nic(struct hinic_hwdev *hwdev, struct nic_service_cap *cap) 14 { 15 if (!IS_NIC_TYPE(hwdev)) 16 return false; 17 18 if (cap) 19 memcpy(cap, &hwdev->cfg_mgmt->svc_cap.nic_cap, sizeof(*cap)); 20 21 return true; 22 } 23 24 static void hinic_parse_shared_res_cap(struct service_cap *cap, 25 struct hinic_dev_cap *dev_cap, 26 __rte_unused enum func_type type) 27 { 28 struct host_shared_resource_cap *shared_cap = &cap->shared_res_cap; 29 30 shared_cap->host_pctxs = dev_cap->host_pctx_num; 31 32 if (dev_cap->host_sf_en) 33 cap->sf_en = true; 34 else 35 cap->sf_en = false; 36 37 shared_cap->host_cctxs = dev_cap->host_ccxt_num; 38 shared_cap->host_scqs = dev_cap->host_scq_num; 39 shared_cap->host_srqs = dev_cap->host_srq_num; 40 shared_cap->host_mpts = dev_cap->host_mpt_num; 41 42 PMD_DRV_LOG(INFO, "Get share resource capability:"); 43 PMD_DRV_LOG(INFO, "host_pctxs: 0x%x, host_cctxs: 0x%x, host_scqs: 0x%x, host_srqs: 0x%x, host_mpts: 0x%x", 44 shared_cap->host_pctxs, shared_cap->host_cctxs, 45 shared_cap->host_scqs, shared_cap->host_srqs, 46 shared_cap->host_mpts); 47 } 48 49 static void hinic_parse_l2nic_res_cap(struct service_cap *cap, 50 struct hinic_dev_cap *dev_cap, 51 enum func_type type) 52 { 53 struct nic_service_cap *nic_cap = &cap->nic_cap; 54 55 if (type == TYPE_PF || type == TYPE_PPF) { 56 nic_cap->max_sqs = dev_cap->nic_max_sq + 1; 57 nic_cap->max_rqs = dev_cap->nic_max_rq + 1; 58 nic_cap->vf_max_sqs = dev_cap->nic_vf_max_sq + 1; 59 nic_cap->vf_max_rqs = dev_cap->nic_vf_max_rq + 1; 60 } else { 61 nic_cap->max_sqs = dev_cap->nic_max_sq; 62 nic_cap->max_rqs = dev_cap->nic_max_rq; 63 nic_cap->vf_max_sqs = 0; 64 nic_cap->vf_max_rqs = 0; 65 } 66 67 if (dev_cap->nic_lro_en) 68 nic_cap->lro_en = true; 69 else 70 nic_cap->lro_en = false; 71 72 nic_cap->lro_sz = dev_cap->nic_lro_sz; 73 nic_cap->tso_sz = dev_cap->nic_tso_sz; 74 75 PMD_DRV_LOG(INFO, "Get l2nic resource capability:"); 76 PMD_DRV_LOG(INFO, "max_sqs: 0x%x, max_rqs: 0x%x, vf_max_sqs: 0x%x, vf_max_rqs: 0x%x", 77 nic_cap->max_sqs, nic_cap->max_rqs, 78 nic_cap->vf_max_sqs, nic_cap->vf_max_rqs); 79 } 80 81 u16 hinic_func_max_qnum(void *hwdev) 82 { 83 struct hinic_hwdev *dev = hwdev; 84 85 return dev->cfg_mgmt->svc_cap.max_sqs; 86 } 87 88 int init_cfg_mgmt(struct hinic_hwdev *hwdev) 89 { 90 struct cfg_mgmt_info *cfg_mgmt; 91 92 cfg_mgmt = kzalloc(sizeof(*cfg_mgmt), GFP_KERNEL); 93 if (!cfg_mgmt) 94 return -ENOMEM; 95 96 hwdev->cfg_mgmt = cfg_mgmt; 97 cfg_mgmt->hwdev = hwdev; 98 99 return 0; 100 } 101 102 void free_cfg_mgmt(struct hinic_hwdev *hwdev) 103 { 104 kfree(hwdev->cfg_mgmt); 105 hwdev->cfg_mgmt = NULL; 106 } 107 108 static void hinic_parse_pub_res_cap(struct service_cap *cap, 109 struct hinic_dev_cap *dev_cap, 110 enum func_type type) 111 { 112 cap->host_id = dev_cap->host_id; 113 cap->ep_id = dev_cap->ep_id; 114 cap->max_cos_id = dev_cap->max_cos_id; 115 cap->valid_cos_bitmap = dev_cap->valid_cos_bitmap; 116 cap->er_id = dev_cap->er_id; 117 cap->port_id = dev_cap->port_id; 118 119 if (type == TYPE_PF || type == TYPE_PPF) { 120 cap->max_vf = dev_cap->max_vf; 121 cap->pf_num = dev_cap->pf_num; 122 cap->pf_id_start = dev_cap->pf_id_start; 123 cap->vf_num = dev_cap->vf_num; 124 cap->vf_id_start = dev_cap->vf_id_start; 125 cap->max_sqs = dev_cap->nic_max_sq + 1; 126 cap->max_rqs = dev_cap->nic_max_rq + 1; 127 } else { 128 cap->max_vf = 0; 129 cap->max_sqs = dev_cap->nic_max_sq; 130 cap->max_rqs = dev_cap->nic_max_rq; 131 } 132 133 cap->chip_svc_type = dev_cap->svc_cap_en; 134 cap->host_total_function = dev_cap->host_total_func; 135 cap->host_oq_id_mask_val = dev_cap->host_oq_id_mask_val; 136 137 PMD_DRV_LOG(INFO, "Get public resource capability:"); 138 PMD_DRV_LOG(INFO, "host_id: 0x%x, ep_id: 0x%x, intr_type: 0x%x, " 139 "max_cos_id: 0x%x, cos_bitmap: 0x%x, er_id: 0x%x, port_id: 0x%x", 140 cap->host_id, cap->ep_id, cap->intr_chip_en, 141 cap->max_cos_id, cap->valid_cos_bitmap, cap->er_id, 142 cap->port_id); 143 PMD_DRV_LOG(INFO, "host_total_function: 0x%x, host_oq_id_mask_val: 0x%x, max_vf: 0x%x", 144 cap->host_total_function, cap->host_oq_id_mask_val, 145 cap->max_vf); 146 PMD_DRV_LOG(INFO, "chip_svc_type: 0x%x", cap->chip_svc_type); 147 PMD_DRV_LOG(INFO, "pf_num: 0x%x, pf_id_start: 0x%x, vf_num: 0x%x, vf_id_start: 0x%x", 148 cap->pf_num, cap->pf_id_start, 149 cap->vf_num, cap->vf_id_start); 150 } 151 152 static void parse_dev_cap(struct hinic_hwdev *dev, 153 struct hinic_dev_cap *dev_cap, 154 enum func_type type) 155 { 156 struct service_cap *cap = &dev->cfg_mgmt->svc_cap; 157 158 /* Public resource */ 159 hinic_parse_pub_res_cap(cap, dev_cap, type); 160 161 /* PPF managed dynamic resource */ 162 if (type == TYPE_PPF) 163 hinic_parse_shared_res_cap(cap, dev_cap, type); 164 165 /* L2 NIC resource */ 166 if (IS_NIC_TYPE(dev)) 167 hinic_parse_l2nic_res_cap(cap, dev_cap, type); 168 } 169 170 static int get_cap_from_fw(struct hinic_hwdev *dev, enum func_type type) 171 { 172 int err; 173 u16 in_len, out_len; 174 struct hinic_dev_cap dev_cap; 175 176 memset(&dev_cap, 0, sizeof(dev_cap)); 177 in_len = sizeof(dev_cap); 178 out_len = in_len; 179 dev_cap.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 180 err = hinic_msg_to_mgmt_sync(dev, HINIC_MOD_CFGM, HINIC_CFG_NIC_CAP, 181 &dev_cap, in_len, &dev_cap, &out_len, 0); 182 if (err || dev_cap.mgmt_msg_head.status || !out_len) { 183 PMD_DRV_LOG(ERR, "Get capability from FW failed, err: %d, status: %d, out_len: %d", 184 err, dev_cap.mgmt_msg_head.status, out_len); 185 return -EIO; 186 } 187 188 parse_dev_cap(dev, &dev_cap, type); 189 return 0; 190 } 191 192 static int get_cap_from_pf(struct hinic_hwdev *dev, enum func_type type) 193 { 194 int err; 195 u16 in_len, out_len; 196 struct hinic_dev_cap dev_cap; 197 198 memset(&dev_cap, 0, sizeof(dev_cap)); 199 in_len = sizeof(dev_cap); 200 out_len = in_len; 201 err = hinic_mbox_to_pf(dev, HINIC_MOD_CFGM, HINIC_CFG_MBOX_CAP, 202 &dev_cap, in_len, &dev_cap, &out_len, 203 CFG_MAX_CMD_TIMEOUT); 204 if (err || dev_cap.mgmt_msg_head.status || !out_len) { 205 PMD_DRV_LOG(ERR, "Get capability from PF failed, err: %d, status: %d, out_len: %d", 206 err, dev_cap.mgmt_msg_head.status, out_len); 207 return -EIO; 208 } 209 210 parse_dev_cap(dev, &dev_cap, type); 211 return 0; 212 } 213 214 static int get_dev_cap(struct hinic_hwdev *dev) 215 { 216 int err; 217 enum func_type type = HINIC_FUNC_TYPE(dev); 218 219 switch (type) { 220 case TYPE_PF: 221 case TYPE_PPF: 222 err = get_cap_from_fw(dev, type); 223 if (err) { 224 PMD_DRV_LOG(ERR, "Get PF/PPF capability failed"); 225 return err; 226 } 227 break; 228 case TYPE_VF: 229 err = get_cap_from_pf(dev, type); 230 if (err) { 231 PMD_DRV_LOG(ERR, "Get VF capability failed, err: %d", 232 err); 233 return err; 234 } 235 break; 236 default: 237 PMD_DRV_LOG(ERR, "Unsupported PCI function type"); 238 return -EINVAL; 239 } 240 241 return 0; 242 } 243 244 int hinic_init_capability(struct hinic_hwdev *hwdev) 245 { 246 return get_dev_cap(hwdev); 247 } 248