net/ice/base: add ethertype IPv6 check for dummy packet
[dpdk.git] / drivers / net / ice / base / ice_common.c
index 6501869..e8d66aa 100644 (file)
@@ -48,6 +48,11 @@ static enum ice_status ice_set_mac_type(struct ice_hw *hw)
        case ICE_DEV_ID_E823L_BACKPLANE:
        case ICE_DEV_ID_E823L_QSFP:
        case ICE_DEV_ID_E823L_SFP:
+       case ICE_DEV_ID_E823C_10G_BASE_T:
+       case ICE_DEV_ID_E823C_BACKPLANE:
+       case ICE_DEV_ID_E823C_QSFP:
+       case ICE_DEV_ID_E823C_SFP:
+       case ICE_DEV_ID_E823C_SGMII:
                hw->mac_type = ICE_MAC_GENERIC;
                break;
        default:
@@ -59,6 +64,28 @@ static enum ice_status ice_set_mac_type(struct ice_hw *hw)
        return ICE_SUCCESS;
 }
 
+/**
+ * ice_is_generic_mac
+ * @hw: pointer to the hardware structure
+ *
+ * returns true if mac_type is ICE_MAC_GENERIC, false if not
+ */
+bool ice_is_generic_mac(struct ice_hw *hw)
+{
+       return hw->mac_type == ICE_MAC_GENERIC;
+}
+
+/**
+ * ice_is_e810
+ * @hw: pointer to the hardware structure
+ *
+ * returns true if the device is E810 based, false if not.
+ */
+bool ice_is_e810(struct ice_hw *hw)
+{
+       return hw->mac_type == ICE_MAC_E810;
+}
+
 /**
  * ice_clear_pf_cfg - Clear PF configuration
  * @hw: pointer to the hardware structure
@@ -232,11 +259,13 @@ ice_aq_get_link_topo_handle(struct ice_port_info *pi, u8 node_type,
 
        ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_topo);
 
-       cmd->addr.node_type_ctx = (ICE_AQC_LINK_TOPO_NODE_CTX_PORT <<
-                                  ICE_AQC_LINK_TOPO_NODE_CTX_S);
+       cmd->addr.topo_params.node_type_ctx =
+               (ICE_AQC_LINK_TOPO_NODE_CTX_PORT <<
+                ICE_AQC_LINK_TOPO_NODE_CTX_S);
 
        /* set node type */
-       cmd->addr.node_type_ctx |= (ICE_AQC_LINK_TOPO_NODE_TYPE_M & node_type);
+       cmd->addr.topo_params.node_type_ctx |=
+               (ICE_AQC_LINK_TOPO_NODE_TYPE_M & node_type);
 
        return ice_aq_send_cmd(pi->hw, &desc, NULL, 0, cd);
 }
@@ -460,6 +489,7 @@ ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
                  (unsigned long long)li->phy_type_high);
        ice_debug(hw, ICE_DBG_LINK, "   media_type = 0x%x\n", *hw_media_type);
        ice_debug(hw, ICE_DBG_LINK, "   link_info = 0x%x\n", li->link_info);
+       ice_debug(hw, ICE_DBG_LINK, "   link_cfg_err = 0x%x\n", li->link_cfg_err);
        ice_debug(hw, ICE_DBG_LINK, "   an_info = 0x%x\n", li->an_info);
        ice_debug(hw, ICE_DBG_LINK, "   ext_info = 0x%x\n", li->ext_info);
        ice_debug(hw, ICE_DBG_LINK, "   fec_info = 0x%x\n", li->fec_info);
@@ -822,10 +852,6 @@ enum ice_status ice_init_hw(struct ice_hw *hw)
        status = ice_aq_manage_mac_read(hw, mac_buf, mac_buf_len, NULL);
        ice_free(hw, mac_buf);
 
