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: Dariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/380779
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Dariusz Stojaczyk 2017-09-29 13:19:30 +02:00 committed by Jim Harris
parent b9ebf948ba
commit fad291df7b
2 changed files with 39 additions and 22 deletions

View File

@ -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;

View File

@ -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;