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 rte_spinlock_unlock(&vsi_update_lock); 147 148 free(param); 149 150 return NULL; 151 } 152 153 static void 154 start_vsi_reset_thread(struct ice_dcf_hw *dcf_hw, bool vfr, uint16_t vf_id) 155 { 156 #define THREAD_NAME_LEN 16 157 struct ice_dcf_reset_event_param *param; 158 char name[THREAD_NAME_LEN]; 159 pthread_t thread; 160 int ret; 161 162 param = malloc(sizeof(*param)); 163 if (!param) { 164 PMD_DRV_LOG(ERR, "Failed to allocate the memory for reset handling"); 165 return; 166 } 167 168 param->dcf_hw = dcf_hw; 169 param->vfr = vfr; 170 param->vf_id = vf_id; 171 172 snprintf(name, sizeof(name), "ice-reset-%u", vf_id); 173 ret = rte_ctrl_thread_create(&thread, name, NULL, 174 ice_dcf_vsi_update_service_handler, param); 175 if (ret != 0) { 176 PMD_DRV_LOG(ERR, "Failed to start the thread for reset handling"); 177 free(param); 178 } 179 } 180 181 static uint32_t 182 ice_dcf_convert_link_speed(enum virtchnl_link_speed virt_link_speed) 183 { 184 uint32_t speed; 185 186 switch (virt_link_speed) { 187 case VIRTCHNL_LINK_SPEED_100MB: 188 speed = 100; 189 break; 190 case VIRTCHNL_LINK_SPEED_1GB: 191 speed = 1000; 192 break; 193 case VIRTCHNL_LINK_SPEED_10GB: 194 speed = 10000; 195 break; 196 case VIRTCHNL_LINK_SPEED_40GB: 197 speed = 40000; 198 break; 199 case VIRTCHNL_LINK_SPEED_20GB: 200 speed = 20000; 201 break; 202 case VIRTCHNL_LINK_SPEED_25GB: 203 speed = 25000; 204 break; 205 case VIRTCHNL_LINK_SPEED_2_5GB: 206 speed = 2500; 207 break; 208 case VIRTCHNL_LINK_SPEED_5GB: 209 speed = 5000; 210 break; 211 default: 212 speed = 0; 213 break; 214 } 215 216 return speed; 217 } 218 219 void 220 ice_dcf_handle_pf_event_msg(struct ice_dcf_hw *dcf_hw, 221 uint8_t *msg, uint16_t msglen) 222 { 223 struct virtchnl_pf_event *pf_msg = (struct virtchnl_pf_event *)msg; 224 225 if (msglen < sizeof(struct virtchnl_pf_event)) { 226 PMD_DRV_LOG(DEBUG, "Invalid event message length : %u", msglen); 227 return; 228 } 229 230 switch (pf_msg->event) { 231 case VIRTCHNL_EVENT_RESET_IMPENDING: 232 PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_RESET_IMPENDING event"); 233 start_vsi_reset_thread(dcf_hw, false, 0); 234 break; 235 case VIRTCHNL_EVENT_LINK_CHANGE: 236 PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_LINK_CHANGE event"); 237 dcf_hw->link_up = pf_msg->event_data.link_event.link_status; 238 if (dcf_hw->vf_res->vf_cap_flags & 239 VIRTCHNL_VF_CAP_ADV_LINK_SPEED) { 240 dcf_hw->link_speed = 241 pf_msg->event_data.link_event_adv.link_speed; 242 } else { 243 enum virtchnl_link_speed speed; 244 speed = pf_msg->event_data.link_event.link_speed; 245 dcf_hw->link_speed = ice_dcf_convert_link_speed(speed); 246 } 247 ice_dcf_link_update(dcf_hw->eth_dev, 0); 248 rte_eth_dev_callback_process(dcf_hw->eth_dev, 249 RTE_ETH_EVENT_INTR_LSC, NULL); 250 break; 251 case VIRTCHNL_EVENT_PF_DRIVER_CLOSE: 252 PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_PF_DRIVER_CLOSE event"); 253 break; 254 case VIRTCHNL_EVENT_DCF_VSI_MAP_UPDATE: 255 PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_DCF_VSI_MAP_UPDATE event : VF%u with VSI num %u", 256 pf_msg->event_data.vf_vsi_map.vf_id, 257 pf_msg->event_data.vf_vsi_map.vsi_id); 258 start_vsi_reset_thread(dcf_hw, true, 259 pf_msg->event_data.vf_vsi_map.vf_id); 260 break; 261 default: 262 PMD_DRV_LOG(ERR, "Unknown event received %u", pf_msg->event); 263 break; 264 } 265 } 266 267 static int 268 ice_dcf_query_port_ets(struct ice_hw *parent_hw, struct ice_dcf_hw *real_hw) 269 { 270 int ret; 271 272 real_hw->ets_config = (struct ice_aqc_port_ets_elem *) 273 ice_malloc(real_hw, sizeof(*real_hw->ets_config)); 274 if (!real_hw->ets_config) 275 return ICE_ERR_NO_MEMORY; 276 277 ret = ice_aq_query_port_ets(parent_hw->port_info, 278 real_hw->ets_config, sizeof(*real_hw->ets_config), 279 NULL); 280 if (ret) { 281 PMD_DRV_LOG(ERR, "DCF Query Port ETS failed"); 282 rte_free(real_hw->ets_config); 283 real_hw->ets_config = NULL; 284 return ret; 285 } 286 287 return ICE_SUCCESS; 288 } 289 290 static int 291 ice_dcf_init_parent_hw(struct ice_hw *hw) 292 { 293 struct ice_aqc_get_phy_caps_data *pcaps; 294 enum ice_status status; 295 296 status = ice_aq_get_fw_ver(hw, NULL); 297 if (status) 298 return status; 299 300 status = ice_get_caps(hw); 301 if (status) 302 return status; 303 304 hw->port_info = (struct ice_port_info *) 305 ice_malloc(hw, sizeof(*hw->port_info)); 306 if (!hw->port_info) 307 return ICE_ERR_NO_MEMORY; 308 309 /* set the back pointer to HW */ 310 hw->port_info->hw = hw; 311 312 /* Initialize port_info struct with switch configuration data */ 313 status = ice_get_initial_sw_cfg(hw); 314 if (status) 315 goto err_unroll_alloc; 316 317 pcaps = (struct ice_aqc_get_phy_caps_data *) 318 ice_malloc(hw, sizeof(*pcaps)); 319 if (!pcaps) { 320 status = ICE_ERR_NO_MEMORY; 321 goto err_unroll_alloc; 322 } 323 324 /* Initialize port_info struct with PHY capabilities */ 325 status = ice_aq_get_phy_caps(hw->port_info, false, 326 ICE_AQC_REPORT_TOPO_CAP_MEDIA, pcaps, NULL); 327 ice_free(hw, pcaps); 328 if (status) 329 goto err_unroll_alloc; 330 331 /* Initialize port_info struct with link information */ 332 status = ice_aq_get_link_info(hw->port_info, false, NULL, NULL); 333 if (status) 334 goto err_unroll_alloc; 335 336 status = ice_init_fltr_mgmt_struct(hw); 337 if (status) 338 goto err_unroll_alloc; 339 340 status = ice_init_hw_tbls(hw); 341 if (status) 342 goto err_unroll_fltr_mgmt_struct; 343 344 PMD_INIT_LOG(INFO, 345 "firmware %d.%d.%d api %d.%d.%d build 0x%08x", 346 hw->fw_maj_ver, hw->fw_min_ver, hw->fw_patch, 347 hw->api_maj_ver, hw->api_min_ver, hw->api_patch, 348 hw->fw_build); 349 350 return ICE_SUCCESS; 351 352 err_unroll_fltr_mgmt_struct: 353 ice_cleanup_fltr_mgmt_struct(hw); 354 err_unroll_alloc: 355 ice_free(hw, hw->port_info); 356 hw->port_info = NULL; 357 358 return status; 359 } 360 361 static void ice_dcf_uninit_parent_hw(struct ice_hw *hw) 362 { 363 ice_cleanup_fltr_mgmt_struct(hw); 364 365 ice_free_seg(hw); 366 ice_free_hw_tbls(hw); 367 368 ice_free(hw, hw->port_info); 369 hw->port_info = NULL; 370 371 ice_clear_all_vsi_ctx(hw); 372 } 373 374 static int 375 ice_dcf_load_pkg(struct ice_adapter *adapter) 376 { 377 struct ice_dcf_adapter *dcf_adapter = 378 container_of(&adapter->hw, struct ice_dcf_adapter, parent.hw); 379 struct virtchnl_pkg_info pkg_info; 380 struct dcf_virtchnl_cmd vc_cmd; 381 bool use_dsn; 382 uint64_t dsn = 0; 383 384 vc_cmd.v_op = VIRTCHNL_OP_DCF_GET_PKG_INFO; 385 vc_cmd.req_msglen = 0; 386 vc_cmd.req_msg = NULL; 387 vc_cmd.rsp_buflen = sizeof(pkg_info); 388 vc_cmd.rsp_msgbuf = (uint8_t *)&pkg_info; 389 390 use_dsn = ice_dcf_execute_virtchnl_cmd(&dcf_adapter->real_hw, &vc_cmd) == 0; 391 if (use_dsn) 392 rte_memcpy(&dsn, pkg_info.dsn, sizeof(dsn)); 393 394 return ice_load_pkg(adapter, use_dsn, dsn); 395 } 396 397 int 398 ice_dcf_init_parent_adapter(struct rte_eth_dev *eth_dev) 399 { 400 struct ice_dcf_adapter *adapter = eth_dev->data->dev_private; 401 struct ice_adapter *parent_adapter = &adapter->parent; 402 struct ice_hw *parent_hw = &parent_adapter->hw; 403 struct ice_dcf_hw *hw = &adapter->real_hw; 404 const struct rte_ether_addr *mac; 405 int err; 406 407 parent_adapter->pf.adapter = parent_adapter; 408 parent_adapter->pf.dev_data = eth_dev->data; 409 /* create a dummy main_vsi */ 410 parent_adapter->pf.main_vsi = 411 rte_zmalloc(NULL, sizeof(struct ice_vsi), 0); 412 if (!parent_adapter->pf.main_vsi) 413 return -ENOMEM; 414 parent_adapter->pf.main_vsi->adapter = parent_adapter; 415 parent_adapter->pf.adapter_stopped = 1; 416 417 parent_hw->back = parent_adapter; 418 parent_hw->mac_type = ICE_MAC_GENERIC; 419 parent_hw->vendor_id = ICE_INTEL_VENDOR_ID; 420 421 ice_init_lock(&parent_hw->adminq.sq_lock); 422 ice_init_lock(&parent_hw->adminq.rq_lock); 423 parent_hw->aq_send_cmd_fn = ice_dcf_send_aq_cmd; 424 parent_hw->aq_send_cmd_param = &adapter->real_hw; 425 parent_hw->dcf_enabled = true; 426 427 err = ice_dcf_init_parent_hw(parent_hw); 428 if (err) { 429 PMD_INIT_LOG(ERR, "failed to init the DCF parent hardware with error %d", 430 err); 431 return err; 432 } 433 434 if (hw->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_QOS) { 435 err = ice_dcf_query_port_ets(parent_hw, hw); 436 if (err) { 437 PMD_INIT_LOG(ERR, "failed to query port ets with error %d", 438 err); 439 goto uninit_hw; 440 } 441 } 442 443 err = ice_dcf_load_pkg(parent_adapter); 444 if (err) { 445 PMD_INIT_LOG(ERR, "failed to load package with error %d", 446 err); 447 goto uninit_hw; 448 } 449 450 parent_adapter->pf.main_vsi->idx = hw->num_vfs; 451 ice_dcf_update_pf_vsi_map(parent_hw, 452 parent_adapter->pf.main_vsi->idx, hw->pf_vsi_id); 453 454 ice_dcf_update_vf_vsi_map(parent_hw, hw->num_vfs, hw->vf_vsi_map); 455 456 err = ice_flow_init(parent_adapter); 457 if (err) { 458 PMD_INIT_LOG(ERR, "Failed to initialize flow"); 459 goto uninit_hw; 460 } 461 462 mac = (const struct rte_ether_addr *)hw->avf.mac.addr; 463 if (rte_is_valid_assigned_ether_addr(mac)) 464 rte_ether_addr_copy(mac, &parent_adapter->pf.dev_addr); 465 else 466 rte_eth_random_addr(parent_adapter->pf.dev_addr.addr_bytes); 467 468 eth_dev->data->mac_addrs = &parent_adapter->pf.dev_addr; 469 470 return 0; 471 472 uninit_hw: 473 ice_dcf_uninit_parent_hw(parent_hw); 474 return err; 475 } 476 477 void 478 ice_dcf_uninit_parent_adapter(struct rte_eth_dev *eth_dev) 479 { 480 struct ice_dcf_adapter *adapter = eth_dev->data->dev_private; 481 struct ice_adapter *parent_adapter = &adapter->parent; 482 struct ice_hw *parent_hw = &parent_adapter->hw; 483 484 eth_dev->data->mac_addrs = NULL; 485 486 ice_flow_uninit(parent_adapter); 487 ice_dcf_uninit_parent_hw(parent_hw); 488 } 489