Loading drivers/media/platform/msm/npu/npu_common.h +6 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,8 @@ #define NPU_MAX_STATS_BUF_SIZE 16384 #define NPU_MAX_PATCH_NUM 160 #define DCVS_MODE_MAX 100 enum npu_power_level { NPU_PWRLEVEL_MINSVS = 0, NPU_PWRLEVEL_LOWSVS, Loading Loading @@ -154,6 +156,8 @@ struct npu_reg { * @uc_pwrlevel - power level from user driver setting * @perf_mode_override - perf mode from sysfs to override perf mode * settings from user driver * @dcvs_mode - dcvs mode from sysfs to turn on dcvs mode * settings from user driver * @devbw - bw device */ struct npu_pwrctrl { Loading @@ -172,6 +176,8 @@ struct npu_pwrctrl { uint32_t cdsprm_pwrlevel; uint32_t fmax_pwrlevel; uint32_t perf_mode_override; uint32_t dcvs_mode; uint32_t cur_dcvs_activity; }; /** Loading drivers/media/platform/msm/npu/npu_dev.c +114 −3 Original line number Diff line number Diff line Loading @@ -68,6 +68,12 @@ static ssize_t npu_show_perf_mode_override(struct device *dev, static ssize_t npu_store_perf_mode_override(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); static ssize_t npu_show_dcvs_mode(struct device *dev, struct device_attribute *attr, char *buf); static ssize_t npu_store_dcvs_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); static ssize_t npu_show_fw_unload_delay_ms(struct device *dev, struct device_attribute *attr, char *buf); Loading Loading @@ -108,6 +114,9 @@ static int npu_exec_network_v2(struct npu_client *client, unsigned long arg); static int npu_receive_event(struct npu_client *client, unsigned long arg); static int npu_set_fw_state(struct npu_client *client, uint32_t enable); static int npu_set_property(struct npu_client *client, unsigned long arg); static long npu_ioctl(struct file *file, unsigned int cmd, unsigned long arg); static unsigned int npu_poll(struct file *filp, struct poll_table_struct *p); Loading Loading @@ -178,6 +187,8 @@ static DEVICE_ATTR(caps, 0444, npu_show_capabilities, NULL); static DEVICE_ATTR(pwr, 0644, npu_show_pwr_state, npu_store_pwr_state); static DEVICE_ATTR(perf_mode_override, 0644, npu_show_perf_mode_override, npu_store_perf_mode_override); static DEVICE_ATTR(dcvs_mode, 0644, npu_show_dcvs_mode, npu_store_dcvs_mode); static DEVICE_ATTR(fw_unload_delay_ms, 0644, npu_show_fw_unload_delay_ms, npu_store_fw_unload_delay_ms); static DEVICE_ATTR(fw_state, 0644, npu_show_fw_state, npu_store_fw_state); Loading @@ -186,6 +197,7 @@ static struct attribute *npu_fs_attrs[] = { &dev_attr_caps.attr, &dev_attr_pwr.attr, &dev_attr_perf_mode_override.attr, &dev_attr_dcvs_mode.attr, &dev_attr_fw_state.attr, &dev_attr_fw_unload_delay_ms.attr, NULL Loading Loading @@ -289,7 +301,7 @@ static ssize_t npu_store_pwr_state(struct device *dev, } /* ------------------------------------------------------------------------- * SysFS - Power State * SysFS - perf_mode_override * ------------------------------------------------------------------------- */ static ssize_t npu_show_perf_mode_override(struct device *dev, Loading Loading @@ -324,6 +336,50 @@ static ssize_t npu_store_perf_mode_override(struct device *dev, return count; } static ssize_t npu_show_dcvs_mode(struct device *dev, struct device_attribute *attr, char *buf) { struct npu_device *npu_dev = dev_get_drvdata(dev); struct npu_pwrctrl *pwr = &npu_dev->pwrctrl; return scnprintf(buf, PAGE_SIZE, "%d\n", pwr->dcvs_mode); } static ssize_t npu_store_dcvs_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct npu_device *npu_dev = dev_get_drvdata(dev); struct msm_npu_property prop; uint32_t val; int ret = 0; ret = kstrtou32(buf, 10, &val); if (ret) { pr_err("Invalid input for dcvs mode setting\n"); return -EINVAL; } val = min(val, (uint32_t)DCVS_MODE_MAX); pr_debug("sysfs: setting dcvs_mode to %d\n", val); prop.prop_id = MSM_NPU_PROP_ID_DCVS_MODE; prop.num_of_params = 1; prop.network_hdl = 0; prop.prop_param[0] = val; ret = npu_host_set_fw_property(npu_dev, &prop); if (ret) { pr_err("npu_host_set_fw_property failed %d\n", ret); return ret; } npu_dev->pwrctrl.dcvs_mode = val; return count; } /* ------------------------------------------------------------------------- * SysFS - Delayed FW unload * ------------------------------------------------------------------------- Loading Loading @@ -582,6 +638,7 @@ int npu_enable_core_power(struct npu_device *npu_dev) pwr->pwr_vote_num = 0; return ret; } pwr->cur_dcvs_activity = DCVS_MODE_MAX; npu_resume_devbw(npu_dev); } pwr->pwr_vote_num++; Loading @@ -593,7 +650,6 @@ int npu_enable_core_power(struct npu_device *npu_dev) void npu_disable_core_power(struct npu_device *npu_dev) { struct npu_pwrctrl *pwr = &npu_dev->pwrctrl; struct npu_thermalctrl *thermalctrl = &npu_dev->thermalctrl; mutex_lock(&npu_dev->dev_lock); if (!pwr->pwr_vote_num) { Loading @@ -606,9 +662,10 @@ void npu_disable_core_power(struct npu_device *npu_dev) npu_suspend_devbw(npu_dev); npu_disable_core_clocks(npu_dev); npu_disable_regulators(npu_dev); pwr->active_pwrlevel = thermalctrl->pwr_level; pwr->active_pwrlevel = pwr->default_pwrlevel; pwr->uc_pwrlevel = pwr->max_pwrlevel; pwr->cdsprm_pwrlevel = pwr->max_pwrlevel; pwr->cur_dcvs_activity = 0; pr_debug("setting back to power level=%d\n", pwr->active_pwrlevel); } Loading Loading @@ -1563,6 +1620,57 @@ static int npu_receive_event(struct npu_client *client, return ret; } static int npu_set_fw_state(struct npu_client *client, uint32_t enable) { struct npu_device *npu_dev = client->npu_dev; int rc = 0; if (enable) { pr_debug("%s: enable fw\n", __func__); rc = fw_init(npu_dev); if (rc) pr_err("enable fw failed\n"); } else { pr_debug("%s: disable fw\n", __func__); fw_deinit(npu_dev, false, true); } return rc; } static int npu_set_property(struct npu_client *client, unsigned long arg) { struct msm_npu_property prop; void __user *argp = (void __user *)arg; int ret = -EINVAL; ret = copy_from_user(&prop, argp, sizeof(prop)); if (ret) { pr_err("fail to copy from user\n"); return -EFAULT; } switch (prop.prop_id) { case MSM_NPU_PROP_ID_FW_STATE: ret = npu_set_fw_state(client, (uint32_t)prop.prop_param[0]); break; case MSM_NPU_PROP_ID_PERF_MODE: ret = npu_host_set_perf_mode(client, (uint32_t)prop.network_hdl, (uint32_t)prop.prop_param[0]); break; default: ret = npu_host_set_fw_property(client->npu_dev, &prop); if (ret) pr_err("npu_host_set_fw_property failed\n"); break; } return ret; } static long npu_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { Loading Loading @@ -1597,6 +1705,9 @@ static long npu_ioctl(struct file *file, unsigned int cmd, case MSM_NPU_RECEIVE_EVENT: ret = npu_receive_event(client, arg); break; case MSM_NPU_SET_PROP: ret = npu_set_property(client, arg); break; default: pr_err("unexpected IOCTL %x\n", cmd); } Loading drivers/media/platform/msm/npu/npu_host_ipc.h +42 −1 Original line number Diff line number Diff line /* Copyright (c) 2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -38,6 +38,8 @@ #define NPU_IPC_CMD_LOAD_V2 0x00000009 /* ipc_cmd_execute_packet_v2 */ #define NPU_IPC_CMD_EXECUTE_V2 0x0000000A /* ipc_cmd_set_property_packet */ #define NPU_IPC_CMD_SET_PROPERTY 0x0000000B /* Messages sent **from** NPU */ /* IPC Message Response -- uint32_t */ Loading @@ -55,6 +57,10 @@ #define NPU_IPC_MSG_LOOPBACK_DONE 0x00010005 /* ipc_msg_execute_pkt_v2 */ #define NPU_IPC_MSG_EXECUTE_V2_DONE 0x00010006 /* ipc_msg_set_property_packet */ #define NPU_IPC_MSG_SET_PROPERTY_DONE 0x00010007 /* ipc_msg_set_power_mode */ #define NPU_IPC_MSG_DCVS_NOTIFY 0x00010010 /* Logging message size */ /* Number 32-bit elements for the maximum log message size */ Loading Loading @@ -103,6 +109,11 @@ /* Debug stats */ #define NUM_LAYER_STATS_PER_EXE_MSG_MAX 110 enum npu_fw_property_id { NPU_FW_PROP_ID_DCVS_MODE = 0, NPU_FW_PROP_ID_INVALID = 0xFFFFFFFF, }; /* ------------------------------------------------------------------------- * Data Structures * ------------------------------------------------------------------------- Loading Loading @@ -271,6 +282,27 @@ struct ipc_cmd_loopback_pkt { uint32_t loopbackParams; }; /* * Set property packet definition */ struct ipc_cmd_set_prop_pkt { struct ipc_cmd_header_pkt header; uint32_t prop_id; uint32_t num_params; uint32_t network_hdl; uint32_t prop_param[0]; }; /* * Set property response packet definition */ struct ipc_msg_set_prop_pkt { struct ipc_msg_header_pkt header; uint32_t prop_id; uint32_t network_hdl; uint32_t prop_value; }; /* * LOAD response packet definition */ Loading Loading @@ -417,4 +449,13 @@ struct ipc_cmd_shutdown_pkt { uint32_t shutdown_flags; }; /* * Notify driver to set power mode (a value from 0 to 100) */ struct ipc_msg_set_dcvs_mode { struct ipc_msg_header_pkt header; /* activity level from 0-100 */ uint32_t activity; }; #endif /* NPU_HOST_IPC_H */ drivers/media/platform/msm/npu/npu_mgr.c +234 −35 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ static int npu_send_misc_cmd(struct npu_device *npu_dev, uint32_t q_idx, static int npu_queue_event(struct npu_client *client, struct npu_kevent *evt); static int npu_notify_dsp(struct npu_device *npu_dev, bool pwr_up); static int npu_notify_aop(struct npu_device *npu_dev, bool on); static int update_dcvs_activity(struct npu_device *npu_dev, uint32_t activity); static void npu_destroy_wq(struct npu_host_ctx *host_ctx); static struct workqueue_struct *npu_create_wq(struct npu_host_ctx *host_ctx, const char *name); Loading Loading @@ -299,8 +300,10 @@ int npu_host_init(struct npu_device *npu_dev) memset(host_ctx, 0, sizeof(*host_ctx)); init_completion(&host_ctx->loopback_done); init_completion(&host_ctx->fw_deinit_done); init_completion(&host_ctx->property_set_done); mutex_init(&host_ctx->lock); atomic_set(&host_ctx->ipc_trans_id, 1); host_ctx->npu_dev = npu_dev; host_ctx->wq = npu_create_wq(host_ctx, "npu_wq"); if (!host_ctx->wq) Loading Loading @@ -701,6 +704,7 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg) uint32_t msg_id; struct npu_network *network = NULL; struct npu_kevent kevt; struct npu_device *npu_dev = host_ctx->npu_dev; msg_id = msg[1]; switch (msg_id) { Loading Loading @@ -908,6 +912,29 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg) complete_all(&host_ctx->loopback_done); break; } case NPU_IPC_MSG_SET_PROPERTY_DONE: { struct ipc_msg_set_prop_pkt *set_prop_rsp_pkt = (struct ipc_msg_set_prop_pkt *)msg; pr_debug("NPU_IPC_MSG_SET_PROPERTY_DONE %d:0x%x:%d\n", set_prop_rsp_pkt->network_hdl, set_prop_rsp_pkt->prop_id, set_prop_rsp_pkt->prop_value); complete_all(&host_ctx->property_set_done); break; } case NPU_IPC_MSG_DCVS_NOTIFY: { struct ipc_msg_set_dcvs_mode *set_dcvs_pkt = (struct ipc_msg_set_dcvs_mode *)msg; pr_debug("NPU_IPC_MSG_DCVS_NOTIFY %d\n", set_dcvs_pkt->activity); update_dcvs_activity(npu_dev, set_dcvs_pkt->activity); break; } default: pr_err("Not supported apps response received %d\n", msg_id); Loading Loading @@ -1125,18 +1152,153 @@ static uint32_t find_networks_perf_mode(struct npu_host_ctx *host_ctx) network = host_ctx->networks; if (!host_ctx->network_num) { /* if no network exists, set to the lowest level */ max_perf_mode = 1; } else { /* find the max level among all the networks */ for (i = 0; i < host_ctx->network_num; i++) { if ((network->perf_mode != 0) && (network->perf_mode > max_perf_mode)) max_perf_mode = network->perf_mode; if ((network->cur_perf_mode != 0) && (network->cur_perf_mode > max_perf_mode)) max_perf_mode = network->cur_perf_mode; network++; } } pr_debug("max perf mode for networks: %d\n", max_perf_mode); return max_perf_mode; } static int set_perf_mode(struct npu_device *npu_dev) { int ret = 0; uint32_t networks_perf_mode; struct npu_host_ctx *host_ctx = &npu_dev->host_ctx; networks_perf_mode = find_networks_perf_mode(host_ctx); ret = npu_set_uc_power_level(npu_dev, networks_perf_mode); if (ret) pr_err("network load failed due to power level set\n"); return ret; } static int update_dcvs_activity(struct npu_device *npu_dev, uint32_t activity) { int ret = 0; npu_dev->pwrctrl.cur_dcvs_activity = activity; if (activity > 0) { pr_debug("Set clocks back to default setting - exit dcvs mode\n"); ret = set_perf_mode(npu_dev); } else { pr_debug("Set clocks to low - enter dcvs mode\n"); ret = npu_set_uc_power_level(npu_dev, 1); } return ret; } static enum npu_fw_property_id npu_host_to_fw_prop_id(uint32_t prop) { uint32_t fw_prop_id = NPU_FW_PROP_ID_INVALID; switch (prop) { case MSM_NPU_PROP_ID_DCVS_MODE: fw_prop_id = NPU_FW_PROP_ID_DCVS_MODE; break; default: pr_err("Invalid host property id %x\n", prop); break; } return fw_prop_id; } int32_t npu_host_set_fw_property(struct npu_device *npu_dev, struct msm_npu_property *property) { int ret = 0, i; uint32_t prop_param, prop_id; struct ipc_cmd_set_prop_pkt *prop_packet = NULL; struct npu_host_ctx *host_ctx = &npu_dev->host_ctx; uint32_t num_of_params, pkt_size; prop_id = npu_host_to_fw_prop_id(property->prop_id); if (prop_id == NPU_FW_PROP_ID_INVALID) return -EINVAL; num_of_params = min_t(uint32_t, property->num_of_params, (uint32_t)PROP_PARAM_MAX_SIZE); pkt_size = sizeof(*prop_packet) + num_of_params * sizeof(uint32_t); prop_packet = kzalloc(pkt_size, GFP_KERNEL); if (!prop_packet) return -ENOMEM; switch (prop_id) { case NPU_FW_PROP_ID_DCVS_MODE: prop_param = min_t(uint32_t, property->prop_param[0], (uint32_t)DCVS_MODE_MAX); property->prop_param[0] = prop_param; pr_debug("setting dcvs_mode to %d\n", prop_param); if (property->network_hdl == 0) { npu_dev->pwrctrl.dcvs_mode = prop_param; pr_debug("Set global dcvs mode %d\n", prop_param); } break; default: pr_err("unsupported property received %d\n", property->prop_id); goto set_prop_exit; } prop_packet->header.cmd_type = NPU_IPC_CMD_SET_PROPERTY; prop_packet->header.size = pkt_size; prop_packet->header.trans_id = atomic_add_return(1, &host_ctx->ipc_trans_id); prop_packet->header.flags = 0; prop_packet->prop_id = prop_id; prop_packet->num_params = num_of_params; prop_packet->network_hdl = property->network_hdl; for (i = 0; i < num_of_params; i++) prop_packet->prop_param[i] = property->prop_param[i]; reinit_completion(&host_ctx->property_set_done); ret = npu_send_misc_cmd(npu_dev, IPC_QUEUE_APPS_EXEC, prop_packet); pr_debug("NPU_IPC_CMD_SET_PROPERTY sent status: %d\n", ret); if (ret) { pr_err("NPU_IPC_CMD_SET_PROPERTY failed\n"); goto set_prop_exit; } ret = wait_for_completion_interruptible_timeout( &host_ctx->property_set_done, (host_ctx->fw_dbg_mode & FW_DBG_MODE_INC_TIMEOUT) ? NW_DEBUG_TIMEOUT : NW_CMD_TIMEOUT); if (!ret) { pr_err_ratelimited("npu: NPU_IPC_CMD_SET_PROPERTY time out\n"); ret = -ETIMEDOUT; goto set_prop_exit; } else if (ret < 0) { pr_err("Wait for set_property done interrupted by signal\n"); goto set_prop_exit; } else if (ret > 0) { ret = 0; } set_prop_exit: kfree(prop_packet); return ret; } int32_t npu_host_load_network(struct npu_client *client, struct msm_npu_load_network_ioctl *load_ioctl) { Loading @@ -1145,7 +1307,6 @@ int32_t npu_host_load_network(struct npu_client *client, struct npu_network *network; struct ipc_cmd_load_pkt load_packet; struct npu_host_ctx *host_ctx = &npu_dev->host_ctx; uint32_t networks_perf_mode = 0; ret = fw_init(npu_dev); if (ret) Loading @@ -1164,7 +1325,8 @@ int32_t npu_host_load_network(struct npu_client *client, network->phy_add = load_ioctl->buf_phys_addr; network->first_block_size = load_ioctl->first_block_size; network->priority = load_ioctl->priority; network->perf_mode = load_ioctl->perf_mode; network->cur_perf_mode = network->init_perf_mode = load_ioctl->perf_mode; /* verify mapped physical address */ if (!npu_mem_verify_addr(client, network->phy_add)) { Loading @@ -1172,14 +1334,6 @@ int32_t npu_host_load_network(struct npu_client *client, goto error_free_network; } networks_perf_mode = find_networks_perf_mode(host_ctx); ret = npu_set_uc_power_level(npu_dev, networks_perf_mode); if (ret) { pr_err("network load failed due to power level set\n"); goto error_free_network; } load_packet.header.cmd_type = NPU_IPC_CMD_LOAD; load_packet.header.size = sizeof(struct ipc_cmd_load_pkt); load_packet.header.trans_id = Loading Loading @@ -1229,6 +1383,7 @@ int32_t npu_host_load_network(struct npu_client *client, load_ioctl->network_hdl = network->network_hdl; network->is_active = true; network_put(network); mutex_unlock(&host_ctx->lock); return ret; Loading @@ -1251,7 +1406,6 @@ int32_t npu_host_load_network_v2(struct npu_client *client, struct npu_network *network; struct ipc_cmd_load_pkt_v2 *load_packet = NULL; struct npu_host_ctx *host_ctx = &npu_dev->host_ctx; uint32_t networks_perf_mode = 0; uint32_t num_patch_params, pkt_size; ret = fw_init(npu_dev); Loading Loading @@ -1285,7 +1439,8 @@ int32_t npu_host_load_network_v2(struct npu_client *client, network->phy_add = load_ioctl->buf_phys_addr; network->first_block_size = load_ioctl->first_block_size; network->priority = load_ioctl->priority; network->perf_mode = load_ioctl->perf_mode; network->cur_perf_mode = network->init_perf_mode = load_ioctl->perf_mode; network->num_layers = load_ioctl->num_layers; /* verify mapped physical address */ Loading @@ -1295,14 +1450,6 @@ int32_t npu_host_load_network_v2(struct npu_client *client, goto error_free_network; } networks_perf_mode = find_networks_perf_mode(host_ctx); ret = npu_set_uc_power_level(npu_dev, networks_perf_mode); if (ret) { pr_err("network load failed due to power level set\n"); goto error_free_network; } load_packet->header.cmd_type = NPU_IPC_CMD_LOAD_V2; load_packet->header.size = pkt_size; load_packet->header.trans_id = Loading Loading @@ -1356,6 +1503,7 @@ int32_t npu_host_load_network_v2(struct npu_client *client, network->is_active = true; kfree(load_packet); network_put(network); mutex_unlock(&host_ctx->lock); return ret; Loading @@ -1378,7 +1526,6 @@ int32_t npu_host_unload_network(struct npu_client *client, struct ipc_cmd_unload_pkt unload_packet; struct npu_network *network; struct npu_host_ctx *host_ctx = &npu_dev->host_ctx; uint32_t networks_perf_mode; /* get the corresponding network for ipc trans id purpose */ mutex_lock(&host_ctx->lock); Loading Loading @@ -1464,11 +1611,11 @@ int32_t npu_host_unload_network(struct npu_client *client, */ network_put(network); free_network(host_ctx, client, network->id); /* recalculate uc_power_level after unload network */ networks_perf_mode = find_networks_perf_mode(host_ctx); ret = npu_set_uc_power_level(npu_dev, networks_perf_mode); if (ret) pr_err("network unload failed to set power level\n"); if (npu_dev->pwrctrl.cur_dcvs_activity) set_perf_mode(npu_dev); mutex_unlock(&host_ctx->lock); if (host_ctx->fw_unload_delay_ms) { flush_delayed_work(&host_ctx->fw_deinit_work); Loading Loading @@ -1502,7 +1649,7 @@ int32_t npu_host_exec_network(struct npu_client *client, return -EINVAL; } if (atomic_inc_return(&host_ctx->network_exeute_cnt) == 1) if (atomic_inc_return(&host_ctx->network_execute_cnt) == 1) npu_notify_cdsprm_cxlimit_activity(npu_dev, true); if (!network->is_active) { Loading Loading @@ -1609,7 +1756,7 @@ int32_t npu_host_exec_network(struct npu_client *client, host_error_hdlr(npu_dev, true); } if (atomic_dec_return(&host_ctx->network_exeute_cnt) == 0) if (atomic_dec_return(&host_ctx->network_execute_cnt) == 0) npu_notify_cdsprm_cxlimit_activity(npu_dev, false); return ret; Loading Loading @@ -1637,7 +1784,7 @@ int32_t npu_host_exec_network_v2(struct npu_client *client, return -EINVAL; } if (atomic_inc_return(&host_ctx->network_exeute_cnt) == 1) if (atomic_inc_return(&host_ctx->network_execute_cnt) == 1) npu_notify_cdsprm_cxlimit_activity(npu_dev, true); if (!network->is_active) { Loading Loading @@ -1766,7 +1913,7 @@ int32_t npu_host_exec_network_v2(struct npu_client *client, host_error_hdlr(npu_dev, true); } if (atomic_dec_return(&host_ctx->network_exeute_cnt) == 0) if (atomic_dec_return(&host_ctx->network_execute_cnt) == 0) npu_notify_cdsprm_cxlimit_activity(npu_dev, false); return ret; Loading Loading @@ -1845,3 +1992,55 @@ void npu_host_cleanup_networks(struct npu_client *client) npu_host_unmap_buf(client, &unmap_req); } } /* * set network or global perf_mode * if network_hdl is 0, set global perf_mode_override * otherwise set network perf_mode: if perf_mode is 0, * change network perf_mode to initial perf_mode from * load_network */ int32_t npu_host_set_perf_mode(struct npu_client *client, uint32_t network_hdl, uint32_t perf_mode) { int ret = 0; struct npu_device *npu_dev = client->npu_dev; struct npu_host_ctx *host_ctx = &npu_dev->host_ctx; struct npu_network *network = NULL; uint32_t networks_perf_mode; mutex_lock(&host_ctx->lock); if (network_hdl == 0) { pr_debug("change perf_mode_override to %d\n", perf_mode); npu_dev->pwrctrl.perf_mode_override = perf_mode; } else { network = get_network_by_hdl(host_ctx, client, network_hdl); if (!network) { pr_err("invalid network handle %x\n", network_hdl); mutex_unlock(&host_ctx->lock); return -EINVAL; } if (perf_mode == 0) { network->cur_perf_mode = network->init_perf_mode; pr_debug("change network %d perf_mode back to %d\n", network_hdl, network->cur_perf_mode); } else { network->cur_perf_mode = perf_mode; pr_debug("change network %d perf_mode to %d\n", network_hdl, network->cur_perf_mode); } } networks_perf_mode = find_networks_perf_mode(host_ctx); ret = npu_set_uc_power_level(npu_dev, networks_perf_mode); if (ret) pr_err("failed to set power level %d\n", networks_perf_mode); if (network) network_put(network); mutex_unlock(&host_ctx->lock); return ret; } drivers/media/platform/msm/npu/npu_mgr.h +9 −3 Original line number Diff line number Diff line Loading @@ -49,7 +49,8 @@ struct npu_network { uint32_t first_block_size; uint32_t network_hdl; uint32_t priority; uint32_t perf_mode; uint32_t cur_perf_mode; uint32_t init_perf_mode; uint32_t num_layers; void *stats_buf; void __user *stats_buf_u; Loading @@ -74,6 +75,7 @@ enum fw_state { struct npu_host_ctx { struct mutex lock; void *subsystem_handle; struct npu_device *npu_dev; enum fw_state fw_state; int32_t fw_ref_cnt; int32_t power_vote_num; Loading @@ -83,6 +85,7 @@ struct npu_host_ctx { struct workqueue_struct *wq; struct completion loopback_done; struct completion fw_deinit_done; struct completion property_set_done; int32_t network_num; struct npu_network networks[MAX_LOADED_NETWORK]; bool sys_cache_disable; Loading @@ -90,7 +93,7 @@ struct npu_host_ctx { uint32_t exec_flags_override; uint32_t fw_unload_delay_ms; atomic_t ipc_trans_id; atomic_t network_exeute_cnt; atomic_t network_execute_cnt; uint32_t err_irq_sts; uint32_t wdg_irq_sts; Loading Loading @@ -134,8 +137,11 @@ int32_t npu_host_exec_network_v2(struct npu_client *client, struct msm_npu_exec_network_ioctl_v2 *exec_ioctl, struct msm_npu_patch_buf_info *patch_buf_info); int32_t npu_host_loopback_test(struct npu_device *npu_dev); int32_t npu_host_set_fw_property(struct npu_device *npu_dev, struct msm_npu_property *property); void npu_host_cleanup_networks(struct npu_client *client); int32_t npu_host_set_perf_mode(struct npu_client *client, uint32_t network_hdl, uint32_t perf_mode); void npu_dump_debug_timeout_stats(struct npu_device *npu_dev); #endif /* _NPU_MGR_H */ Loading
drivers/media/platform/msm/npu/npu_common.h +6 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,8 @@ #define NPU_MAX_STATS_BUF_SIZE 16384 #define NPU_MAX_PATCH_NUM 160 #define DCVS_MODE_MAX 100 enum npu_power_level { NPU_PWRLEVEL_MINSVS = 0, NPU_PWRLEVEL_LOWSVS, Loading Loading @@ -154,6 +156,8 @@ struct npu_reg { * @uc_pwrlevel - power level from user driver setting * @perf_mode_override - perf mode from sysfs to override perf mode * settings from user driver * @dcvs_mode - dcvs mode from sysfs to turn on dcvs mode * settings from user driver * @devbw - bw device */ struct npu_pwrctrl { Loading @@ -172,6 +176,8 @@ struct npu_pwrctrl { uint32_t cdsprm_pwrlevel; uint32_t fmax_pwrlevel; uint32_t perf_mode_override; uint32_t dcvs_mode; uint32_t cur_dcvs_activity; }; /** Loading
drivers/media/platform/msm/npu/npu_dev.c +114 −3 Original line number Diff line number Diff line Loading @@ -68,6 +68,12 @@ static ssize_t npu_show_perf_mode_override(struct device *dev, static ssize_t npu_store_perf_mode_override(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); static ssize_t npu_show_dcvs_mode(struct device *dev, struct device_attribute *attr, char *buf); static ssize_t npu_store_dcvs_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); static ssize_t npu_show_fw_unload_delay_ms(struct device *dev, struct device_attribute *attr, char *buf); Loading Loading @@ -108,6 +114,9 @@ static int npu_exec_network_v2(struct npu_client *client, unsigned long arg); static int npu_receive_event(struct npu_client *client, unsigned long arg); static int npu_set_fw_state(struct npu_client *client, uint32_t enable); static int npu_set_property(struct npu_client *client, unsigned long arg); static long npu_ioctl(struct file *file, unsigned int cmd, unsigned long arg); static unsigned int npu_poll(struct file *filp, struct poll_table_struct *p); Loading Loading @@ -178,6 +187,8 @@ static DEVICE_ATTR(caps, 0444, npu_show_capabilities, NULL); static DEVICE_ATTR(pwr, 0644, npu_show_pwr_state, npu_store_pwr_state); static DEVICE_ATTR(perf_mode_override, 0644, npu_show_perf_mode_override, npu_store_perf_mode_override); static DEVICE_ATTR(dcvs_mode, 0644, npu_show_dcvs_mode, npu_store_dcvs_mode); static DEVICE_ATTR(fw_unload_delay_ms, 0644, npu_show_fw_unload_delay_ms, npu_store_fw_unload_delay_ms); static DEVICE_ATTR(fw_state, 0644, npu_show_fw_state, npu_store_fw_state); Loading @@ -186,6 +197,7 @@ static struct attribute *npu_fs_attrs[] = { &dev_attr_caps.attr, &dev_attr_pwr.attr, &dev_attr_perf_mode_override.attr, &dev_attr_dcvs_mode.attr, &dev_attr_fw_state.attr, &dev_attr_fw_unload_delay_ms.attr, NULL Loading Loading @@ -289,7 +301,7 @@ static ssize_t npu_store_pwr_state(struct device *dev, } /* ------------------------------------------------------------------------- * SysFS - Power State * SysFS - perf_mode_override * ------------------------------------------------------------------------- */ static ssize_t npu_show_perf_mode_override(struct device *dev, Loading Loading @@ -324,6 +336,50 @@ static ssize_t npu_store_perf_mode_override(struct device *dev, return count; } static ssize_t npu_show_dcvs_mode(struct device *dev, struct device_attribute *attr, char *buf) { struct npu_device *npu_dev = dev_get_drvdata(dev); struct npu_pwrctrl *pwr = &npu_dev->pwrctrl; return scnprintf(buf, PAGE_SIZE, "%d\n", pwr->dcvs_mode); } static ssize_t npu_store_dcvs_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct npu_device *npu_dev = dev_get_drvdata(dev); struct msm_npu_property prop; uint32_t val; int ret = 0; ret = kstrtou32(buf, 10, &val); if (ret) { pr_err("Invalid input for dcvs mode setting\n"); return -EINVAL; } val = min(val, (uint32_t)DCVS_MODE_MAX); pr_debug("sysfs: setting dcvs_mode to %d\n", val); prop.prop_id = MSM_NPU_PROP_ID_DCVS_MODE; prop.num_of_params = 1; prop.network_hdl = 0; prop.prop_param[0] = val; ret = npu_host_set_fw_property(npu_dev, &prop); if (ret) { pr_err("npu_host_set_fw_property failed %d\n", ret); return ret; } npu_dev->pwrctrl.dcvs_mode = val; return count; } /* ------------------------------------------------------------------------- * SysFS - Delayed FW unload * ------------------------------------------------------------------------- Loading Loading @@ -582,6 +638,7 @@ int npu_enable_core_power(struct npu_device *npu_dev) pwr->pwr_vote_num = 0; return ret; } pwr->cur_dcvs_activity = DCVS_MODE_MAX; npu_resume_devbw(npu_dev); } pwr->pwr_vote_num++; Loading @@ -593,7 +650,6 @@ int npu_enable_core_power(struct npu_device *npu_dev) void npu_disable_core_power(struct npu_device *npu_dev) { struct npu_pwrctrl *pwr = &npu_dev->pwrctrl; struct npu_thermalctrl *thermalctrl = &npu_dev->thermalctrl; mutex_lock(&npu_dev->dev_lock); if (!pwr->pwr_vote_num) { Loading @@ -606,9 +662,10 @@ void npu_disable_core_power(struct npu_device *npu_dev) npu_suspend_devbw(npu_dev); npu_disable_core_clocks(npu_dev); npu_disable_regulators(npu_dev); pwr->active_pwrlevel = thermalctrl->pwr_level; pwr->active_pwrlevel = pwr->default_pwrlevel; pwr->uc_pwrlevel = pwr->max_pwrlevel; pwr->cdsprm_pwrlevel = pwr->max_pwrlevel; pwr->cur_dcvs_activity = 0; pr_debug("setting back to power level=%d\n", pwr->active_pwrlevel); } Loading Loading @@ -1563,6 +1620,57 @@ static int npu_receive_event(struct npu_client *client, return ret; } static int npu_set_fw_state(struct npu_client *client, uint32_t enable) { struct npu_device *npu_dev = client->npu_dev; int rc = 0; if (enable) { pr_debug("%s: enable fw\n", __func__); rc = fw_init(npu_dev); if (rc) pr_err("enable fw failed\n"); } else { pr_debug("%s: disable fw\n", __func__); fw_deinit(npu_dev, false, true); } return rc; } static int npu_set_property(struct npu_client *client, unsigned long arg) { struct msm_npu_property prop; void __user *argp = (void __user *)arg; int ret = -EINVAL; ret = copy_from_user(&prop, argp, sizeof(prop)); if (ret) { pr_err("fail to copy from user\n"); return -EFAULT; } switch (prop.prop_id) { case MSM_NPU_PROP_ID_FW_STATE: ret = npu_set_fw_state(client, (uint32_t)prop.prop_param[0]); break; case MSM_NPU_PROP_ID_PERF_MODE: ret = npu_host_set_perf_mode(client, (uint32_t)prop.network_hdl, (uint32_t)prop.prop_param[0]); break; default: ret = npu_host_set_fw_property(client->npu_dev, &prop); if (ret) pr_err("npu_host_set_fw_property failed\n"); break; } return ret; } static long npu_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { Loading Loading @@ -1597,6 +1705,9 @@ static long npu_ioctl(struct file *file, unsigned int cmd, case MSM_NPU_RECEIVE_EVENT: ret = npu_receive_event(client, arg); break; case MSM_NPU_SET_PROP: ret = npu_set_property(client, arg); break; default: pr_err("unexpected IOCTL %x\n", cmd); } Loading
drivers/media/platform/msm/npu/npu_host_ipc.h +42 −1 Original line number Diff line number Diff line /* Copyright (c) 2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -38,6 +38,8 @@ #define NPU_IPC_CMD_LOAD_V2 0x00000009 /* ipc_cmd_execute_packet_v2 */ #define NPU_IPC_CMD_EXECUTE_V2 0x0000000A /* ipc_cmd_set_property_packet */ #define NPU_IPC_CMD_SET_PROPERTY 0x0000000B /* Messages sent **from** NPU */ /* IPC Message Response -- uint32_t */ Loading @@ -55,6 +57,10 @@ #define NPU_IPC_MSG_LOOPBACK_DONE 0x00010005 /* ipc_msg_execute_pkt_v2 */ #define NPU_IPC_MSG_EXECUTE_V2_DONE 0x00010006 /* ipc_msg_set_property_packet */ #define NPU_IPC_MSG_SET_PROPERTY_DONE 0x00010007 /* ipc_msg_set_power_mode */ #define NPU_IPC_MSG_DCVS_NOTIFY 0x00010010 /* Logging message size */ /* Number 32-bit elements for the maximum log message size */ Loading Loading @@ -103,6 +109,11 @@ /* Debug stats */ #define NUM_LAYER_STATS_PER_EXE_MSG_MAX 110 enum npu_fw_property_id { NPU_FW_PROP_ID_DCVS_MODE = 0, NPU_FW_PROP_ID_INVALID = 0xFFFFFFFF, }; /* ------------------------------------------------------------------------- * Data Structures * ------------------------------------------------------------------------- Loading Loading @@ -271,6 +282,27 @@ struct ipc_cmd_loopback_pkt { uint32_t loopbackParams; }; /* * Set property packet definition */ struct ipc_cmd_set_prop_pkt { struct ipc_cmd_header_pkt header; uint32_t prop_id; uint32_t num_params; uint32_t network_hdl; uint32_t prop_param[0]; }; /* * Set property response packet definition */ struct ipc_msg_set_prop_pkt { struct ipc_msg_header_pkt header; uint32_t prop_id; uint32_t network_hdl; uint32_t prop_value; }; /* * LOAD response packet definition */ Loading Loading @@ -417,4 +449,13 @@ struct ipc_cmd_shutdown_pkt { uint32_t shutdown_flags; }; /* * Notify driver to set power mode (a value from 0 to 100) */ struct ipc_msg_set_dcvs_mode { struct ipc_msg_header_pkt header; /* activity level from 0-100 */ uint32_t activity; }; #endif /* NPU_HOST_IPC_H */
drivers/media/platform/msm/npu/npu_mgr.c +234 −35 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ static int npu_send_misc_cmd(struct npu_device *npu_dev, uint32_t q_idx, static int npu_queue_event(struct npu_client *client, struct npu_kevent *evt); static int npu_notify_dsp(struct npu_device *npu_dev, bool pwr_up); static int npu_notify_aop(struct npu_device *npu_dev, bool on); static int update_dcvs_activity(struct npu_device *npu_dev, uint32_t activity); static void npu_destroy_wq(struct npu_host_ctx *host_ctx); static struct workqueue_struct *npu_create_wq(struct npu_host_ctx *host_ctx, const char *name); Loading Loading @@ -299,8 +300,10 @@ int npu_host_init(struct npu_device *npu_dev) memset(host_ctx, 0, sizeof(*host_ctx)); init_completion(&host_ctx->loopback_done); init_completion(&host_ctx->fw_deinit_done); init_completion(&host_ctx->property_set_done); mutex_init(&host_ctx->lock); atomic_set(&host_ctx->ipc_trans_id, 1); host_ctx->npu_dev = npu_dev; host_ctx->wq = npu_create_wq(host_ctx, "npu_wq"); if (!host_ctx->wq) Loading Loading @@ -701,6 +704,7 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg) uint32_t msg_id; struct npu_network *network = NULL; struct npu_kevent kevt; struct npu_device *npu_dev = host_ctx->npu_dev; msg_id = msg[1]; switch (msg_id) { Loading Loading @@ -908,6 +912,29 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg) complete_all(&host_ctx->loopback_done); break; } case NPU_IPC_MSG_SET_PROPERTY_DONE: { struct ipc_msg_set_prop_pkt *set_prop_rsp_pkt = (struct ipc_msg_set_prop_pkt *)msg; pr_debug("NPU_IPC_MSG_SET_PROPERTY_DONE %d:0x%x:%d\n", set_prop_rsp_pkt->network_hdl, set_prop_rsp_pkt->prop_id, set_prop_rsp_pkt->prop_value); complete_all(&host_ctx->property_set_done); break; } case NPU_IPC_MSG_DCVS_NOTIFY: { struct ipc_msg_set_dcvs_mode *set_dcvs_pkt = (struct ipc_msg_set_dcvs_mode *)msg; pr_debug("NPU_IPC_MSG_DCVS_NOTIFY %d\n", set_dcvs_pkt->activity); update_dcvs_activity(npu_dev, set_dcvs_pkt->activity); break; } default: pr_err("Not supported apps response received %d\n", msg_id); Loading Loading @@ -1125,18 +1152,153 @@ static uint32_t find_networks_perf_mode(struct npu_host_ctx *host_ctx) network = host_ctx->networks; if (!host_ctx->network_num) { /* if no network exists, set to the lowest level */ max_perf_mode = 1; } else { /* find the max level among all the networks */ for (i = 0; i < host_ctx->network_num; i++) { if ((network->perf_mode != 0) && (network->perf_mode > max_perf_mode)) max_perf_mode = network->perf_mode; if ((network->cur_perf_mode != 0) && (network->cur_perf_mode > max_perf_mode)) max_perf_mode = network->cur_perf_mode; network++; } } pr_debug("max perf mode for networks: %d\n", max_perf_mode); return max_perf_mode; } static int set_perf_mode(struct npu_device *npu_dev) { int ret = 0; uint32_t networks_perf_mode; struct npu_host_ctx *host_ctx = &npu_dev->host_ctx; networks_perf_mode = find_networks_perf_mode(host_ctx); ret = npu_set_uc_power_level(npu_dev, networks_perf_mode); if (ret) pr_err("network load failed due to power level set\n"); return ret; } static int update_dcvs_activity(struct npu_device *npu_dev, uint32_t activity) { int ret = 0; npu_dev->pwrctrl.cur_dcvs_activity = activity; if (activity > 0) { pr_debug("Set clocks back to default setting - exit dcvs mode\n"); ret = set_perf_mode(npu_dev); } else { pr_debug("Set clocks to low - enter dcvs mode\n"); ret = npu_set_uc_power_level(npu_dev, 1); } return ret; } static enum npu_fw_property_id npu_host_to_fw_prop_id(uint32_t prop) { uint32_t fw_prop_id = NPU_FW_PROP_ID_INVALID; switch (prop) { case MSM_NPU_PROP_ID_DCVS_MODE: fw_prop_id = NPU_FW_PROP_ID_DCVS_MODE; break; default: pr_err("Invalid host property id %x\n", prop); break; } return fw_prop_id; } int32_t npu_host_set_fw_property(struct npu_device *npu_dev, struct msm_npu_property *property) { int ret = 0, i; uint32_t prop_param, prop_id; struct ipc_cmd_set_prop_pkt *prop_packet = NULL; struct npu_host_ctx *host_ctx = &npu_dev->host_ctx; uint32_t num_of_params, pkt_size; prop_id = npu_host_to_fw_prop_id(property->prop_id); if (prop_id == NPU_FW_PROP_ID_INVALID) return -EINVAL; num_of_params = min_t(uint32_t, property->num_of_params, (uint32_t)PROP_PARAM_MAX_SIZE); pkt_size = sizeof(*prop_packet) + num_of_params * sizeof(uint32_t); prop_packet = kzalloc(pkt_size, GFP_KERNEL); if (!prop_packet) return -ENOMEM; switch (prop_id) { case NPU_FW_PROP_ID_DCVS_MODE: prop_param = min_t(uint32_t, property->prop_param[0], (uint32_t)DCVS_MODE_MAX); property->prop_param[0] = prop_param; pr_debug("setting dcvs_mode to %d\n", prop_param); if (property->network_hdl == 0) { npu_dev->pwrctrl.dcvs_mode = prop_param; pr_debug("Set global dcvs mode %d\n", prop_param); } break; default: pr_err("unsupported property received %d\n", property->prop_id); goto set_prop_exit; } prop_packet->header.cmd_type = NPU_IPC_CMD_SET_PROPERTY; prop_packet->header.size = pkt_size; prop_packet->header.trans_id = atomic_add_return(1, &host_ctx->ipc_trans_id); prop_packet->header.flags = 0; prop_packet->prop_id = prop_id; prop_packet->num_params = num_of_params; prop_packet->network_hdl = property->network_hdl; for (i = 0; i < num_of_params; i++) prop_packet->prop_param[i] = property->prop_param[i]; reinit_completion(&host_ctx->property_set_done); ret = npu_send_misc_cmd(npu_dev, IPC_QUEUE_APPS_EXEC, prop_packet); pr_debug("NPU_IPC_CMD_SET_PROPERTY sent status: %d\n", ret); if (ret) { pr_err("NPU_IPC_CMD_SET_PROPERTY failed\n"); goto set_prop_exit; } ret = wait_for_completion_interruptible_timeout( &host_ctx->property_set_done, (host_ctx->fw_dbg_mode & FW_DBG_MODE_INC_TIMEOUT) ? NW_DEBUG_TIMEOUT : NW_CMD_TIMEOUT); if (!ret) { pr_err_ratelimited("npu: NPU_IPC_CMD_SET_PROPERTY time out\n"); ret = -ETIMEDOUT; goto set_prop_exit; } else if (ret < 0) { pr_err("Wait for set_property done interrupted by signal\n"); goto set_prop_exit; } else if (ret > 0) { ret = 0; } set_prop_exit: kfree(prop_packet); return ret; } int32_t npu_host_load_network(struct npu_client *client, struct msm_npu_load_network_ioctl *load_ioctl) { Loading @@ -1145,7 +1307,6 @@ int32_t npu_host_load_network(struct npu_client *client, struct npu_network *network; struct ipc_cmd_load_pkt load_packet; struct npu_host_ctx *host_ctx = &npu_dev->host_ctx; uint32_t networks_perf_mode = 0; ret = fw_init(npu_dev); if (ret) Loading @@ -1164,7 +1325,8 @@ int32_t npu_host_load_network(struct npu_client *client, network->phy_add = load_ioctl->buf_phys_addr; network->first_block_size = load_ioctl->first_block_size; network->priority = load_ioctl->priority; network->perf_mode = load_ioctl->perf_mode; network->cur_perf_mode = network->init_perf_mode = load_ioctl->perf_mode; /* verify mapped physical address */ if (!npu_mem_verify_addr(client, network->phy_add)) { Loading @@ -1172,14 +1334,6 @@ int32_t npu_host_load_network(struct npu_client *client, goto error_free_network; } networks_perf_mode = find_networks_perf_mode(host_ctx); ret = npu_set_uc_power_level(npu_dev, networks_perf_mode); if (ret) { pr_err("network load failed due to power level set\n"); goto error_free_network; } load_packet.header.cmd_type = NPU_IPC_CMD_LOAD; load_packet.header.size = sizeof(struct ipc_cmd_load_pkt); load_packet.header.trans_id = Loading Loading @@ -1229,6 +1383,7 @@ int32_t npu_host_load_network(struct npu_client *client, load_ioctl->network_hdl = network->network_hdl; network->is_active = true; network_put(network); mutex_unlock(&host_ctx->lock); return ret; Loading @@ -1251,7 +1406,6 @@ int32_t npu_host_load_network_v2(struct npu_client *client, struct npu_network *network; struct ipc_cmd_load_pkt_v2 *load_packet = NULL; struct npu_host_ctx *host_ctx = &npu_dev->host_ctx; uint32_t networks_perf_mode = 0; uint32_t num_patch_params, pkt_size; ret = fw_init(npu_dev); Loading Loading @@ -1285,7 +1439,8 @@ int32_t npu_host_load_network_v2(struct npu_client *client, network->phy_add = load_ioctl->buf_phys_addr; network->first_block_size = load_ioctl->first_block_size; network->priority = load_ioctl->priority; network->perf_mode = load_ioctl->perf_mode; network->cur_perf_mode = network->init_perf_mode = load_ioctl->perf_mode; network->num_layers = load_ioctl->num_layers; /* verify mapped physical address */ Loading @@ -1295,14 +1450,6 @@ int32_t npu_host_load_network_v2(struct npu_client *client, goto error_free_network; } networks_perf_mode = find_networks_perf_mode(host_ctx); ret = npu_set_uc_power_level(npu_dev, networks_perf_mode); if (ret) { pr_err("network load failed due to power level set\n"); goto error_free_network; } load_packet->header.cmd_type = NPU_IPC_CMD_LOAD_V2; load_packet->header.size = pkt_size; load_packet->header.trans_id = Loading Loading @@ -1356,6 +1503,7 @@ int32_t npu_host_load_network_v2(struct npu_client *client, network->is_active = true; kfree(load_packet); network_put(network); mutex_unlock(&host_ctx->lock); return ret; Loading @@ -1378,7 +1526,6 @@ int32_t npu_host_unload_network(struct npu_client *client, struct ipc_cmd_unload_pkt unload_packet; struct npu_network *network; struct npu_host_ctx *host_ctx = &npu_dev->host_ctx; uint32_t networks_perf_mode; /* get the corresponding network for ipc trans id purpose */ mutex_lock(&host_ctx->lock); Loading Loading @@ -1464,11 +1611,11 @@ int32_t npu_host_unload_network(struct npu_client *client, */ network_put(network); free_network(host_ctx, client, network->id); /* recalculate uc_power_level after unload network */ networks_perf_mode = find_networks_perf_mode(host_ctx); ret = npu_set_uc_power_level(npu_dev, networks_perf_mode); if (ret) pr_err("network unload failed to set power level\n"); if (npu_dev->pwrctrl.cur_dcvs_activity) set_perf_mode(npu_dev); mutex_unlock(&host_ctx->lock); if (host_ctx->fw_unload_delay_ms) { flush_delayed_work(&host_ctx->fw_deinit_work); Loading Loading @@ -1502,7 +1649,7 @@ int32_t npu_host_exec_network(struct npu_client *client, return -EINVAL; } if (atomic_inc_return(&host_ctx->network_exeute_cnt) == 1) if (atomic_inc_return(&host_ctx->network_execute_cnt) == 1) npu_notify_cdsprm_cxlimit_activity(npu_dev, true); if (!network->is_active) { Loading Loading @@ -1609,7 +1756,7 @@ int32_t npu_host_exec_network(struct npu_client *client, host_error_hdlr(npu_dev, true); } if (atomic_dec_return(&host_ctx->network_exeute_cnt) == 0) if (atomic_dec_return(&host_ctx->network_execute_cnt) == 0) npu_notify_cdsprm_cxlimit_activity(npu_dev, false); return ret; Loading Loading @@ -1637,7 +1784,7 @@ int32_t npu_host_exec_network_v2(struct npu_client *client, return -EINVAL; } if (atomic_inc_return(&host_ctx->network_exeute_cnt) == 1) if (atomic_inc_return(&host_ctx->network_execute_cnt) == 1) npu_notify_cdsprm_cxlimit_activity(npu_dev, true); if (!network->is_active) { Loading Loading @@ -1766,7 +1913,7 @@ int32_t npu_host_exec_network_v2(struct npu_client *client, host_error_hdlr(npu_dev, true); } if (atomic_dec_return(&host_ctx->network_exeute_cnt) == 0) if (atomic_dec_return(&host_ctx->network_execute_cnt) == 0) npu_notify_cdsprm_cxlimit_activity(npu_dev, false); return ret; Loading Loading @@ -1845,3 +1992,55 @@ void npu_host_cleanup_networks(struct npu_client *client) npu_host_unmap_buf(client, &unmap_req); } } /* * set network or global perf_mode * if network_hdl is 0, set global perf_mode_override * otherwise set network perf_mode: if perf_mode is 0, * change network perf_mode to initial perf_mode from * load_network */ int32_t npu_host_set_perf_mode(struct npu_client *client, uint32_t network_hdl, uint32_t perf_mode) { int ret = 0; struct npu_device *npu_dev = client->npu_dev; struct npu_host_ctx *host_ctx = &npu_dev->host_ctx; struct npu_network *network = NULL; uint32_t networks_perf_mode; mutex_lock(&host_ctx->lock); if (network_hdl == 0) { pr_debug("change perf_mode_override to %d\n", perf_mode); npu_dev->pwrctrl.perf_mode_override = perf_mode; } else { network = get_network_by_hdl(host_ctx, client, network_hdl); if (!network) { pr_err("invalid network handle %x\n", network_hdl); mutex_unlock(&host_ctx->lock); return -EINVAL; } if (perf_mode == 0) { network->cur_perf_mode = network->init_perf_mode; pr_debug("change network %d perf_mode back to %d\n", network_hdl, network->cur_perf_mode); } else { network->cur_perf_mode = perf_mode; pr_debug("change network %d perf_mode to %d\n", network_hdl, network->cur_perf_mode); } } networks_perf_mode = find_networks_perf_mode(host_ctx); ret = npu_set_uc_power_level(npu_dev, networks_perf_mode); if (ret) pr_err("failed to set power level %d\n", networks_perf_mode); if (network) network_put(network); mutex_unlock(&host_ctx->lock); return ret; }
drivers/media/platform/msm/npu/npu_mgr.h +9 −3 Original line number Diff line number Diff line Loading @@ -49,7 +49,8 @@ struct npu_network { uint32_t first_block_size; uint32_t network_hdl; uint32_t priority; uint32_t perf_mode; uint32_t cur_perf_mode; uint32_t init_perf_mode; uint32_t num_layers; void *stats_buf; void __user *stats_buf_u; Loading @@ -74,6 +75,7 @@ enum fw_state { struct npu_host_ctx { struct mutex lock; void *subsystem_handle; struct npu_device *npu_dev; enum fw_state fw_state; int32_t fw_ref_cnt; int32_t power_vote_num; Loading @@ -83,6 +85,7 @@ struct npu_host_ctx { struct workqueue_struct *wq; struct completion loopback_done; struct completion fw_deinit_done; struct completion property_set_done; int32_t network_num; struct npu_network networks[MAX_LOADED_NETWORK]; bool sys_cache_disable; Loading @@ -90,7 +93,7 @@ struct npu_host_ctx { uint32_t exec_flags_override; uint32_t fw_unload_delay_ms; atomic_t ipc_trans_id; atomic_t network_exeute_cnt; atomic_t network_execute_cnt; uint32_t err_irq_sts; uint32_t wdg_irq_sts; Loading Loading @@ -134,8 +137,11 @@ int32_t npu_host_exec_network_v2(struct npu_client *client, struct msm_npu_exec_network_ioctl_v2 *exec_ioctl, struct msm_npu_patch_buf_info *patch_buf_info); int32_t npu_host_loopback_test(struct npu_device *npu_dev); int32_t npu_host_set_fw_property(struct npu_device *npu_dev, struct msm_npu_property *property); void npu_host_cleanup_networks(struct npu_client *client); int32_t npu_host_set_perf_mode(struct npu_client *client, uint32_t network_hdl, uint32_t perf_mode); void npu_dump_debug_timeout_stats(struct npu_device *npu_dev); #endif /* _NPU_MGR_H */