drivers/net/ethernet/mellanox/mlx4/catas.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/mellanox/mlx4/catas.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx4/catas.c
Extension
.c
Size
9161 bytes
Lines
336
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (rst_ack == rst_req) {
			mlx4_warn(dev, "VF Reset succeed\n");
			return 0;
		}
		cond_resched();
	}
	mlx4_err(dev, "Fail to send reset over the communication channel\n");
	return -ETIMEDOUT;
}

int mlx4_comm_internal_err(u32 slave_read)
{
	return (u32)COMM_CHAN_EVENT_INTERNAL_ERR ==
		(slave_read & (u32)COMM_CHAN_EVENT_INTERNAL_ERR) ? 1 : 0;
}

void mlx4_enter_error_state(struct mlx4_dev_persistent *persist)
{
	int err;
	struct mlx4_dev *dev;

	if (!mlx4_internal_err_reset)
		return;

	mutex_lock(&persist->device_state_mutex);
	if (persist->state & MLX4_DEVICE_STATE_INTERNAL_ERROR)
		goto out;

	dev = persist->dev;
	mlx4_err(dev, "device is going to be reset\n");
	if (mlx4_is_slave(dev)) {
		err = mlx4_reset_slave(dev);
	} else {
		mlx4_crdump_collect(dev);
		err = mlx4_reset_master(dev);
	}

	if (!err) {
		mlx4_err(dev, "device was reset successfully\n");
	} else {
		/* EEH could have disabled the PCI channel during reset. That's
		 * recoverable and the PCI error flow will handle it.
		 */
		if (!pci_channel_offline(dev->persist->pdev))
			BUG_ON(1);
	}
	dev->persist->state |= MLX4_DEVICE_STATE_INTERNAL_ERROR;
	mutex_unlock(&persist->device_state_mutex);

	/* At that step HW was already reset, now notify clients */
	mlx4_dispatch_event(dev, MLX4_DEV_EVENT_CATASTROPHIC_ERROR, NULL);
	mlx4_cmd_wake_completions(dev);
	return;

out:
	mutex_unlock(&persist->device_state_mutex);
}

static void mlx4_handle_error_state(struct mlx4_dev_persistent *persist)
{
	struct mlx4_dev *dev = persist->dev;
	struct devlink *devlink;
	int err = 0;

	mlx4_enter_error_state(persist);
	devlink = priv_to_devlink(mlx4_priv(dev));
	devl_lock(devlink);
	mutex_lock(&persist->interface_state_mutex);
	if (persist->interface_state & MLX4_INTERFACE_STATE_UP &&
	    !(persist->interface_state & MLX4_INTERFACE_STATE_DELETION)) {
		err = mlx4_restart_one(persist->pdev);
		mlx4_info(persist->dev, "mlx4_restart_one was ended, ret=%d\n",
			  err);
	}
	mutex_unlock(&persist->interface_state_mutex);
	devl_unlock(devlink);
}

static void dump_err_buf(struct mlx4_dev *dev)
{
	struct mlx4_priv *priv = mlx4_priv(dev);

	int i;

	mlx4_err(dev, "Internal error detected:\n");
	for (i = 0; i < priv->fw.catas_size; ++i)
		mlx4_err(dev, "  buf[%02x]: %08x\n",
			 i, swab32(readl(priv->catas_err.map + i)));
}

Annotation

Implementation Notes