Commit fad291df authored by Dariusz Stojaczyk's avatar Dariusz Stojaczyk Committed by Jim Harris
Browse files

rte_virtio: save mem-mapped PCI resource regions



Added virtio_hw->pci_bar[6] to store information
about mapped memory regions. They have to be
stored to make it possible to unmap them.

The unmapping itself is done in a separate
patch.

Change-Id: I5dcffd0674e855a02086b3d8e4adc5fac451229a
Signed-off-by: default avatarDariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/380779


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent b9ebf948
Loading
Loading
Loading
Loading
+30 −22
Original line number Diff line number Diff line
@@ -576,13 +576,11 @@ vtpci_isr(struct virtio_dev *dev)
}

static void *
get_cfg_addr(struct spdk_pci_device *dev, struct virtio_pci_cap *cap)
get_cfg_addr(struct virtio_hw *hw, struct virtio_pci_cap *cap)
{
	uint8_t  bar    = cap->bar;
	uint32_t length = cap->length;
	uint32_t offset = cap->offset;
	uint8_t *bar_vaddr;
	uint64_t bar_paddr, bar_len;

	if (bar > 5) {
		PMD_INIT_LOG(ERR, "invalid bar: %u", bar);
@@ -595,43 +593,36 @@ get_cfg_addr(struct spdk_pci_device *dev, struct virtio_pci_cap *cap)
		return NULL;
	}

	spdk_pci_device_map_bar(dev, bar, (void *) &bar_vaddr, &bar_paddr, &bar_len);
	/* FIXME the bar should be also unmapped.
	 * However, current spdk_pci_device_map_bar
	 * implementation doesn't alloc anything,
	 * so there's no leak whatsoever.
	 */

	if (offset + length > bar_len) {
	if (offset + length > hw->pci_bar[bar].len) {
		PMD_INIT_LOG(ERR,
			"invalid cap: overflows bar space: %u > %" PRIu64,
			offset + length, dev->mem_resource[bar].len);
		return NULL;
	}

	if (bar_vaddr == NULL) {
	if (hw->pci_bar[bar].vaddr == NULL) {
		PMD_INIT_LOG(ERR, "bar %u base addr is NULL", bar);
		return NULL;
	}

	return bar_vaddr + offset;
	return hw->pci_bar[bar].vaddr + offset;
}

static int
virtio_read_caps(struct spdk_pci_device *dev, struct virtio_hw *hw)
virtio_read_caps(struct virtio_hw *hw)
{
	uint8_t pos;
	struct virtio_pci_cap cap;
	int ret;

	ret = spdk_pci_device_cfg_read(dev, &pos, 1, PCI_CAPABILITY_LIST);
	ret = spdk_pci_device_cfg_read(hw->pci_dev, &pos, 1, PCI_CAPABILITY_LIST);
	if (ret < 0) {
		PMD_INIT_LOG(DEBUG, "failed to read pci capability list");
		return -1;
	}

	while (pos) {
		ret = spdk_pci_device_cfg_read(dev, &cap, sizeof(cap), pos);
		ret = spdk_pci_device_cfg_read(hw->pci_dev, &cap, sizeof(cap), pos);
		if (ret < 0) {
			PMD_INIT_LOG(ERR,
				"failed to read pci cap at pos: %x", pos);
@@ -654,18 +645,18 @@ virtio_read_caps(struct spdk_pci_device *dev, struct virtio_hw *hw)

		switch (cap.cfg_type) {
		case VIRTIO_PCI_CAP_COMMON_CFG:
			hw->common_cfg = get_cfg_addr(dev, &cap);
			hw->common_cfg = get_cfg_addr(hw, &cap);
			break;
		case VIRTIO_PCI_CAP_NOTIFY_CFG:
			spdk_pci_device_cfg_read(dev, &hw->notify_off_multiplier,
			spdk_pci_device_cfg_read(hw->pci_dev, &hw->notify_off_multiplier,
					4, pos + sizeof(cap));
			hw->notify_base = get_cfg_addr(dev, &cap);
			hw->notify_base = get_cfg_addr(hw, &cap);
			break;
		case VIRTIO_PCI_CAP_DEVICE_CFG:
			hw->dev_cfg = get_cfg_addr(dev, &cap);
			hw->dev_cfg = get_cfg_addr(hw, &cap);
			break;
		case VIRTIO_PCI_CAP_ISR_CFG:
			hw->isr = get_cfg_addr(dev, &cap);
			hw->isr = get_cfg_addr(hw, &cap);
			break;
		}

@@ -695,18 +686,35 @@ pci_enum_virtio_probe_cb(void *ctx, struct spdk_pci_device *pci_dev)
{
	struct virtio_hw *hw;
	struct virtio_dev *vdev;
	uint8_t *bar_vaddr;
	uint64_t bar_paddr, bar_len;
	int rc;
	unsigned i;

	hw = calloc(1, sizeof(*hw));
	vdev = &hw->vdev;
	vdev->is_hw = 1;
	hw->pci_dev = pci_dev;

	for (i = 0; i < 6; ++i) {
		rc = spdk_pci_device_map_bar(pci_dev, i, (void *) &bar_vaddr, &bar_paddr,
					     &bar_len);
		if (rc != 0) {
			PMD_DRV_LOG(ERR, "failed to memmap PCI BAR %d", i);
			free(hw);
			return -1;
		}

		hw->pci_bar[i].vaddr = bar_vaddr;
		hw->pci_bar[i].len = bar_len;
	}

	/*
	 * Try if we can succeed reading virtio pci caps, which exists
	 * only on modern pci device. If failed, we fallback to legacy
	 * virtio handling.
	 */
	if (virtio_read_caps(pci_dev, hw) == 0) {
	if (virtio_read_caps(hw) == 0) {
		PMD_INIT_LOG(INFO, "modern virtio pci detected.");
		VTPCI_OPS(vdev) = &modern_ops;
		vdev->modern = 1;
+9 −0
Original line number Diff line number Diff line
@@ -218,6 +218,15 @@ struct virtio_hw {
	uint32_t    notify_off_multiplier;
	uint8_t     *isr;
	uint16_t    *notify_base;

	struct {
		/** Mem-mapped resources from given PCI BAR */
		void        *vaddr;

		/** Length of the address space */
		uint32_t    len;
	} pci_bar[6];

	struct virtio_pci_common_cfg *common_cfg;
	struct spdk_pci_device *pci_dev;
	struct virtio_scsi_config *dev_cfg;