From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pd0-f180.google.com (mail-pd0-f180.google.com [209.85.192.180]) by dpdk.org (Postfix) with ESMTP id 6704FC380 for ; Wed, 17 Jun 2015 01:51:42 +0200 (CEST) Received: by pdjn11 with SMTP id n11so24806478pdj.0 for ; Tue, 16 Jun 2015 16:51:41 -0700 (PDT) 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=9VlAiCSuZ0dImD8ywheRZSVld66z3wGx6vVaCHNaqPw=; b=b+S7jy3KUh6sglZLx2Xm9xdpdPM1bxcJH4/QFRlyB9Hk1Lumb7aDyDv0kCadJmy/y7 exZnwaZk+NOiHDPLdDh4n9O7WfVpieV58RyMcGw3adqAQ0uPOONdnaiskRm6e3cHDrQt rlsi/LuZlARF/moAjpEzYO9c+48KmR7XBOiKUvoi2/gNWkYpIU1Rue7lMpA9DwJwvZp3 WHDdtmhO4jWe8mlAfD7PS95rWygyyHZ3MUcjKIrIqPQE76wT9PYZ1L/ZL53OsKnikisY v5e0AbY5istA17yx+nP/4M9WMd0wt7QTZ3TBWi24dLHBuLYPP7YfmGZPBtH6BvkY4v+3 /Thg== X-Gm-Message-State: ALoCoQmfAAhvT34VNEHQy/0vFoB5tgdS/hYGrVY4DDRemFr8jNMh+X36K4vCdtrSi6U4cs54HfpJ X-Received: by 10.70.130.168 with SMTP id of8mr5077827pdb.131.1434498701844; Tue, 16 Jun 2015 16:51:41 -0700 (PDT) Received: from urahara.home.lan (static-50-53-82-155.bvtn.or.frontiernet.net. [50.53.82.155]) by mx.google.com with ESMTPSA id pp6sm2501917pbb.79.2015.06.16.16.51.40 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 16 Jun 2015 16:51:40 -0700 (PDT) From: Stephen Hemminger To: ameen.rahman@qlogic.com Date: Tue, 16 Jun 2015 16:51:37 -0700 Message-Id: <1434498700-8522-2-git-send-email-stephen@networkplumber.org> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1434498700-8522-1-git-send-email-stephen@networkplumber.org> References: <1434498700-8522-1-git-send-email-stephen@networkplumber.org> Cc: dev@dpdk.org, Stephen Hemminger Subject: [dpdk-dev] [PATCH 1/4] eal: provide functions to access PCI config 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: , X-List-Received-Date: Tue, 16 Jun 2015 23:51:42 -0000 From: Stephen Hemminger Some drivers need ability to access PCI config (for example for power management). This adds an abstraction to do this for both Linux and BSD. Signed-off-by: Stephen Hemminger --- lib/librte_eal/bsdapp/eal/eal_pci.c | 83 +++++++++++++++++++++++++ lib/librte_eal/bsdapp/eal/rte_eal_version.map | 2 + lib/librte_eal/common/include/rte_pci.h | 28 +++++++++ lib/librte_eal/linuxapp/eal/eal_pci.c | 50 +++++++++++++++ lib/librte_eal/linuxapp/eal/eal_pci_init.h | 11 ++++ lib/librte_eal/linuxapp/eal/eal_pci_uio.c | 14 +++++ lib/librte_eal/linuxapp/eal/eal_pci_vfio.c | 16 +++++ lib/librte_eal/linuxapp/eal/rte_eal_version.map | 2 + 8 files changed, 206 insertions(+) diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c index 61e8921..bf6bc93 100644 --- a/lib/librte_eal/bsdapp/eal/eal_pci.c +++ b/lib/librte_eal/bsdapp/eal/eal_pci.c @@ -490,6 +490,89 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *d return 1; } +/* Read PCI config space. */ +int rte_eal_pci_read_config(const struct rte_pci_device *dev, + void *buf, size_t len, off_t offset) +{ + int fd = -1; + struct pci_io pi = { + .pi_sel = { + .pc_domain = dev->addr.domain, + .pc_bus = dev->addr.bus, + .pc_dev = dev->addr.devid, + .pc_func = dev->addr.function, + }, + .pi_reg = offset, + .pi_width = len, + }; + + if (len == 3 || len > sizeof(pi.pi_data)) { + RTE_LOG(ERR, EAL, "%s(): invalid pci read length\n", __func__); + goto error; + } + + fd = open("/dev/pci", O_RDONLY); + if (fd < 0) { + RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__); + goto error; + } + + if (ioctl(fd, PCIOCREAD, &pi) < 0) + goto error; + close(fd); + + memcpy(buf, &pi.pi_data, len); + return 0; + + error: + if (fd >= 0) + close(fd); + return -1; +} + +/* Write PCI config space. */ +int rte_eal_pci_write_config(const struct rte_pci_device *dev, + const void *buf, size_t len, off_t offset) +{ + int fd = -1; + + struct pci_io pi = { + .pi_sel = { + .pc_domain = dev->addr.domain, + .pc_bus = dev->addr.bus, + .pc_dev = dev->addr.devid, + .pc_func = dev->addr.function, + }, + .pi_reg = offset, + .pi_data = *(u_int32_t *)buf, + .pi_width = len, + }; + + if (len == 3 || len > sizeof(pi.pi_data)) { + RTE_LOG(ERR, EAL, "%s(): invalid pci read length\n", __func__); + goto error; + } + + memcpy(pi.pi_data, buf, len); + + fd = open("/dev/pci", O_RDONLY); + if (fd < 0) { + RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__); + goto error; + } + + if (ioctl(fd, PCIOCWRITE, &pi) < 0) + goto error; + + close(fd); + return 0; + + error: + if (fd >= 0) + close(fd); + return -1; +} + /* Init the PCI EAL subsystem */ int rte_eal_pci_init(void) diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map index 67b6a6c..6d2ee41 100644 --- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map +++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map @@ -39,8 +39,10 @@ DPDK_2.0 { rte_eal_mp_wait_lcore; rte_eal_pci_dump; rte_eal_pci_probe; + rte_eal_pci_read_config; rte_eal_pci_register; rte_eal_pci_unregister; + rte_eal_pci_write_config; rte_eal_process_type; rte_eal_remote_launch; rte_eal_tailq_lookup; diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h index b4f38bc..62fb0ea 100644 --- a/lib/librte_eal/common/include/rte_pci.h +++ b/lib/librte_eal/common/include/rte_pci.h @@ -394,6 +394,34 @@ void rte_eal_pci_register(struct rte_pci_driver *driver); */ void rte_eal_pci_unregister(struct rte_pci_driver *driver); +/** + * Read PCI config space. + * + * @param device + * A pointer to a rte_pci_device structure describing the device + * to use + * @param buf + * A data buffer where the bytes should be read into + * @param size + * The length of the data buffer. + */ +int rte_eal_pci_read_config(const struct rte_pci_device *device, + void *buf, size_t len, off_t offset); + +/** + * Write PCI config space. + * + * @param device + * A pointer to a rte_pci_device structure describing the device + * to use + * @param buf + * A data buffer containing the bytes should be written + * @param size + * The length of the data buffer. + */ +int rte_eal_pci_write_config(const struct rte_pci_device *device, + const void *buf, size_t len, off_t offset); + #ifdef __cplusplus } #endif diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c index d2adc66..575963b 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c @@ -756,6 +756,56 @@ rte_eal_pci_close_one_driver(struct rte_pci_driver *dr __rte_unused, } #endif /* RTE_LIBRTE_EAL_HOTPLUG */ +/* Read PCI config space. */ +int rte_eal_pci_read_config(const struct rte_pci_device *device, + void *buf, size_t len, off_t offset) +{ + const struct rte_intr_handle *intr_handle = &device->intr_handle; + + switch (intr_handle->type) { + case RTE_INTR_HANDLE_UIO: + case RTE_INTR_HANDLE_UIO_INTX: + return pci_uio_read_config(intr_handle, buf, len, offset); + +#ifdef VFIO_PRESENT + case RTE_INTR_HANDLE_VFIO_MSIX: + case RTE_INTR_HANDLE_VFIO_MSI: + case RTE_INTR_HANDLE_VFIO_LEGACY: + return pci_vfio_read_config(intr_handle, buf, len, offset); +#endif + default: + RTE_LOG(ERR, EAL, + "Unknown handle type of fd %d\n", + intr_handle->fd); + return -1; + } +} + +/* Write PCI config space. */ +int rte_eal_pci_write_config(const struct rte_pci_device *device, + const void *buf, size_t len, off_t offset) +{ + const struct rte_intr_handle *intr_handle = &device->intr_handle; + + switch (intr_handle->type) { + case RTE_INTR_HANDLE_UIO: + case RTE_INTR_HANDLE_UIO_INTX: + return pci_uio_write_config(intr_handle, buf, len, offset); + +#ifdef VFIO_PRESENT + case RTE_INTR_HANDLE_VFIO_MSIX: + case RTE_INTR_HANDLE_VFIO_MSI: + case RTE_INTR_HANDLE_VFIO_LEGACY: + return pci_vfio_write_config(intr_handle, buf, len, offset); +#endif + default: + RTE_LOG(ERR, EAL, + "Unknown handle type of fd %d\n", + intr_handle->fd); + return -1; + } +} + /* Init the PCI EAL subsystem */ int rte_eal_pci_init(void) diff --git a/lib/librte_eal/linuxapp/eal/eal_pci_init.h b/lib/librte_eal/linuxapp/eal/eal_pci_init.h index aa7b755..c28e5b0 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci_init.h +++ b/lib/librte_eal/linuxapp/eal/eal_pci_init.h @@ -68,6 +68,11 @@ void *pci_find_max_end_va(void); void *pci_map_resource(void *requested_addr, int fd, off_t offset, size_t size, int additional_flags); +int pci_uio_read_config(const struct rte_intr_handle *intr_handle, + void *buf, size_t len, off_t offs); +int pci_uio_write_config(const struct rte_intr_handle *intr_handle, + const void *buf, size_t len, off_t offs); + /* map IGB_UIO resource prototype */ int pci_uio_map_resource(struct rte_pci_device *dev); @@ -86,6 +91,12 @@ int pci_vfio_enable(void); int pci_vfio_is_enabled(void); int pci_vfio_mp_sync_setup(void); +/* access config space */ +int pci_vfio_read_config(const struct rte_intr_handle *intr_handle, + void *buf, size_t len, off_t offs); +int pci_vfio_write_config(const struct rte_intr_handle *intr_handle, + const void *buf, size_t len, off_t offs); + /* map VFIO resource prototype */ int pci_vfio_map_resource(struct rte_pci_device *dev); int pci_vfio_get_group_fd(int iommu_group_fd); diff --git a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c index b5116a7..ee7483e 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c @@ -58,6 +58,20 @@ EAL_REGISTER_TAILQ(rte_uio_tailq) #define OFF_MAX ((uint64_t)(off_t)-1) +int +pci_uio_read_config(const struct rte_intr_handle *intr_handle, + void *buf, size_t len, off_t offset) +{ + return pread(intr_handle->uio_cfg_fd, buf, len, offset); +} + +int +pci_uio_write_config(const struct rte_intr_handle *intr_handle, + const void *buf, size_t len, off_t offset) +{ + return pwrite(intr_handle->uio_cfg_fd, buf, len, offset); +} + static int pci_uio_set_bus_master(int dev_fd) { diff --git a/lib/librte_eal/linuxapp/eal/eal_pci_vfio.c b/lib/librte_eal/linuxapp/eal/eal_pci_vfio.c index 426953a..3d72ee1 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci_vfio.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci_vfio.c @@ -77,6 +77,22 @@ EAL_REGISTER_TAILQ(rte_vfio_tailq) /* per-process VFIO config */ static struct vfio_config vfio_cfg; +int +pci_vfio_read_config(const struct rte_intr_handle *intr_handle, + void *buf, size_t len, off_t offs) +{ + return pread64(intr_handle->vfio_dev_fd, buf, len, + VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) + offs); +} + +int +pci_vfio_write_config(const struct rte_intr_handle *intr_handle, + const void *buf, size_t len, off_t offs) +{ + return pwrite64(intr_handle->vfio_dev_fd, buf, len, + VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) + offs); +} + /* get PCI BAR number where MSI-X interrupts are */ static int pci_vfio_get_msix_bar(int fd, int *msix_bar, uint32_t *msix_table_offset, diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map index 7e850a9..494aae0 100644 --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map @@ -42,9 +42,11 @@ DPDK_2.0 { rte_eal_pci_dump; rte_eal_pci_probe; rte_eal_pci_probe_one; + rte_eal_pci_read_config; rte_eal_pci_register; rte_eal_pci_scan; rte_eal_pci_unregister; + rte_eal_pci_write_config; rte_eal_process_type; rte_eal_remote_launch; rte_eal_tailq_lookup; -- 2.1.4