/** * msm_bus_scale_unregister_client() - Unregister the client from the bus driver * @cl: Handle to the client */ void msm_bus_scale_unregister_client(uint32_t cl) { int i; struct msm_bus_client *client = (struct msm_bus_client *)(cl); bool warn = false; if (IS_ERR_OR_NULL(client)) return; for (i = 0; i < client->pdata->usecase->num_paths; i++) { if ((client->pdata->usecase[0].vectors[i].ab) || (client->pdata->usecase[0].vectors[i].ib)) { warn = true; break; } } if (warn) { int num_paths = client->pdata->usecase->num_paths; int ab[num_paths], ib[num_paths]; WARN(1, "%s called unregister with non-zero vectors\n", client->pdata->name); /* * Save client values and zero them out to * cleanly unregister */ for (i = 0; i < num_paths; i++) { ab[i] = client->pdata->usecase[0].vectors[i].ab; ib[i] = client->pdata->usecase[0].vectors[i].ib; client->pdata->usecase[0].vectors[i].ab = 0; client->pdata->usecase[0].vectors[i].ib = 0; } msm_bus_scale_client_update_request(cl, 0); /* Restore client vectors if required for re-registering. */ for (i = 0; i < num_paths; i++) { client->pdata->usecase[0].vectors[i].ab = ab[i]; client->pdata->usecase[0].vectors[i].ib = ib[i]; } } else if (client->curr != 0) msm_bus_scale_client_update_request(cl, 0); MSM_BUS_DBG("Unregistering client %d\n", cl); #ifdef SEC_FEATURE_USE_RT_MUTEX rt_mutex_lock(&msm_bus_lock); #else mutex_lock(&msm_bus_lock); #endif msm_bus_scale_client_reset_pnodes(cl); msm_bus_dbg_client_data(client->pdata, MSM_BUS_DBG_UNREGISTER, cl); #ifdef SEC_FEATURE_USE_RT_MUTEX rt_mutex_unlock(&msm_bus_lock); #else mutex_unlock(&msm_bus_lock); #endif kfree(client->src_pnode); kfree(client); }
/** * msm_bus_scale_unregister_client() - Unregister the client from the bus driver * @cl: Handle to the client */ void msm_bus_scale_unregister_client(uint32_t cl) { struct msm_bus_client *client = (struct msm_bus_client *)(cl); if (IS_ERR(client) || (!client)) return; if (client->curr != 0) msm_bus_scale_client_update_request(cl, 0); MSM_BUS_DBG("Unregistering client %d\n", cl); mutex_lock(&msm_bus_lock); msm_bus_scale_client_reset_pnodes(cl); msm_bus_dbg_client_data(client->pdata, MSM_BUS_DBG_UNREGISTER, cl); mutex_unlock(&msm_bus_lock); kfree(client->src_pnode); kfree(client); }
/** * msm_bus_scale_client_update_request() - Update the request for bandwidth * from a particular client * * cl: Handle to the client * index: Index into the vector, to which the bw and clock values need to be * updated */ int msm_bus_scale_client_update_request(uint32_t cl, unsigned index) { int i, ret = 0; struct msm_bus_scale_pdata *pdata; int pnode, src, curr, ctx; unsigned long req_clk, req_bw, curr_clk, curr_bw; struct msm_bus_client *client = (struct msm_bus_client *)cl; if (IS_ERR_OR_NULL(client)) { MSM_BUS_ERR("msm_bus_scale_client update req error %d\n", (uint32_t)client); return -ENXIO; } mutex_lock(&msm_bus_lock); if (client->curr == index) goto err; curr = client->curr; pdata = client->pdata; //tcd add start if (!pdata) { MSM_BUS_ERR("Null pdata passed to update-request\n"); return -ENXIO; } //tcd end if (index >= pdata->num_usecases) { MSM_BUS_ERR("Client %u passed invalid index: %d\n", (uint32_t)client, index); ret = -ENXIO; goto err; } MSM_BUS_DBG("cl: %u index: %d curr: %d" " num_paths: %d\n", cl, index, client->curr, client->pdata->usecase->num_paths); for (i = 0; i < pdata->usecase->num_paths; i++) { src = msm_bus_board_get_iid(client->pdata->usecase[index]. vectors[i].src); if (src == -ENXIO) { MSM_BUS_ERR("Master %d not supported. Request cannot" " be updated\n", client->pdata->usecase-> vectors[i].src); goto err; } if (msm_bus_board_get_iid(client->pdata->usecase[index]. vectors[i].dst) == -ENXIO) { MSM_BUS_ERR("Slave %d not supported. Request cannot" " be updated\n", client->pdata->usecase-> vectors[i].dst); } pnode = client->src_pnode[i]; req_clk = client->pdata->usecase[index].vectors[i].ib; req_bw = client->pdata->usecase[index].vectors[i].ab; if (curr < 0) { curr_clk = 0; curr_bw = 0; } else { curr_clk = client->pdata->usecase[curr].vectors[i].ib; curr_bw = client->pdata->usecase[curr].vectors[i].ab; MSM_BUS_DBG("ab: %lu ib: %lu\n", curr_bw, curr_clk); } //tcd add start if (index == 0) { /* This check protects the bus driver from clients * that can leave non-zero requests after * unregistering. */ req_clk = 0; req_bw = 0; } //tcd end if (!pdata->active_only) { ret = update_path(src, pnode, req_clk, req_bw, curr_clk, curr_bw, 0, pdata->active_only); if (ret) { MSM_BUS_ERR("Update path failed! %d\n", ret); goto err; } } ret = update_path(src, pnode, req_clk, req_bw, curr_clk, curr_bw, ACTIVE_CTX, pdata->active_only); if (ret) { MSM_BUS_ERR("Update Path failed! %d\n", ret); goto err; } } client->curr = index; ctx = ACTIVE_CTX; msm_bus_dbg_client_data(client->pdata, index, cl); bus_for_each_dev(&msm_bus_type, NULL, NULL, msm_bus_commit_fn); err: mutex_unlock(&msm_bus_lock); return ret; }
/** * msm_bus_scale_register_client() - Register the clients with the msm bus * driver * @pdata: Platform data of the client, containing src, dest, ab, ib * * Client data contains the vectors specifying arbitrated bandwidth (ab) * and instantaneous bandwidth (ib) requested between a particular * src and dest. */ uint32_t msm_bus_scale_register_client(struct msm_bus_scale_pdata *pdata) { struct msm_bus_client *client = NULL; int i; int src, dest, nfab; struct msm_bus_fabric_device *deffab; deffab = msm_bus_get_fabric_device(MSM_BUS_FAB_DEFAULT); if (!deffab) { MSM_BUS_ERR("Error finding default fabric\n"); return -ENXIO; } nfab = msm_bus_get_num_fab(); if (nfab < deffab->board_algo->board_nfab) { MSM_BUS_ERR("Can't register client!\n" "Num of fabrics up: %d\n", nfab); return 0; } if ((!pdata) || (pdata->usecase->num_paths == 0) || IS_ERR(pdata)) { MSM_BUS_ERR("Cannot register client with null data\n"); return 0; } client = kzalloc(sizeof(struct msm_bus_client), GFP_KERNEL); if (!client) { MSM_BUS_ERR("Error allocating client\n"); return 0; } mutex_lock(&msm_bus_lock); client->pdata = pdata; client->curr = -1; for (i = 0; i < pdata->usecase->num_paths; i++) { int *pnode; struct msm_bus_fabric_device *srcfab; pnode = krealloc(client->src_pnode, ((i + 1) * sizeof(int)), GFP_KERNEL); if (ZERO_OR_NULL_PTR(pnode)) { MSM_BUS_ERR("Invalid Pnode ptr!\n"); continue; } else client->src_pnode = pnode; if (!IS_MASTER_VALID(pdata->usecase->vectors[i].src)) { MSM_BUS_ERR("Invalid Master ID %d in request!\n", pdata->usecase->vectors[i].src); goto err; } if (!IS_SLAVE_VALID(pdata->usecase->vectors[i].dst)) { MSM_BUS_ERR("Invalid Slave ID %d in request!\n", pdata->usecase->vectors[i].dst); goto err; } src = msm_bus_board_get_iid(pdata->usecase->vectors[i].src); if (src == -ENXIO) { MSM_BUS_ERR("Master %d not supported. Client cannot be" " registered\n", pdata->usecase->vectors[i].src); goto err; } dest = msm_bus_board_get_iid(pdata->usecase->vectors[i].dst); if (dest == -ENXIO) { MSM_BUS_ERR("Slave %d not supported. Client cannot be" " registered\n", pdata->usecase->vectors[i].dst); goto err; } srcfab = msm_bus_get_fabric_device(GET_FABID(src)); srcfab->visited = true; pnode[i] = getpath(src, dest); bus_for_each_dev(&msm_bus_type, NULL, NULL, clearvisitedflag); if (pnode[i] == -ENXIO) { MSM_BUS_ERR("Cannot register client now! Try again!\n"); goto err; } } msm_bus_dbg_client_data(client->pdata, MSM_BUS_DBG_REGISTER, (uint32_t)client); mutex_unlock(&msm_bus_lock); MSM_BUS_DBG("ret: %u num_paths: %d\n", (uint32_t)client, pdata->usecase->num_paths); return (uint32_t)(client); err: kfree(client->src_pnode); kfree(client); mutex_unlock(&msm_bus_lock); return 0; }
/** * msm_bus_scale_client_update_request() - Update the request for bandwidth * from a particular client * * cl: Handle to the client * index: Index into the vector, to which the bw and clock values need to be * updated */ int msm_bus_scale_client_update_request(uint32_t cl, unsigned index) { int i, ret = 0; struct msm_bus_scale_pdata *pdata; int pnode, src, curr, ctx; unsigned long req_clk, req_bw, curr_clk, curr_bw; struct msm_bus_client *client = (struct msm_bus_client *)cl; if (IS_ERR(client)) { MSM_BUS_ERR("msm_bus_scale_client update req error %d\n", (uint32_t)client); ret = -ENXIO; goto err; } mutex_lock(&msm_bus_lock); if (client->curr == index) goto err; curr = client->curr; pdata = client->pdata; if ((index < 0) || (index >= pdata->num_usecases)) { MSM_BUS_ERR("Client %u passed invalid index: %d\n", (uint32_t)client, index); ret = -ENXIO; goto err; } MSM_BUS_DBG("cl: %u index: %d curr: %d" " num_paths: %d\n", cl, index, client->curr, client->pdata->usecase->num_paths); for (i = 0; i < pdata->usecase->num_paths; i++) { src = msm_bus_board_get_iid(client->pdata->usecase[index]. vectors[i].src); pnode = client->src_pnode[i]; req_clk = client->pdata->usecase[index].vectors[i].ib; req_bw = client->pdata->usecase[index].vectors[i].ab; if (curr < 0) { curr_clk = 0; curr_bw = 0; } else { curr_clk = client->pdata->usecase[curr].vectors[i].ib; curr_bw = client->pdata->usecase[curr].vectors[i].ab; MSM_BUS_DBG("ab: %lu ib: %lu\n", curr_bw, curr_clk); } if (!pdata->active_only) { ret = update_path(src, pnode, req_clk, req_bw, curr_clk, curr_bw, 0, pdata->active_only); if (ret) { MSM_BUS_ERR("Update path failed! %d\n", ret); goto err; } } ret = update_path(src, pnode, req_clk, req_bw, curr_clk, curr_bw, ACTIVE_CTX, pdata->active_only); if (ret) { MSM_BUS_ERR("Update Path failed! %d\n", ret); goto err; } } client->curr = index; ctx = ACTIVE_CTX; msm_bus_dbg_client_data(client->pdata, index, cl); bus_for_each_dev(&msm_bus_type, NULL, (void *)ctx, msm_bus_commit_fn); err: mutex_unlock(&msm_bus_lock); return ret; }
/** * msm_bus_scale_client_update_request() - Update the request for bandwidth * from a particular client * * cl: Handle to the client * index: Index into the vector, to which the bw and clock values need to be * updated */ int msm_bus_scale_client_update_request(uint32_t cl, unsigned index) { int i, ret = 0; struct msm_bus_scale_pdata *pdata; int pnode, src, curr, ctx; uint64_t req_clk, req_bw, curr_clk, curr_bw; struct msm_bus_client *client = (struct msm_bus_client *)cl; #ifdef DEBUG_MSM_BUS_ARB_REQ static int log_cnt = 0; #endif if (IS_ERR_OR_NULL(client)) { MSM_BUS_ERR("msm_bus_scale_client update req error %d\n", (uint32_t)client); return -ENXIO; } #ifdef SEC_FEATURE_USE_RT_MUTEX rt_mutex_lock(&msm_bus_lock); #else mutex_lock(&msm_bus_lock); #endif if (client->curr == index) goto err; curr = client->curr; pdata = client->pdata; if (!pdata) { MSM_BUS_ERR("Null pdata passed to update-request\n"); return -ENXIO; } if (index >= pdata->num_usecases) { MSM_BUS_ERR("Client %u passed invalid index: %d\n", (uint32_t)client, index); ret = -ENXIO; goto err; } MSM_BUS_DBG("cl: %u index: %d curr: %d num_paths: %d\n", cl, index, client->curr, client->pdata->usecase->num_paths); for (i = 0; i < pdata->usecase->num_paths; i++) { src = msm_bus_board_get_iid(client->pdata->usecase[index]. vectors[i].src); if (src == -ENXIO) { MSM_BUS_ERR("Master %d not supported. Request cannot" " be updated\n", client->pdata->usecase-> vectors[i].src); goto err; } if (msm_bus_board_get_iid(client->pdata->usecase[index]. vectors[i].dst) == -ENXIO) { MSM_BUS_ERR("Slave %d not supported. Request cannot" " be updated\n", client->pdata->usecase-> vectors[i].dst); } pnode = client->src_pnode[i]; req_clk = client->pdata->usecase[index].vectors[i].ib; req_bw = client->pdata->usecase[index].vectors[i].ab; #ifdef DEBUG_MSM_BUS_ARB_REQ //Debug code to collect client info { struct msm_bus_fabric_device *fabdev_d = msm_bus_get_fabric_device(GET_FABID(src)); if (MSM_BUS_FAB_APPSS == fabdev_d->id) { if (log_cnt >= 1000) log_cnt = 0; log_req[log_cnt].ab = client->pdata->usecase[index].vectors[i].ab; log_req[log_cnt].ib = client->pdata->usecase[index].vectors[i].ib; log_req[log_cnt].src = client->pdata->usecase[index].vectors[i].src; log_req[log_cnt].dst = client->pdata->usecase[index].vectors[i].dst; log_req[log_cnt].cnt = arch_counter_get_cntpct(); strncpy(log_req[log_cnt].name, client->pdata->name, 19); log_cnt++; //printk("*** cl: %s ab: %llu ib: %llu\n", client->pdata->name, req_bw, req_clk); } } #endif if (curr < 0) { curr_clk = 0; curr_bw = 0; } else { curr_clk = client->pdata->usecase[curr].vectors[i].ib; curr_bw = client->pdata->usecase[curr].vectors[i].ab; MSM_BUS_DBG("ab: %llu ib: %llu\n", curr_bw, curr_clk); } if (!pdata->active_only) { ret = update_path(src, pnode, req_clk, req_bw, curr_clk, curr_bw, 0, pdata->active_only); if (ret) { MSM_BUS_ERR("Update path failed! %d\n", ret); goto err; } } ret = update_path(src, pnode, req_clk, req_bw, curr_clk, curr_bw, ACTIVE_CTX, pdata->active_only); if (ret) { MSM_BUS_ERR("Update Path failed! %d\n", ret); goto err; } } client->curr = index; ctx = ACTIVE_CTX; msm_bus_dbg_client_data(client->pdata, index, cl); bus_for_each_dev(&msm_bus_type, NULL, NULL, msm_bus_commit_fn); err: #ifdef SEC_FEATURE_USE_RT_MUTEX rt_mutex_unlock(&msm_bus_lock); #else mutex_unlock(&msm_bus_lock); #endif return ret; }
static int update_request_legacy(uint32_t cl, unsigned index) { int i, ret = 0; struct msm_bus_scale_pdata *pdata; int pnode, src = 0, curr, ctx; uint64_t req_clk = 0, req_bw = 0, curr_clk = 0, curr_bw = 0; struct msm_bus_client *client = (struct msm_bus_client *)cl; if (IS_ERR_OR_NULL(client)) { MSM_BUS_ERR("msm_bus_scale_client update req error %d\n", (uint32_t)client); return -ENXIO; } mutex_lock(&msm_bus_lock); if (client->curr == index) goto err; curr = client->curr; pdata = client->pdata; if (!pdata) { MSM_BUS_ERR("Null pdata passed to update-request\n"); ret = -ENXIO; goto err; } if (index >= pdata->num_usecases) { MSM_BUS_ERR("Client %u passed invalid index: %d\n", (uint32_t)client, index); ret = -ENXIO; goto err; } MSM_BUS_DBG("cl: %u index: %d curr: %d num_paths: %d\n", cl, index, client->curr, client->pdata->usecase->num_paths); for (i = 0; i < pdata->usecase->num_paths; i++) { src = msm_bus_board_get_iid(client->pdata->usecase[index]. vectors[i].src); if (src == -ENXIO) { MSM_BUS_ERR("Master %d not supported. Request cannot" " be updated\n", client->pdata->usecase-> vectors[i].src); goto err; } if (msm_bus_board_get_iid(client->pdata->usecase[index]. vectors[i].dst) == -ENXIO) { MSM_BUS_ERR("Slave %d not supported. Request cannot" " be updated\n", client->pdata->usecase-> vectors[i].dst); } pnode = client->src_pnode[i]; req_clk = client->pdata->usecase[index].vectors[i].ib; req_bw = client->pdata->usecase[index].vectors[i].ab; if (curr < 0) { curr_clk = 0; curr_bw = 0; } else { curr_clk = client->pdata->usecase[curr].vectors[i].ib; curr_bw = client->pdata->usecase[curr].vectors[i].ab; MSM_BUS_DBG("ab: %llu ib: %llu\n", curr_bw, curr_clk); } if (!pdata->active_only) { ret = update_path(src, pnode, req_clk, req_bw, curr_clk, curr_bw, 0, pdata->active_only); if (ret) { MSM_BUS_ERR("Update path failed! %d\n", ret); goto err; } } ret = update_path(src, pnode, req_clk, req_bw, curr_clk, curr_bw, ACTIVE_CTX, pdata->active_only); if (ret) { MSM_BUS_ERR("Update Path failed! %d\n", ret); goto err; } } client->curr = index; ctx = ACTIVE_CTX; msm_bus_dbg_client_data(client->pdata, index, cl); bus_for_each_dev(&msm_bus_type, NULL, NULL, msm_bus_commit_fn); /* For NR/RT limited masters, if freq is going up , apply the changes * after we commit clk data. */ if (is_nr_lim(src) && ((req_clk > curr_clk) || (req_bw > curr_bw))) bus_for_each_dev(&msm_bus_type, NULL, NULL, msm_bus_commit_limiter); err: mutex_unlock(&msm_bus_lock); return ret; }