123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- // SPDX-License-Identifier: GPL-2.0
- /* Copyright (c) 2018, Intel Corporation. */
- #include "ice_switch.h"
- /**
- * ice_aq_get_sw_cfg - get switch configuration
- * @hw: pointer to the hardware structure
- * @buf: pointer to the result buffer
- * @buf_size: length of the buffer available for response
- * @req_desc: pointer to requested descriptor
- * @num_elems: pointer to number of elements
- * @cd: pointer to command details structure or NULL
- *
- * Get switch configuration (0x0200) to be placed in 'buff'.
- * This admin command returns information such as initial VSI/port number
- * and switch ID it belongs to.
- *
- * NOTE: *req_desc is both an input/output parameter.
- * The caller of this function first calls this function with *request_desc set
- * to 0. If the response from f/w has *req_desc set to 0, all the switch
- * configuration information has been returned; if non-zero (meaning not all
- * the information was returned), the caller should call this function again
- * with *req_desc set to the previous value returned by f/w to get the
- * next block of switch configuration information.
- *
- * *num_elems is output only parameter. This reflects the number of elements
- * in response buffer. The caller of this function to use *num_elems while
- * parsing the response buffer.
- */
- static enum ice_status
- ice_aq_get_sw_cfg(struct ice_hw *hw, struct ice_aqc_get_sw_cfg_resp *buf,
- u16 buf_size, u16 *req_desc, u16 *num_elems,
- struct ice_sq_cd *cd)
- {
- struct ice_aqc_get_sw_cfg *cmd;
- enum ice_status status;
- struct ice_aq_desc desc;
- ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sw_cfg);
- cmd = &desc.params.get_sw_conf;
- cmd->element = cpu_to_le16(*req_desc);
- status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
- if (!status) {
- *req_desc = le16_to_cpu(cmd->element);
- *num_elems = le16_to_cpu(cmd->num_elems);
- }
- return status;
- }
- /* ice_init_port_info - Initialize port_info with switch configuration data
- * @pi: pointer to port_info
- * @vsi_port_num: VSI number or port number
- * @type: Type of switch element (port or VSI)
- * @swid: switch ID of the switch the element is attached to
- * @pf_vf_num: PF or VF number
- * @is_vf: true if the element is a VF, false otherwise
- */
- static void
- ice_init_port_info(struct ice_port_info *pi, u16 vsi_port_num, u8 type,
- u16 swid, u16 pf_vf_num, bool is_vf)
- {
- switch (type) {
- case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT:
- pi->lport = (u8)(vsi_port_num & ICE_LPORT_MASK);
- pi->sw_id = swid;
- pi->pf_vf_num = pf_vf_num;
- pi->is_vf = is_vf;
- pi->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL;
- pi->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL;
- break;
- default:
- ice_debug(pi->hw, ICE_DBG_SW,
- "incorrect VSI/port type received\n");
- break;
- }
- }
- /* ice_get_initial_sw_cfg - Get initial port and default VSI data
- * @hw: pointer to the hardware structure
- */
- enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw)
- {
- struct ice_aqc_get_sw_cfg_resp *rbuf;
- enum ice_status status;
- u16 req_desc = 0;
- u16 num_elems;
- u16 i;
- rbuf = devm_kzalloc(ice_hw_to_dev(hw), ICE_SW_CFG_MAX_BUF_LEN,
- GFP_KERNEL);
- if (!rbuf)
- return ICE_ERR_NO_MEMORY;
- /* Multiple calls to ice_aq_get_sw_cfg may be required
- * to get all the switch configuration information. The need
- * for additional calls is indicated by ice_aq_get_sw_cfg
- * writing a non-zero value in req_desc
- */
- do {
- status = ice_aq_get_sw_cfg(hw, rbuf, ICE_SW_CFG_MAX_BUF_LEN,
- &req_desc, &num_elems, NULL);
- if (status)
- break;
- for (i = 0; i < num_elems; i++) {
- struct ice_aqc_get_sw_cfg_resp_elem *ele;
- u16 pf_vf_num, swid, vsi_port_num;
- bool is_vf = false;
- u8 type;
- ele = rbuf[i].elements;
- vsi_port_num = le16_to_cpu(ele->vsi_port_num) &
- ICE_AQC_GET_SW_CONF_RESP_VSI_PORT_NUM_M;
- pf_vf_num = le16_to_cpu(ele->pf_vf_num) &
- ICE_AQC_GET_SW_CONF_RESP_FUNC_NUM_M;
- swid = le16_to_cpu(ele->swid);
- if (le16_to_cpu(ele->pf_vf_num) &
- ICE_AQC_GET_SW_CONF_RESP_IS_VF)
- is_vf = true;
- type = le16_to_cpu(ele->vsi_port_num) >>
- ICE_AQC_GET_SW_CONF_RESP_TYPE_S;
- if (type == ICE_AQC_GET_SW_CONF_RESP_VSI) {
- /* FW VSI is not needed. Just continue. */
- continue;
- }
- ice_init_port_info(hw->port_info, vsi_port_num,
- type, swid, pf_vf_num, is_vf);
- }
- } while (req_desc && !status);
- devm_kfree(ice_hw_to_dev(hw), (void *)rbuf);
- return status;
- }
|