My "event/dlb2: add probe" review, referenced below: [1] http://mails.dpdk.org/archives/dev/2020-October/184962.html
> -----Original Message----- > From: McDaniel, Timothy <timothy.mcdan...@intel.com> > Sent: Friday, September 11, 2020 2:18 PM > To: Burakov, Anatoly <anatoly.bura...@intel.com> > Cc: dev@dpdk.org; Carrillo, Erik G <erik.g.carri...@intel.com>; Eads, Gage > <gage.e...@intel.com>; Van Haaren, Harry <harry.van.haa...@intel.com>; > jer...@marvell.com > Subject: [PATCH v4 06/22] event/dlb: add probe > > The DLB hardware is a PCI device. This commit adds > support for probe and other initialization. Given the size, this commit warrants a more detailed commit message -- like the dlb2 PMD's "add probe" commit. > > Signed-off-by: Timothy McDaniel <timothy.mcdan...@intel.com> > --- > drivers/event/dlb/dlb.c | 493 ++++++ > drivers/event/dlb/dlb_iface.c | 41 + > drivers/event/dlb/dlb_iface.h | 27 + > drivers/event/dlb/dlb_priv.h | 20 +- > drivers/event/dlb/meson.build | 6 +- > drivers/event/dlb/pf/base/dlb_hw_types.h | 334 ++++ > drivers/event/dlb/pf/base/dlb_osdep.h | 326 ++++ > drivers/event/dlb/pf/base/dlb_osdep_bitmap.h | 441 +++++ > drivers/event/dlb/pf/base/dlb_osdep_list.h | 131 ++ > drivers/event/dlb/pf/base/dlb_osdep_types.h | 31 + > drivers/event/dlb/pf/base/dlb_regs.h | 2368 > ++++++++++++++++++++++++++ > drivers/event/dlb/pf/base/dlb_resource.c | 302 ++++ > drivers/event/dlb/pf/base/dlb_resource.h | 876 ++++++++++ > drivers/event/dlb/pf/dlb_main.c | 591 +++++++ > drivers/event/dlb/pf/dlb_main.h | 52 + > drivers/event/dlb/pf/dlb_pf.c | 232 +++ > 16 files changed, 6254 insertions(+), 17 deletions(-) > create mode 100644 drivers/event/dlb/dlb.c > create mode 100644 drivers/event/dlb/dlb_iface.c > create mode 100644 drivers/event/dlb/dlb_iface.h > create mode 100644 drivers/event/dlb/pf/base/dlb_hw_types.h > create mode 100644 drivers/event/dlb/pf/base/dlb_osdep.h > create mode 100644 drivers/event/dlb/pf/base/dlb_osdep_bitmap.h > create mode 100644 drivers/event/dlb/pf/base/dlb_osdep_list.h > create mode 100644 drivers/event/dlb/pf/base/dlb_osdep_types.h > create mode 100644 drivers/event/dlb/pf/base/dlb_regs.h > create mode 100644 drivers/event/dlb/pf/base/dlb_resource.c > create mode 100644 drivers/event/dlb/pf/base/dlb_resource.h > create mode 100644 drivers/event/dlb/pf/dlb_main.c > create mode 100644 drivers/event/dlb/pf/dlb_main.h > create mode 100644 drivers/event/dlb/pf/dlb_pf.c > > diff --git a/drivers/event/dlb/dlb.c b/drivers/event/dlb/dlb.c > new file mode 100644 > index 0000000..e2acb61 > --- /dev/null > +++ b/drivers/event/dlb/dlb.c > @@ -0,0 +1,493 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2016-2020 Intel Corporation > + */ > + > +#include <assert.h> > +#include <errno.h> > +#include <nmmintrin.h> > +#include <pthread.h> > +#include <stdbool.h> > +#include <stdint.h> > +#include <stdio.h> > +#include <string.h> > +#include <sys/fcntl.h> > +#include <sys/mman.h> > +#include <unistd.h> > + > +#include <rte_common.h> > +#include <rte_config.h> > +#include <rte_cycles.h> > +#include <rte_debug.h> > +#include <rte_dev.h> > +#include <rte_errno.h> > +#include <rte_io.h> > +#include <rte_kvargs.h> > +#include <rte_log.h> > +#include <rte_malloc.h> > +#include <rte_mbuf.h> > +#include <rte_prefetch.h> > +#include <rte_ring.h> > +#include <rte_string_fns.h> > + > +#include <rte_eventdev.h> > +#include <rte_eventdev_pmd.h> > + > +#include "dlb_priv.h" > +#include "dlb_iface.h" > +#include "dlb_inline_fns.h" > + > +/* > + * Resources exposed to eventdev. > + */ > +#if (RTE_EVENT_MAX_QUEUES_PER_DEV > UINT8_MAX) > +#error "RTE_EVENT_MAX_QUEUES_PER_DEV cannot fit in member > max_event_queues" > +#endif > +static struct rte_event_dev_info evdev_dlb_default_info = { > + .driver_name = "", /* probe will set */ > + .min_dequeue_timeout_ns = DLB_MIN_DEQUEUE_TIMEOUT_NS, > + .max_dequeue_timeout_ns = DLB_MAX_DEQUEUE_TIMEOUT_NS, > +#if (RTE_EVENT_MAX_QUEUES_PER_DEV < DLB_MAX_NUM_LDB_QUEUES) > + .max_event_queues = RTE_EVENT_MAX_QUEUES_PER_DEV, > +#else > + .max_event_queues = DLB_MAX_NUM_LDB_QUEUES, > +#endif > + .max_event_queue_flows = DLB_MAX_NUM_FLOWS, > + .max_event_queue_priority_levels = DLB_QID_PRIORITIES, > + .max_event_priority_levels = DLB_QID_PRIORITIES, > + .max_event_ports = DLB_MAX_NUM_LDB_PORTS, > + .max_event_port_dequeue_depth = DLB_MAX_CQ_DEPTH, > + .max_event_port_enqueue_depth = DLB_MAX_ENQUEUE_DEPTH, > + .max_event_port_links = DLB_MAX_NUM_QIDS_PER_LDB_CQ, > + .max_num_events = DLB_MAX_NUM_LDB_CREDITS, > + .max_single_link_event_port_queue_pairs = > DLB_MAX_NUM_DIR_PORTS, > + .event_dev_cap = (RTE_EVENT_DEV_CAP_QUEUE_QOS | > + RTE_EVENT_DEV_CAP_EVENT_QOS | > + RTE_EVENT_DEV_CAP_BURST_MODE | > + RTE_EVENT_DEV_CAP_DISTRIBUTED_SCHED | > + RTE_EVENT_DEV_CAP_IMPLICIT_RELEASE_DISABLE | > + RTE_EVENT_DEV_CAP_QUEUE_ALL_TYPES), > +}; > + > +struct process_local_port_data > +dlb_port[DLB_MAX_NUM_PORTS][NUM_DLB_PORT_TYPES]; > + > +static int > +dlb_hw_query_resources(struct dlb_eventdev *dlb) > +{ > + struct dlb_hw_dev *handle = &dlb->qm_instance; > + struct dlb_hw_resource_info *dlb_info = &handle->info; > + int ret; > + > + ret = dlb_iface_get_num_resources(handle, > + &dlb->hw_rsrc_query_results); > + if (ret) { > + DLB_LOG_ERR("ioctl get dlb num resources, err=%d\n", > + ret); This can fit on one line, and 'ioctl' in the print doesn't look right. > + return ret; > + } > + > + /* Complete filling in device resource info returned to evdev app, > + * overriding any default values. > + * The capabilities (CAPs) were set at compile time. > + */ > + > + evdev_dlb_default_info.max_event_queues = > + dlb->hw_rsrc_query_results.num_ldb_queues; > + > + evdev_dlb_default_info.max_event_ports = > + dlb->hw_rsrc_query_results.num_ldb_ports; > + > + evdev_dlb_default_info.max_num_events = > + dlb->hw_rsrc_query_results.max_contiguous_ldb_credits; > + > + /* Save off values used when creating the scheduling domain. */ > + > + handle->info.num_sched_domains = > + dlb->hw_rsrc_query_results.num_sched_domains; > + > + handle->info.hw_rsrc_max.nb_events_limit = > + dlb->hw_rsrc_query_results.max_contiguous_ldb_credits; > + > + handle->info.hw_rsrc_max.num_queues = > + dlb->hw_rsrc_query_results.num_ldb_queues + > + dlb->hw_rsrc_query_results.num_dir_ports; > + > + handle->info.hw_rsrc_max.num_ldb_queues = > + dlb->hw_rsrc_query_results.num_ldb_queues; > + > + handle->info.hw_rsrc_max.num_ldb_ports = > + dlb->hw_rsrc_query_results.num_ldb_ports; > + > + handle->info.hw_rsrc_max.num_dir_ports = > + dlb->hw_rsrc_query_results.num_dir_ports; > + > + handle->info.hw_rsrc_max.reorder_window_size = > + dlb->hw_rsrc_query_results.num_hist_list_entries; > + > + rte_memcpy(dlb_info, &handle->info.hw_rsrc_max, sizeof(*dlb_info)); > + > + return 0; > +} > + > +/* Wrapper for string to int conversion. Substituted for atoi(...), which is > + * unsafe. > + */ > +#define RTE_BASE_10 10 > + > +static int > +dlb_string_to_int(int *result, const char *str) > +{ > + long ret; > + > + if (str == NULL || result == NULL) > + return -EINVAL; > + > + errno = 0; > + ret = strtol(str, NULL, RTE_BASE_10); > + if (errno) > + return -errno; Same possible issue I mentioned in [1] -- doesn't look like this handles an invalid string correctly. > + > + /* long int and int may be different width for some architectures */ > + if (ret < INT_MIN || ret > INT_MAX) > + return -EINVAL; > + > + *result = ret; > + return 0; > +} > + > +static int > +set_numa_node(const char *key __rte_unused, const char *value, void > *opaque) > +{ > + int *socket_id = opaque; > + int ret; > + > + ret = dlb_string_to_int(socket_id, value); > + if (ret < 0) > + return ret; > + > + if (*socket_id > RTE_MAX_NUMA_NODES) > + return -EINVAL; > + > + return 0; > +} > + > +static int > +set_max_num_events(const char *key __rte_unused, > + const char *value, > + void *opaque) > +{ > + int *max_num_events = opaque; > + int ret; > + > + if (value == NULL || opaque == NULL) { > + DLB_LOG_ERR("NULL pointer\n"); > + return -EINVAL; > + } > + > + ret = dlb_string_to_int(max_num_events, value); > + if (ret < 0) > + return ret; > + > + if (*max_num_events < 0 || *max_num_events > > DLB_MAX_NUM_LDB_CREDITS) { > + DLB_LOG_ERR("dlb: max_num_events must be between 0 and > %d\n", > + DLB_MAX_NUM_LDB_CREDITS); > + return -EINVAL; > + } > + > + return 0; > +} > + > +static int > +set_num_dir_credits(const char *key __rte_unused, > + const char *value, > + void *opaque) > +{ > + int *num_dir_credits = opaque; > + int ret; > + > + if (value == NULL || opaque == NULL) { > + DLB_LOG_ERR("NULL pointer\n"); > + return -EINVAL; > + } > + > + ret = dlb_string_to_int(num_dir_credits, value); > + if (ret < 0) > + return ret; > + > + if (*num_dir_credits < 0 || > + *num_dir_credits > DLB_MAX_NUM_DIR_CREDITS) { > + DLB_LOG_ERR("dlb: num_dir_credits must be between 0 and > %d\n", > + DLB_MAX_NUM_DIR_CREDITS); > + return -EINVAL; > + } > + > + return 0; > +} > + > +static int > +set_dev_id(const char *key __rte_unused, > + const char *value, > + void *opaque) > +{ > + int *dev_id = opaque; > + int ret; > + > + if (value == NULL || opaque == NULL) { > + DLB_LOG_ERR("NULL pointer\n"); > + return -EINVAL; > + } > + > + ret = dlb_string_to_int(dev_id, value); > + if (ret < 0) > + return ret; > + > + return 0; > +} > + > +static int > +set_defer_sched(const char *key __rte_unused, > + const char *value, > + void *opaque) > +{ > + int *defer_sched = opaque; > + > + if (value == NULL || opaque == NULL) { > + DLB_LOG_ERR("NULL pointer\n"); > + return -EINVAL; > + } > + > + if (strncmp(value, "on", 2) != 0) { > + DLB_LOG_ERR("Invalid defer_sched argument \"%s\" (expected > \"on\")\n", > + value); > + return -EINVAL; > + } > + > + *defer_sched = 1; > + > + return 0; > +} > + > +static int > +set_num_atm_inflights(const char *key __rte_unused, > + const char *value, > + void *opaque) > +{ > + int *num_atm_inflights = opaque; > + int ret; > + > + if (value == NULL || opaque == NULL) { > + DLB_LOG_ERR("NULL pointer\n"); > + return -EINVAL; > + } > + > + ret = dlb_string_to_int(num_atm_inflights, value); > + if (ret < 0) > + return ret; > + > + if (*num_atm_inflights < 0 || > + *num_atm_inflights > DLB_MAX_NUM_ATM_INFLIGHTS) { > + DLB_LOG_ERR("dlb: atm_inflights must be between 0 and %d\n", > + DLB_MAX_NUM_ATM_INFLIGHTS); > + return -EINVAL; > + } > + > + return 0; > +} > + > +void > +dlb_entry_points_init(struct rte_eventdev *dev) > +{ > + static struct rte_eventdev_ops dlb_eventdev_entry_ops = { > + }; > + > + /* Expose PMD's eventdev interface */ > + dev->dev_ops = &dlb_eventdev_entry_ops; > + Extra whitespace here, but this gets removed later in the series. > +} > + > +int > +dlb_primary_eventdev_probe(struct rte_eventdev *dev, > + const char *name, > + struct dlb_devargs *dlb_args) > +{ > + struct dlb_eventdev *dlb; > + int err, i; > + > + dlb = dev->data->dev_private; > + > + dlb->event_dev = dev; /* backlink */ > + > + evdev_dlb_default_info.driver_name = name; > + > + dlb->max_num_events_override = dlb_args->max_num_events; > + dlb->num_dir_credits_override = dlb_args->num_dir_credits_override; > + dlb->qm_instance.device_path_id = dlb_args->dev_id; > + dlb->defer_sched = dlb_args->defer_sched; > + dlb->num_atm_inflights_per_queue = dlb_args->num_atm_inflights; > + > + /* Open the interface. > + * For vdev mode, this means open the dlb kernel module. > + */ > + err = dlb_iface_open(&dlb->qm_instance, name); > + if (err < 0) { > + DLB_LOG_ERR("could not open event hardware device, > err=%d\n", > + err); > + return err; > + } > + > + err = dlb_iface_get_device_version(&dlb->qm_instance, &dlb- > >revision); > + if (err < 0) { > + DLB_LOG_ERR("dlb: failed to get the device version, err=%d\n", > + err); > + return err; > + } > + > + err = dlb_hw_query_resources(dlb); > + if (err) { > + DLB_LOG_ERR("get resources err=%d for %s\n", > + err, name); Nit: this fits on one line > + return err; > + } > + > + err = dlb_iface_get_cq_poll_mode(&dlb->qm_instance, &dlb- > >poll_mode); > + if (err < 0) { > + DLB_LOG_ERR("dlb: failed to get the poll mode, err=%d\n", > + err); Nit: this fits on one line > + return err; > + } > + > + /* Initialize each port's token pop mode */ > + for (i = 0; i < DLB_MAX_NUM_PORTS; i++) > + dlb->ev_ports[i].qm_port.token_pop_mode = AUTO_POP; > + > + rte_spinlock_init(&dlb->qm_instance.resource_lock); > + > + dlb_iface_low_level_io_init(dlb); > + > + dlb_entry_points_init(dev); > + > + return 0; > +} > + > +int > +dlb_secondary_eventdev_probe(struct rte_eventdev *dev, > + const char *name) > +{ > + struct dlb_eventdev *dlb; > + int err; > + > + dlb = dev->data->dev_private; > + > + evdev_dlb_default_info.driver_name = name; > + > + err = dlb_iface_open(&dlb->qm_instance, name); > + if (err < 0) { > + DLB_LOG_ERR("could not open event hardware device, > err=%d\n", > + err); > + return err; > + } > + > + err = dlb_hw_query_resources(dlb); > + if (err) { > + DLB_LOG_ERR("get resources err=%d for %s\n", > + err, name); Nit: this fits on one line > + return err; > + } > + > + dlb_iface_low_level_io_init(dlb); > + > + dlb_entry_points_init(dev); > + > + return 0; > +} > + > +int > +dlb_parse_params(const char *params, > + const char *name, > + struct dlb_devargs *dlb_args) > +{ > + int ret = 0; > + static const char * const args[] = { NUMA_NODE_ARG, > + DLB_MAX_NUM_EVENTS, > + DLB_NUM_DIR_CREDITS, > + DEV_ID_ARG, > + DLB_DEFER_SCHED_ARG, > + DLB_NUM_ATM_INFLIGHTS_ARG, > + NULL }; > + > + if (params && params[0] != '\0') { > + struct rte_kvargs *kvlist = rte_kvargs_parse(params, args); > + > + if (!kvlist) { > + DLB_LOG_INFO("Ignoring unsupported parameters when > creating device '%s'\n", > + name); > + } else { > + int ret = rte_kvargs_process(kvlist, NUMA_NODE_ARG, > + set_numa_node, > + &dlb_args->socket_id); > + if (ret != 0) { > + DLB_LOG_ERR("%s: Error parsing numa node > parameter", > + name); > + rte_kvargs_free(kvlist); > + return ret; > + } > + > + ret = rte_kvargs_process(kvlist, > DLB_MAX_NUM_EVENTS, > + set_max_num_events, > + &dlb_args->max_num_events); > + if (ret != 0) { > + DLB_LOG_ERR("%s: Error parsing > max_num_events parameter", > + name); > + rte_kvargs_free(kvlist); > + return ret; > + } > + > + ret = rte_kvargs_process(kvlist, > + DLB_NUM_DIR_CREDITS, > + set_num_dir_credits, > + &dlb_args->num_dir_credits_override); > + if (ret != 0) { > + DLB_LOG_ERR("%s: Error parsing num_dir_credits > parameter", > + name); > + rte_kvargs_free(kvlist); > + return ret; > + } > + > + ret = rte_kvargs_process(kvlist, DEV_ID_ARG, > + set_dev_id, > + &dlb_args->dev_id); > + if (ret != 0) { > + DLB_LOG_ERR("%s: Error parsing dev_id > parameter", > + name); > + rte_kvargs_free(kvlist); > + return ret; > + } > + > + ret = rte_kvargs_process(kvlist, DLB_DEFER_SCHED_ARG, > + set_defer_sched, > + &dlb_args->defer_sched); > + if (ret != 0) { > + DLB_LOG_ERR("%s: Error parsing defer_sched > parameter", > + name); > + rte_kvargs_free(kvlist); > + return ret; > + } > + > + ret = rte_kvargs_process(kvlist, > + > DLB_NUM_ATM_INFLIGHTS_ARG, > + set_num_atm_inflights, > + &dlb_args->num_atm_inflights); > + if (ret != 0) { > + DLB_LOG_ERR("%s: Error parsing atm_inflights > parameter", > + name); > + rte_kvargs_free(kvlist); > + return ret; > + } > + > + rte_kvargs_free(kvlist); > + } > + } > + return ret; > +} > +RTE_LOG_REGISTER(eventdev_dlb_log_level, pmd.event.dlb, NOTICE); > + Blank newline at the end of the file > diff --git a/drivers/event/dlb/dlb_iface.c b/drivers/event/dlb/dlb_iface.c > new file mode 100644 > index 0000000..3f17bd1 > --- /dev/null > +++ b/drivers/event/dlb/dlb_iface.c > @@ -0,0 +1,41 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2016-2020 Intel Corporation > + */ > + > +#include <stdbool.h> > +#include <stdint.h> > + > +#include <rte_debug.h> > +#include <rte_bus_pci.h> > +#include <rte_log.h> > +#include <rte_dev.h> > +#include <rte_mbuf.h> > +#include <rte_ring.h> > +#include <rte_errno.h> > +#include <rte_kvargs.h> > +#include <rte_malloc.h> > +#include <rte_cycles.h> > +#include <rte_io.h> > +#include <rte_eventdev.h> As in [1], doesn't look like stdbool.h and the rte_*.h includes are needed. [...] > diff --git a/drivers/event/dlb/dlb_priv.h b/drivers/event/dlb/dlb_priv.h > index 482c5b2..acb8158 100644 > --- a/drivers/event/dlb/dlb_priv.h > +++ b/drivers/event/dlb/dlb_priv.h > @@ -527,18 +527,14 @@ int test_dlb_eventdev(void); > > int dlb_primary_eventdev_probe(struct rte_eventdev *dev, > const char *name, > - struct dlb_devargs *dlb_args, > - bool is_vdev); > + struct dlb_devargs *dlb_args); > > int dlb_secondary_eventdev_probe(struct rte_eventdev *dev, > - const char *name, > - bool is_vdev); > + const char *name); > + > uint32_t dlb_get_queue_depth(struct dlb_eventdev *dlb, > struct dlb_eventdev_queue *queue); > > -int set_numa_node(const char *key __rte_unused, const char *value, > - void *opaque); > - > int set_dir_ports(const char *key __rte_unused, > const char *value __rte_unused, > void *opaque __rte_unused); > @@ -547,20 +543,12 @@ int set_dir_queues(const char *key __rte_unused, > const char *value __rte_unused, > void *opaque __rte_unused); > > -int set_max_num_events(const char *key __rte_unused, const char *value, > - void *opaque); > - > -int set_num_dir_credits(const char *key __rte_unused, const char *value, > - void *opaque); > - > void dlb_drain(struct rte_eventdev *dev); > > -void dlb_entry_points_init(struct rte_eventdev *dev); > - > int dlb_parse_params(const char *params, > const char *name, > struct dlb_devargs *dlb_args); > > -int dlb_string_to_int(int *result, const char *str); > +void dlb_entry_points_init(struct rte_eventdev *dev); > > #endif /* _DLB_PRIV_H_ */ Looks like all these dlb_priv.h changes were intended for patch #3 [...] > diff --git a/drivers/event/dlb/pf/base/dlb_osdep_bitmap.h > b/drivers/event/dlb/pf/base/dlb_osdep_bitmap.h > new file mode 100644 > index 0000000..3ebd4ea > --- /dev/null > +++ b/drivers/event/dlb/pf/base/dlb_osdep_bitmap.h > @@ -0,0 +1,441 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2016-2020 Intel Corporation > + */ > + > +#ifndef __DLB_OSDEP_BITMAP_H__ > +#define __DLB_OSDEP_BITMAP_H__ > + > +#include <stdint.h> > +#include <stdbool.h> > +#include <stdio.h> > +#include <unistd.h> > +#include <rte_bitmap.h> > +#include <rte_string_fns.h> > +#include <rte_malloc.h> > +#include <rte_errno.h> > +#include "../dlb_main.h" > + > +/*************************/ > +/*** Bitmap operations ***/ > +/*************************/ > +struct dlb_bitmap { > + struct rte_bitmap *map; > + unsigned int len; > + struct dlb_hw *hw; > +}; > + > +/** > + * dlb_bitmap_alloc() - alloc a bitmap data structure > + * @bitmap: pointer to dlb_bitmap structure pointer. > + * @len: number of entries in the bitmap. > + * > + * This function allocates a bitmap and initializes it with length @len. All > + * entries are initially zero. > + * > + * Return: > + * Returns 0 upon success, < 0 otherwise. > + * > + * Errors: > + * EINVAL - bitmap is NULL or len is 0. > + * ENOMEM - could not allocate memory for the bitmap data structure. > + */ > +static inline int dlb_bitmap_alloc(struct dlb_hw *hw, > + struct dlb_bitmap **bitmap, > + unsigned int len) > +{ > + struct dlb_bitmap *bm; > + void *mem; > + uint32_t alloc_size; > + uint32_t nbits = (uint32_t) len; > + RTE_SET_USED(hw); > + > + if (!bitmap || nbits == 0) > + return -EINVAL; > + > + /* Allocate DLB bitmap control struct */ > + bm = rte_malloc("DLB_PF", > + sizeof(struct dlb_bitmap), > + RTE_CACHE_LINE_SIZE); > + > + if (!bm) > + return -ENOMEM; > + > + /* Allocate bitmap memory */ > + alloc_size = rte_bitmap_get_memory_footprint(nbits); > + mem = rte_malloc("DLB_PF_BITMAP", alloc_size, > RTE_CACHE_LINE_SIZE); > + if (!mem) { > + rte_free(bm); > + return -ENOMEM; > + } > + > + bm->map = rte_bitmap_init(len, mem, alloc_size); > + if (!bm->map) { > + rte_free(mem); > + rte_free(bm); > + return -ENOMEM; > + } > + > + bm->len = len; > + > + *bitmap = bm; > + > + return 0; > +} > + > +/** > + * dlb_bitmap_free() - free a previously allocated bitmap data structure > + * @bitmap: pointer to dlb_bitmap structure. > + * > + * This function frees a bitmap that was allocated with dlb_bitmap_alloc(). > + */ > +static inline void dlb_bitmap_free(struct dlb_bitmap *bitmap) > +{ > + if (!bitmap) > + return; > + > + rte_free(bitmap->map); > + rte_free(bitmap); > +} > + > +/** > + * dlb_bitmap_fill() - fill a bitmap with all 1s > + * @bitmap: pointer to dlb_bitmap structure. > + * > + * This function sets all bitmap values to 1. > + * > + * Return: > + * Returns 0 upon success, < 0 otherwise. > + * > + * Errors: > + * EINVAL - bitmap is NULL or is uninitialized. > + */ > +static inline int dlb_bitmap_fill(struct dlb_bitmap *bitmap) > +{ > + unsigned int i; > + > + if (!bitmap || !bitmap->map) > + return -EINVAL; > + > + for (i = 0; i != bitmap->len; i++) > + rte_bitmap_set(bitmap->map, i); > + > + return 0; > +} > + > +/** > + * dlb_bitmap_fill() - fill a bitmap with all 0s dlb_bitmap_fill -> dlb_bitmap_zero [...] > diff --git a/drivers/event/dlb/pf/dlb_main.c b/drivers/event/dlb/pf/dlb_main.c > new file mode 100644 > index 0000000..7a55140 > --- /dev/null > +++ b/drivers/event/dlb/pf/dlb_main.c > @@ -0,0 +1,591 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2016-2020 Intel Corporation > + */ > + > +#include <stdint.h> > +#include <stdbool.h> > +#include <stdio.h> > +#include <errno.h> > +#include <assert.h> > +#include <unistd.h> > +#include <string.h> > + > +#include <rte_malloc.h> > +#include <rte_errno.h> > + > +#include "base/dlb_resource.h" > +#include "base/dlb_osdep.h" > +#include "base/dlb_regs.h" > +#include "../dlb_priv.h" > +#include "../dlb_inline_fns.h" > +#include "../dlb_user.h" > +#include "dlb_main.h" > + > +unsigned int dlb_unregister_timeout_s = > DLB_DEFAULT_UNREGISTER_TIMEOUT_S; > + > +#define DLB_PCI_CFG_SPACE_SIZE 256 > +#define DLB_PCI_CAP_POINTER 0x34 > +#define DLB_PCI_CAP_NEXT(hdr) (((hdr) >> 8) & 0xFC) > +#define DLB_PCI_CAP_ID(hdr) ((hdr) & 0xFF) > +#define DLB_PCI_EXT_CAP_NEXT(hdr) (((hdr) >> 20) & 0xFFC) > +#define DLB_PCI_EXT_CAP_ID(hdr) ((hdr) & 0xFFFF) > +#define DLB_PCI_EXT_CAP_ID_ERR 1 > +#define DLB_PCI_ERR_UNCOR_MASK 8 > +#define DLB_PCI_ERR_UNC_UNSUP 0x00100000 > + > +#define DLB_PCI_EXP_DEVCTL 8 > +#define DLB_PCI_LNKCTL 16 > +#define DLB_PCI_SLTCTL 24 > +#define DLB_PCI_RTCTL 28 > +#define DLB_PCI_EXP_DEVCTL2 40 > +#define DLB_PCI_LNKCTL2 48 > +#define DLB_PCI_SLTCTL2 56 > +#define DLB_PCI_CMD 4 > +#define DLB_PCI_X_CMD 2 > +#define DLB_PCI_EXP_DEVSTA 10 > +#define DLB_PCI_EXP_DEVSTA_TRPND 0x20 > +#define DLB_PCI_EXP_DEVCTL_BCR_FLR 0x8000 > +#define DLB_PCI_PASID_CTRL 6 > +#define DLB_PCI_PASID_CAP 4 > + > +#define DLB_PCI_CAP_ID_EXP 0x10 > +#define DLB_PCI_CAP_ID_MSIX 0x11 > +#define DLB_PCI_EXT_CAP_ID_PAS 0x1B > +#define DLB_PCI_EXT_CAP_ID_PRI 0x13 > +#define DLB_PCI_EXT_CAP_ID_ACS 0xD > + > +#define DLB_PCI_PASID_CAP_EXEC 0x2 > +#define DLB_PCI_PASID_CAP_PRIV 0x4 > +#define DLB_PCI_PASID_CTRL_ENABLE 0x1 > +#define DLB_PCI_PRI_CTRL_ENABLE 0x1 > +#define DLB_PCI_PRI_ALLOC_REQ 0xC > +#define DLB_PCI_PRI_CTRL 0x4 > +#define DLB_PCI_MSIX_FLAGS 0x2 > +#define DLB_PCI_MSIX_FLAGS_ENABLE 0x8000 > +#define DLB_PCI_MSIX_FLAGS_MASKALL 0x4000 > +#define DLB_PCI_ERR_ROOT_STATUS 0x30 > +#define DLB_PCI_ERR_COR_STATUS 0x10 > +#define DLB_PCI_ERR_UNCOR_STATUS 0x4 > +#define DLB_PCI_COMMAND_INTX_DISABLE 0x400 > +#define DLB_PCI_ACS_CAP 0x4 > +#define DLB_PCI_ACS_CTRL 0x6 > +#define DLB_PCI_ACS_SV 0x1 > +#define DLB_PCI_ACS_RR 0x4 > +#define DLB_PCI_ACS_CR 0x8 > +#define DLB_PCI_ACS_UF 0x10 > +#define DLB_PCI_ACS_EC 0x20 > + > +static int dlb_pci_find_ext_capability(struct rte_pci_device *pdev, uint32_t > id) > +{ > + uint32_t hdr; > + size_t sz; > + int pos; > + > + pos = DLB_PCI_CFG_SPACE_SIZE; > + sz = sizeof(hdr); > + > + while (pos > 0xFF) { > + if (rte_pci_read_config(pdev, &hdr, sz, pos) != (int)sz) > + return -1; > + > + if (DLB_PCI_EXT_CAP_ID(hdr) == id) > + return pos; > + > + pos = DLB_PCI_EXT_CAP_NEXT(hdr); > + } > + > + return -1; > +} > + > +static int dlb_pci_find_capability(struct rte_pci_device *pdev, uint32_t id) > +{ > + uint8_t pos; > + int ret; > + uint16_t hdr; > + > + ret = rte_pci_read_config(pdev, &pos, 1, DLB_PCI_CAP_POINTER); > + pos &= 0xFC; > + > + if (ret != 1) > + return -1; > + > + while (pos > 0x3F) { > + ret = rte_pci_read_config(pdev, &hdr, 2, pos); > + if (ret != 2) > + return -1; > + > + if (DLB_PCI_CAP_ID(hdr) == id) > + return pos; > + > + if (DLB_PCI_CAP_ID(hdr) == 0xFF) > + return -1; > + > + pos = DLB_PCI_CAP_NEXT(hdr); > + } > + > + return -1; > +} > + > +static int dlb_mask_ur_err(struct rte_pci_device *pdev) > +{ > + uint32_t mask; > + size_t sz = sizeof(mask); > + int pos = dlb_pci_find_ext_capability(pdev, DLB_PCI_EXT_CAP_ID_ERR); > + > + if (pos < 0) { > + printf("[%s()] failed to find the aer capability\n", > + __func__); > + return pos; > + } > + > + pos += DLB_PCI_ERR_UNCOR_MASK; > + > + if (rte_pci_read_config(pdev, &mask, sz, pos) != (int)sz) { > + printf("[%s()] Failed to read uncorrectable error mask reg\n", > + __func__); > + return -1; > + } > + > + /* Mask Unsupported Request errors */ > + mask |= DLB_PCI_ERR_UNC_UNSUP; > + > + if (rte_pci_write_config(pdev, &mask, sz, pos) != (int)sz) { > + printf("[%s()] Failed to write uncorrectable error mask reg at > offset %d\n", > + __func__, pos); > + return -1; > + } > + > + return 0; > +} > + > +struct dlb_dev * > +dlb_probe(struct rte_pci_device *pdev) > +{ > + struct dlb_dev *dlb_dev; > + int ret = 0; > + > + DLB_INFO(dlb_dev, "probe\n"); > + > + dlb_dev = rte_malloc("DLB_PF", sizeof(struct dlb_dev), > + RTE_CACHE_LINE_SIZE); > + > + if (!dlb_dev) { > + ret = -ENOMEM; > + goto dlb_dev_malloc_fail; > + } > + > + /* PCI Bus driver has already mapped bar space into process. > + * Save off our IO register and FUNC addresses. > + */ > + > + /* BAR 0 */ > + if (pdev->mem_resource[0].addr == NULL) { > + DLB_ERR(dlb_dev, "probe: BAR 0 addr (csr_kva) is NULL\n"); > + ret = -EINVAL; > + goto pci_mmap_bad_addr; > + } > + dlb_dev->hw.func_kva = (void *)(uintptr_t)pdev- > >mem_resource[0].addr; > + dlb_dev->hw.func_phys_addr = pdev->mem_resource[0].phys_addr; > + > + DLB_INFO(dlb_dev, "DLB FUNC VA=%p, PA=%p, len=%"PRIu64"\n", > + (void *)dlb_dev->hw.func_kva, > + (void *)dlb_dev->hw.func_phys_addr, > + pdev->mem_resource[0].len); > + > + /* BAR 2 */ > + if (pdev->mem_resource[2].addr == NULL) { > + DLB_ERR(dlb_dev, "probe: BAR 2 addr (func_kva) is NULL\n"); > + ret = -EINVAL; > + goto pci_mmap_bad_addr; > + } > + dlb_dev->hw.csr_kva = (void *)(uintptr_t)pdev- > >mem_resource[2].addr; > + dlb_dev->hw.csr_phys_addr = pdev->mem_resource[2].phys_addr; > + > + DLB_INFO(dlb_dev, "DLB CSR VA=%p, PA=%p, len=%"PRIu64"\n", > + (void *)dlb_dev->hw.csr_kva, > + (void *)dlb_dev->hw.csr_phys_addr, > + pdev->mem_resource[2].len); > + > + dlb_dev->pdev = pdev; > + > + ret = dlb_pf_reset(dlb_dev); > + if (ret) > + goto dlb_reset_fail; > + > + /* DLB incorrectly sends URs in response to certain messages. Mask UR > + * errors to prevent these from being propagated to the MCA. > + */ > + ret = dlb_mask_ur_err(pdev); > + if (ret) > + goto mask_ur_err_fail; > + > + ret = dlb_pf_init_driver_state(dlb_dev); > + if (ret) > + goto init_driver_state_fail; > + > + ret = dlb_resource_init(&dlb_dev->hw); > + if (ret) > + goto resource_init_fail; > + > + dlb_dev->revision = os_get_dev_revision(&dlb_dev->hw); > + > + dlb_pf_init_hardware(dlb_dev); > + > + return dlb_dev; > + > +resource_init_fail: > + dlb_resource_free(&dlb_dev->hw); > +init_driver_state_fail: > +mask_ur_err_fail: > +dlb_reset_fail: > +pci_mmap_bad_addr: > + rte_free(dlb_dev); > +dlb_dev_malloc_fail: > + rte_errno = ret; > + return NULL; > +} > + > +int > +dlb_pf_reset(struct dlb_dev *dlb_dev) > +{ > + int msix_cap_offset, err_cap_offset, acs_cap_offset, wait_count; > + uint16_t dev_ctl_word, dev_ctl2_word, lnk_word, lnk_word2; > + uint16_t rt_ctl_word, pri_reqs_dword, pri_ctrl_word; > + struct rte_pci_device *pdev = dlb_dev->pdev; > + uint16_t devsta_busy_word, devctl_word; > + int pcie_cap_offset, pri_cap_offset; > + uint16_t slt_word, slt_word2, cmd; > + int ret = 0, i = 0; > + uint32_t dword[16]; > + off_t off; > + > + /* Save PCI config state */ > + > + for (i = 0; i < 16; i++) { > + if (rte_pci_read_config(pdev, &dword[i], 4, i * 4) != 4) > + return ret; > + } > + > + pcie_cap_offset = dlb_pci_find_capability(pdev, DLB_PCI_CAP_ID_EXP); > + > + if (pcie_cap_offset < 0) { > + printf("[%s()] failed to find the pcie capability\n", > + __func__); > + return pcie_cap_offset; > + } > + > + off = pcie_cap_offset + DLB_PCI_EXP_DEVCTL; > + if (rte_pci_read_config(pdev, &dev_ctl_word, 2, off) != 2) > + dev_ctl_word = 0; > + > + off = pcie_cap_offset + DLB_PCI_LNKCTL; > + if (rte_pci_read_config(pdev, &lnk_word, 2, off) != 2) > + lnk_word = 0; > + > + off = pcie_cap_offset + DLB_PCI_SLTCTL; > + if (rte_pci_read_config(pdev, &slt_word, 2, off) != 2) > + slt_word = 0; > + > + off = pcie_cap_offset + DLB_PCI_RTCTL; > + if (rte_pci_read_config(pdev, &rt_ctl_word, 2, off) != 2) > + rt_ctl_word = 0; > + > + off = pcie_cap_offset + DLB_PCI_EXP_DEVCTL2; > + if (rte_pci_read_config(pdev, &dev_ctl2_word, 2, off) != 2) > + dev_ctl2_word = 0; > + > + off = pcie_cap_offset + DLB_PCI_LNKCTL2; > + if (rte_pci_read_config(pdev, &lnk_word2, 2, off) != 2) > + lnk_word2 = 0; > + > + off = pcie_cap_offset + DLB_PCI_SLTCTL2; > + if (rte_pci_read_config(pdev, &slt_word2, 2, off) != 2) > + slt_word2 = 0; > + > + pri_cap_offset = dlb_pci_find_ext_capability(pdev, > + DLB_PCI_EXT_CAP_ID_PRI); > + if (pri_cap_offset >= 0) { > + off = pri_cap_offset + DLB_PCI_PRI_ALLOC_REQ; > + if (rte_pci_read_config(pdev, &pri_reqs_dword, 4, off) != 4) > + pri_reqs_dword = 0; > + } > + > + /* clear the PCI command register before issuing the FLR */ > + > + off = DLB_PCI_CMD; > + cmd = 0; > + if (rte_pci_write_config(pdev, &cmd, 2, off) != 2) { > + printf("[%s()] failed to write pci config space at offset %d\n", > + __func__, (int)off); > + return -1; > + } > + > + /* issue the FLR */ > + for (wait_count = 0; wait_count < 4; wait_count++) { > + int sleep_time; > + > + off = pcie_cap_offset + DLB_PCI_EXP_DEVSTA; > + ret = rte_pci_read_config(pdev, &devsta_busy_word, 2, off); > + if (ret != 2) { > + printf("[%s()] failed to read the pci device status\n", > + __func__); > + return ret; > + } > + > + if (!(devsta_busy_word & DLB_PCI_EXP_DEVSTA_TRPND)) > + break; > + > + sleep_time = (1 << (wait_count)) * 100; > + rte_delay_ms(sleep_time); > + } > + > + if (wait_count == 4) { > + printf("[%s()] wait for pci pending transactions timed out\n", > + __func__); > + return -1; > + } > + > + off = pcie_cap_offset + DLB_PCI_EXP_DEVCTL; > + ret = rte_pci_read_config(pdev, &devctl_word, 2, off); > + if (ret != 2) { > + printf("[%s()] failed to read the pcie device control\n", > + __func__); > + return ret; > + } > + > + devctl_word |= DLB_PCI_EXP_DEVCTL_BCR_FLR; > + > + if (rte_pci_write_config(pdev, &devctl_word, 2, off) != 2) { > + printf("[%s()] failed to write the pcie device control at offset > %d\n", > + __func__, (int)off); > + return -1; > + } > + > + rte_delay_ms(100); > + > + /* Restore PCI config state */ > + > + if (pcie_cap_offset >= 0) { > + off = pcie_cap_offset + DLB_PCI_EXP_DEVCTL; > + if (rte_pci_write_config(pdev, &dev_ctl_word, 2, off) != 2) { > + printf("[%s()] failed to write the pcie device control > at > offset %d\n", > + __func__, (int)off); > + return -1; > + } > + > + off = pcie_cap_offset + DLB_PCI_LNKCTL; > + if (rte_pci_write_config(pdev, &lnk_word, 2, off) != 2) { > + printf("[%s()] failed to write pci config space at > offset > %d\n", > + __func__, (int)off); > + return -1; > + } > + > + off = pcie_cap_offset + DLB_PCI_SLTCTL; > + if (rte_pci_write_config(pdev, &slt_word, 2, off) != 2) { > + printf("[%s()] failed to write pci config space at > offset > %d\n", > + __func__, (int)off); > + return -1; > + } > + > + off = pcie_cap_offset + DLB_PCI_RTCTL; > + if (rte_pci_write_config(pdev, &rt_ctl_word, 2, off) != 2) { > + printf("[%s()] failed to write pci config space at > offset > %d\n", > + __func__, (int)off); > + return -1; > + } > + > + off = pcie_cap_offset + DLB_PCI_EXP_DEVCTL2; > + if (rte_pci_write_config(pdev, &dev_ctl2_word, 2, off) != 2) { > + printf("[%s()] failed to write pci config space at > offset > %d\n", > + __func__, (int)off); > + return -1; > + } > + > + off = pcie_cap_offset + DLB_PCI_LNKCTL2; > + if (rte_pci_write_config(pdev, &lnk_word2, 2, off) != 2) { > + printf("[%s()] failed to write pci config space at > offset > %d\n", > + __func__, (int)off); > + return -1; > + } > + > + off = pcie_cap_offset + DLB_PCI_SLTCTL2; > + if (rte_pci_write_config(pdev, &slt_word2, 2, off) != 2) { > + printf("[%s()] failed to write pci config space at > offset > %d\n", > + __func__, (int)off); > + return -1; > + } > + } > + > + if (pri_cap_offset >= 0) { > + pri_ctrl_word = DLB_PCI_PRI_CTRL_ENABLE; > + > + off = pri_cap_offset + DLB_PCI_PRI_ALLOC_REQ; > + if (rte_pci_write_config(pdev, &pri_reqs_dword, 4, off) != 4) { > + printf("[%s()] failed to write pci config space at > offset > %d\n", > + __func__, (int)off); > + return -1; > + } > + > + off = pri_cap_offset + DLB_PCI_PRI_CTRL; > + if (rte_pci_write_config(pdev, &pri_ctrl_word, 2, off) != 2) { > + printf("[%s()] failed to write pci config space at > offset > %d\n", > + __func__, (int)off); > + return -1; > + } > + } > + > + err_cap_offset = dlb_pci_find_ext_capability(pdev, > + DLB_PCI_EXT_CAP_ID_ERR); > + if (err_cap_offset >= 0) { > + uint32_t tmp; > + > + off = err_cap_offset + DLB_PCI_ERR_ROOT_STATUS; > + if (rte_pci_read_config(pdev, &tmp, 4, off) != 4) > + tmp = 0; > + > + if (rte_pci_write_config(pdev, &tmp, 4, off) != 4) { > + printf("[%s()] failed to write pci config space at > offset > %d\n", > + __func__, (int)off); > + return -1; > + } > + > + off = err_cap_offset + DLB_PCI_ERR_COR_STATUS; > + if (rte_pci_read_config(pdev, &tmp, 4, off) != 4) > + tmp = 0; > + > + if (rte_pci_write_config(pdev, &tmp, 4, off) != 4) { > + printf("[%s()] failed to write pci config space at > offset > %d\n", > + __func__, (int)off); > + return -1; > + } > + > + off = err_cap_offset + DLB_PCI_ERR_UNCOR_STATUS; > + if (rte_pci_read_config(pdev, &tmp, 4, off) != 4) > + tmp = 0; > + > + if (rte_pci_write_config(pdev, &tmp, 4, off) != 4) { > + printf("[%s()] failed to write pci config space at > offset > %d\n", > + __func__, (int)off); > + return -1; > + } > + } > + > + for (i = 16; i > 0; i--) { > + off = (i - 1) * 4; > + if (rte_pci_write_config(pdev, &dword[i - 1], 4, off) != 4) { > + printf("[%s()] failed to write pci config space at > offset > %d\n", > + __func__, (int)off); > + return -1; > + } > + } > + > + off = DLB_PCI_CMD; > + if (rte_pci_read_config(pdev, &cmd, 2, off) == 2) { > + cmd &= ~DLB_PCI_COMMAND_INTX_DISABLE; > + if (rte_pci_write_config(pdev, &cmd, 2, off) != 2) { > + printf("[%s()] failed to write pci config space\n", > + __func__); > + return -1; > + } > + } > + > + msix_cap_offset = dlb_pci_find_capability(pdev, > DLB_PCI_CAP_ID_MSIX); > + if (msix_cap_offset >= 0) { > + off = msix_cap_offset + DLB_PCI_MSIX_FLAGS; > + if (rte_pci_read_config(pdev, &cmd, 2, off) == 2) { > + cmd |= DLB_PCI_MSIX_FLAGS_ENABLE; > + cmd |= DLB_PCI_MSIX_FLAGS_MASKALL; > + if (rte_pci_write_config(pdev, &cmd, 2, off) != 2) { > + printf("[%s()] failed to write msix flags\n", > + __func__); > + return -1; > + } > + } > + > + off = msix_cap_offset + DLB_PCI_MSIX_FLAGS; > + if (rte_pci_read_config(pdev, &cmd, 2, off) == 2) { > + cmd &= ~DLB_PCI_MSIX_FLAGS_MASKALL; > + if (rte_pci_write_config(pdev, &cmd, 2, off) != 2) { > + printf("[%s()] failed to write msix flags\n", > + __func__); > + return -1; > + } > + } > + } > + > + acs_cap_offset = dlb_pci_find_ext_capability(pdev, > + DLB_PCI_EXT_CAP_ID_ACS); > + if (acs_cap_offset >= 0) { > + uint16_t acs_cap, acs_ctrl, acs_mask; > + off = acs_cap_offset + DLB_PCI_ACS_CAP; > + if (rte_pci_read_config(pdev, &acs_cap, 2, off) != 2) > + acs_cap = 0; > + > + off = acs_cap_offset + DLB_PCI_ACS_CTRL; > + if (rte_pci_read_config(pdev, &acs_ctrl, 2, off) != 2) > + acs_ctrl = 0; > + > + acs_mask = DLB_PCI_ACS_SV | DLB_PCI_ACS_RR; > + acs_mask |= (DLB_PCI_ACS_CR | DLB_PCI_ACS_UF); > + acs_ctrl |= (acs_cap & acs_mask); > + > + if (rte_pci_write_config(pdev, &acs_ctrl, 2, off) != 2) { > + printf("[%s()] failed to write pci config space at > offset > %d\n", > + __func__, (int)off); > + return -1; > + } > + > + off = acs_cap_offset + DLB_PCI_ACS_CTRL; > + if (rte_pci_read_config(pdev, &acs_ctrl, 2, off) != 2) > + acs_ctrl = 0; > + > + acs_mask = DLB_PCI_ACS_RR | DLB_PCI_ACS_CR | > DLB_PCI_ACS_EC; > + acs_ctrl &= ~acs_mask; > + > + off = acs_cap_offset + DLB_PCI_ACS_CTRL; > + if (rte_pci_write_config(pdev, &acs_ctrl, 2, off) != 2) { > + printf("[%s()] failed to write pci config space at > offset > %d\n", > + __func__, (int)off); > + return -1; > + } > + } > + > + return 0; > +} Like I suggested in [1], this PCI-specific code might be a good candidate for a separate file. Thanks, Gage