Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d4eb4cd7 authored by Huy Nguyen's avatar Huy Nguyen Committed by David S. Miller
Browse files

net/mlx5: Add handling for port module event



For each asynchronous port module event:
  1. print with ratelimit to the dmesg log
  2. increment the corresponding event counter

Signed-off-by: default avatarHuy Nguyen <huyn@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4ce3bf2f
Loading
Loading
Loading
Loading
+12 −0
Original line number Original line Diff line number Diff line
@@ -139,6 +139,8 @@ static const char *eqe_type_str(u8 type)
		return "MLX5_EVENT_TYPE_PORT_CHANGE";
		return "MLX5_EVENT_TYPE_PORT_CHANGE";
	case MLX5_EVENT_TYPE_GPIO_EVENT:
	case MLX5_EVENT_TYPE_GPIO_EVENT:
		return "MLX5_EVENT_TYPE_GPIO_EVENT";
		return "MLX5_EVENT_TYPE_GPIO_EVENT";
	case MLX5_EVENT_TYPE_PORT_MODULE_EVENT:
		return "MLX5_EVENT_TYPE_PORT_MODULE_EVENT";
	case MLX5_EVENT_TYPE_REMOTE_CONFIG:
	case MLX5_EVENT_TYPE_REMOTE_CONFIG:
		return "MLX5_EVENT_TYPE_REMOTE_CONFIG";
		return "MLX5_EVENT_TYPE_REMOTE_CONFIG";
	case MLX5_EVENT_TYPE_DB_BF_CONGESTION:
	case MLX5_EVENT_TYPE_DB_BF_CONGESTION:
@@ -285,6 +287,11 @@ static int mlx5_eq_int(struct mlx5_core_dev *dev, struct mlx5_eq *eq)
			mlx5_eswitch_vport_event(dev->priv.eswitch, eqe);
			mlx5_eswitch_vport_event(dev->priv.eswitch, eqe);
			break;
			break;
#endif
#endif

		case MLX5_EVENT_TYPE_PORT_MODULE_EVENT:
			mlx5_port_module_event(dev, eqe);
			break;

		default:
		default:
			mlx5_core_warn(dev, "Unhandled event 0x%x on EQ 0x%x\n",
			mlx5_core_warn(dev, "Unhandled event 0x%x on EQ 0x%x\n",
				       eqe->type, eq->eqn);
				       eqe->type, eq->eqn);
@@ -480,6 +487,11 @@ int mlx5_start_eqs(struct mlx5_core_dev *dev)
	    mlx5_core_is_pf(dev))
	    mlx5_core_is_pf(dev))
		async_event_mask |= (1ull << MLX5_EVENT_TYPE_NIC_VPORT_CHANGE);
		async_event_mask |= (1ull << MLX5_EVENT_TYPE_NIC_VPORT_CHANGE);


	if (MLX5_CAP_GEN(dev, port_module_event))
		async_event_mask |= (1ull << MLX5_EVENT_TYPE_PORT_MODULE_EVENT);
	else
		mlx5_core_dbg(dev, "port_module_event is not set\n");

	err = mlx5_create_map_eq(dev, &table->cmd_eq, MLX5_EQ_VEC_CMD,
	err = mlx5_create_map_eq(dev, &table->cmd_eq, MLX5_EQ_VEC_CMD,
				 MLX5_NUM_CMD_EQE, 1ull << MLX5_EVENT_TYPE_CMD,
				 MLX5_NUM_CMD_EQE, 1ull << MLX5_EVENT_TYPE_CMD,
				 "mlx5_cmd_eq", &dev->priv.uuari.uars[0]);
				 "mlx5_cmd_eq", &dev->priv.uuari.uars[0]);
+1 −0
Original line number Original line Diff line number Diff line
@@ -81,6 +81,7 @@ int mlx5_cmd_init_hca(struct mlx5_core_dev *dev);
int mlx5_cmd_teardown_hca(struct mlx5_core_dev *dev);
int mlx5_cmd_teardown_hca(struct mlx5_core_dev *dev);
void mlx5_core_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event,
void mlx5_core_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event,
		     unsigned long param);
		     unsigned long param);
void mlx5_port_module_event(struct mlx5_core_dev *dev, struct mlx5_eqe *eqe);
void mlx5_enter_error_state(struct mlx5_core_dev *dev);
void mlx5_enter_error_state(struct mlx5_core_dev *dev);
void mlx5_disable_device(struct mlx5_core_dev *dev);
void mlx5_disable_device(struct mlx5_core_dev *dev);
void mlx5_recover_device(struct mlx5_core_dev *dev);
void mlx5_recover_device(struct mlx5_core_dev *dev);
+57 −0
Original line number Original line Diff line number Diff line
@@ -746,3 +746,60 @@ void mlx5_query_port_fcs(struct mlx5_core_dev *mdev, bool *supported,
	*supported = !!(MLX5_GET(pcmr_reg, out, fcs_cap));
	*supported = !!(MLX5_GET(pcmr_reg, out, fcs_cap));
	*enabled = !!(MLX5_GET(pcmr_reg, out, fcs_chk));
	*enabled = !!(MLX5_GET(pcmr_reg, out, fcs_chk));
}
}