-       if (status)
-               goto err_unroll_fltr_mgmt_struct;
-       /* enable jumbo frame support at MAC level */
-       status = ice_aq_set_mac_cfg(hw, ICE_AQ_SET_MAC_FRAME_SIZE_MAX, NULL);
        if (status)
                goto err_unroll_fltr_mgmt_struct;
        /* Obtain counter base index which would be used by flow director */
@@ -1346,6 +1372,127 @@ ice_clear_tx_drbell_q_ctx(struct ice_hw *hw, u32 tx_drbell_q_index)
        return ICE_SUCCESS;
 }
 
+/* Sideband Queue command wrappers */
+
+/**
+ * ice_get_sbq - returns the right control queue to use for sideband
+ * @hw: pointer to the hardware structure
+ */
+static struct ice_ctl_q_info *ice_get_sbq(struct ice_hw *hw)
+{
+       if (!ice_is_generic_mac(hw))
+               return &hw->adminq;
+       return &hw->sbq;
+}
+
+/**
+ * ice_sbq_send_cmd - send Sideband Queue command to Sideband Queue
+ * @hw: pointer to the HW struct
+ * @desc: descriptor describing the command
+ * @buf: buffer to use for indirect commands (NULL for direct commands)
+ * @buf_size: size of buffer for indirect commands (0 for direct commands)
+ * @cd: pointer to command details structure
+ */
+static enum ice_status
+ice_sbq_send_cmd(struct ice_hw *hw, struct ice_sbq_cmd_desc *desc,
+                void *buf, u16 buf_size, struct ice_sq_cd *cd)
+{
+       return ice_sq_send_cmd(hw, ice_get_sbq(hw), (struct ice_aq_desc *)desc,
+                              buf, buf_size, cd);
+}
+
+/**
+ * ice_sbq_send_cmd_nolock - send Sideband Queue command to Sideband Queue
+ *                           but do not lock sq_lock
+ * @hw: pointer to the HW struct
+ * @desc: descriptor describing the command
+ * @buf: buffer to use for indirect commands (NULL for direct commands)
+ * @buf_size: size of buffer for indirect commands (0 for direct commands)
+ * @cd: pointer to command details structure
+ */
+static enum ice_status
+ice_sbq_send_cmd_nolock(struct ice_hw *hw, struct ice_sbq_cmd_desc *desc,
+                       void *buf, u16 buf_size, struct ice_sq_cd *cd)
+{
+       return ice_sq_send_cmd_nolock(hw, ice_get_sbq(hw),
+                                     (struct ice_aq_desc *)desc, buf,
+                                     buf_size, cd);
+}
+
+/**
+ * ice_sbq_rw_reg_lp - Fill Sideband Queue command, with lock parameter
+ * @hw: pointer to the HW struct
+ * @in: message info to be filled in descriptor
+ * @lock: true to lock the sq_lock (the usual case); false if the sq_lock has
+ *        already been locked at a higher level
+ */
+enum ice_status ice_sbq_rw_reg_lp(struct ice_hw *hw,
+                                 struct ice_sbq_msg_input *in, bool lock)
+{
+       struct ice_sbq_cmd_desc desc = {0};
+       struct ice_sbq_msg_req msg = {0};
+       enum ice_status status;
+       u16 msg_len;
+
+       msg_len = sizeof(msg);
+
+       msg.dest_dev = in->dest_dev;
+       msg.opcode = in->opcode;
+       msg.flags = ICE_SBQ_MSG_FLAGS;
+       msg.sbe_fbe = ICE_SBQ_MSG_SBE_FBE;
+       msg.msg_addr_low = CPU_TO_LE16(in->msg_addr_low);
+       msg.msg_addr_high = CPU_TO_LE32(in->msg_addr_high);
+
+       if (in->opcode)
+               msg.data = CPU_TO_LE32(in->data);
+       else
+               /* data read comes back in completion, so shorten the struct by
+                * sizeof(msg.data)
+                */
+               msg_len -= sizeof(msg.data);
+
+       desc.flags = CPU_TO_LE16(ICE_AQ_FLAG_RD);
+       desc.opcode = CPU_TO_LE16(ice_sbq_opc_neigh_dev_req);
+       desc.param0.cmd_len = CPU_TO_LE16(msg_len);
+       if (lock)
+               status = ice_sbq_send_cmd(hw, &desc, &msg, msg_len, NULL);
+       else
+               status = ice_sbq_send_cmd_nolock(hw, &desc, &msg, msg_len,
+                                                NULL);
+       if (!status && !in->opcode)
+               in->data = LE32_TO_CPU
+                       (((struct ice_sbq_msg_cmpl *)&msg)->data);
+       return status;
+}
+
+/**
+ * ice_sbq_rw_reg - Fill Sideband Queue command
+ * @hw: pointer to the HW struct
+ * @in: message info to be filled in descriptor
+ */
+enum ice_status ice_sbq_rw_reg(struct ice_hw *hw, struct ice_sbq_msg_input *in)
+{
+       return ice_sbq_rw_reg_lp(hw, in, true);
+}
+
+/**
+ * ice_sbq_lock - Lock the sideband queue's sq_lock
+ * @hw: pointer to the HW struct
+ */
+void ice_sbq_lock(struct ice_hw *hw)
+{
+       ice_acquire_lock(&ice_get_sbq(hw)->sq_lock);
+}
+
+/**
+ * ice_sbq_unlock - Unlock the sideband queue's sq_lock
+ * @hw: pointer to the HW struct
+ */
+void ice_sbq_unlock(struct ice_hw *hw)
+{
+       ice_release_lock(&ice_get_sbq(hw)->sq_lock);
+}
+
 /* FW Admin Queue command wrappers */
 
 /**
@@ -1994,6 +2141,44 @@ ice_parse_common_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps,
                ice_debug(hw, ICE_DBG_INIT, "%s: max_mtu = %d\n",
                          prefix, caps->max_mtu);
                break;
+       case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG0:
+       case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG1:
+       case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG2:
+       case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG3:
+       {
+               u8 index = cap - ICE_AQC_CAPS_EXT_TOPO_DEV_IMG0;
+
+               caps->ext_topo_dev_img_ver_high[index] = number;
+               caps->ext_topo_dev_img_ver_low[index] = logical_id;
+               caps->ext_topo_dev_img_part_num[index] =
+                       (phys_id & ICE_EXT_TOPO_DEV_IMG_PART_NUM_M) >>
+                       ICE_EXT_TOPO_DEV_IMG_PART_NUM_S;
+               caps->ext_topo_dev_img_load_en[index] =
+                       (phys_id & ICE_EXT_TOPO_DEV_IMG_LOAD_EN) != 0;
+               caps->ext_topo_dev_img_prog_en[index] =
+                       (phys_id & ICE_EXT_TOPO_DEV_IMG_PROG_EN) != 0;
+               ice_debug(hw, ICE_DBG_INIT,
+                         "%s: ext_topo_dev_img_ver_high[%d] = %d\n",
+                         prefix, index,
+                         caps->ext_topo_dev_img_ver_high[index]);
+               ice_debug(hw, ICE_DBG_INIT,
+                         "%s: ext_topo_dev_img_ver_low[%d] = %d\n",
+                         prefix, index,
+                         caps->ext_topo_dev_img_ver_low[index]);
+               ice_debug(hw, ICE_DBG_INIT,
+                         "%s: ext_topo_dev_img_part_num[%d] = %d\n",
+                         prefix, index,
+                         caps->ext_topo_dev_img_part_num[index]);
+               ice_debug(hw, ICE_DBG_INIT,
+                         "%s: ext_topo_dev_img_load_en[%d] = %d\n",
+                         prefix, index,
+                         caps->ext_topo_dev_img_load_en[index]);
+               ice_debug(hw, ICE_DBG_INIT,
+                         "%s: ext_topo_dev_img_prog_en[%d] = %d\n",
+                         prefix, index,
+                         caps->ext_topo_dev_img_prog_en[index]);
+               break;
+       }
        default:
                /* Not one of the recognized common capabilities */
                found = false;
