drivers/net/ethernet/mellanox/mlxsw/core_linecard_dev.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/mellanox/mlxsw/core_linecard_dev.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlxsw/core_linecard_dev.c
Extension
.c
Size
5092 bytes
Lines
187
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

struct mlxsw_linecard_dev {
	struct mlxsw_linecard *linecard;
};

struct mlxsw_linecard_bdev {
	struct auxiliary_device adev;
	struct mlxsw_linecard *linecard;
	struct mlxsw_linecard_dev *linecard_dev;
};

static DEFINE_IDA(mlxsw_linecard_bdev_ida);

static int mlxsw_linecard_bdev_id_alloc(void)
{
	return ida_alloc(&mlxsw_linecard_bdev_ida, GFP_KERNEL);
}

static void mlxsw_linecard_bdev_id_free(int id)
{
	ida_free(&mlxsw_linecard_bdev_ida, id);
}

static void mlxsw_linecard_bdev_release(struct device *device)
{
	struct auxiliary_device *adev =
			container_of(device, struct auxiliary_device, dev);
	struct mlxsw_linecard_bdev *linecard_bdev =
			container_of(adev, struct mlxsw_linecard_bdev, adev);

	mlxsw_linecard_bdev_id_free(adev->id);
	kfree(linecard_bdev);
}

int mlxsw_linecard_bdev_add(struct mlxsw_linecard *linecard)
{
	struct mlxsw_linecard_bdev *linecard_bdev;
	int err;
	int id;

	id = mlxsw_linecard_bdev_id_alloc();
	if (id < 0)
		return id;

	linecard_bdev = kzalloc_obj(*linecard_bdev);
	if (!linecard_bdev) {
		mlxsw_linecard_bdev_id_free(id);
		return -ENOMEM;
	}
	linecard_bdev->adev.id = id;
	linecard_bdev->adev.name = MLXSW_LINECARD_DEV_ID_NAME;
	linecard_bdev->adev.dev.release = mlxsw_linecard_bdev_release;
	linecard_bdev->adev.dev.parent = linecard->linecards->bus_info->dev;
	linecard_bdev->linecard = linecard;

	err = auxiliary_device_init(&linecard_bdev->adev);
	if (err) {
		mlxsw_linecard_bdev_id_free(id);
		kfree(linecard_bdev);
		return err;
	}

	err = auxiliary_device_add(&linecard_bdev->adev);
	if (err) {
		auxiliary_device_uninit(&linecard_bdev->adev);
		return err;
	}

	linecard->bdev = linecard_bdev;
	return 0;
}

void mlxsw_linecard_bdev_del(struct mlxsw_linecard *linecard)
{
	struct mlxsw_linecard_bdev *linecard_bdev = linecard->bdev;

	if (!linecard_bdev)
		/* Unprovisioned line cards do not have an auxiliary device. */
		return;
	auxiliary_device_delete(&linecard_bdev->adev);
	auxiliary_device_uninit(&linecard_bdev->adev);
	linecard->bdev = NULL;
}

static int mlxsw_linecard_dev_devlink_info_get(struct devlink *devlink,
					       struct devlink_info_req *req,
					       struct netlink_ext_ack *extack)
{
	struct mlxsw_linecard_dev *linecard_dev = devlink_priv(devlink);
	struct mlxsw_linecard *linecard = linecard_dev->linecard;

Annotation

Implementation Notes