static const char *mlx5_pme_status[MLX5_MODULE_STATUS_NUM] = {
	"Cable plugged",   /* MLX5_MODULE_STATUS_PLUGGED    = 0x1 */
	"Cable unplugged", /* MLX5_MODULE_STATUS_UNPLUGGED  = 0x2 */
	"Cable error",     /* MLX5_MODULE_STATUS_ERROR      = 0x3 */
};

static const char *mlx5_pme_error[MLX5_MODULE_EVENT_ERROR_NUM] = {
	"Power budget exceeded",
	"Long Range for non MLNX cable",
	"Bus stuck(I2C or data shorted)",
	"No EEPROM/retry timeout",
	"Enforce part number list",
	"Unknown identifier",
	"High Temperature",
	"Bad or shorted cable/module",
	"Unknown status",
};

void mlx5_port_module_event(struct mlx5_core_dev *dev, struct mlx5_eqe *eqe)
{
	enum port_module_event_status_type module_status;
	enum port_module_event_error_type error_type;
	struct mlx5_eqe_port_module *module_event_eqe;
	struct mlx5_priv *priv = &dev->priv;
	u8 module_num;

	module_event_eqe = &eqe->data.port_module;
	module_num = module_event_eqe->module;
	module_status = module_event_eqe->module_status &
			PORT_MODULE_EVENT_MODULE_STATUS_MASK;
	error_type = module_event_eqe->error_type &
		     PORT_MODULE_EVENT_ERROR_TYPE_MASK;

	if (module_status < MLX5_MODULE_STATUS_ERROR) {
		priv->pme_stats.status_counters[module_status - 1]++;
	} else if (module_status == MLX5_MODULE_STATUS_ERROR) {
		if (error_type >= MLX5_MODULE_EVENT_ERROR_UNKNOWN)
			/* Unknown error type */
			error_type = MLX5_MODULE_EVENT_ERROR_UNKNOWN;
		priv->pme_stats.error_counters[error_type]++;
	}

	if (!printk_ratelimit())
		return;

	if (module_status < MLX5_MODULE_STATUS_ERROR)
		mlx5_core_info(dev,
			       "Port module event: module %u, %s\n",
			       module_num, mlx5_pme_status[module_status - 1]);

	else if (module_status == MLX5_MODULE_STATUS_ERROR)
		mlx5_core_info(dev,
			       "Port module event[error]: module %u, %s, %s\n",
			       module_num, mlx5_pme_status[module_status - 1],
			       mlx5_pme_error[error_type]);
}
+27 −0
Original line number Original line Diff line number Diff line
@@ -498,6 +498,31 @@ struct mlx5_rl_table {
	struct mlx5_rl_entry   *rl_entry;
	struct mlx5_rl_entry   *rl_entry;
};
};


enum port_module_event_status_type {
	MLX5_MODULE_STATUS_PLUGGED   = 0x1,
	MLX5_MODULE_STATUS_UNPLUGGED = 0x2,
	MLX5_MODULE_STATUS_ERROR     = 0x3,
	MLX5_MODULE_STATUS_NUM       = 0x3,
};

enum  port_module_event_error_type {
	MLX5_MODULE_EVENT_ERROR_POWER_BUDGET_EXCEEDED,
	MLX5_MODULE_EVENT_ERROR_LONG_RANGE_FOR_NON_MLNX_CABLE_MODULE,
	MLX5_MODULE_EVENT_ERROR_BUS_STUCK,
	MLX5_MODULE_EVENT_ERROR_NO_EEPROM_RETRY_TIMEOUT,
	MLX5_MODULE_EVENT_ERROR_ENFORCE_PART_NUMBER_LIST,
	MLX5_MODULE_EVENT_ERROR_UNKNOWN_IDENTIFIER,
	MLX5_MODULE_EVENT_ERROR_HIGH_TEMPERATURE,
	MLX5_MODULE_EVENT_ERROR_BAD_CABLE,
	MLX5_MODULE_EVENT_ERROR_UNKNOWN,
	MLX5_MODULE_EVENT_ERROR_NUM,
};

struct mlx5_port_module_event_stats {
	u64 status_counters[MLX5_MODULE_STATUS_NUM];
	u64 error_counters[MLX5_MODULE_EVENT_ERROR_NUM];
};

struct mlx5_priv {
struct mlx5_priv {
	char			name[MLX5_MAX_NAME_LEN];
	char			name[MLX5_MAX_NAME_LEN];
	struct mlx5_eq_table	eq_table;
	struct mlx5_eq_table	eq_table;
@@ -559,6 +584,8 @@ struct mlx5_priv {
	unsigned long		pci_dev_data;
	unsigned long		pci_dev_data;
	struct mlx5_fc_stats		fc_stats;
	struct mlx5_fc_stats		fc_stats;
	struct mlx5_rl_table            rl_table;
	struct mlx5_rl_table            rl_table;

	struct mlx5_port_module_event_stats  pme_stats;
};
};


enum mlx5_device_state {
enum mlx5_device_state {