Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ice: Add tx_scheduling_layers devlink param

It was observed that Tx performance was inconsistent across all queues
and/or VSIs and that it was directly connected to existing 9-layer
topology of the Tx scheduler.

Introduce new private devlink param - tx_scheduling_layers. This parameter
gives user flexibility to choose the 5-layer transmit scheduler topology
which helps to smooth out the transmit performance.

Allowed parameter values are 5 and 9.

Example usage:

Show:
devlink dev param show pci/0000:4b:00.0 name tx_scheduling_layers
pci/0000:4b:00.0:
name tx_scheduling_layers type driver-specific
values:
cmode permanent value 9

Set:
devlink dev param set pci/0000:4b:00.0 name tx_scheduling_layers value 5
cmode permanent

devlink dev param set pci/0000:4b:00.0 name tx_scheduling_layers value 9
cmode permanent

Signed-off-by: Lukasz Czapnik <lukasz.czapnik@intel.com>
Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Co-developed-by: Mateusz Polchlopek <mateusz.polchlopek@intel.com>
Signed-off-by: Mateusz Polchlopek <mateusz.polchlopek@intel.com>
Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>

authored by

Lukasz Czapnik and committed by
Tony Nguyen
109eb291 cc5776fe

+191 -10
+170 -2
drivers/net/ethernet/intel/ice/devlink/devlink.c
··· 524 524 } 525 525 526 526 /** 527 + * ice_get_tx_topo_user_sel - Read user's choice from flash 528 + * @pf: pointer to pf structure 529 + * @layers: value read from flash will be saved here 530 + * 531 + * Reads user's preference for Tx Scheduler Topology Tree from PFA TLV. 532 + * 533 + * Return: zero when read was successful, negative values otherwise. 534 + */ 535 + static int ice_get_tx_topo_user_sel(struct ice_pf *pf, uint8_t *layers) 536 + { 537 + struct ice_aqc_nvm_tx_topo_user_sel usr_sel = {}; 538 + struct ice_hw *hw = &pf->hw; 539 + int err; 540 + 541 + err = ice_acquire_nvm(hw, ICE_RES_READ); 542 + if (err) 543 + return err; 544 + 545 + err = ice_aq_read_nvm(hw, ICE_AQC_NVM_TX_TOPO_MOD_ID, 0, 546 + sizeof(usr_sel), &usr_sel, true, true, NULL); 547 + if (err) 548 + goto exit_release_res; 549 + 550 + if (usr_sel.data & ICE_AQC_NVM_TX_TOPO_USER_SEL) 551 + *layers = ICE_SCHED_5_LAYERS; 552 + else 553 + *layers = ICE_SCHED_9_LAYERS; 554 + 555 + exit_release_res: 556 + ice_release_nvm(hw); 557 + 558 + return err; 559 + } 560 + 561 + /** 562 + * ice_update_tx_topo_user_sel - Save user's preference in flash 563 + * @pf: pointer to pf structure 564 + * @layers: value to be saved in flash 565 + * 566 + * Variable "layers" defines user's preference about number of layers in Tx 567 + * Scheduler Topology Tree. This choice should be stored in PFA TLV field 568 + * and be picked up by driver, next time during init. 569 + * 570 + * Return: zero when save was successful, negative values otherwise. 571 + */ 572 + static int ice_update_tx_topo_user_sel(struct ice_pf *pf, int layers) 573 + { 574 + struct ice_aqc_nvm_tx_topo_user_sel usr_sel = {}; 575 + struct ice_hw *hw = &pf->hw; 576 + int err; 577 + 578 + err = ice_acquire_nvm(hw, ICE_RES_WRITE); 579 + if (err) 580 + return err; 581 + 582 + err = ice_aq_read_nvm(hw, ICE_AQC_NVM_TX_TOPO_MOD_ID, 0, 583 + sizeof(usr_sel), &usr_sel, true, true, NULL); 584 + if (err) 585 + goto exit_release_res; 586 + 587 + if (layers == ICE_SCHED_5_LAYERS) 588 + usr_sel.data |= ICE_AQC_NVM_TX_TOPO_USER_SEL; 589 + else 590 + usr_sel.data &= ~ICE_AQC_NVM_TX_TOPO_USER_SEL; 591 + 592 + err = ice_write_one_nvm_block(pf, ICE_AQC_NVM_TX_TOPO_MOD_ID, 2, 593 + sizeof(usr_sel.data), &usr_sel.data, 594 + true, NULL, NULL); 595 + exit_release_res: 596 + ice_release_nvm(hw); 597 + 598 + return err; 599 + } 600 + 601 + /** 602 + * ice_devlink_tx_sched_layers_get - Get tx_scheduling_layers parameter 603 + * @devlink: pointer to the devlink instance 604 + * @id: the parameter ID to set 605 + * @ctx: context to store the parameter value 606 + * 607 + * Return: zero on success and negative value on failure. 608 + */ 609 + static int ice_devlink_tx_sched_layers_get(struct devlink *devlink, u32 id, 610 + struct devlink_param_gset_ctx *ctx) 611 + { 612 + struct ice_pf *pf = devlink_priv(devlink); 613 + int err; 614 + 615 + err = ice_get_tx_topo_user_sel(pf, &ctx->val.vu8); 616 + if (err) 617 + return err; 618 + 619 + return 0; 620 + } 621 + 622 + /** 623 + * ice_devlink_tx_sched_layers_set - Set tx_scheduling_layers parameter 624 + * @devlink: pointer to the devlink instance 625 + * @id: the parameter ID to set 626 + * @ctx: context to get the parameter value 627 + * @extack: netlink extended ACK structure 628 + * 629 + * Return: zero on success and negative value on failure. 630 + */ 631 + static int ice_devlink_tx_sched_layers_set(struct devlink *devlink, u32 id, 632 + struct devlink_param_gset_ctx *ctx, 633 + struct netlink_ext_ack *extack) 634 + { 635 + struct ice_pf *pf = devlink_priv(devlink); 636 + int err; 637 + 638 + err = ice_update_tx_topo_user_sel(pf, ctx->val.vu8); 639 + if (err) 640 + return err; 641 + 642 + NL_SET_ERR_MSG_MOD(extack, 643 + "Tx scheduling layers have been changed on this device. You must do the PCI slot powercycle for the change to take effect."); 644 + 645 + return 0; 646 + } 647 + 648 + /** 649 + * ice_devlink_tx_sched_layers_validate - Validate passed tx_scheduling_layers 650 + * parameter value 651 + * @devlink: unused pointer to devlink instance 652 + * @id: the parameter ID to validate 653 + * @val: value to validate 654 + * @extack: netlink extended ACK structure 655 + * 656 + * Supported values are: 657 + * - 5 - five layers Tx Scheduler Topology Tree 658 + * - 9 - nine layers Tx Scheduler Topology Tree 659 + * 660 + * Return: zero when passed parameter value is supported. Negative value on 661 + * error. 662 + */ 663 + static int ice_devlink_tx_sched_layers_validate(struct devlink *devlink, u32 id, 664 + union devlink_param_value val, 665 + struct netlink_ext_ack *extack) 666 + { 667 + if (val.vu8 != ICE_SCHED_5_LAYERS && val.vu8 != ICE_SCHED_9_LAYERS) { 668 + NL_SET_ERR_MSG_MOD(extack, 669 + "Wrong number of tx scheduler layers provided."); 670 + return -EINVAL; 671 + } 672 + 673 + return 0; 674 + } 675 + 676 + /** 527 677 * ice_tear_down_devlink_rate_tree - removes devlink-rate exported tree 528 678 * @pf: pf struct 529 679 * ··· 1385 1235 return 0; 1386 1236 } 1387 1237 1238 + enum ice_param_id { 1239 + ICE_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX, 1240 + ICE_DEVLINK_PARAM_ID_TX_SCHED_LAYERS, 1241 + }; 1242 + 1388 1243 static const struct devlink_param ice_devlink_params[] = { 1389 1244 DEVLINK_PARAM_GENERIC(ENABLE_ROCE, BIT(DEVLINK_PARAM_CMODE_RUNTIME), 1390 1245 ice_devlink_enable_roce_get, ··· 1399 1244 ice_devlink_enable_iw_get, 1400 1245 ice_devlink_enable_iw_set, 1401 1246 ice_devlink_enable_iw_validate), 1402 - 1247 + DEVLINK_PARAM_DRIVER(ICE_DEVLINK_PARAM_ID_TX_SCHED_LAYERS, 1248 + "tx_scheduling_layers", 1249 + DEVLINK_PARAM_TYPE_U8, 1250 + BIT(DEVLINK_PARAM_CMODE_PERMANENT), 1251 + ice_devlink_tx_sched_layers_get, 1252 + ice_devlink_tx_sched_layers_set, 1253 + ice_devlink_tx_sched_layers_validate), 1403 1254 }; 1404 1255 1405 1256 static void ice_devlink_free(void *devlink_ptr) ··· 1465 1304 int ice_devlink_register_params(struct ice_pf *pf) 1466 1305 { 1467 1306 struct devlink *devlink = priv_to_devlink(pf); 1307 + struct ice_hw *hw = &pf->hw; 1308 + size_t params_size; 1309 + 1310 + params_size = ARRAY_SIZE(ice_devlink_params); 1311 + 1312 + if (!hw->func_caps.common_cap.tx_sched_topo_comp_mode_en) 1313 + params_size--; 1468 1314 1469 1315 return devl_params_register(devlink, ice_devlink_params, 1470 - ARRAY_SIZE(ice_devlink_params)); 1316 + params_size); 1471 1317 } 1472 1318 1473 1319 void ice_devlink_unregister_params(struct ice_pf *pf)
+9
drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
··· 1684 1684 1685 1685 #define ICE_AQC_NVM_START_POINT 0 1686 1686 1687 + #define ICE_AQC_NVM_TX_TOPO_MOD_ID 0x14B 1688 + 1689 + struct ice_aqc_nvm_tx_topo_user_sel { 1690 + __le16 length; 1691 + u8 data; 1692 + #define ICE_AQC_NVM_TX_TOPO_USER_SEL BIT(4) 1693 + u8 reserved; 1694 + }; 1695 + 1687 1696 /* NVM Checksum Command (direct, 0x0706) */ 1688 1697 struct ice_aqc_nvm_checksum { 1689 1698 u8 flags;
+3 -4
drivers/net/ethernet/intel/ice/ice_fw_update.c
··· 286 286 * 287 287 * Returns: zero on success, or a negative error code on failure. 288 288 */ 289 - static int 290 - ice_write_one_nvm_block(struct ice_pf *pf, u16 module, u32 offset, 291 - u16 block_size, u8 *block, bool last_cmd, 292 - u8 *reset_level, struct netlink_ext_ack *extack) 289 + int ice_write_one_nvm_block(struct ice_pf *pf, u16 module, u32 offset, 290 + u16 block_size, u8 *block, bool last_cmd, 291 + u8 *reset_level, struct netlink_ext_ack *extack) 293 292 { 294 293 u16 completion_module, completion_retval; 295 294 struct device *dev = ice_pf_to_dev(pf);
+3
drivers/net/ethernet/intel/ice/ice_fw_update.h
··· 9 9 struct netlink_ext_ack *extack); 10 10 int ice_get_pending_updates(struct ice_pf *pf, u8 *pending, 11 11 struct netlink_ext_ack *extack); 12 + int ice_write_one_nvm_block(struct ice_pf *pf, u16 module, u32 offset, 13 + u16 block_size, u8 *block, bool last_cmd, 14 + u8 *reset_level, struct netlink_ext_ack *extack); 12 15 13 16 #endif
+3 -4
drivers/net/ethernet/intel/ice/ice_nvm.c
··· 18 18 * 19 19 * Read the NVM using the admin queue commands (0x0701) 20 20 */ 21 - static int 22 - ice_aq_read_nvm(struct ice_hw *hw, u16 module_typeid, u32 offset, u16 length, 23 - void *data, bool last_command, bool read_shadow_ram, 24 - struct ice_sq_cd *cd) 21 + int ice_aq_read_nvm(struct ice_hw *hw, u16 module_typeid, u32 offset, 22 + u16 length, void *data, bool last_command, 23 + bool read_shadow_ram, struct ice_sq_cd *cd) 25 24 { 26 25 struct ice_aq_desc desc; 27 26 struct ice_aqc_nvm *cmd;
+3
drivers/net/ethernet/intel/ice/ice_nvm.h
··· 14 14 15 15 int ice_acquire_nvm(struct ice_hw *hw, enum ice_aq_res_access_type access); 16 16 void ice_release_nvm(struct ice_hw *hw); 17 + int ice_aq_read_nvm(struct ice_hw *hw, u16 module_typeid, u32 offset, 18 + u16 length, void *data, bool last_command, 19 + bool read_shadow_ram, struct ice_sq_cd *cd); 17 20 int 18 21 ice_read_flat_nvm(struct ice_hw *hw, u32 offset, u32 *length, u8 *data, 19 22 bool read_shadow_ram);