|
@@ -2034,6 +2034,43 @@ i40e_status i40e_aq_send_msg_to_vf(struct i40e_hw *hw, u16 vfid,
|
|
|
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
|
|
@@ -2292,6 +2329,7 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff,
|
|
|
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;
|
|
@@ -2427,6 +2465,34 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff,
|
|
|
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
|
|
|
*/
|