From f7e407a0fe58d76d54e3d1f9d2cb117036cd095b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20=C3=85strand?= Date: Fri, 23 Oct 2020 21:25:05 +0200 Subject: Add PMU config to inference creation Add PMU configuration information to inference creation. Change-Id: Id8a69517a5d3e4822dbaf46f76cadb2700b3d981 --- kernel/ethosu_core_interface.h | 9 ++++++ kernel/ethosu_inference.c | 68 +++++++++++++++++++++++++++++++++++++++--- kernel/ethosu_inference.h | 26 ++++++++++------ kernel/ethosu_mailbox.c | 16 +++++++++- kernel/ethosu_mailbox.h | 5 +++- kernel/uapi/ethosu.h | 49 ++++++++++++++++++++++++++---- 6 files changed, 153 insertions(+), 20 deletions(-) diff --git a/kernel/ethosu_core_interface.h b/kernel/ethosu_core_interface.h index 0dd1996..86e10ac 100644 --- a/kernel/ethosu_core_interface.h +++ b/kernel/ethosu_core_interface.h @@ -30,6 +30,9 @@ /** Maximum number of IFM/OFM buffers per inference */ #define ETHOSU_CORE_BUFFER_MAX 16 +/** Maximum number of PMU counters to be returned for inference */ +#define ETHOSU_CORE_PMU_MAX 4 + /** * enum ethosu_core_msg_type - Message types * @@ -87,6 +90,8 @@ struct ethosu_core_inference_req { uint32_t ofm_count; struct ethosu_core_buffer ofm[ETHOSU_CORE_BUFFER_MAX]; struct ethosu_core_buffer network; + uint8_t pmu_event_config[ETHOSU_CORE_PMU_MAX]; + uint32_t pmu_cycle_counter_enable; }; struct ethosu_core_inference_rsp { @@ -94,6 +99,10 @@ struct ethosu_core_inference_rsp { uint32_t ofm_count; uint32_t ofm_size[ETHOSU_CORE_BUFFER_MAX]; uint32_t status; + uint8_t pmu_event_config[ETHOSU_CORE_PMU_MAX]; + uint32_t pmu_event_count[ETHOSU_CORE_PMU_MAX]; + uint32_t pmu_cycle_counter_enable; + uint64_t pmu_cycle_counter_count; }; #endif diff --git a/kernel/ethosu_inference.c b/kernel/ethosu_inference.c index e9530cf..586ffca 100644 --- a/kernel/ethosu_inference.c +++ b/kernel/ethosu_inference.c @@ -89,7 +89,10 @@ static int ethosu_inference_send(struct ethosu_inference *inf) ret = ethosu_mailbox_inference(&inf->edev->mailbox, inf, inf->ifm_count, inf->ifm, inf->ofm_count, inf->ofm, - inf->net->buf); + inf->net->buf, + inf->pmu_event_config, + ETHOSU_PMU_EVENT_MAX, + inf->pmu_cycle_counter_enable); if (ret) return ret; @@ -172,7 +175,8 @@ static long ethosu_inference_ioctl(struct file *file, unsigned long arg) { struct ethosu_inference *inf = file->private_data; - int ret = -EINVAL; + void __user *udata = (void __user *)arg; + int ret; ret = mutex_lock_interruptible(&inf->edev->mutex); if (ret) @@ -182,11 +186,27 @@ static long ethosu_inference_ioctl(struct file *file, switch (cmd) { case ETHOSU_IOCTL_INFERENCE_STATUS: { - ret = inf->status; + struct ethosu_uapi_result_status uapi; + int i; + + uapi.status = inf->status; + + for (i = 0; i < ETHOSU_PMU_EVENT_MAX; i++) { + uapi.pmu_config.events[i] = + inf->pmu_event_config[i]; + uapi.pmu_count.events[i] = + inf->pmu_event_count[i]; + } + + uapi.pmu_config.cycle_count = inf->pmu_cycle_counter_enable; + uapi.pmu_count.cycle_count = inf->pmu_cycle_counter_count; dev_info(inf->edev->dev, "Ioctl: Inference status. status=%s (%d)\n", - status_to_string(ret), ret); + status_to_string(uapi.status), uapi.status); + + ret = copy_to_user(udata, &uapi, sizeof(uapi)) ? -EFAULT : 0; + break; } default: { @@ -243,6 +263,25 @@ int ethosu_inference_create(struct ethosu_device *edev, inf->ofm_count++; } + /* Configure PMU and cycle counter */ + dev_info(inf->edev->dev, + "Configuring events for PMU. events=[%u, %u, %u, %u]\n", + uapi->pmu_config.events[0], uapi->pmu_config.events[1], + uapi->pmu_config.events[2], uapi->pmu_config.events[3]); + + /* Configure events and reset count for all events */ + for (i = 0; i < ETHOSU_PMU_EVENT_MAX; i++) { + inf->pmu_event_config[i] = uapi->pmu_config.events[i]; + inf->pmu_event_count[i] = 0; + } + + if (uapi->pmu_config.cycle_count) + dev_info(inf->edev->dev, "Enabling cycle counter\n"); + + /* Configure cycle counter and reset any previous count */ + inf->pmu_cycle_counter_enable = uapi->pmu_config.cycle_count; + inf->pmu_cycle_counter_count = 0; + /* Increment network reference count */ ethosu_network_get(net); @@ -321,6 +360,7 @@ void ethosu_inference_rsp(struct ethosu_device *edev, struct ethosu_inference *inf = (struct ethosu_inference *)rsp->user_arg; int ret; + int i; ret = ethosu_inference_find(inf, &edev->inference_list); if (ret) { @@ -352,6 +392,26 @@ void ethosu_inference_rsp(struct ethosu_device *edev, inf->status = ETHOSU_UAPI_STATUS_ERROR; } + for (i = 0; i < ETHOSU_CORE_PMU_MAX; i++) { + inf->pmu_event_config[i] = rsp->pmu_event_config[i]; + inf->pmu_event_count[i] = rsp->pmu_event_count[i]; + } + + inf->pmu_cycle_counter_enable = rsp->pmu_cycle_counter_enable; + inf->pmu_cycle_counter_count = rsp->pmu_cycle_counter_count; + + dev_info(edev->dev, + "PMU events. config=[%u, %u %u, %u], count=[%u, %u, %u, %u]\n", + inf->pmu_event_config[0], inf->pmu_event_count[0], + inf->pmu_event_config[1], inf->pmu_event_count[1], + inf->pmu_event_config[2], inf->pmu_event_count[2], + inf->pmu_event_config[3], inf->pmu_event_count[3] + ); + + dev_info(edev->dev, + "PMU cycle counter. enable=%u, count=%llu\n", + inf->pmu_cycle_counter_enable, + inf->pmu_cycle_counter_count); wake_up_interruptible(&inf->waitq); ethosu_inference_put(inf); diff --git a/kernel/ethosu_inference.h b/kernel/ethosu_inference.h index c0d8461..07370ca 100644 --- a/kernel/ethosu_inference.h +++ b/kernel/ethosu_inference.h @@ -44,15 +44,19 @@ struct file; /** * struct ethosu_inference - Inference struct - * @edev: Arm Ethos-U device - * @file: File handle - * @kref: Reference counter - * @waitq: Wait queue - * @ifm: Pointer to IFM buffer - * @ofm: Pointer to OFM buffer - * @net: Pointer to network - * @pending: Pending response from the firmware - * @status: Inference status + * @edev: Arm Ethos-U device + * @file: File handle + * @kref: Reference counter + * @waitq: Wait queue + * @ifm: Pointer to IFM buffer + * @ofm: Pointer to OFM buffer + * @net: Pointer to network + * @pending: Pending response from the firmware + * @status: Inference status + * @pmu_event_config: PMU event configuration + * @pmu_event_count: PMU event count after inference + * @pmu_cycle_counter_enable: PMU cycle counter config + * @pmu_cycle_counter_count: PMU cycle counter count after inference */ struct ethosu_inference { struct ethosu_device *edev; @@ -66,6 +70,10 @@ struct ethosu_inference { struct ethosu_network *net; bool pending; enum ethosu_uapi_status status; + uint8_t pmu_event_config[ETHOSU_PMU_EVENT_MAX]; + uint32_t pmu_event_count[ETHOSU_PMU_EVENT_MAX]; + uint32_t pmu_cycle_counter_enable; + uint64_t pmu_cycle_counter_count; struct list_head list; }; diff --git a/kernel/ethosu_mailbox.c b/kernel/ethosu_mailbox.c index 47c4698..77b9614 100644 --- a/kernel/ethosu_mailbox.c +++ b/kernel/ethosu_mailbox.c @@ -175,14 +175,25 @@ int ethosu_mailbox_inference(struct ethosu_mailbox *mbox, struct ethosu_buffer **ifm, uint32_t ofm_count, struct ethosu_buffer **ofm, - struct ethosu_buffer *network) + struct ethosu_buffer *network, + uint8_t *pmu_event_config, + uint8_t pmu_event_config_count, + uint8_t pmu_cycle_counter_enable) { struct ethosu_core_inference_req inf; uint32_t i; + /* Verify that the uapi and core has the same number of pmus */ + if (pmu_event_config_count != ETHOSU_CORE_PMU_MAX) { + dev_err(mbox->dev, "PMU count misconfigured.\n"); + + return -EINVAL; + } + inf.user_arg = (ptrdiff_t)user_arg; inf.ifm_count = ifm_count; inf.ofm_count = ofm_count; + inf.pmu_cycle_counter_enable = pmu_cycle_counter_enable; for (i = 0; i < ifm_count; i++) ethosu_core_set_size(ifm[i], &inf.ifm[i]); @@ -190,6 +201,9 @@ int ethosu_mailbox_inference(struct ethosu_mailbox *mbox, for (i = 0; i < ofm_count; i++) ethosu_core_set_capacity(ofm[i], &inf.ofm[i]); + for (i = 0; i < ETHOSU_CORE_PMU_MAX; i++) + inf.pmu_event_config[i] = pmu_event_config[i]; + ethosu_core_set_size(network, &inf.network); return ethosu_queue_write_msg(mbox, ETHOSU_CORE_MSG_INFERENCE_REQ, diff --git a/kernel/ethosu_mailbox.h b/kernel/ethosu_mailbox.h index 5a77b54..8f539ee 100644 --- a/kernel/ethosu_mailbox.h +++ b/kernel/ethosu_mailbox.h @@ -104,6 +104,9 @@ int ethosu_mailbox_inference(struct ethosu_mailbox *mbox, struct ethosu_buffer **ifm, uint32_t ofm_count, struct ethosu_buffer **ofm, - struct ethosu_buffer *network); + struct ethosu_buffer *network, + uint8_t *pmu_event_config, + uint8_t pmu_event_config_count, + uint8_t pmu_cycle_counter_enable); #endif /* ETHOSU_MAILBOX_H */ diff --git a/kernel/uapi/ethosu.h b/kernel/uapi/ethosu.h index d790db4..8f870c9 100644 --- a/kernel/uapi/ethosu.h +++ b/kernel/uapi/ethosu.h @@ -49,11 +49,15 @@ struct ethosu_uapi_network_create) #define ETHOSU_IOCTL_INFERENCE_CREATE ETHOSU_IOR(0x30, \ struct ethosu_uapi_inference_create) -#define ETHOSU_IOCTL_INFERENCE_STATUS ETHOSU_IO(0x31) +#define ETHOSU_IOCTL_INFERENCE_STATUS ETHOSU_IOR(0x31, \ + struct ethosu_uapi_result_status) /* Maximum number of IFM/OFM file descriptors per network */ #define ETHOSU_FD_MAX 16 +/* Maximum number of PMUs available */ +#define ETHOSU_PMU_EVENT_MAX 4 + /**************************************************************************** * Types ****************************************************************************/ @@ -94,6 +98,27 @@ struct ethosu_uapi_network_create { __u32 fd; }; +/** + * struct ethosu_uapi_pmu_config - Configure performance counters + * @events: Array of counters to configure, set to non-zero for + * each counter to enable corresponding event. + * @cycle_count: Set to enable the cycle counter. + */ +struct ethosu_uapi_pmu_config { + __u32 events[ETHOSU_PMU_EVENT_MAX]; + __u32 cycle_count; +}; + +/** + * struct ethosu_uapi_pmu_counts - Status of performance counters + * @events: Count for respective configured events. + * @cycle_count: Count for cycle counter. + */ +struct ethosu_uapi_pmu_counts { + __u32 events[ETHOSU_PMU_EVENT_MAX]; + __u64 cycle_count; +}; + /** * struct ethosu_uapi_inference_create - Create network request * @ifm_count: Number of IFM file descriptors @@ -102,10 +127,24 @@ struct ethosu_uapi_network_create { * @ofm_fd: OFM buffer file descriptors */ struct ethosu_uapi_inference_create { - __u32 ifm_count; - __u32 ifm_fd[ETHOSU_FD_MAX]; - __u32 ofm_count; - __u32 ofm_fd[ETHOSU_FD_MAX]; + __u32 ifm_count; + __u32 ifm_fd[ETHOSU_FD_MAX]; + __u32 ofm_count; + __u32 ofm_fd[ETHOSU_FD_MAX]; + struct ethosu_uapi_pmu_config pmu_config; +}; + +/** + * struct ethosu_uapi_result_status - Status of inference + * @status Status of run inference. + * @pmu_config Configured performance counters. + * @pmu_count Perfomance counters values, when status is + * ETHOSU_UAPI_STATUS_OK. + */ +struct ethosu_uapi_result_status { + enum ethosu_uapi_status status; + struct ethosu_uapi_pmu_config pmu_config; + struct ethosu_uapi_pmu_counts pmu_count; }; #endif -- cgit v1.2.1