From patchwork Tue Aug 26 00:44:29 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Hemminger X-Patchwork-Id: 219 Return-Path: Received: from mx0b-000f0801.pphosted.com (mx0b-000f0801.pphosted.com [67.231.152.113]) by dpdk.org (Postfix) with ESMTP id 3BC6A3975 for ; Tue, 26 Aug 2014 02:40:39 +0200 (CEST) Received: from pps.filterd (m0000700 [127.0.0.1]) by mx0b-000f0801.pphosted.com (8.14.5/8.14.5) with SMTP id s7Q0bJdW008048 for ; Mon, 25 Aug 2014 17:44:32 -0700 Received: from hq1wp-exchub01.corp.brocade.com ([144.49.131.13]) by mx0b-000f0801.pphosted.com with ESMTP id 1nyvsc3enf-1 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NOT) for ; Mon, 25 Aug 2014 17:44:32 -0700 Received: from HQ1WP-EXHUB01.corp.brocade.com (10.70.36.14) by HQ1WP-EXCHUB01.corp.brocade.com (10.70.36.99) with Microsoft SMTP Server (TLS) id 14.3.123.3; Mon, 25 Aug 2014 17:44:31 -0700 Received: from urahara (10.72.32.14) by imap.brocade.com (10.70.36.22) with Microsoft SMTP Server (TLS) id 8.3.298.1; Mon, 25 Aug 2014 17:44:30 -0700 Date: Mon, 25 Aug 2014 17:44:29 -0700 From: Stephen Hemminger To: "dev@dpdk.org" Message-ID: <20140825174429.2065320b@urahara> Organization: Brocade MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:5.12.52, 1.0.27, 0.0.0000 definitions=2014-08-26_01:2014-08-25, 2014-08-25, 1970-01-01 signatures=0 X-Proofpoint-Spam-Details: rule=notspam policy=default score=3 spamscore=3 suspectscore=5 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=7.0.1-1402240000 definitions=main-1408260007 X-Mailman-Approved-At: Tue, 26 Aug 2014 08:50:00 +0200 Subject: [dpdk-dev] [RFC] PCI config access for drivers 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, 26 Aug 2014 00:40:39 -0000 Some drivers need ability to access PCI config (for example for power management). This adds an abstraction to do this; only implemented on Linux, but should be possible on BSD. Signed-off-by: Stephen Hemminger --- a/lib/librte_eal/common/include/rte_pci.h 2014-06-24 09:20:05.651993525 -0700 +++ b/lib/librte_eal/common/include/rte_pci.h 2014-06-24 09:25:42.150616572 -0700 @@ -151,6 +151,7 @@ struct rte_pci_device { const struct rte_pci_driver *driver; /**< Associated driver */ uint16_t max_vfs; /**< sriov enable if not zero */ int numa_node; /**< NUMA node connection */ + int config_fd; /**< PCI config access */ struct rte_devargs *devargs; /**< Device user arguments */ }; @@ -298,6 +299,34 @@ void rte_eal_pci_register(struct rte_pci */ 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 --- a/lib/librte_eal/linuxapp/eal/eal_pci.c 2014-06-24 09:20:05.651993525 -0700 +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c 2014-06-24 09:20:05.651993525 -0700 @@ -219,6 +219,7 @@ pci_scan_one(const char *dirname, uint16 dev->addr.bus = bus; dev->addr.devid = devid; dev->addr.function = function; + dev->config_fd = -1; /* get vendor id */ snprintf(filename, sizeof(filename), "%s/vendor", dirname); @@ -578,6 +579,20 @@ rte_eal_pci_probe_one_driver(struct rte_ return 1; } +/* Read PCI config space. */ +int rte_eal_pci_read_config(const struct rte_pci_device *device, + void *buf, size_t len, off_t offset) +{ + return pread(device->config_fd, buf, len, offset); +} + +/* 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) +{ + return pwrite(device->config_fd, buf, len, offset); +} + /* Init the PCI EAL subsystem */ int rte_eal_pci_init(void) --- a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c 2014-06-24 08:35:31.832146544 -0700 +++ b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c 2014-06-24 09:37:44.892296443 -0700 @@ -280,6 +280,7 @@ pci_uio_map_resource(struct rte_pci_devi int i, j; char dirname[PATH_MAX]; char devname[PATH_MAX]; /* contains the /dev/uioX */ + char cfgname[PATH_MAX]; void *mapaddr; int uio_num; uint64_t phaddr; @@ -326,11 +327,23 @@ pci_uio_map_resource(struct rte_pci_devi snprintf(uio_res->path, sizeof(uio_res->path), "%s", devname); memcpy(&uio_res->pci_addr, &dev->addr, sizeof(uio_res->pci_addr)); + /* Open fd for access to PCI config */ + snprintf(cfgname, sizeof(cfgname), + "%s/device/config", dirname); + dev->config_fd = open(cfgname, O_RDWR); + if (dev->config_fd < 0) { + RTE_LOG(ERR, EAL, "%s(): cannot open %s: %s\n", + __func__, cfgname, strerror(errno)); + rte_free(uio_res); + return -1; + } + /* collect info about device mappings */ nb_maps = pci_uio_get_mappings(dirname, uio_res->maps, RTE_DIM(uio_res->maps)); if (nb_maps < 0) { rte_free(uio_res); + close(dev->config_fd); return nb_maps; } @@ -379,6 +392,7 @@ pci_uio_map_resource(struct rte_pci_devi if (fail) { rte_free(uio_res); + close(dev->config_fd); close(fd); return -1; }