1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2020 Intel Corporation 3 */ 4 #include <sys/types.h> 5 #include <sys/stat.h> 6 #include <pthread.h> 7 #include <unistd.h> 8 9 #include <rte_spinlock.h> 10 11 #include "ice_dcf_ethdev.h" 12 #include "ice_generic_flow.h" 13 14 #define ICE_DCF_VSI_UPDATE_SERVICE_INTERVAL 100000 /* us */ 15 static rte_spinlock_t vsi_update_lock = RTE_SPINLOCK_INITIALIZER; 16 17 struct ice_dcf_reset_event_param { 18 struct ice_dcf_hw *dcf_hw; 19 20 bool vfr; /* VF reset event */ 21 uint16_t vf_id; /* The reset VF ID */ 22 }; 23 24 static __rte_always_inline void 25 ice_dcf_update_vsi_ctx(struct ice_hw *hw, uint16_t vsi_handle, 26 uint16_t vsi_map) 27 { 28 struct ice_vsi_ctx *vsi_ctx; 29 bool first_update = false; 30 uint16_t new_vsi_num; 31 32 if (unlikely(vsi_handle >= ICE_MAX_VSI)) { 33 PMD_DRV_LOG(ERR, "Invalid vsi handle %u", vsi_handle); 34 return; 35 } 36 37 vsi_ctx = hw->vsi_ctx[vsi_handle]; 38 39 if (vsi_map & VIRTCHNL_DCF_VF_VSI_VALID) { 40 if (!vsi_ctx) { 41 vsi_ctx = ice_malloc(hw, sizeof(*vsi_ctx)); 42 if (!vsi_ctx) { 43 PMD_DRV_LOG(ERR, "No memory for vsi context %u", 44 vsi_handle); 45 return; 46 } 47 hw->vsi_ctx[vsi_handle] = vsi_ctx; 48 first_update = true; 49 } 50 51 new_vsi_num = (vsi_map & VIRTCHNL_DCF_VF_VSI_ID_M) >> 52 VIRTCHNL_DCF_VF_VSI_ID_S; 53 54 /* Redirect rules if vsi mapping table changes. */ 55 if (!first_update) { 56 struct ice_flow_redirect rd; 57 58 memset(&rd, 0, sizeof(struct ice_flow_redirect)); 59 rd.type = ICE_FLOW_REDIRECT_VSI; 60 rd.vsi_handle = vsi_handle; 61 rd.new_vsi_num = new_vsi_num; 62 ice_flow_redirect((struct ice_adapter *)hw->back, &rd); 63 } else { 64 vsi_ctx->vsi_num = new_vsi_num; 65 } 66 67 PMD_DRV_LOG(DEBUG, "VF%u is assigned with vsi number %u", 68 vsi_handle, vsi_ctx->vsi_num); 69 } else { 70 hw->vsi_ctx[vsi_handle] = NULL; 71 72 ice_free(hw, vsi_ctx); 73 74 PMD_DRV_LOG(NOTICE, "VF%u is disabled", vsi_handle); 75 } 76 } 77 78 static void 79 ice_dcf_update_vf_vsi_map(struct ice_hw *hw, uint16_t num_vfs, 80 uint16_t *vf_vsi_map) 81 { 82 uint16_t vf_id; 83 84 for (vf_id = 0; vf_id < num_vfs; vf_id++) 85 ice_dcf_update_vsi_ctx(hw, vf_id, vf_vsi_map[vf_id]); 86 } 87 88 static void 89 ice_dcf_update_pf_vsi_map(struct ice_hw *hw, uint16_t pf_vsi_idx, 90 uint16_t pf_vsi_num) 91 { 92 struct ice_vsi_ctx *vsi_ctx; 93 94 if (unlikely(pf_vsi_idx >= ICE_MAX_VSI)) { 95 PMD_DRV_LOG(ERR, "Invalid vsi handle %u", pf_vsi_idx); 96 return; 97 } 98 99 vsi_ctx = hw->vsi_ctx[pf_vsi_idx]; 100 101 if (!vsi_ctx) 102 vsi_ctx = ice_malloc(hw, sizeof(*vsi_ctx)); 103 104 if (!vsi_ctx) { 105 PMD_DRV_LOG(ERR, "No memory for vsi context %u", 106 pf_vsi_idx); 107 return; 108 } 109 110 vsi_ctx->vsi_num = pf_vsi_num; 111 hw->vsi_ctx[pf_vsi_idx] = vsi_ctx; 112 113 PMD_DRV_LOG(DEBUG, "VF%u is assigned with vsi number %u", 114 pf_vsi_idx, vsi_ctx->vsi_num); 115 } 116 117 static void* 118 ice_dcf_vsi_update_service_handler(void *param) 119 { 120 struct ice_dcf_reset_event_param *reset_param = param; 121 struct ice_dcf_hw *hw = reset_param->dcf_hw; 122 struct ice_dcf_adapter *adapter; 123 124 pthread_detach(pthread_self()); 125 126 rte_delay_us(ICE_DCF_VSI_UPDATE_SERVICE_INTERVAL); 127 128 rte_spinlock_lock(&vsi_update_lock); 129 130 adapter = container_of(hw, struct ice_dcf_adapter, real_hw); 131 132 if (!ice_dcf_handle_vsi_update_event(hw)) 133 ice_dcf_update_vf_vsi_map(&adapter->parent.hw, 134 hw->num_vfs, hw->vf_vsi_map); 135 136 if (reset_param->vfr && adapter->repr_infos) { 137 struct rte_eth_dev *vf_rep_eth_dev = 138 adapter->repr_infos[reset_param->vf_id].vf_rep_eth_dev; 139 if (vf_rep_eth_dev && vf_rep_eth_dev->data->dev_started) { 140 PMD_DRV_LOG(DEBUG, "VF%u representor is resetting", 141 reset_param->vf_id); 142 ice_dcf_vf_repr_init_vlan(vf_rep_eth_dev); 143 } 144 } 145 146 if (hw->tm_conf.committed) 147 ice_dcf_replay_vf_bw(hw, reset_param->vf_id); 148 149 rte_spinlock_unlock(&vsi_update_lock); 150 151 free(param); 152 153 return NULL; 154 } 155 156 static void 157 start_vsi_reset_thread(struct ice_dcf_hw *dcf_hw, bool vfr, uint16_t vf_id) 158 { 159 #define THREAD_NAME_LEN 16 160 struct ice_dcf_reset_event_param *param; 161 char name[THREAD_NAME_LEN]; 162 pthread_t thread; 163 int ret; 164 165 param = malloc(sizeof(*param)); 166 if (!param) { 167 PMD_DRV_LOG(ERR, "Failed to allocate the memory for reset handling"); 168 return; 169 } 170 171 param->dcf_hw = dcf_hw; 172 param->vfr = vfr; 173 param->vf_id = vf_id; 174 175 snprintf(name, sizeof(name), "ice-reset-%u", vf_id); 176 ret = rte_ctrl_thread_create(&thread, name, NULL, 177 ice_dcf_vsi_update_service_handler, param); 178 if (ret != 0) { 179 PMD_DRV_LOG(ERR, "Failed to start the thread for reset handling"); 180 free(param); 181 } 182 } 183 184 static uint32_t 185 ice_dcf_convert_link_speed(enum virtchnl_link_speed virt_link_speed) 186 { 187 uint32_t speed; 188 189 switch (virt_link_speed) { 190 case VIRTCHNL_LINK_SPEED_100MB: 191 speed = 100; 192 break; 193 case VIRTCHNL_LINK_SPEED_1GB: 194 speed = 1000; 195 break; 196 case VIRTCHNL_LINK_SPEED_10GB: 197 speed = 10000; 198 break; 199 case VIRTCHNL_LINK_SPEED_40GB: 200 speed = 40000; 201 break; 202 case VIRTCHNL_LINK_SPEED_20GB: 203 speed = 20000; 204 break; 205 case VIRTCHNL_LINK_SPEED_25GB: 206 speed = 25000; 207 break; 208 case VIRTCHNL_LINK_SPEED_2_5GB: 209 speed = 2500; 210 break; 211 case VIRTCHNL_LINK_SPEED_5GB: 212 speed = 5000; 213 break; 214 default: 215 speed = 0; 216 break; 217 } 218 219 return speed; 220 } 221 222 void 223 ice_dcf_handle_pf_event_msg(struct ice_dcf_hw *dcf_hw, 224 uint8_t *msg, uint16_t msglen) 225 { 226 struct virtchnl_pf_event *pf_msg = (struct virtchnl_pf_event *)msg; 227 228 if (msglen < sizeof(struct virtchnl_pf_event)) { 229 PMD_DRV_LOG(DEBUG, "Invalid event message length : %u", msglen); 230 return; 231 } 232 233 switch (pf_msg->event) { 234 case VIRTCHNL_EVENT_RESET_IMPENDING: 235 PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_RESET_IMPENDING event"); 236 dcf_hw->resetting = true; 237 break; 238 case VIRTCHNL_EVENT_LINK_CHANGE: 239 PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_LINK_CHANGE event"); 240 dcf_hw->link_up = pf_msg->event_data.link_event.link_status; 241 if (dcf_hw->vf_res->vf_cap_flags & 242 VIRTCHNL_VF_CAP_ADV_LINK_SPEED) { 243 dcf_hw->link_speed = 244 pf_msg->event_data.link_event_adv.link_speed; 245 } else { 246 enum virtchnl_link_speed speed; 247 speed = pf_msg->event_data.link_event.link_speed; 248 dcf_hw->link_speed = ice_dcf_convert_link_speed(speed); 249 } 250 ice_dcf_link_update(dcf_hw->eth_dev, 0); 251 rte_eth_dev_callback_process(dcf_hw->eth_dev, 252 RTE_ETH_EVENT_INTR_LSC, NULL); 253 break; 254 case VIRTCHNL_EVENT_PF_DRIVER_CLOSE: 255 PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_PF_DRIVER_CLOSE event"); 256 break; 257 case VIRTCHNL_EVENT_DCF_VSI_MAP_UPDATE: 258 PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_DCF_VSI_MAP_UPDATE event : VF%u with VSI num %u", 259 pf_msg->event_data.vf_vsi_map.vf_id, 260 pf_msg->event_data.vf_vsi_map.vsi_id); 261 start_vsi_reset_thread(dcf_hw, true, 262 pf_msg->event_data.vf_vsi_map.vf_id); 263 break; 264 default: 265 PMD_DRV_LOG(ERR, "Unknown event received %u", pf_msg->event); 266 break; 267 } 268 } 269 270 static int 271 ice_dcf_query_port_ets(struct ice_hw *parent_hw, struct ice_dcf_hw *real_hw) 272 { 273 int ret; 274 275 real_hw->ets_config = (struct ice_aqc_port_ets_elem *) 276 ice_malloc(real_hw, sizeof(*real_hw->ets_config)); 277 if (!real_hw->ets_config) 278 return ICE_ERR_NO_MEMORY; 279 280 ret = ice_aq_query_port_ets(parent_hw->port_info, 281 real_hw->ets_config, sizeof(*real_hw->ets_config), 282 NULL); 283 if (ret) { 284 PMD_DRV_LOG(ERR, "DCF Query Port ETS failed"); 285 rte_free(real_hw->ets_config); 286 real_hw->ets_config = NULL; 287 return ret; 288 } 289 290 return ICE_SUCCESS; 291 } 292 293 static int 294 ice_dcf_init_parent_hw(struct ice_hw *hw) 295 { 296 struct ice_aqc_get_phy_caps_data *pcaps; 297 enum ice_status status; 298 299 status = ice_aq_get_fw_ver(hw, NULL); 300 if (status) 301 return status; 302 303 status = ice_get_caps(hw); 304 if (status) 305 return status; 306 307 hw->port_info = (struct ice_port_info *) 308 ice_malloc(hw, sizeof(*hw->port_info)); 309 if (!hw->port_info) 310 return ICE_ERR_NO_MEMORY; 311 312 /* set the back pointer to HW */ 313 hw->port_info->hw = hw; 314 315 /* Initialize port_info struct with switch configuration data */ 316 status = ice_get_initial_sw_cfg(hw); 317 if (status) 318 goto err_unroll_alloc; 319 320 pcaps = (struct ice_aqc_get_phy_caps_data *) 321 ice_malloc(hw, sizeof(*pcaps)); 322 if (!pcaps) { 323 status = ICE_ERR_NO_MEMORY; 324 goto err_unroll_alloc; 325 } 326 327 /* Initialize port_info struct with PHY capabilities */ 328 status = ice_aq_get_phy_caps(hw->port_info, false, 329 ICE_AQC_REPORT_TOPO_CAP_MEDIA, pcaps, NULL); 330 ice_free(hw, pcaps); 331 if (status) 332 goto err_unroll_alloc; 333 334 /* Initialize port_info struct with link information */ 335 status = ice_aq_get_link_info(hw->port_info, false, NULL, NULL); 336 if (status) 337 goto err_unroll_alloc; 338 339 status = ice_init_fltr_mgmt_struct(hw); 340 if (status) 341 goto err_unroll_alloc; 342 343 status = ice_init_hw_tbls(hw); 344 if (status) 345 goto err_unroll_fltr_mgmt_struct; 346 347 PMD_INIT_LOG(INFO, 348 "firmware %d.%d.%d api %d.%d.%d build 0x%08x", 349 hw->fw_maj_ver, hw->fw_min_ver, hw->fw_patch, 350 hw->api_maj_ver, hw->api_min_ver, hw->api_patch, 351 hw->fw_build); 352 353 return ICE_SUCCESS; 354 355 err_unroll_fltr_mgmt_struct: 356 ice_cleanup_fltr_mgmt_struct(hw); 357 err_unroll_alloc: 358 ice_free(hw, hw->port_info); 359 hw->port_info = NULL; 360 hw->switch_info = NULL; 361 362 return status; 363 } 364 365 static void ice_dcf_uninit_parent_hw(struct ice_hw *hw) 366 { 367 ice_cleanup_fltr_mgmt_struct(hw); 368 369 ice_free_seg(hw); 370 ice_free_hw_tbls(hw); 371 372 ice_free(hw, hw->port_info); 373 hw->port_info = NULL; 374 hw->switch_info = NULL; 375 376 ice_clear_all_vsi_ctx(hw); 377 } 378 379 static int 380 ice_dcf_load_pkg(struct ice_adapter *adapter) 381 { 382 struct ice_dcf_adapter *dcf_adapter = 383 container_of(&adapter->hw, struct ice_dcf_adapter, parent.hw); 384 struct virtchnl_pkg_info pkg_info; 385 struct dcf_virtchnl_cmd vc_cmd; 386 bool use_dsn; 387 uint64_t dsn = 0; 388 389 vc_cmd.v_op = VIRTCHNL_OP_DCF_GET_PKG_INFO; 390 vc_cmd.req_msglen = 0; 391 vc_cmd.req_msg = NULL; 392 vc_cmd.rsp_buflen = sizeof(pkg_info); 393 vc_cmd.rsp_msgbuf = (uint8_t *)&pkg_info; 394 395 use_dsn = ice_dcf_execute_virtchnl_cmd(&dcf_adapter->real_hw, &vc_cmd) == 0; 396 if (use_dsn) 397 rte_memcpy(&dsn, pkg_info.dsn, sizeof(dsn)); 398 399 return ice_load_pkg(adapter, use_dsn, dsn); 400 } 401 402 int 403 ice_dcf_init_parent_adapter(struct rte_eth_dev *eth_dev) 404 { 405 struct ice_dcf_adapter *adapter = eth_dev->data->dev_private; 406 struct ice_adapter *parent_adapter = &adapter->parent; 407 struct ice_hw *parent_hw = &parent_adapter->hw; 408 struct ice_dcf_hw *hw = &adapter->real_hw; 409 const struct rte_ether_addr *mac; 410 int err; 411 412 parent_adapter->pf.adapter = parent_adapter; 413 parent_adapter->pf.dev_data = eth_dev->data; 414 /* create a dummy main_vsi */ 415 parent_adapter->pf.main_vsi = 416 rte_zmalloc(NULL, sizeof(struct ice_vsi), 0); 417 if (!parent_adapter->pf.main_vsi) 418 return -ENOMEM; 419 parent_adapter->pf.main_vsi->adapter = parent_adapter; 420 parent_adapter->pf.adapter_stopped = 1; 421 422 parent_hw->back = parent_adapter; 423 parent_hw->mac_type = ICE_MAC_GENERIC; 424 parent_hw->vendor_id = ICE_INTEL_VENDOR_ID; 425 426 ice_init_lock(&parent_hw->adminq.sq_lock); 427 ice_init_lock(&parent_hw->adminq.rq_lock); 428 parent_hw->aq_send_cmd_fn = ice_dcf_send_aq_cmd; 429 parent_hw->aq_send_cmd_param = &adapter->real_hw; 430 parent_hw->dcf_enabled = true; 431 432 err = ice_dcf_init_parent_hw(parent_hw); 433 if (err) { 434 PMD_INIT_LOG(ERR, "failed to init the DCF parent hardware with error %d", 435 err); 436 return err; 437 } 438 439 if (hw->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_QOS) { 440 err = ice_dcf_query_port_ets(parent_hw, hw); 441 if (err) { 442 PMD_INIT_LOG(ERR, "failed to query port ets with error %d", 443 err); 444 goto uninit_hw; 445 } 446 } 447 448 err = ice_dcf_load_pkg(parent_adapter); 449 if (err) { 450 PMD_INIT_LOG(ERR, "failed to load package with error %d", 451 err); 452 goto uninit_hw; 453 } 454 455 parent_adapter->pf.main_vsi->idx = hw->num_vfs; 456 ice_dcf_update_pf_vsi_map(parent_hw, 457 parent_adapter->pf.main_vsi->idx, hw->pf_vsi_id); 458 459 ice_dcf_update_vf_vsi_map(parent_hw, hw->num_vfs, hw->vf_vsi_map); 460 461 err = ice_flow_init(parent_adapter); 462 if (err) { 463 PMD_INIT_LOG(ERR, "Failed to initialize flow"); 464 goto uninit_hw; 465 } 466 467 mac = (const struct rte_ether_addr *)hw->avf.mac.addr; 468 if (rte_is_valid_assigned_ether_addr(mac)) 469 rte_ether_addr_copy(mac, &parent_adapter->pf.dev_addr); 470 else 471 rte_eth_random_addr(parent_adapter->pf.dev_addr.addr_bytes); 472 473 eth_dev->data->mac_addrs = &parent_adapter->pf.dev_addr; 474 475 return 0; 476 477 uninit_hw: 478 ice_dcf_uninit_parent_hw(parent_hw); 479 return err; 480 } 481 482 void 483 ice_dcf_uninit_parent_adapter(struct rte_eth_dev *eth_dev) 484 { 485 struct ice_dcf_adapter *adapter = eth_dev->data->dev_private; 486 struct ice_adapter *parent_adapter = &adapter->parent; 487 struct ice_hw *parent_hw = &parent_adapter->hw; 488 489 eth_dev->data->mac_addrs = NULL; 490 rte_free(parent_adapter->pf.main_vsi); 491 parent_adapter->pf.main_vsi = NULL; 492 493 ice_flow_uninit(parent_adapter); 494 ice_dcf_uninit_parent_hw(parent_hw); 495 } 496