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:
parent
b9ebf948ba
commit
fad291df7b
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user