From patchwork Mon Jan 18 09:13:09 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tetsuya Mukawa X-Patchwork-Id: 9929 X-Patchwork-Delegate: bruce.richardson@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id 1B59B8E59; Mon, 18 Jan 2016 10:13:34 +0100 (CET) Received: from mail-pf0-f175.google.com (mail-pf0-f175.google.com [209.85.192.175]) by dpdk.org (Postfix) with ESMTP id 4FB008DA1 for ; Mon, 18 Jan 2016 10:13:32 +0100 (CET) Received: by mail-pf0-f175.google.com with SMTP id e65so155275170pfe.0 for ; Mon, 18 Jan 2016 01:13:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=igel-co-jp.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=3NiTmNIMhVXcIc1mrIVqJEYAEeBom3/rx2hCi+KO/8c=; b=i5yu0nPvJIW1zydm9xb1n/qADj8k/H4FkJFTbgwpUtWi7PHvJ3zoeG/VNsn4rm7ZNv URUiwgU4FxaHmWO3vTA+AhDcgk9TWicZcS6bAVnJPMfD6XrS26TWm2Ou+hcsBXYroPmq RhWltEsyxbCknWUnQjusVCKeR9KWNy2ZMBe4aYbIDIKv2sUOoGi4RECRx6epD0MTo9bf D1cfAJZDtR1X3D8xmBgVTUsovOQKjxz3kzWN7+ozHHU1I/beXyVciL6czlH2wSh9xu2r QI5C51AzK6mmR+MVNYCwgmBQsousd+h9FISoqzjApBUlurQZzt7yGjfPX/F2bSbpVK4W Od8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=3NiTmNIMhVXcIc1mrIVqJEYAEeBom3/rx2hCi+KO/8c=; b=T3uq9ioHgf6Ha5vsmjOH3RkvrGL3q++xYMdvM4CstAMUsaVjnET0CH8cR3iWqSUJOd EsCZTc5H1hteF+Xm4UfP/eMg1PmmrqYOIHBM4h9954iURer8EQbIpVWqNDR5H018QBqf 9qjeE3fZqrGdQHvDOjjbQ6oXNJiFlXkYdlFw5u4n6VzjdE33kZ8F5XiRu7e2XemrFQeY ONnOHW0u1NlKmeMzn3EFl0E4/neJ2mrIp+ZDqyC/+Ekdy5MPM7l4B+T+OsOO+dB69ZHv Q724YpLAMJtDDzEyMXufrzTbWx3jPR/Kib6KB7deQL6BXGSWmferMGXcP5fkOCueOrPK 8WyA== X-Gm-Message-State: ALoCoQlfEDZ6hr0lnLTdWpOuloxm+zzKVUvJBEKT5G8YbLHdahfhqWfQ3LKr3nvsWTL9Jkwa+ZPQXmWTq6ghzNviwuqZXj4OZA== X-Received: by 10.98.7.156 with SMTP id 28mr34886913pfh.49.1453108411737; Mon, 18 Jan 2016 01:13:31 -0800 (PST) Received: from localhost.localdomain (napt.igel.co.jp. [219.106.231.132]) by smtp.gmail.com with ESMTPSA id g10sm32278308pfd.49.2016.01.18.01.13.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 18 Jan 2016 01:13:31 -0800 (PST) From: Tetsuya Mukawa To: dev@dpdk.org Date: Mon, 18 Jan 2016 18:13:09 +0900 Message-Id: <1453108389-21006-4-git-send-email-mukawa@igel.co.jp> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1453108389-21006-1-git-send-email-mukawa@igel.co.jp> References: <1453108389-21006-1-git-send-email-mukawa@igel.co.jp> Subject: [dpdk-dev] [PATCH 3/3] virtio: Add a new layer to abstract pci access method X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" This patch adds below function pointers to abstract pci access method. - legacy_read8/16/32 - legacy_write8/16/32 - modern_read8/16/32 - modern_write8/16/32 - map_pci_cfg - unmap_pci_cfg - get_cfg_addr - read_pci_cfg This layer will be used when virtio-net PMD supports container extension. The legacy_xxxxx are for handling legacy virtio-net device, and the modern_xxxxx are for handling virtio-1.0 device. This new layer also abstract how to access to pci configuration space. Signed-off-by: Tetsuya Mukawa --- drivers/net/virtio/virtio_ethdev.c | 4 +- drivers/net/virtio/virtio_pci.c | 449 ++++++++++++++++++++++++++----------- drivers/net/virtio/virtio_pci.h | 34 ++- 3 files changed, 354 insertions(+), 133 deletions(-) diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c index b98d195..c477b05 100644 --- a/drivers/net/virtio/virtio_ethdev.c +++ b/drivers/net/virtio/virtio_ethdev.c @@ -1037,7 +1037,7 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev) pci_dev = eth_dev->pci_dev; - if (vtpci_init(pci_dev, hw) < 0) + if (vtpci_init(eth_dev, hw) < 0) return -1; /* Reset the device although not necessary at startup */ @@ -1177,7 +1177,7 @@ eth_virtio_dev_uninit(struct rte_eth_dev *eth_dev) rte_intr_callback_unregister(&pci_dev->intr_handle, virtio_interrupt_handler, eth_dev); - vtpci_uninit(dev, hw) + vtpci_uninit(eth_dev, hw); PMD_INIT_LOG(DEBUG, "dev_uninit completed"); diff --git a/drivers/net/virtio/virtio_pci.c b/drivers/net/virtio/virtio_pci.c index ffcd2fa..20b64eb 100644 --- a/drivers/net/virtio/virtio_pci.c +++ b/drivers/net/virtio/virtio_pci.c @@ -68,6 +68,190 @@ #define VIRTIO_WRITE_REG_4(hw, reg, value) \ outl_p((unsigned int)(value), (VIRTIO_PCI_REG_ADDR((hw), (reg)))) +static uint8_t +phys_legacy_read8(struct virtio_hw *hw, uint8_t *addr) +{ + return VIRTIO_READ_REG_1(hw, (uint64_t)addr); +} + +static uint16_t +phys_legacy_read16(struct virtio_hw *hw, uint16_t *addr) +{ + return VIRTIO_READ_REG_2(hw, (uint64_t)addr); +} + +static uint32_t +phys_legacy_read32(struct virtio_hw *hw, uint32_t *addr) +{ + return VIRTIO_READ_REG_4(hw, (uint64_t)addr); +} + +static void +phys_legacy_write8(struct virtio_hw *hw, uint8_t *addr, uint8_t val) +{ + return VIRTIO_WRITE_REG_1(hw, (uint64_t)addr, val); +} + +static void +phys_legacy_write16(struct virtio_hw *hw, uint16_t *addr, uint16_t val) +{ + return VIRTIO_WRITE_REG_2(hw, (uint64_t)addr, val); +} + +static void +phys_legacy_write32(struct virtio_hw *hw, uint32_t *addr, uint32_t val) +{ + return VIRTIO_WRITE_REG_4(hw, (uint64_t)addr, val); +} + +#define MODERN_READ_DEF(nr_bits, type) \ +static inline type \ +io_read##nr_bits(type *addr) \ +{ \ + return *(volatile type *)addr; \ +} + +#define MODERN_WRITE_DEF(nr_bits, type) \ +static inline void \ +io_write##nr_bits(type *addr, type val) \ +{ \ + *(volatile type *)addr = val; \ +} + +MODERN_READ_DEF (8, uint8_t) +MODERN_WRITE_DEF(8, uint8_t) + +MODERN_READ_DEF (16, uint16_t) +MODERN_WRITE_DEF(16, uint16_t) + +MODERN_READ_DEF (32, uint32_t) +MODERN_WRITE_DEF(32, uint32_t) + +static uint8_t +phys_modern_read8(struct virtio_hw *hw __rte_unused, uint8_t *addr) +{ + return io_read8((uint8_t *)addr); +} + +static uint16_t +phys_modern_read16(struct virtio_hw *hw __rte_unused, uint16_t *addr) +{ + return io_read16((uint16_t *)addr); +} + +static uint32_t +phys_modern_read32(struct virtio_hw *hw __rte_unused, uint32_t *addr) +{ + return io_read32((uint32_t *)addr); +} + +static void +phys_modern_write8(struct virtio_hw *hw __rte_unused, + uint8_t *addr, uint8_t val) +{ + return io_write8((uint8_t *)addr, val); +} + +static void +phys_modern_write16(struct virtio_hw *hw __rte_unused, + uint16_t *addr, uint16_t val) +{ + return io_write16((uint16_t *)addr, val); +} + +static void +phys_modern_write32(struct virtio_hw *hw __rte_unused, + uint32_t *addr, uint32_t val) +{ + return io_write32((uint32_t *)addr, val); +} + +static int +phys_map_pci_cfg(struct virtio_hw *hw) +{ + return rte_eal_pci_map_device(hw->dev); +} + +static void +phys_unmap_pci_cfg(struct virtio_hw *hw) +{ + rte_eal_pci_unmap_device(hw->dev); +} + +static int +phys_read_pci_cfg(struct virtio_hw *hw, void *buf, size_t len, off_t offset) +{ + return rte_eal_pci_read_config(hw->dev, buf, len, offset); +} + +static void * +phys_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 *base; + + if (bar > 5) { + PMD_INIT_LOG(ERR, "invalid bar: %u", bar); + return NULL; + } + + if (offset + length > hw->dev->mem_resource[bar].len) { + PMD_INIT_LOG(ERR, + "invalid cap: overflows bar space: %u > %"PRIu64, + offset + length, hw->dev->mem_resource[bar].len); + return NULL; + } + + base = hw->dev->mem_resource[bar].addr; + if (base == NULL) { + PMD_INIT_LOG(ERR, "bar %u base addr is NULL", bar); + return NULL; + } + + return base + offset; +} + +static const struct virtio_pci_access_ops phys_access_ops = { + .legacy_read8 = phys_legacy_read8, + .legacy_read16 = phys_legacy_read16, + .legacy_read32 = phys_legacy_read32, + .legacy_write8 = phys_legacy_write8, + .legacy_write16 = phys_legacy_write16, + .legacy_write32 = phys_legacy_write32, + + .modern_read8 = phys_modern_read8, + .modern_read16 = phys_modern_read16, + .modern_read32 = phys_modern_read32, + .modern_write8 = phys_modern_write8, + .modern_write16 = phys_modern_write16, + .modern_write32 = phys_modern_write32, + + .map_pci_cfg = phys_map_pci_cfg, + .unmap_pci_cfg = phys_unmap_pci_cfg, + .read_pci_cfg = phys_read_pci_cfg, + .get_cfg_addr = phys_get_cfg_addr, +}; + +static int +vtpci_access_init(struct rte_eth_dev *dev, struct virtio_hw *hw) +{ + if (dev->dev_type == RTE_ETH_DEV_PCI) { + hw->vtpci_access_ops = &phys_access_ops; + return 0; + } + + PMD_DRV_LOG(ERR, "Unkown virtio-net device."); + return -1; +} + +static void +vtpci_access_uninit(struct rte_eth_dev *dev __rte_unused, struct virtio_hw *hw) +{ + hw->vtpci_access_ops = NULL; +} + static void legacy_read_dev_config(struct virtio_hw *hw, uint64_t offset, void *dst, int length) @@ -80,13 +264,16 @@ legacy_read_dev_config(struct virtio_hw *hw, uint64_t offset, for (d = dst; length > 0; d += size, off += size, length -= size) { if (length >= 4) { size = 4; - *(uint32_t *)d = VIRTIO_READ_REG_4(hw, off); + *(uint32_t *)d = hw->vtpci_access_ops->legacy_read32( + hw, (uint32_t *)off); } else if (length >= 2) { size = 2; - *(uint16_t *)d = VIRTIO_READ_REG_2(hw, off); + *(uint16_t *)d = hw->vtpci_access_ops->legacy_read16( + hw, (uint16_t *)off); } else { size = 1; - *d = VIRTIO_READ_REG_1(hw, off); + *d = hw->vtpci_access_ops->legacy_read8( + hw, (uint8_t *)off); } } } @@ -103,13 +290,16 @@ legacy_write_dev_config(struct virtio_hw *hw, uint64_t offset, for (s = src; length > 0; s += size, off += size, length -= size) { if (length >= 4) { size = 4; - VIRTIO_WRITE_REG_4(hw, off, *(const uint32_t *)s); + hw->vtpci_access_ops->legacy_write32(hw, + (uint32_t *)off, *(const uint32_t *)s); } else if (length >= 2) { size = 2; - VIRTIO_WRITE_REG_2(hw, off, *(const uint16_t *)s); + hw->vtpci_access_ops->legacy_write16(hw, + (uint16_t *)off, *(const uint16_t *)s); } else { size = 1; - VIRTIO_WRITE_REG_1(hw, off, *s); + hw->vtpci_access_ops->legacy_write8(hw, + (uint8_t *)off, *s); } } } @@ -117,7 +307,8 @@ legacy_write_dev_config(struct virtio_hw *hw, uint64_t offset, static uint64_t legacy_get_features(struct virtio_hw *hw) { - return VIRTIO_READ_REG_4(hw, VIRTIO_PCI_HOST_FEATURES); + return hw->vtpci_access_ops->legacy_read32(hw, + (uint32_t *)VIRTIO_PCI_HOST_FEATURES); } static void @@ -128,19 +319,22 @@ legacy_set_features(struct virtio_hw *hw, uint64_t features) "only 32 bit features are allowed for legacy virtio!"); return; } - VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_GUEST_FEATURES, features); + hw->vtpci_access_ops->legacy_write32(hw, + (uint32_t *)VIRTIO_PCI_GUEST_FEATURES, features); } static uint8_t legacy_get_status(struct virtio_hw *hw) { - return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_STATUS); + return hw->vtpci_access_ops->legacy_read8(hw, + (uint8_t *)VIRTIO_PCI_STATUS); } static void legacy_set_status(struct virtio_hw *hw, uint8_t status) { - VIRTIO_WRITE_REG_1(hw, VIRTIO_PCI_STATUS, status); + hw->vtpci_access_ops->legacy_write8(hw, + (uint8_t *)VIRTIO_PCI_STATUS, status); } static void @@ -152,45 +346,56 @@ legacy_reset(struct virtio_hw *hw) static uint8_t legacy_get_isr(struct virtio_hw *hw) { - return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_ISR); + return hw->vtpci_access_ops->legacy_read8(hw, + (uint8_t *)VIRTIO_PCI_ISR); } /* Enable one vector (0) for Link State Intrerrupt */ static uint16_t legacy_set_config_irq(struct virtio_hw *hw, uint16_t vec) { - VIRTIO_WRITE_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR, vec); - return VIRTIO_READ_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR); + hw->vtpci_access_ops->legacy_write16(hw, + (uint16_t *)VIRTIO_MSI_CONFIG_VECTOR, vec); + return hw->vtpci_access_ops->legacy_read16(hw, + (uint16_t *)VIRTIO_MSI_CONFIG_VECTOR); } static uint16_t legacy_get_queue_num(struct virtio_hw *hw, uint16_t queue_id) { - VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_SEL, queue_id); - return VIRTIO_READ_REG_2(hw, VIRTIO_PCI_QUEUE_NUM); + hw->vtpci_access_ops->legacy_write16(hw, + (uint16_t *)VIRTIO_PCI_QUEUE_SEL, queue_id); + return hw->vtpci_access_ops->legacy_read16(hw, + (uint16_t *)VIRTIO_PCI_QUEUE_NUM); } static void legacy_setup_queue(struct virtio_hw *hw, struct virtqueue *vq) { - VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_SEL, vq->vq_queue_index); + hw->vtpci_access_ops->legacy_write16(hw, + (uint16_t *)VIRTIO_PCI_QUEUE_SEL, vq->vq_queue_index); - VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_QUEUE_PFN, - vq->mz->phys_addr >> VIRTIO_PCI_QUEUE_ADDR_SHIFT); + hw->vtpci_access_ops->legacy_write32(hw, + (uint32_t *)VIRTIO_PCI_QUEUE_PFN, + vq->vq_ring_mem >> VIRTIO_PCI_QUEUE_ADDR_SHIFT); } static void legacy_del_queue(struct virtio_hw *hw, struct virtqueue *vq) { - VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_SEL, vq->vq_queue_index); + hw->vtpci_access_ops->legacy_write16(hw, + (uint16_t *)VIRTIO_PCI_QUEUE_SEL, vq->vq_queue_index); - VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_QUEUE_PFN, 0); + hw->vtpci_access_ops->legacy_write32(hw, + (uint32_t *)VIRTIO_PCI_QUEUE_PFN, 0); } static void legacy_notify_queue(struct virtio_hw *hw, struct virtqueue *vq) { - VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_NOTIFY, vq->vq_queue_index); + hw->vtpci_access_ops->legacy_write16(hw, + (uint16_t *)VIRTIO_PCI_QUEUE_NOTIFY, + vq->vq_queue_index); } #ifdef RTE_EXEC_ENV_LINUXAPP @@ -468,35 +673,12 @@ static const struct virtio_pci_ops legacy_ops = { .notify_queue = legacy_notify_queue, }; - -#define MODERN_READ_DEF(nr_bits, type) \ -static inline type \ -io_read##nr_bits(type *addr) \ -{ \ - return *(volatile type *)addr; \ -} - -#define MODERN_WRITE_DEF(nr_bits, type) \ -static inline void \ -io_write##nr_bits(type *addr, type val) \ -{ \ - *(volatile type *)addr = val; \ -} - -MODERN_READ_DEF (8, uint8_t) -MODERN_WRITE_DEF(8, uint8_t) - -MODERN_READ_DEF (16, uint16_t) -MODERN_WRITE_DEF(16, uint16_t) - -MODERN_READ_DEF (32, uint32_t) -MODERN_WRITE_DEF(32, uint32_t) - static inline void -io_write64_twopart(uint32_t *lo, uint32_t *hi, uint64_t val) +io_write64_twopart(struct virtio_hw *hw, + uint32_t *lo, uint32_t *hi, uint64_t val) { - io_write32(lo, (uint32_t)val); - io_write32(hi, val >> 32); + hw->vtpci_access_ops->modern_write32(hw, lo, (uint32_t)val); + hw->vtpci_access_ops->modern_write32(hw, hi, val >> 32); } static void @@ -508,13 +690,16 @@ modern_read_dev_config(struct virtio_hw *hw, uint64_t offset, uint8_t old_gen, new_gen; do { - old_gen = io_read8(&hw->common_cfg->config_generation); + old_gen = hw->vtpci_access_ops->modern_read8(hw, + &hw->common_cfg->config_generation); p = dst; for (i = 0; i < length; i++) - *p++ = io_read8((uint8_t *)hw->dev_cfg + offset + i); + *p++ = hw->vtpci_access_ops->modern_read8(hw, + (uint8_t *)hw->dev_cfg + offset + i); - new_gen = io_read8(&hw->common_cfg->config_generation); + new_gen = hw->vtpci_access_ops->modern_read8(hw, + &hw->common_cfg->config_generation); } while (old_gen != new_gen); } @@ -526,7 +711,8 @@ modern_write_dev_config(struct virtio_hw *hw, uint64_t offset, const uint8_t *p = src; for (i = 0; i < length; i++) - io_write8((uint8_t *)hw->dev_cfg + offset + i, *p++); + hw->vtpci_access_ops->modern_write8(hw, + (uint8_t *)hw->dev_cfg + offset + i, *p++); } static uint64_t @@ -534,11 +720,15 @@ modern_get_features(struct virtio_hw *hw) { uint32_t features_lo, features_hi; - io_write32(&hw->common_cfg->device_feature_select, 0); - features_lo = io_read32(&hw->common_cfg->device_feature); + hw->vtpci_access_ops->modern_write32(hw, + &hw->common_cfg->device_feature_select, 0); + features_lo = hw->vtpci_access_ops->modern_read32(hw, + &hw->common_cfg->device_feature); - io_write32(&hw->common_cfg->device_feature_select, 1); - features_hi = io_read32(&hw->common_cfg->device_feature); + hw->vtpci_access_ops->modern_write32(hw, + &hw->common_cfg->device_feature_select, 1); + features_hi = hw->vtpci_access_ops->modern_read32(hw, + &hw->common_cfg->device_feature); return ((uint64_t)(features_hi) << 32) | features_lo; } @@ -546,25 +736,30 @@ modern_get_features(struct virtio_hw *hw) static void modern_set_features(struct virtio_hw *hw, uint64_t features) { - io_write32(&hw->common_cfg->guest_feature_select, 0); - io_write32(&hw->common_cfg->guest_feature, - features & ((1ULL << 32) - 1)); + hw->vtpci_access_ops->modern_write32(hw, + &hw->common_cfg->guest_feature_select, 0); + hw->vtpci_access_ops->modern_write32(hw, + &hw->common_cfg->guest_feature, + features & ((1ULL << 32) - 1)); - io_write32(&hw->common_cfg->guest_feature_select, 1); - io_write32(&hw->common_cfg->guest_feature, - features >> 32); + hw->vtpci_access_ops->modern_write32(hw, + &hw->common_cfg->guest_feature_select, 1); + hw->vtpci_access_ops->modern_write32(hw, + &hw->common_cfg->guest_feature, features >> 32); } static uint8_t modern_get_status(struct virtio_hw *hw) { - return io_read8(&hw->common_cfg->device_status); + return hw->vtpci_access_ops->modern_read8(hw, + &hw->common_cfg->device_status); } static void modern_set_status(struct virtio_hw *hw, uint8_t status) { - io_write8(&hw->common_cfg->device_status, status); + hw->vtpci_access_ops->modern_write8(hw, + &hw->common_cfg->device_status, status); } static void @@ -577,21 +772,25 @@ modern_reset(struct virtio_hw *hw) static uint8_t modern_get_isr(struct virtio_hw *hw) { - return io_read8(hw->isr); + return hw->vtpci_access_ops->modern_read8(hw, hw->isr); } static uint16_t modern_set_config_irq(struct virtio_hw *hw, uint16_t vec) { - io_write16(&hw->common_cfg->msix_config, vec); - return io_read16(&hw->common_cfg->msix_config); + hw->vtpci_access_ops->modern_write16(hw, + &hw->common_cfg->msix_config, vec); + return hw->vtpci_access_ops->modern_read16(hw, + &hw->common_cfg->msix_config); } static uint16_t modern_get_queue_num(struct virtio_hw *hw, uint16_t queue_id) { - io_write16(&hw->common_cfg->queue_select, queue_id); - return io_read16(&hw->common_cfg->queue_size); + hw->vtpci_access_ops->modern_write16(hw, + &hw->common_cfg->queue_select, queue_id); + return hw->vtpci_access_ops->modern_read16(hw, + &hw->common_cfg->queue_size); } static void @@ -606,20 +805,23 @@ modern_setup_queue(struct virtio_hw *hw, struct virtqueue *vq) ring[vq->vq_nentries]), VIRTIO_PCI_VRING_ALIGN); - io_write16(&hw->common_cfg->queue_select, vq->vq_queue_index); + hw->vtpci_access_ops->modern_write16(hw, + &hw->common_cfg->queue_select, vq->vq_queue_index); - io_write64_twopart(&hw->common_cfg->queue_desc_lo, + io_write64_twopart(hw, &hw->common_cfg->queue_desc_lo, &hw->common_cfg->queue_desc_hi, desc_addr); - io_write64_twopart(&hw->common_cfg->queue_avail_lo, + io_write64_twopart(hw, &hw->common_cfg->queue_avail_lo, &hw->common_cfg->queue_avail_hi, avail_addr); - io_write64_twopart(&hw->common_cfg->queue_used_lo, + io_write64_twopart(hw, &hw->common_cfg->queue_used_lo, &hw->common_cfg->queue_used_hi, used_addr); - notify_off = io_read16(&hw->common_cfg->queue_notify_off); + notify_off = hw->vtpci_access_ops->modern_read16(hw, + &hw->common_cfg->queue_notify_off); vq->notify_addr = (void *)((uint8_t *)hw->notify_base + notify_off * hw->notify_off_multiplier); - io_write16(&hw->common_cfg->queue_enable, 1); + hw->vtpci_access_ops->modern_write16(hw, + &hw->common_cfg->queue_enable, 1); PMD_INIT_LOG(DEBUG, "queue %u addresses:", vq->vq_queue_index); PMD_INIT_LOG(DEBUG, "\t desc_addr: %"PRIx64, desc_addr); @@ -632,22 +834,24 @@ modern_setup_queue(struct virtio_hw *hw, struct virtqueue *vq) static void modern_del_queue(struct virtio_hw *hw, struct virtqueue *vq) { - io_write16(&hw->common_cfg->queue_select, vq->vq_queue_index); + hw->vtpci_access_ops->modern_write16(hw, + &hw->common_cfg->queue_select, vq->vq_queue_index); - io_write64_twopart(&hw->common_cfg->queue_desc_lo, + io_write64_twopart(hw, &hw->common_cfg->queue_desc_lo, &hw->common_cfg->queue_desc_hi, 0); - io_write64_twopart(&hw->common_cfg->queue_avail_lo, + io_write64_twopart(hw, &hw->common_cfg->queue_avail_lo, &hw->common_cfg->queue_avail_hi, 0); - io_write64_twopart(&hw->common_cfg->queue_used_lo, + io_write64_twopart(hw, &hw->common_cfg->queue_used_lo, &hw->common_cfg->queue_used_hi, 0); - io_write16(&hw->common_cfg->queue_enable, 0); + hw->vtpci_access_ops->modern_write16(hw, + &hw->common_cfg->queue_enable, 0); } static void modern_notify_queue(struct virtio_hw *hw __rte_unused, struct virtqueue *vq) { - io_write16(vq->notify_addr, 1); + hw->vtpci_access_ops->modern_write16(hw, vq->notify_addr, 1); } static const struct virtio_pci_ops modern_ops = { @@ -666,7 +870,6 @@ static const struct virtio_pci_ops modern_ops = { .notify_queue = modern_notify_queue, }; - void vtpci_read_dev_config(struct virtio_hw *hw, uint64_t offset, void *dst, int length) @@ -739,55 +942,28 @@ vtpci_irq_config(struct virtio_hw *hw, uint16_t vec) return hw->vtpci_ops->set_config_irq(hw, vec); } -static void * -get_cfg_addr(struct rte_pci_device *dev, struct virtio_pci_cap *cap) -{ - uint8_t bar = cap->bar; - uint32_t length = cap->length; - uint32_t offset = cap->offset; - uint8_t *base; - - if (bar > 5) { - PMD_INIT_LOG(ERR, "invalid bar: %u", bar); - return NULL; - } - - if (offset + length > dev->mem_resource[bar].len) { - PMD_INIT_LOG(ERR, - "invalid cap: overflows bar space: %u > %"PRIu64, - offset + length, dev->mem_resource[bar].len); - return NULL; - } - - base = dev->mem_resource[bar].addr; - if (base == NULL) { - PMD_INIT_LOG(ERR, "bar %u base addr is NULL", bar); - return NULL; - } - - return base + offset; -} - static int -virtio_read_caps(struct rte_pci_device *dev, struct virtio_hw *hw) +virtio_read_caps(struct virtio_hw *hw) { uint8_t pos; struct virtio_pci_cap cap; int ret; - if (rte_eal_pci_map_device(dev) < 0) { + if (hw->vtpci_access_ops->map_pci_cfg(hw) < 0) { PMD_INIT_LOG(DEBUG, "failed to map pci device!"); return -1; } - ret = rte_eal_pci_read_config(dev, &pos, 1, PCI_CAPABILITY_LIST); + ret = hw->vtpci_access_ops->read_pci_cfg( + hw, &pos, 1, PCI_CAPABILITY_LIST); if (ret < 0) { PMD_INIT_LOG(DEBUG, "failed to read pci capability list"); return -1; } while (pos) { - ret = rte_eal_pci_read_config(dev, &cap, sizeof(cap), pos); + ret = hw->vtpci_access_ops->read_pci_cfg( + hw, &cap, sizeof(cap), pos); if (ret < 0) { PMD_INIT_LOG(ERR, "failed to read pci cap at pos: %x", pos); @@ -807,18 +983,22 @@ virtio_read_caps(struct rte_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 = + hw->vtpci_access_ops->get_cfg_addr(hw, &cap); break; case VIRTIO_PCI_CAP_NOTIFY_CFG: - rte_eal_pci_read_config(dev, &hw->notify_off_multiplier, + hw->vtpci_access_ops->read_pci_cfg(hw, + &hw->notify_off_multiplier, 4, pos + sizeof(cap)); - hw->notify_base = get_cfg_addr(dev, &cap); + hw->notify_base = + hw->vtpci_access_ops->get_cfg_addr(hw, &cap); break; case VIRTIO_PCI_CAP_DEVICE_CFG: - hw->dev_cfg = get_cfg_addr(dev, &cap); + hw->dev_cfg = + hw->vtpci_access_ops->get_cfg_addr(hw, &cap); break; case VIRTIO_PCI_CAP_ISR_CFG: - hw->isr = get_cfg_addr(dev, &cap); + hw->isr = hw->vtpci_access_ops->get_cfg_addr(hw, &cap); break; } @@ -844,42 +1024,53 @@ virtio_read_caps(struct rte_pci_device *dev, struct virtio_hw *hw) } int -vtpci_init(struct rte_pci_device *dev, struct virtio_hw *hw) +vtpci_init(struct rte_eth_dev *eth_dev, struct virtio_hw *hw) { - hw->dev = dev; + struct rte_pci_device *pci_dev = eth_dev->pci_dev; + + hw->dev = pci_dev; + + if (pci_dev == NULL) { + PMD_INIT_LOG(INFO, "No pci device specified."); + return -1; + } + + if (vtpci_access_init(eth_dev, hw) < 0) + return -1; /* * 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(dev, hw) == 0) { + if (virtio_read_caps(hw) == 0) { PMD_INIT_LOG(INFO, "modern virtio pci detected."); hw->vtpci_ops = &modern_ops; hw->modern = 1; - dev->driver->drv_flags |= RTE_PCI_DRV_INTR_LSC; + pci_dev->driver->drv_flags |= RTE_PCI_DRV_INTR_LSC; return 0; } PMD_INIT_LOG(INFO, "trying with legacy virtio pci."); - if (legacy_virtio_resource_init(dev) < 0) + if (legacy_virtio_resource_init(pci_dev) < 0) return -1; hw->vtpci_ops = &legacy_ops; - hw->use_msix = legacy_virtio_has_msix(&dev->addr); - hw->io_base = (uint32_t)(uintptr_t)dev->mem_resource[0].addr; + hw->use_msix = legacy_virtio_has_msix(&pci_dev->addr); + hw->io_base = (uint32_t)(uintptr_t)pci_dev->mem_resource[0].addr; hw->modern = 0; return 0; } void -vtpci_uninit(struct rte_pci_device *dev, struct virtio_hw *hw) +vtpci_uninit(struct rte_eth_dev *eth_dev, struct virtio_hw *hw) { hw->dev = NULL; hw->vtpci_ops = NULL; hw->use_msix = 0; hw->io_base = 0; hw->modern = 0; - rte_eal_pci_unmap_device(dev); + hw->vtpci_access_ops->unmap_pci_cfg(hw); + vtpci_access_uninit(eth_dev, hw); } diff --git a/drivers/net/virtio/virtio_pci.h b/drivers/net/virtio/virtio_pci.h index ec1d46b..b102679 100644 --- a/drivers/net/virtio/virtio_pci.h +++ b/drivers/net/virtio/virtio_pci.h @@ -222,6 +222,35 @@ struct virtio_pci_common_cfg { struct virtio_hw; +struct virtio_pci_access_ops { + uint8_t (*legacy_read8)(struct virtio_hw *hw, uint8_t *addr); + uint16_t (*legacy_read16)(struct virtio_hw *hw, uint16_t *addr); + uint32_t (*legacy_read32)(struct virtio_hw *hw, uint32_t *addr); + void (*legacy_write8)(struct virtio_hw *hw, + uint8_t *addr, uint8_t val); + void (*legacy_write16)(struct virtio_hw *hw, + uint16_t *addr, uint16_t val); + void (*legacy_write32)(struct virtio_hw *hw, + uint32_t *addr, uint32_t val); + + uint8_t (*modern_read8)(struct virtio_hw *hw, uint8_t *addr); + uint16_t (*modern_read16)(struct virtio_hw *hw, uint16_t *addr); + uint32_t (*modern_read32)(struct virtio_hw *hw, uint32_t *addr); + void (*modern_write8)(struct virtio_hw *hw, + uint8_t *addr, uint8_t val); + void (*modern_write16)(struct virtio_hw *hw, + uint16_t *addr, uint16_t val); + void (*modern_write32)(struct virtio_hw *hw, + uint32_t *addr, uint32_t val); + + int (*map_pci_cfg)(struct virtio_hw *hw); + void (*unmap_pci_cfg)(struct virtio_hw *hw); + void *(*get_cfg_addr)(struct virtio_hw *hw, + struct virtio_pci_cap *cap); + int (*read_pci_cfg)(struct virtio_hw *hw, + void *buf, size_t len, off_t offset); +}; + struct virtio_pci_ops { void (*read_dev_cfg)(struct virtio_hw *hw, uint64_t offset, void *dst, int len); @@ -266,6 +295,7 @@ struct virtio_hw { struct virtio_pci_common_cfg *common_cfg; struct virtio_net_config *dev_cfg; const struct virtio_pci_ops *vtpci_ops; + const struct virtio_pci_access_ops *vtpci_access_ops; }; /* @@ -327,8 +357,8 @@ vtpci_with_feature(struct virtio_hw *hw, uint64_t bit) /* * Function declaration from virtio_pci.c */ -int vtpci_init(struct rte_pci_device *, struct virtio_hw *); -void vtpci_uninit(struct rte_pci_device *dev, struct virtio_hw *); +int vtpci_init(struct rte_eth_dev *, struct virtio_hw *); +void vtpci_uninit(struct rte_eth_dev *, struct virtio_hw *); void vtpci_reset(struct virtio_hw *); void vtpci_reinit_complete(struct virtio_hw *);