From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by dpdk.org (Postfix) with ESMTP id 2AB70376C for ; Mon, 2 Feb 2015 06:42:44 +0100 (CET) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga102.jf.intel.com with ESMTP; 01 Feb 2015 21:39:17 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.09,504,1418112000"; d="scan'208";a="660143782" Received: from pgsmsx101.gar.corp.intel.com ([10.221.44.78]) by fmsmga001.fm.intel.com with ESMTP; 01 Feb 2015 21:42:40 -0800 Received: from shsmsx103.ccr.corp.intel.com (10.239.4.69) by PGSMSX101.gar.corp.intel.com (10.221.44.78) with Microsoft SMTP Server (TLS) id 14.3.195.1; Mon, 2 Feb 2015 13:42:39 +0800 Received: from shsmsx101.ccr.corp.intel.com ([169.254.1.253]) by SHSMSX103.ccr.corp.intel.com ([169.254.4.91]) with mapi id 14.03.0195.001; Mon, 2 Feb 2015 13:42:39 +0800 From: "Qiu, Michael" To: Tetsuya Mukawa , "dev@dpdk.org" Thread-Topic: [PATCH v6 12/13] eal/pci: Add rte_eal_dev_attach/detach() functions Thread-Index: AQHQPdPy7Blels9imUGFi8evC3UPTA== Date: Mon, 2 Feb 2015 05:42:38 +0000 Message-ID: <533710CFB86FA344BFBF2D6802E60286CD256A@SHSMSX101.ccr.corp.intel.com> References: <1421664027-17971-9-git-send-email-mukawa@igel.co.jp> <1422763322-13742-1-git-send-email-mukawa@igel.co.jp> <1422763322-13742-13-git-send-email-mukawa@igel.co.jp> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.239.127.40] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Subject: Re: [dpdk-dev] [PATCH v6 12/13] eal/pci: Add rte_eal_dev_attach/detach() functions 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: Mon, 02 Feb 2015 05:42:45 -0000 On 2/1/2015 12:02 PM, Tetsuya Mukawa wrote:=0A= > These functions are used for attaching or detaching a port.=0A= > When rte_eal_dev_attach() is called, the function tries to realize the=0A= > device name as pci address. If this is done successfully,=0A= > rte_eal_dev_attach() will attach physical device port. If not, attaches= =0A= > virtual devive port.=0A= > When rte_eal_dev_detach() is called, the function gets the device type=0A= > of this port to know whether the port is came from physical or virtual.= =0A= > And then specific detaching function will be called.=0A= >=0A= > v5:=0A= > - Change function names like below.=0A= > rte_eal_dev_find_and_invoke() to rte_eal_vdev_find_and_invoke().=0A= > rte_eal_dev_invoke() to rte_eal_vdev_invoke().=0A= > - Add code to handle a return value of rte_eal_devargs_remove().=0A= > - Fix pci address format in rte_eal_dev_detach().=0A= > v4:=0A= > - Fix comment.=0A= > - Add error checking.=0A= > - Fix indent of 'if' statement.=0A= > - Change function name.=0A= >=0A= > Signed-off-by: Tetsuya Mukawa =0A= > ---=0A= > lib/librte_eal/common/eal_common_dev.c | 274 ++++++++++++++++++++++++++= ++++++=0A= > lib/librte_eal/common/eal_private.h | 11 ++=0A= > lib/librte_eal/common/include/rte_dev.h | 33 ++++=0A= > lib/librte_eal/linuxapp/eal/Makefile | 1 +=0A= > lib/librte_eal/linuxapp/eal/eal_pci.c | 6 +-=0A= > 5 files changed, 322 insertions(+), 3 deletions(-)=0A= >=0A= > diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/comm= on/eal_common_dev.c=0A= > index eae5656..e3a3f54 100644=0A= > --- a/lib/librte_eal/common/eal_common_dev.c=0A= > +++ b/lib/librte_eal/common/eal_common_dev.c=0A= > @@ -32,10 +32,13 @@=0A= > * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE= .=0A= > */=0A= > =0A= > +#include =0A= > +#include =0A= > #include =0A= > #include =0A= > #include =0A= > =0A= > +#include =0A= > #include =0A= > #include =0A= > #include =0A= > @@ -107,3 +110,274 @@ rte_eal_dev_init(void)=0A= > }=0A= > return 0;=0A= > }=0A= > +=0A= > +/* So far, DPDK hotplug function only supports linux */=0A= > +#ifdef ENABLE_HOTPLUG=0A= > +static void=0A= > +rte_eal_vdev_invoke(struct rte_driver *driver,=0A= > + struct rte_devargs *devargs, enum rte_eal_invoke_type type)=0A= > +{=0A= > + if ((driver =3D=3D NULL) || (devargs =3D=3D NULL))=0A= > + return;=0A= > +=0A= > + switch (type) {=0A= > + case RTE_EAL_INVOKE_TYPE_PROBE:=0A= > + driver->init(devargs->virtual.drv_name, devargs->args);=0A= > + break;=0A= > + case RTE_EAL_INVOKE_TYPE_CLOSE:=0A= > + driver->uninit(devargs->virtual.drv_name, devargs->args);=0A= > + break;=0A= > + default:=0A= > + break;=0A= > + }=0A= > +}=0A= > +=0A= > +static int=0A= > +rte_eal_vdev_find_and_invoke(const char *name, int type)=0A= > +{=0A= > + struct rte_devargs *devargs;=0A= > + struct rte_driver *driver;=0A= > +=0A= > + if (name =3D=3D NULL)=0A= > + return -EINVAL;=0A= > +=0A= > + /* call the init function for each virtual device */=0A= > + TAILQ_FOREACH(devargs, &devargs_list, next) {=0A= > +=0A= > + if (devargs->type !=3D RTE_DEVTYPE_VIRTUAL)=0A= > + continue;=0A= > +=0A= > + if (strncmp(name, devargs->virtual.drv_name, strlen(name)))=0A= > + continue;=0A= > +=0A= > + TAILQ_FOREACH(driver, &dev_driver_list, next) {=0A= > + if (driver->type !=3D PMD_VDEV)=0A= > + continue;=0A= > +=0A= > + /* search a driver prefix in virtual device name */=0A= > + if (!strncmp(driver->name, devargs->virtual.drv_name,=0A= > + strlen(driver->name))) {=0A= > + rte_eal_vdev_invoke(driver, devargs, type);=0A= > + break;=0A= > + }=0A= > + }=0A= > +=0A= > + if (driver =3D=3D NULL) {=0A= > + RTE_LOG(WARNING, EAL, "no driver found for %s\n",=0A= > + devargs->virtual.drv_name);=0A= > + }=0A= > + return 0;=0A= > + }=0A= > + return 1;=0A= > +}=0A= > +=0A= > +/* attach the new physical device, then store port_id of the device */= =0A= > +static int=0A= > +rte_eal_dev_attach_pdev(struct rte_pci_addr *addr, uint8_t *port_id)=0A= > +{=0A= > + uint8_t new_port_id;=0A= > + struct rte_eth_dev devs[RTE_MAX_ETHPORTS];=0A= > +=0A= > + if ((addr =3D=3D NULL) || (port_id =3D=3D NULL))=0A= > + goto err;=0A= > +=0A= > + /* save current port status */=0A= > + rte_eth_dev_save(devs);=0A= > + /* re-construct pci_device_list */=0A= > + if (rte_eal_pci_scan())=0A= > + goto err;=0A= > + /* invoke probe func of the driver can handle the new device */=0A= > + if (rte_eal_pci_probe_one(addr))=0A= > + goto err;=0A= > + /* get port_id enabled by above procedures */=0A= > + if (rte_eth_dev_get_changed_port(devs, &new_port_id))=0A= > + goto err;=0A= > +=0A= > + *port_id =3D new_port_id;=0A= > + return 0;=0A= > +err:=0A= > + RTE_LOG(ERR, EAL, "Drver, cannot attach the device\n");=0A= =0A= Sorry, what does "Drver" means?=0A= =0A= My English is bad, also I haven't gotten this work in google=0A= =0A= Thanks,=0A= Michael=0A= > + return -1;=0A= > +}=0A= > +=0A= > +/* detach the new physical device, then store pci_addr of the device */= =0A= > +static int=0A= > +rte_eal_dev_detach_pdev(uint8_t port_id, struct rte_pci_addr *addr)=0A= > +{=0A= > + struct rte_pci_addr freed_addr;=0A= > + struct rte_pci_addr vp;=0A= > +=0A= > + if (addr =3D=3D NULL)=0A= > + goto err;=0A= > +=0A= > + /* check whether the driver supports detach feature, or not */=0A= > + if (rte_eth_dev_check_detachable(port_id))=0A= > + goto err;=0A= > +=0A= > + /* get pci address by port id */=0A= > + if (rte_eth_dev_get_addr_by_port(port_id, &freed_addr))=0A= > + goto err;=0A= > +=0A= > + /* Zerod pci addr means the port comes from virtual device */=0A= > + vp.domain =3D vp.bus =3D vp.devid =3D vp.function =3D 0;=0A= > + if (eal_compare_pci_addr(&vp, &freed_addr) =3D=3D 0)=0A= > + goto err;=0A= > +=0A= > + /* invoke close func of the driver,=0A= > + * also remove the device from pci_device_list */=0A= > + if (rte_eal_pci_close_one(&freed_addr))=0A= > + goto err;=0A= > +=0A= > + *addr =3D freed_addr;=0A= > + return 0;=0A= > +err:=0A= > + RTE_LOG(ERR, EAL, "Drver, cannot detach the device\n");=0A= =0A= Here, "Drver"=0A= > + return -1;=0A= > +}=0A= > +=0A= > +static void=0A= > +get_vdev_name(char *vdevargs)=0A= > +{=0A= > + char *sep;=0A= > +=0A= > + if (vdevargs =3D=3D NULL)=0A= > + return;=0A= > +=0A= > + /* set the first ',' to '\0' to split name and arguments */=0A= > + sep =3D strchr(vdevargs, ',');=0A= > + if (sep !=3D NULL)=0A= > + sep[0] =3D '\0';=0A= > +}=0A= > +=0A= > +/* attach the new virtual device, then store port_id of the device */=0A= > +static int=0A= > +rte_eal_dev_attach_vdev(const char *vdevargs, uint8_t *port_id)=0A= > +{=0A= > + char *args;=0A= > + uint8_t new_port_id;=0A= > + struct rte_eth_dev devs[RTE_MAX_ETHPORTS];=0A= > +=0A= > + if ((vdevargs =3D=3D NULL) || (port_id =3D=3D NULL))=0A= > + goto err0;=0A= > +=0A= > + args =3D strdup(vdevargs);=0A= > + if (args =3D=3D NULL)=0A= > + goto err0;=0A= > +=0A= > + /* save current port status */=0A= > + rte_eth_dev_save(devs);=0A= > + /* add the vdevargs to devargs_list */=0A= > + if (rte_eal_devargs_add(RTE_DEVTYPE_VIRTUAL, args))=0A= > + goto err1;=0A= > + /* parse vdevargs, then retrieve device name */=0A= > + get_vdev_name(args);=0A= > + /* walk around dev_driver_list to find the driver of the device,=0A= > + * then invoke probe function o the driver */=0A= > + if (rte_eal_vdev_find_and_invoke(args, RTE_EAL_INVOKE_TYPE_PROBE))=0A= > + goto err2;=0A= > + /* get port_id enabled by above procedures */=0A= > + if (rte_eth_dev_get_changed_port(devs, &new_port_id))=0A= > + goto err2;=0A= > +=0A= > + free(args);=0A= > + *port_id =3D new_port_id;=0A= > + return 0;=0A= > +err2:=0A= > + rte_eal_devargs_remove(RTE_DEVTYPE_VIRTUAL, args);=0A= > +err1:=0A= > + free(args);=0A= > +err0:=0A= > + RTE_LOG(ERR, EAL, "Drver, cannot detach the device\n");=0A= =0A= Here also "Drver",=0A= =0A= =0A= Thanks,=0A= Michael=0A= > + return -1;=0A= > +}=0A= > +=0A= > +/* detach the new virtual device, then store the name of the device */= =0A= > +static int=0A= > +rte_eal_dev_detach_vdev(uint8_t port_id, char *vdevname)=0A= > +{=0A= > + char name[RTE_ETH_NAME_MAX_LEN];=0A= > +=0A= > + if (vdevname =3D=3D NULL)=0A= > + goto err;=0A= > +=0A= > + /* check whether the driver supports detach feature, or not */=0A= > + if (rte_eth_dev_check_detachable(port_id))=0A= > + goto err;=0A= > +=0A= > + /* get device name by port id */=0A= > + if (rte_eth_dev_get_name_by_port(port_id, name))=0A= > + goto err;=0A= > + /* walk around dev_driver_list to find the driver of the device,=0A= > + * then invoke close function o the driver */=0A= > + if (rte_eal_vdev_find_and_invoke(name, RTE_EAL_INVOKE_TYPE_CLOSE))=0A= > + goto err;=0A= > + /* remove the vdevname from devargs_list */=0A= > + if (rte_eal_devargs_remove(RTE_DEVTYPE_VIRTUAL, name))=0A= > + goto err;=0A= > +=0A= > + strncpy(vdevname, name, sizeof(name));=0A= > + return 0;=0A= > +err:=0A= > + RTE_LOG(ERR, EAL, "Drver, cannot detach the device\n");=0A= > + return -1;=0A= > +}=0A= > +=0A= > +/* attach the new device, then store port_id of the device */=0A= > +int=0A= > +rte_eal_dev_attach(const char *devargs, uint8_t *port_id)=0A= > +{=0A= > + struct rte_pci_addr addr;=0A= > +=0A= > + if ((devargs =3D=3D NULL) || (port_id =3D=3D NULL))=0A= > + return -EINVAL;=0A= > +=0A= > + if (eal_parse_pci_DomBDF(devargs, &addr) =3D=3D 0)=0A= > + return rte_eal_dev_attach_pdev(&addr, port_id);=0A= > + else=0A= > + return rte_eal_dev_attach_vdev(devargs, port_id);=0A= > +}=0A= > +=0A= > +/* detach the device, then store the name of the device */=0A= > +int=0A= > +rte_eal_dev_detach(uint8_t port_id, char *name)=0A= > +{=0A= > + struct rte_pci_addr addr;=0A= > + int ret;=0A= > +=0A= > + if (name =3D=3D NULL)=0A= > + return -EINVAL;=0A= > +=0A= > + if (rte_eth_dev_get_device_type(port_id) =3D=3D RTE_ETH_DEV_PHYSICAL) {= =0A= > + ret =3D rte_eth_dev_get_addr_by_port(port_id, &addr);=0A= > + if (ret < 0)=0A= > + return ret;=0A= > +=0A= > + ret =3D rte_eal_dev_detach_pdev(port_id, &addr);=0A= > + if (ret =3D=3D 0)=0A= > + snprintf(name, RTE_ETH_NAME_MAX_LEN,=0A= > + "%04x:%02x:%02x.%d",=0A= > + addr.domain, addr.bus,=0A= > + addr.devid, addr.function);=0A= > +=0A= > + return ret;=0A= > + } else=0A= > + return rte_eal_dev_detach_vdev(port_id, name);=0A= > +}=0A= > +#else /* ENABLE_HOTPLUG */=0A= > +int=0A= > +rte_eal_dev_attach(const char *devargs __rte_unused,=0A= > + uint8_t *port_id __rte_unused)=0A= > +{=0A= > + RTE_LOG(ERR, EAL, "Hotplug support isn't enabled\n");=0A= > + return -1;=0A= > +}=0A= > +=0A= > +/* detach the device, then store the name of the device */=0A= > +int=0A= > +rte_eal_dev_detach(uint8_t port_id __rte_unused,=0A= > + char *name __rte_unused)=0A= > +{=0A= > + RTE_LOG(ERR, EAL, "Hotplug support isn't enabled\n");=0A= > + return -1;=0A= > +}=0A= > +#endif /* ENABLE_HOTPLUG */=0A= > diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/= eal_private.h=0A= > index 1a362ab..8168a7a 100644=0A= > --- a/lib/librte_eal/common/eal_private.h=0A= > +++ b/lib/librte_eal/common/eal_private.h=0A= > @@ -163,6 +163,17 @@ enum rte_eal_invoke_type {=0A= > };=0A= > =0A= > /**=0A= > + * Scan the content of the PCI bus, and the devices in the devices=0A= > + * list=0A= > + *=0A= > + * This function is private to EAL.=0A= > + *=0A= > + * @return=0A= > + * 0 on success, negative on error=0A= > + */=0A= > +int rte_eal_pci_scan(void);=0A= > +=0A= > +/**=0A= > * Mmap memory for single PCI device=0A= > *=0A= > * This function is private to EAL.=0A= > diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/com= mon/include/rte_dev.h=0A= > index f7e3a10..e63dd1c 100644=0A= > --- a/lib/librte_eal/common/include/rte_dev.h=0A= > +++ b/lib/librte_eal/common/include/rte_dev.h=0A= > @@ -47,6 +47,7 @@ extern "C" {=0A= > #endif=0A= > =0A= > #include =0A= > +#include =0A= > =0A= > /** Double linked list of device drivers. */=0A= > TAILQ_HEAD(rte_driver_list, rte_driver);=0A= > @@ -57,6 +58,11 @@ TAILQ_HEAD(rte_driver_list, rte_driver);=0A= > typedef int (rte_dev_init_t)(const char *name, const char *args);=0A= > =0A= > /**=0A= > + * Uninitilization function called for each device driver once.=0A= > + */=0A= > +typedef int (rte_dev_uninit_t)(const char *name, const char *args);=0A= > +=0A= > +/**=0A= > * Driver type enumeration=0A= > */=0A= > enum pmd_type {=0A= > @@ -72,6 +78,7 @@ struct rte_driver {=0A= > enum pmd_type type; /**< PMD Driver type */=0A= > const char *name; /**< Driver name. */=0A= > rte_dev_init_t *init; /**< Device init. function. */=0A= > + rte_dev_uninit_t *uninit; /**< Device uninit. function. */=0A= > };=0A= > =0A= > /**=0A= > @@ -93,6 +100,32 @@ void rte_eal_driver_register(struct rte_driver *drive= r);=0A= > void rte_eal_driver_unregister(struct rte_driver *driver);=0A= > =0A= > /**=0A= > + * Attach a new device.=0A= > + *=0A= > + * @param devargs=0A= > + * A pointer to a strings array describing the new device=0A= > + * to be attached. The strings should be a pci address like=0A= > + * '0000:01:00.0' or virtual device name like 'eth_pcap0'.=0A= > + * @param port_id=0A= > + * A pointer to a port identifier actually attached.=0A= > + * @return=0A= > + * 0 on success and port_id is filled, negative on error=0A= > + */=0A= > +int rte_eal_dev_attach(const char *devargs, uint8_t *port_id);=0A= > +=0A= > +/**=0A= > + * Detach a device.=0A= > + *=0A= > + * @param port_id=0A= > + * The port identifier of the device to detach.=0A= > + * @param addr=0A= > + * A pointer to a device name actually detached.=0A= > + * @return=0A= > + * 0 on success and devname is filled, negative on error=0A= > + */=0A= > +int rte_eal_dev_detach(uint8_t port_id, char *devname);=0A= > +=0A= > +/**=0A= > * Initalize all the registered drivers in this process=0A= > */=0A= > int rte_eal_dev_init(void);=0A= > diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxa= pp/eal/Makefile=0A= > index 72ecf3a..0ec83b5 100644=0A= > --- a/lib/librte_eal/linuxapp/eal/Makefile=0A= > +++ b/lib/librte_eal/linuxapp/eal/Makefile=0A= > @@ -41,6 +41,7 @@ CFLAGS +=3D -I$(RTE_SDK)/lib/librte_eal/common/include= =0A= > CFLAGS +=3D -I$(RTE_SDK)/lib/librte_ring=0A= > CFLAGS +=3D -I$(RTE_SDK)/lib/librte_mempool=0A= > CFLAGS +=3D -I$(RTE_SDK)/lib/librte_malloc=0A= > +CFLAGS +=3D -I$(RTE_SDK)/lib/librte_mbuf=0A= > CFLAGS +=3D -I$(RTE_SDK)/lib/librte_ether=0A= > CFLAGS +=3D -I$(RTE_SDK)/lib/librte_ivshmem=0A= > CFLAGS +=3D -I$(RTE_SDK)/lib/librte_pmd_ring=0A= > diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linux= app/eal/eal_pci.c=0A= > index 831422e..1f43688 100644=0A= > --- a/lib/librte_eal/linuxapp/eal/eal_pci.c=0A= > +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c=0A= > @@ -431,8 +431,8 @@ error:=0A= > * Scan the content of the PCI bus, and the devices in the devices=0A= > * list=0A= > */=0A= > -static int=0A= > -pci_scan(void)=0A= > +int=0A= > +rte_eal_pci_scan(void)=0A= > {=0A= > struct dirent *e;=0A= > DIR *dir;=0A= > @@ -764,7 +764,7 @@ rte_eal_pci_init(void)=0A= > if (internal_config.no_pci)=0A= > return 0;=0A= > =0A= > - if (pci_scan() < 0) {=0A= > + if (rte_eal_pci_scan() < 0) {=0A= > RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);=0A= > return -1;=0A= > }=0A= =0A=