From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 6BBC1426B2; Tue, 3 Oct 2023 22:46:21 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id EFC8840297; Tue, 3 Oct 2023 22:46:20 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id 9F8F740262 for ; Tue, 3 Oct 2023 22:46:19 +0200 (CEST) Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 393FRjgA022179; Tue, 3 Oct 2023 13:46:18 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : mime-version : content-transfer-encoding : content-type; s=pfpt0220; bh=AydO1983lvFs0yeo0q4MQ8mmDMisMC0PPplShCPOBxg=; b=M+yuiF0DA12WMCJQ89HIMBLUeKagl/Z1Uc5QG+htDMuT6CNCSx6qoDQ3kxa6kUnyM9IR XuGgUSb/nZWi7oU3WqWKQOP+uNE5wT9GRkVZQB/VRdYoZVOBRl80JCZTMpL35CGXgxBn EqonGksu9Q+Zqym3kHcC4dQa+ny1CKelKuvgT5wCS+eaZEeFnIehBHXvMNLpcqbG0TNz c+e+c0xYOukYv6eBN41gkwHplVkZBBw4C3Q4PVXLWng1eqf57psNyMr/k4Nk4zyR2w7a EaI063X89mcifARL+MGbGniJgwFv8jxDRWPWeeJPcjeorfpykOzUg3CivQ/qUEZbBx9e WQ== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3tgbasbjvc-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Tue, 03 Oct 2023 13:46:18 -0700 Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Tue, 3 Oct 2023 13:46:17 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Tue, 3 Oct 2023 13:46:16 -0700 Received: from cavium-DT10.. (unknown [10.28.34.39]) by maili.marvell.com (Postfix) with ESMTP id C01FE3F7084; Tue, 3 Oct 2023 13:46:10 -0700 (PDT) From: Tomasz Duszynski To: , Jakub Palider , Tomasz Duszynski , Anatoly Burakov CC: , Subject: [PATCH 1/2] raw/cnxk_gpio: support multi-process mode Date: Tue, 3 Oct 2023 22:46:02 +0200 Message-ID: <20231003204603.3377509-1-tduszynski@marvell.com> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-Proofpoint-ORIG-GUID: xSFLHvr-nrt80EDbRmb6_mGUvMvcw9Xn X-Proofpoint-GUID: xSFLHvr-nrt80EDbRmb6_mGUvMvcw9Xn X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-10-03_18,2023-10-02_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org GPIO PMD uses a mixture of standard sysfs attributes and custom ioctl()s to control behaviour of respective GPIOs available in the system. This means that each userspace application, either running as a primary or a secondary, should be able to control a set of distinct GPIOs. In rare cases where multiple processes need to control the same set of GPIOs userspace application is responsible for synchronizing accesses. Signed-off-by: Tomasz Duszynski Reviewed-by: Jerin Jacob Kollanukkaran --- doc/guides/rawdevs/cnxk_gpio.rst | 7 ++ drivers/raw/cnxk_gpio/cnxk_gpio.c | 143 ++++++++++++++++++++---------- 2 files changed, 104 insertions(+), 46 deletions(-) diff --git a/doc/guides/rawdevs/cnxk_gpio.rst b/doc/guides/rawdevs/cnxk_gpio.rst index adff535a77..848ad329e7 100644 --- a/doc/guides/rawdevs/cnxk_gpio.rst +++ b/doc/guides/rawdevs/cnxk_gpio.rst @@ -21,6 +21,7 @@ Following features are available: - set GPIO edge that triggers interrupt - set GPIO active low - register interrupt handler for specific GPIO +- multiprocess aware Requirements ------------ @@ -30,6 +31,12 @@ for installing interrupt handlers for low latency signal processing. Driver is shipped with Marvell SDK. +Limitations +----------- + +In multiprocess mode user-space application must ensure no GPIO sharing across +processes takes place. + Device Setup ------------ diff --git a/drivers/raw/cnxk_gpio/cnxk_gpio.c b/drivers/raw/cnxk_gpio/cnxk_gpio.c index e2907c18b5..dcd646397e 100644 --- a/drivers/raw/cnxk_gpio/cnxk_gpio.c +++ b/drivers/raw/cnxk_gpio/cnxk_gpio.c @@ -19,6 +19,12 @@ #define CNXK_GPIO_BUFSZ 128 #define CNXK_GPIO_CLASS_PATH "/sys/class/gpio" +#define CNXK_GPIO_PARAMS_MZ_NAME "cnxk_gpio_params_mz" + +struct cnxk_gpio_params { + char allowlist[CNXK_GPIO_BUFSZ]; + int num; +}; static const char *const cnxk_gpio_args[] = { #define CNXK_GPIO_ARG_GPIOCHIP "gpiochip" @@ -28,8 +34,6 @@ static const char *const cnxk_gpio_args[] = { NULL }; -static char *allowlist; - static void cnxk_gpio_format_name(char *name, size_t len) { @@ -44,8 +48,8 @@ cnxk_gpio_filter_gpiochip(const struct dirent *dirent) return !strncmp(dirent->d_name, pattern, strlen(pattern)); } -static void -cnxk_gpio_set_defaults(struct cnxk_gpiochip *gpiochip) +static int +cnxk_gpio_set_defaults(struct cnxk_gpio_params *params) { struct dirent **namelist; int n; @@ -53,12 +57,14 @@ cnxk_gpio_set_defaults(struct cnxk_gpiochip *gpiochip) n = scandir(CNXK_GPIO_CLASS_PATH, &namelist, cnxk_gpio_filter_gpiochip, alphasort); if (n < 0 || n == 0) - return; + return -ENODEV; - sscanf(namelist[0]->d_name, "gpiochip%d", &gpiochip->num); + sscanf(namelist[0]->d_name, "gpiochip%d", ¶ms->num); while (n--) free(namelist[n]); free(namelist); + + return 0; } static int @@ -78,21 +84,53 @@ cnxk_gpio_parse_arg_gpiochip(const char *key __rte_unused, const char *value, } static int -cnxk_gpio_parse_arg_allowlist(const char *key __rte_unused, const char *value, - void *extra_args __rte_unused) +cnxk_gpio_parse_arg_allowlist(const char *key __rte_unused, const char *value, void *extra_args) { - allowlist = strdup(value); - if (!allowlist) + char *allowlist = extra_args; + + rte_strlcpy(allowlist, value, sizeof(((struct cnxk_gpio_params *)0)->allowlist)); + + return 0; +} + +static int +cnxk_gpio_params_store(struct cnxk_gpio_params *params) +{ + const struct rte_memzone *mz; + + mz = rte_memzone_reserve(CNXK_GPIO_PARAMS_MZ_NAME, sizeof(*params), rte_socket_id(), 0); + if (!mz) return -ENOMEM; + memcpy(mz->addr, params, sizeof(*params)); + return 0; } +static void +cnxk_gpio_params_restore(struct cnxk_gpio_params *params) +{ + const struct rte_memzone *mz; + + mz = rte_memzone_lookup(CNXK_GPIO_PARAMS_MZ_NAME); + if (!mz) + return; + + memcpy(params, mz->addr, sizeof(*params)); +} + +static void +cnxk_gpio_params_release(void) +{ + if (rte_eal_process_type() == RTE_PROC_PRIMARY) + rte_memzone_free(rte_memzone_lookup(CNXK_GPIO_PARAMS_MZ_NAME)); +} + static int -cnxk_gpio_parse_args(struct cnxk_gpiochip *gpiochip, const char *args) +cnxk_gpio_parse_args(struct cnxk_gpio_params *params, const char *args) { struct rte_kvargs *kvlist; - int ret; + int ret, num = 0; kvlist = rte_kvargs_parse(args, cnxk_gpio_args); if (!kvlist) @@ -101,21 +139,21 @@ cnxk_gpio_parse_args(struct cnxk_gpiochip *gpiochip, const char *args) ret = rte_kvargs_count(kvlist, CNXK_GPIO_ARG_GPIOCHIP); if (ret == 1) { ret = rte_kvargs_process(kvlist, CNXK_GPIO_ARG_GPIOCHIP, - cnxk_gpio_parse_arg_gpiochip, - &gpiochip->num); + cnxk_gpio_parse_arg_gpiochip, ¶ms->num); if (ret) goto out; } + num++; ret = rte_kvargs_count(kvlist, CNXK_GPIO_ARG_ALLOWLIST); if (ret == 1) { ret = rte_kvargs_process(kvlist, CNXK_GPIO_ARG_ALLOWLIST, - cnxk_gpio_parse_arg_allowlist, NULL); + cnxk_gpio_parse_arg_allowlist, params->allowlist); if (ret) goto out; } - ret = 0; + ret = num++; out: rte_kvargs_free(kvlist); @@ -123,7 +161,7 @@ cnxk_gpio_parse_args(struct cnxk_gpiochip *gpiochip, const char *args) } static int -cnxk_gpio_parse_allowlist(struct cnxk_gpiochip *gpiochip) +cnxk_gpio_parse_allowlist(struct cnxk_gpiochip *gpiochip, char *allowlist) { int i, ret, val, queue = 0; char *token; @@ -133,6 +171,12 @@ cnxk_gpio_parse_allowlist(struct cnxk_gpiochip *gpiochip) if (!list) return -ENOMEM; + allowlist = strdup(allowlist); + if (!allowlist) { + ret = -ENOMEM; + goto out; + } + /* replace brackets with something meaningless for strtol() */ allowlist[0] = ' '; allowlist[strlen(allowlist) - 1] = ' '; @@ -166,11 +210,13 @@ cnxk_gpio_parse_allowlist(struct cnxk_gpiochip *gpiochip) list[queue++] = val; } while ((token = strtok(NULL, ","))); + free(allowlist); gpiochip->allowlist = list; gpiochip->num_queues = queue; return 0; out: + free(allowlist); rte_free(list); return ret; @@ -562,8 +608,7 @@ cnxk_gpio_process_buf(struct cnxk_gpio *gpio, struct rte_rawdev_buf *rbuf) *(int *)rsp = val; break; case CNXK_GPIO_MSG_TYPE_REGISTER_IRQ: - ret = cnxk_gpio_register_irq(gpio, - (struct cnxk_gpio_irq *)msg->data); + ret = cnxk_gpio_register_irq(gpio, (struct cnxk_gpio_irq *)msg->data); break; case CNXK_GPIO_MSG_TYPE_UNREGISTER_IRQ: ret = cnxk_gpio_unregister_irq(gpio); @@ -658,18 +703,15 @@ static const struct rte_rawdev_ops cnxk_gpio_rawdev_ops = { static int cnxk_gpio_probe(struct rte_vdev_device *dev) { + struct cnxk_gpio_params params = { }; char name[RTE_RAWDEV_NAME_MAX_LEN]; struct cnxk_gpiochip *gpiochip; struct rte_rawdev *rawdev; char buf[CNXK_GPIO_BUFSZ]; int ret; - if (rte_eal_process_type() != RTE_PROC_PRIMARY) - return 0; - cnxk_gpio_format_name(name, sizeof(name)); - rawdev = rte_rawdev_pmd_allocate(name, sizeof(*gpiochip), - rte_socket_id()); + rawdev = rte_rawdev_pmd_allocate(name, sizeof(*gpiochip), rte_socket_id()); if (!rawdev) { RTE_LOG(ERR, PMD, "failed to allocate %s rawdev", name); return -ENOMEM; @@ -678,22 +720,37 @@ cnxk_gpio_probe(struct rte_vdev_device *dev) rawdev->dev_ops = &cnxk_gpio_rawdev_ops; rawdev->device = &dev->device; rawdev->driver_name = dev->device.name; - gpiochip = rawdev->dev_private; - cnxk_gpio_set_defaults(gpiochip); - /* defaults may be overwritten by this call */ - ret = cnxk_gpio_parse_args(gpiochip, rte_vdev_device_args(dev)); - if (ret) - goto out; + ret = cnxk_gpio_set_defaults(¶ms); + if (ret) { + RTE_LOG(ERR, PMD, "failed to set defaults\n"); + return ret; + } + + if (rte_eal_process_type() == RTE_PROC_PRIMARY) { + ret = cnxk_gpio_parse_args(¶ms, rte_vdev_device_args(dev)); + if (ret < 0) + goto out; + if (ret > 0) { + ret = cnxk_gpio_params_store(¶ms); + if (ret) { + RTE_LOG(ERR, PMD, "failed to store params\n"); + goto out; + } + } + } else { + cnxk_gpio_params_restore(¶ms); + } + + gpiochip->num = params.num; ret = cnxk_gpio_irq_init(gpiochip); if (ret) goto out; /* read gpio base */ - snprintf(buf, sizeof(buf), "%s/gpiochip%d/base", CNXK_GPIO_CLASS_PATH, - gpiochip->num); + snprintf(buf, sizeof(buf), "%s/gpiochip%d/base", CNXK_GPIO_CLASS_PATH, gpiochip->num); ret = cnxk_gpio_read_attr_int(buf, &gpiochip->base); if (ret) { RTE_LOG(ERR, PMD, "failed to read %s", buf); @@ -701,8 +758,7 @@ cnxk_gpio_probe(struct rte_vdev_device *dev) } /* read number of available gpios */ - snprintf(buf, sizeof(buf), "%s/gpiochip%d/ngpio", CNXK_GPIO_CLASS_PATH, - gpiochip->num); + snprintf(buf, sizeof(buf), "%s/gpiochip%d/ngpio", CNXK_GPIO_CLASS_PATH, gpiochip->num); ret = cnxk_gpio_read_attr_int(buf, &gpiochip->num_gpios); if (ret) { RTE_LOG(ERR, PMD, "failed to read %s", buf); @@ -710,16 +766,13 @@ cnxk_gpio_probe(struct rte_vdev_device *dev) } gpiochip->num_queues = gpiochip->num_gpios; - if (allowlist) { - ret = cnxk_gpio_parse_allowlist(gpiochip); - free(allowlist); - allowlist = NULL; - if (ret) - goto out; + ret = cnxk_gpio_parse_allowlist(gpiochip, params.allowlist); + if (ret) { + RTE_LOG(ERR, PMD, "failed to parse allowed gpios\n"); + goto out; } - gpiochip->gpios = rte_calloc(NULL, gpiochip->num_gpios, - sizeof(struct cnxk_gpio *), 0); + gpiochip->gpios = rte_calloc(NULL, gpiochip->num_gpios, sizeof(struct cnxk_gpio *), 0); if (!gpiochip->gpios) { RTE_LOG(ERR, PMD, "failed to allocate gpios memory"); ret = -ENOMEM; @@ -728,8 +781,8 @@ cnxk_gpio_probe(struct rte_vdev_device *dev) return 0; out: - free(allowlist); rte_free(gpiochip->allowlist); + cnxk_gpio_params_release(); rte_rawdev_pmd_release(rawdev); return ret; @@ -746,9 +799,6 @@ cnxk_gpio_remove(struct rte_vdev_device *dev) RTE_SET_USED(dev); - if (rte_eal_process_type() != RTE_PROC_PRIMARY) - return 0; - cnxk_gpio_format_name(name, sizeof(name)); rawdev = rte_rawdev_pmd_get_named_dev(name); if (!rawdev) @@ -769,6 +819,7 @@ cnxk_gpio_remove(struct rte_vdev_device *dev) rte_free(gpiochip->allowlist); rte_free(gpiochip->gpios); cnxk_gpio_irq_fini(); + cnxk_gpio_params_release(); rte_rawdev_pmd_release(rawdev); return 0; -- 2.34.1