return status;
 }
 
+/**
+ * i40e_aq_debug_read_register
+ * @hw: pointer to the hw struct
+ * @reg_addr: register address
+ * @reg_val: register value
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Read the register using the admin queue commands
+ **/
+i40e_status i40e_aq_debug_read_register(struct i40e_hw *hw,
+                               u32  reg_addr, u64 *reg_val,
+                               struct i40e_asq_cmd_details *cmd_details)
+{
+       struct i40e_aq_desc desc;
+       struct i40e_aqc_debug_reg_read_write *cmd_resp =
+               (struct i40e_aqc_debug_reg_read_write *)&desc.params.raw;
+       i40e_status status;
+
+       if (reg_val == NULL)
+               return I40E_ERR_PARAM;
+
+       i40e_fill_default_direct_cmd_desc(&desc,
+                                         i40e_aqc_opc_debug_read_reg);
+
+       cmd_resp->address = cpu_to_le32(reg_addr);
+
+       status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+
+       if (!status) {
+               *reg_val = ((u64)cmd_resp->value_high << 32) |
+                           (u64)cmd_resp->value_low;
+               *reg_val = le64_to_cpu(*reg_val);
+       }
+
+       return status;
+}
+
 /**
  * i40e_aq_debug_write_register
  * @hw: pointer to the hw struct
                                     enum i40e_admin_queue_opc list_type_opc)
 {
        struct i40e_aqc_list_capabilities_element_resp *cap;
+       u32 valid_functions, num_functions;
        u32 number, logical_id, phys_id;
        struct i40e_hw_capabilities *p;
        u32 i = 0;
        if (p->npar_enable || p->mfp_mode_1)
                p->fcoe = false;
 
+       /* count the enabled ports (aka the "not disabled" ports) */
+       hw->num_ports = 0;
+       for (i = 0; i < 4; i++) {
+               u32 port_cfg_reg = I40E_PRTGEN_CNF + (4 * i);
+               u64 port_cfg = 0;
+
+               /* use AQ read to get the physical register offset instead
+                * of the port relative offset
+                */
+               i40e_aq_debug_read_register(hw, port_cfg_reg, &port_cfg, NULL);
+               if (!(port_cfg & I40E_PRTGEN_CNF_PORT_DIS_MASK))
+                       hw->num_ports++;
+       }
+
+       valid_functions = p->valid_functions;
+       num_functions = 0;
+       while (valid_functions) {
+               if (valid_functions & 1)
+                       num_functions++;
+               valid_functions >>= 1;
+       }
+
+       /* partition id is 1-based, and functions are evenly spread
+        * across the ports as partitions
+        */
+       hw->partition_id = (hw->pf_id / hw->num_ports) + 1;
+       hw->num_partitions = num_functions / hw->num_ports;
+
        /* additional HW specific goodies that might
         * someday be HW version specific
         */
 
 i40e_status i40e_aq_debug_write_register(struct i40e_hw *hw,
                                        u32 reg_addr, u64 reg_val,
                                        struct i40e_asq_cmd_details *cmd_details);
+i40e_status i40e_aq_debug_read_register(struct i40e_hw *hw,
+                               u32  reg_addr, u64 *reg_val,
+                               struct i40e_asq_cmd_details *cmd_details);
 i40e_status i40e_aq_set_phy_debug(struct i40e_hw *hw, u8 cmd_flags,
                                struct i40e_asq_cmd_details *cmd_details);
 i40e_status i40e_aq_set_default_vsi(struct i40e_hw *hw, u16 vsi_id,