drivers/virtio/virtio_pci_admin_legacy_io.c

Source file repositories/reference/linux-study-clean/drivers/virtio/virtio_pci_admin_legacy_io.c

File Facts

System
Linux kernel
Corpus path
drivers/virtio/virtio_pci_admin_legacy_io.c
Extension
.c
Size
6952 bytes
Lines
245
Domain
Driver Families
Bucket
drivers/virtio
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved
 */

#include <linux/virtio_pci_admin.h>
#include "virtio_pci_common.h"

/*
 * virtio_pci_admin_has_legacy_io - Checks whether the legacy IO
 * commands are supported
 * @dev: VF pci_dev
 *
 * Returns true on success.
 */
bool virtio_pci_admin_has_legacy_io(struct pci_dev *pdev)
{
	struct virtio_device *virtio_dev = virtio_pci_vf_get_pf_dev(pdev);
	struct virtio_pci_device *vp_dev;

	if (!virtio_dev)
		return false;

	if (!virtio_has_feature(virtio_dev, VIRTIO_F_ADMIN_VQ))
		return false;

	vp_dev = to_vp_device(virtio_dev);

	if ((vp_dev->admin_vq.supported_cmds & VIRTIO_LEGACY_ADMIN_CMD_BITMAP) ==
		VIRTIO_LEGACY_ADMIN_CMD_BITMAP)
		return true;
	return false;
}
EXPORT_SYMBOL_GPL(virtio_pci_admin_has_legacy_io);

static int virtio_pci_admin_legacy_io_write(struct pci_dev *pdev, u16 opcode,
					    u8 offset, u8 size, u8 *buf)
{
	struct virtio_device *virtio_dev = virtio_pci_vf_get_pf_dev(pdev);
	struct virtio_admin_cmd_legacy_wr_data *data;
	struct virtio_admin_cmd cmd = {};
	struct scatterlist data_sg;
	int vf_id;
	int ret;

	if (!virtio_dev)
		return -ENODEV;

	vf_id = pci_iov_vf_id(pdev);
	if (vf_id < 0)
		return vf_id;

	data = kzalloc(sizeof(*data) + size, GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	data->offset = offset;
	memcpy(data->registers, buf, size);
	sg_init_one(&data_sg, data, sizeof(*data) + size);
	cmd.opcode = cpu_to_le16(opcode);
	cmd.group_type = cpu_to_le16(VIRTIO_ADMIN_GROUP_TYPE_SRIOV);
	cmd.group_member_id = cpu_to_le64(vf_id + 1);
	cmd.data_sg = &data_sg;
	ret = vp_modern_admin_cmd_exec(virtio_dev, &cmd);

	kfree(data);
	return ret;
}

/*
 * virtio_pci_admin_legacy_io_write_common - Write legacy common configuration
 * of a member device
 * @dev: VF pci_dev
 * @offset: starting byte offset within the common configuration area to write to
 * @size: size of the data to write
 * @buf: buffer which holds the data
 *
 * Note: caller must serialize access for the given device.
 * Returns 0 on success, or negative on failure.
 */
int virtio_pci_admin_legacy_common_io_write(struct pci_dev *pdev, u8 offset,
					    u8 size, u8 *buf)
{
	return virtio_pci_admin_legacy_io_write(pdev,
					VIRTIO_ADMIN_CMD_LEGACY_COMMON_CFG_WRITE,
					offset, size, buf);
}
EXPORT_SYMBOL_GPL(virtio_pci_admin_legacy_common_io_write);

/*

Annotation

Implementation Notes