ice_switch.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Copyright (c) 2018, Intel Corporation. */
  3. #include "ice_switch.h"
  4. /**
  5. * ice_aq_get_sw_cfg - get switch configuration
  6. * @hw: pointer to the hardware structure
  7. * @buf: pointer to the result buffer
  8. * @buf_size: length of the buffer available for response
  9. * @req_desc: pointer to requested descriptor
  10. * @num_elems: pointer to number of elements
  11. * @cd: pointer to command details structure or NULL
  12. *
  13. * Get switch configuration (0x0200) to be placed in 'buff'.
  14. * This admin command returns information such as initial VSI/port number
  15. * and switch ID it belongs to.
  16. *
  17. * NOTE: *req_desc is both an input/output parameter.
  18. * The caller of this function first calls this function with *request_desc set
  19. * to 0. If the response from f/w has *req_desc set to 0, all the switch
  20. * configuration information has been returned; if non-zero (meaning not all
  21. * the information was returned), the caller should call this function again
  22. * with *req_desc set to the previous value returned by f/w to get the
  23. * next block of switch configuration information.
  24. *
  25. * *num_elems is output only parameter. This reflects the number of elements
  26. * in response buffer. The caller of this function to use *num_elems while
  27. * parsing the response buffer.
  28. */
  29. static enum ice_status
  30. ice_aq_get_sw_cfg(struct ice_hw *hw, struct ice_aqc_get_sw_cfg_resp *buf,
  31. u16 buf_size, u16 *req_desc, u16 *num_elems,
  32. struct ice_sq_cd *cd)
  33. {
  34. struct ice_aqc_get_sw_cfg *cmd;
  35. enum ice_status status;
  36. struct ice_aq_desc desc;
  37. ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sw_cfg);
  38. cmd = &desc.params.get_sw_conf;
  39. cmd->element = cpu_to_le16(*req_desc);
  40. status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
  41. if (!status) {
  42. *req_desc = le16_to_cpu(cmd->element);
  43. *num_elems = le16_to_cpu(cmd->num_elems);
  44. }
  45. return status;
  46. }
  47. /* ice_init_port_info - Initialize port_info with switch configuration data
  48. * @pi: pointer to port_info
  49. * @vsi_port_num: VSI number or port number
  50. * @type: Type of switch element (port or VSI)
  51. * @swid: switch ID of the switch the element is attached to
  52. * @pf_vf_num: PF or VF number
  53. * @is_vf: true if the element is a VF, false otherwise
  54. */
  55. static void
  56. ice_init_port_info(struct ice_port_info *pi, u16 vsi_port_num, u8 type,
  57. u16 swid, u16 pf_vf_num, bool is_vf)
  58. {
  59. switch (type) {
  60. case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT:
  61. pi->lport = (u8)(vsi_port_num & ICE_LPORT_MASK);
  62. pi->sw_id = swid;
  63. pi->pf_vf_num = pf_vf_num;
  64. pi->is_vf = is_vf;
  65. pi->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL;
  66. pi->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL;
  67. break;
  68. default:
  69. ice_debug(pi->hw, ICE_DBG_SW,
  70. "incorrect VSI/port type received\n");
  71. break;
  72. }
  73. }
  74. /* ice_get_initial_sw_cfg - Get initial port and default VSI data
  75. * @hw: pointer to the hardware structure
  76. */
  77. enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw)
  78. {
  79. struct ice_aqc_get_sw_cfg_resp *rbuf;
  80. enum ice_status status;
  81. u16 req_desc = 0;
  82. u16 num_elems;
  83. u16 i;
  84. rbuf = devm_kzalloc(ice_hw_to_dev(hw), ICE_SW_CFG_MAX_BUF_LEN,
  85. GFP_KERNEL);
  86. if (!rbuf)
  87. return ICE_ERR_NO_MEMORY;
  88. /* Multiple calls to ice_aq_get_sw_cfg may be required
  89. * to get all the switch configuration information. The need
  90. * for additional calls is indicated by ice_aq_get_sw_cfg
  91. * writing a non-zero value in req_desc
  92. */
  93. do {
  94. status = ice_aq_get_sw_cfg(hw, rbuf, ICE_SW_CFG_MAX_BUF_LEN,
  95. &req_desc, &num_elems, NULL);
  96. if (status)
  97. break;
  98. for (i = 0; i < num_elems; i++) {
  99. struct ice_aqc_get_sw_cfg_resp_elem *ele;
  100. u16 pf_vf_num, swid, vsi_port_num;
  101. bool is_vf = false;
  102. u8 type;
  103. ele = rbuf[i].elements;
  104. vsi_port_num = le16_to_cpu(ele->vsi_port_num) &
  105. ICE_AQC_GET_SW_CONF_RESP_VSI_PORT_NUM_M;
  106. pf_vf_num = le16_to_cpu(ele->pf_vf_num) &
  107. ICE_AQC_GET_SW_CONF_RESP_FUNC_NUM_M;
  108. swid = le16_to_cpu(ele->swid);
  109. if (le16_to_cpu(ele->pf_vf_num) &
  110. ICE_AQC_GET_SW_CONF_RESP_IS_VF)
  111. is_vf = true;
  112. type = le16_to_cpu(ele->vsi_port_num) >>
  113. ICE_AQC_GET_SW_CONF_RESP_TYPE_S;
  114. if (type == ICE_AQC_GET_SW_CONF_RESP_VSI) {
  115. /* FW VSI is not needed. Just continue. */
  116. continue;
  117. }
  118. ice_init_port_info(hw->port_info, vsi_port_num,
  119. type, swid, pf_vf_num, is_vf);
  120. }
  121. } while (req_desc && !status);
  122. devm_kfree(ice_hw_to_dev(hw), (void *)rbuf);
  123. return status;
  124. }