@@ -2044,6 +2229,60 @@ ice_parse_vsi_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
                  func_p->guar_num_vsi);
 }
 
+/**
+ * ice_parse_1588_func_caps - Parse ICE_AQC_CAPS_1588 function caps
+ * @hw: pointer to the HW struct
+ * @func_p: pointer to function capabilities structure
+ * @cap: pointer to the capability element to parse
+ *
+ * Extract function capabilities for ICE_AQC_CAPS_1588.
+ */
+static void
+ice_parse_1588_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
+                        struct ice_aqc_list_caps_elem *cap)
+{
+       struct ice_ts_func_info *info = &func_p->ts_func_info;
+       u32 number = LE32_TO_CPU(cap->number);
+
+       info->ena = ((number & ICE_TS_FUNC_ENA_M) != 0);
+       func_p->common_cap.ieee_1588 = info->ena;
+
+       info->src_tmr_owned = ((number & ICE_TS_SRC_TMR_OWND_M) != 0);
+       info->tmr_ena = ((number & ICE_TS_TMR_ENA_M) != 0);
+       info->tmr_index_owned = ((number & ICE_TS_TMR_IDX_OWND_M) != 0);
+       info->tmr_index_assoc = ((number & ICE_TS_TMR_IDX_ASSOC_M) != 0);
+
+       info->clk_freq = (number & ICE_TS_CLK_FREQ_M) >> ICE_TS_CLK_FREQ_S;
+       info->clk_src = ((number & ICE_TS_CLK_SRC_M) != 0);
+
+       if (info->clk_freq < NUM_ICE_TIME_REF_FREQ) {
+               info->time_ref = (enum ice_time_ref_freq)info->clk_freq;
+       } else {
+               /* Unknown clock frequency, so assume a (probably incorrect)
+                * default to avoid out-of-bounds look ups of frequency
+                * related information.
+                */
+               ice_debug(hw, ICE_DBG_INIT, "1588 func caps: unknown clock frequency %u\n",
+                         info->clk_freq);
+               info->time_ref = ICE_TIME_REF_FREQ_25_000;
+       }
+
+       ice_debug(hw, ICE_DBG_INIT, "func caps: ieee_1588 = %u\n",
+                 func_p->common_cap.ieee_1588);
+       ice_debug(hw, ICE_DBG_INIT, "func caps: src_tmr_owned = %u\n",
+                 info->src_tmr_owned);
+       ice_debug(hw, ICE_DBG_INIT, "func caps: tmr_ena = %u\n",
+                 info->tmr_ena);
+       ice_debug(hw, ICE_DBG_INIT, "func caps: tmr_index_owned = %u\n",
+                 info->tmr_index_owned);
+       ice_debug(hw, ICE_DBG_INIT, "func caps: tmr_index_assoc = %u\n",
+                 info->tmr_index_assoc);
+       ice_debug(hw, ICE_DBG_INIT, "func caps: clk_freq = %u\n",
+                 info->clk_freq);
+       ice_debug(hw, ICE_DBG_INIT, "func caps: clk_src = %u\n",
+                 info->clk_src);
+}
+
 /**
  * ice_parse_fdir_func_caps - Parse ICE_AQC_CAPS_FD function caps
  * @hw: pointer to the HW struct
@@ -2109,6 +2348,9 @@ ice_parse_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
                case ICE_AQC_CAPS_VSI:
                        ice_parse_vsi_func_caps(hw, func_p, &cap_resp[i]);
                        break;
+               case ICE_AQC_CAPS_1588:
+                       ice_parse_1588_func_caps(hw, func_p, &cap_resp[i]);
+                       break;
                case ICE_AQC_CAPS_FD:
                        ice_parse_fdir_func_caps(hw, func_p);
                        break;
@@ -2162,6 +2404,57 @@ ice_parse_vsi_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
                  dev_p->num_vsi_allocd_to_host);
 }
 
+/**
+ * ice_parse_1588_dev_caps - Parse ICE_AQC_CAPS_1588 device caps
+ * @hw: pointer to the HW struct
+ * @dev_p: pointer to device capabilities structure
+ * @cap: capability element to parse
+ *
+ * Parse ICE_AQC_CAPS_1588 for device capabilities.
+ */
+static void
+ice_parse_1588_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
+                       struct ice_aqc_list_caps_elem *cap)
+{
+       struct ice_ts_dev_info *info = &dev_p->ts_dev_info;
+       u32 logical_id = LE32_TO_CPU(cap->logical_id);
+       u32 phys_id = LE32_TO_CPU(cap->phys_id);
+       u32 number = LE32_TO_CPU(cap->number);
+
+       info->ena = ((number & ICE_TS_DEV_ENA_M) != 0);
+       dev_p->common_cap.ieee_1588 = info->ena;
+
+       info->tmr0_owner = number & ICE_TS_TMR0_OWNR_M;
+       info->tmr0_owned = ((number & ICE_TS_TMR0_OWND_M) != 0);
+       info->tmr0_ena = ((number & ICE_TS_TMR0_ENA_M) != 0);
+
+       info->tmr1_owner = (number & ICE_TS_TMR1_OWNR_M) >> ICE_TS_TMR1_OWNR_S;
+       info->tmr1_owned = ((number & ICE_TS_TMR1_OWND_M) != 0);
+       info->tmr1_ena = ((number & ICE_TS_TMR1_ENA_M) != 0);
+
+       info->ena_ports = logical_id;
+       info->tmr_own_map = phys_id;
+
+       ice_debug(hw, ICE_DBG_INIT, "dev caps: ieee_1588 = %u\n",
+                 dev_p->common_cap.ieee_1588);
+       ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr0_owner = %u\n",
+                 info->tmr0_owner);
+       ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr0_owned = %u\n",
+                 info->tmr0_owned);
+       ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr0_ena = %u\n",
+                 info->tmr0_ena);
+       ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr1_owner = %u\n",
+                 info->tmr1_owner);
+       ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr1_owned = %u\n",
+                 info->tmr1_owned);
+       ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr1_ena = %u\n",
+                 info->tmr1_ena);
+       ice_debug(hw, ICE_DBG_INIT, "dev caps: ieee_1588 ena_ports = %u\n",
+                 info->ena_ports);
+       ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr_own_map = %u\n",
+                 info->tmr_own_map);
+}
+
 /**
  * ice_parse_fdir_dev_caps - Parse ICE_AQC_CAPS_FD device caps
  * @hw: pointer to the HW struct
@@ -2220,6 +2513,9 @@ ice_parse_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
                case ICE_AQC_CAPS_VSI:
                        ice_parse_vsi_dev_caps(hw, dev_p, &cap_resp[i]);
                        break;
+               case ICE_AQC_CAPS_1588:
+                       ice_parse_1588_dev_caps(hw, dev_p, &cap_resp[i]);
+                       break;
                case  ICE_AQC_CAPS_FD:
                        ice_parse_fdir_dev_caps(hw, dev_p, &cap_resp[i]);
                        break;
@@ -3358,6 +3654,76 @@ ice_aq_sff_eeprom(struct ice_hw *hw, u16 lport, u8 bus_addr,
        return status;
 }
 
+/**
+ * ice_aq_prog_topo_dev_nvm
+ * @hw: pointer to the hardware structure
+ * @topo_params: pointer to structure storing topology parameters for a device
+ * @cd: pointer to command details structure or NULL
+ *
+ * Program Topology Device NVM (0x06F2)
+ *
+ */
+enum ice_status
+ice_aq_prog_topo_dev_nvm(struct ice_hw *hw,
+                        struct ice_aqc_link_topo_params *topo_params,
+                        struct ice_sq_cd *cd)
+{
+       struct ice_aqc_prog_topo_dev_nvm *cmd;
+       struct ice_aq_desc desc;
+
+       cmd = &desc.params.prog_topo_dev_nvm;
+
+       ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_prog_topo_dev_nvm);
+
+       ice_memcpy(&cmd->topo_params, topo_params, sizeof(*topo_params),
+                  ICE_NONDMA_TO_NONDMA);
+
+       return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+}
+
+/**
+ * ice_aq_read_topo_dev_nvm
+ * @hw: pointer to the hardware structure
+ * @topo_params: pointer to structure storing topology parameters for a device
+ * @start_address: byte offset in the topology device NVM
+ * @data: pointer to data buffer
+ * @data_size: number of bytes to be read from the topology device NVM
+ * @cd: pointer to command details structure or NULL
+ * Read Topology Device NVM (0x06F3)
+ *
+ */
+enum ice_status
+ice_aq_read_topo_dev_nvm(struct ice_hw *hw,
+                        struct ice_aqc_link_topo_params *topo_params,
+                        u32 start_address, u8 *data, u8 data_size,
+                        struct ice_sq_cd *cd)
+{
+       struct ice_aqc_read_topo_dev_nvm *cmd;
+       struct ice_aq_desc desc;
+       enum ice_status status;
+
+       if (!data || data_size == 0 ||
+           data_size > ICE_AQC_READ_TOPO_DEV_NVM_DATA_READ_SIZE)
+               return ICE_ERR_PARAM;
+
+       cmd = &desc.params.read_topo_dev_nvm;
+
+       ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_read_topo_dev_nvm);
+
+       desc.datalen = data_size;
+       ice_memcpy(&cmd->topo_params, topo_params, sizeof(*topo_params),
+                  ICE_NONDMA_TO_NONDMA);
+       cmd->start_address = CPU_TO_LE32(start_address);
+
+       status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+       if (status)
+               return status;
+
+       ice_memcpy(data, cmd->data_read, data_size, ICE_NONDMA_TO_NONDMA);
+
+       return ICE_SUCCESS;
+}
+
 /**
  * __ice_aq_get_set_rss_lut
  * @hw: pointer to the hardware structure
@@ -4760,6 +5126,158 @@ enum ice_fw_modes ice_get_fw_mode(struct ice_hw *hw)
                return ICE_FW_MODE_NORMAL;
 }
 
+/**
+ * ice_aq_read_i2c
+ * @hw: pointer to the hw struct
+ * @topo_addr: topology address for a device to communicate with
+ * @bus_addr: 7-bit I2C bus address
+ * @addr: I2C memory address (I2C offset) with up to 16 bits
+ * @params: I2C parameters: bit [7] - Repeated start, bits [6:5] data offset size,
+ *                         bit [4] - I2C address type, bits [3:0] - data size to read (0-16 bytes)
+ * @data: pointer to data (0 to 16 bytes) to be read from the I2C device
+ * @cd: pointer to command details structure or NULL
+ *
+ * Read I2C (0x06E2)
+ */
+enum ice_status
+ice_aq_read_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr,
+               u16 bus_addr, __le16 addr, u8 params, u8 *data,
+               struct ice_sq_cd *cd)
+{
+       struct ice_aq_desc desc = { 0 };
+       struct ice_aqc_i2c *cmd;
+       enum ice_status status;
+       u8 data_size;
+
+       ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_read_i2c);
+       cmd = &desc.params.read_write_i2c;
+
+       if (!data)
+               return ICE_ERR_PARAM;
+
+       data_size = (params & ICE_AQC_I2C_DATA_SIZE_M) >> ICE_AQC_I2C_DATA_SIZE_S;
+
+       cmd->i2c_bus_addr = CPU_TO_LE16(bus_addr);
+       cmd->topo_addr = topo_addr;
+       cmd->i2c_params = params;
+       cmd->i2c_addr = addr;
+
+       status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+       if (!status) {
+               struct ice_aqc_read_i2c_resp *resp;
+               u8 i;
+
+               resp = &desc.params.read_i2c_resp;
+               for (i = 0; i < data_size; i++) {
+                       *data = resp->i2c_data[i];
+                       data++;
+               }
+       }
+
+       return status;
+}
+
+/**
+ * ice_aq_write_i2c
+ * @hw: pointer to the hw struct
+ * @topo_addr: topology address for a device to communicate with
+ * @bus_addr: 7-bit I2C bus address
+ * @addr: I2C memory address (I2C offset) with up to 16 bits
+ * @params: I2C parameters: bit [4] - I2C address type, bits [3:0] - data size to write (0-7 bytes)
+ * @data: pointer to data (0 to 4 bytes) to be written to the I2C device
+ * @cd: pointer to command details structure or NULL
+ *
+ * Write I2C (0x06E3)
+ */
+enum ice_status
+ice_aq_write_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr,
+                u16 bus_addr, __le16 addr, u8 params, u8 *data,
+                struct ice_sq_cd *cd)
+{
+       struct ice_aq_desc desc = { 0 };
+       struct ice_aqc_i2c *cmd;
+       u8 i, data_size;
+
+       ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_write_i2c);
+       cmd = &desc.params.read_write_i2c;
+
+       data_size = (params & ICE_AQC_I2C_DATA_SIZE_M) >> ICE_AQC_I2C_DATA_SIZE_S;
+
+       /* data_size limited to 4 */
+       if (data_size > 4)
+               return ICE_ERR_PARAM;
+
+       cmd->i2c_bus_addr = CPU_TO_LE16(bus_addr);
+       cmd->topo_addr = topo_addr;
+       cmd->i2c_params = params;
+       cmd->i2c_addr = addr;
+
+       for (i = 0; i < data_size; i++) {
+               cmd->i2c_data[i] = *data;
+               data++;
+       }
+
+       return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+}
+
+/**
+ * ice_aq_set_gpio
+ * @hw: pointer to the hw struct
+ * @gpio_ctrl_handle: GPIO controller node handle
+ * @pin_idx: IO Number of the GPIO that needs to be set
+ * @value: SW provide IO value to set in the LSB
+ * @cd: pointer to command details structure or NULL
+ *
+ * Sends 0x06EC AQ command to set the GPIO pin state that's part of the topology
+ */
+enum ice_status
+ice_aq_set_gpio(struct ice_hw *hw, u16 gpio_ctrl_handle, u8 pin_idx, bool value,
+               struct ice_sq_cd *cd)
+{
+       struct ice_aqc_gpio *cmd;
+       struct ice_aq_desc desc;
+
+       ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_gpio);
+       cmd = &desc.params.read_write_gpio;
+       cmd->gpio_ctrl_handle = gpio_ctrl_handle;
+       cmd->gpio_num = pin_idx;
+       cmd->gpio_val = value ? 1 : 0;
+
+       return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+}
+
+/**
+ * ice_aq_get_gpio
+ * @hw: pointer to the hw struct
+ * @gpio_ctrl_handle: GPIO controller node handle
+ * @pin_idx: IO Number of the GPIO that needs to be set
+ * @value: IO value read
+ * @cd: pointer to command details structure or NULL
+ *
+ * Sends 0x06ED AQ command to get the value of a GPIO signal which is part of
+ * the topology
+ */
+enum ice_status
+ice_aq_get_gpio(struct ice_hw *hw, u16 gpio_ctrl_handle, u8 pin_idx,
+               bool *value, struct ice_sq_cd *cd)
+{
+       struct ice_aqc_gpio *cmd;
+       struct ice_aq_desc desc;
+       enum ice_status status;
+
+       ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_gpio);
+       cmd = &desc.params.read_write_gpio;
+       cmd->gpio_ctrl_handle = gpio_ctrl_handle;
+       cmd->gpio_num = pin_idx;
+
+       status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+       if (status)
+               return status;
+
+       *value = !!cmd->gpio_val;
+       return ICE_SUCCESS;
+}
+
 /**
  * ice_fw_supports_link_override
  * @hw: pointer to the hardware structure