static int m_display_present(lua_State * L) { struct ldisplay_t * display = luaL_checkudata(L, 1, MT_DISPLAY); cairo_t * cr; if(display->showfps) { char buf[32]; ktime_t now = ktime_get(); s64_t delta = ktime_ms_delta(now, display->stamp); if(delta > 0) display->fps = ((double)1000.0 / (double)delta) * 0.618 + display->fps * 0.382; display->frame++; display->stamp = now; cr = display->cr[display->index]; cairo_save(cr); cairo_set_font_size(cr, 24); cairo_set_source_rgb(cr, 0.4, 0.4, 0.4); cairo_move_to(cr, 0, 24); snprintf(buf, sizeof(buf), "%.2f %d", display->fps, display->frame); cairo_show_text(cr, buf); cairo_restore(cr); } cairo_xboot_surface_present(display->cs[display->index]); display->index = (display->index + 1) % 2; cr = display->cr[display->index]; cairo_save(cr); cairo_set_source_rgb(cr, 1, 1, 1); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_paint(cr); cairo_restore(cr); return 0; }
static long calc_speed(void) { uint64_t k; long ms; ms = ktime_ms_delta(finish, start); if (ms == 0) return 0; k = (uint64_t)goodebcnt * (mtd->erasesize / 1024) * 1000; do_div(k, ms); return k; }
void display_present(struct display_t * disp, void * o, void (*draw)(struct display_t *, void *)) { cairo_t * cr; struct region_t rn, ro, * r; char fps[32]; int count; int i; if(disp) { if(disp->cursor.show && disp->cursor.dirty) { region_init(&rn, disp->cursor.nx, disp->cursor.ny, disp->cursor.width, disp->cursor.height); region_init(&ro, disp->cursor.ox, disp->cursor.oy, disp->cursor.width, disp->cursor.height); display_region_list_add(disp, &rn); display_region_list_add(disp, &ro); disp->cursor.dirty = 0; } if(disp->fps.show) { ktime_t now = ktime_get(); s64_t delta = ktime_ms_delta(now, disp->fps.stamp); if(delta > 0) disp->fps.rate = ((double)1000.0 / (double)delta) * 0.618 + disp->fps.rate * 0.382; disp->fps.frame++; disp->fps.stamp = now; int len = snprintf(fps, sizeof(fps), "%.2f %ld", disp->fps.rate, disp->fps.frame); region_init(&rn, 0, 0, len * (24 / 2), 24); display_region_list_add(disp, &rn); } if((count = disp->rl->count) > 0) { cr = disp->cr; cairo_reset_clip(cr); for(i = 0; i < count; i++) { r = &disp->rl->region[i]; cairo_rectangle(cr, r->x, r->y, r->w, r->h); } cairo_clip(cr); cairo_save(cr); cairo_set_source_rgb(cr, 1, 1, 1); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); cairo_paint(cr); cairo_restore(cr); if(draw) draw(disp, o); #if 0 { static int flag = 0; cairo_save(cr); flag = !flag; if(flag) cairo_set_source_rgba(cr, 1, 0, 0, 0.7); else cairo_set_source_rgba(cr, 0, 1, 0, 0.7); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); cairo_paint(cr); cairo_restore(cr); } #endif if(disp->cursor.show) { cairo_save(cr); cairo_set_source_surface(cr, disp->cursor.cs, disp->cursor.nx, disp->cursor.ny); cairo_paint(cr); cairo_restore(cr); } if(disp->fps.show) { cairo_save(cr); cairo_set_font_size(cr, 24); cairo_set_source_rgb(cr, 0.4, 0.4, 0.4); cairo_move_to(cr, 0, 24); cairo_show_text(cr, fps); cairo_restore(cr); } cairo_xboot_surface_present(disp->cs, disp->rl); } } }
/* * This function transfers the ownership of the PCC to the platform * So it must be called while holding write_lock(pcc_lock) */ static int send_pcc_cmd(int pcc_ss_id, u16 cmd) { int ret = -EIO, i; struct cppc_pcc_data *pcc_ss_data = pcc_data[pcc_ss_id]; struct acpi_pcct_shared_memory *generic_comm_base = (struct acpi_pcct_shared_memory *)pcc_ss_data->pcc_comm_addr; unsigned int time_delta; /* * For CMD_WRITE we know for a fact the caller should have checked * the channel before writing to PCC space */ if (cmd == CMD_READ) { /* * If there are pending cpc_writes, then we stole the channel * before write completion, so first send a WRITE command to * platform */ if (pcc_ss_data->pending_pcc_write_cmd) send_pcc_cmd(pcc_ss_id, CMD_WRITE); ret = check_pcc_chan(pcc_ss_id, false); if (ret) goto end; } else /* CMD_WRITE */ pcc_ss_data->pending_pcc_write_cmd = FALSE; /* * Handle the Minimum Request Turnaround Time(MRTT) * "The minimum amount of time that OSPM must wait after the completion * of a command before issuing the next command, in microseconds" */ if (pcc_ss_data->pcc_mrtt) { time_delta = ktime_us_delta(ktime_get(), pcc_ss_data->last_cmd_cmpl_time); if (pcc_ss_data->pcc_mrtt > time_delta) udelay(pcc_ss_data->pcc_mrtt - time_delta); } /* * Handle the non-zero Maximum Periodic Access Rate(MPAR) * "The maximum number of periodic requests that the subspace channel can * support, reported in commands per minute. 0 indicates no limitation." * * This parameter should be ideally zero or large enough so that it can * handle maximum number of requests that all the cores in the system can * collectively generate. If it is not, we will follow the spec and just * not send the request to the platform after hitting the MPAR limit in * any 60s window */ if (pcc_ss_data->pcc_mpar) { if (pcc_ss_data->mpar_count == 0) { time_delta = ktime_ms_delta(ktime_get(), pcc_ss_data->last_mpar_reset); if ((time_delta < 60 * MSEC_PER_SEC) && pcc_ss_data->last_mpar_reset) { pr_debug("PCC cmd not sent due to MPAR limit"); ret = -EIO; goto end; } pcc_ss_data->last_mpar_reset = ktime_get(); pcc_ss_data->mpar_count = pcc_ss_data->pcc_mpar; } pcc_ss_data->mpar_count--; } /* Write to the shared comm region. */ writew_relaxed(cmd, &generic_comm_base->command); /* Flip CMD COMPLETE bit */ writew_relaxed(0, &generic_comm_base->status); pcc_ss_data->platform_owns_pcc = true; /* Ring doorbell */ ret = mbox_send_message(pcc_ss_data->pcc_channel, &cmd); if (ret < 0) { pr_err("Err sending PCC mbox message. cmd:%d, ret:%d\n", cmd, ret); goto end; } /* wait for completion and check for PCC errro bit */ ret = check_pcc_chan(pcc_ss_id, true); if (pcc_ss_data->pcc_mrtt) pcc_ss_data->last_cmd_cmpl_time = ktime_get(); if (pcc_ss_data->pcc_channel->mbox->txdone_irq) mbox_chan_txdone(pcc_ss_data->pcc_channel, ret); else mbox_client_txdone(pcc_ss_data->pcc_channel, ret); end: if (cmd == CMD_WRITE) { if (unlikely(ret)) { for_each_possible_cpu(i) { struct cpc_desc *desc = per_cpu(cpc_desc_ptr, i); if (!desc) continue; if (desc->write_cmd_id == pcc_ss_data->pcc_write_cnt) desc->write_cmd_status = ret; } } pcc_ss_data->pcc_write_cnt++; wake_up_all(&pcc_ss_data->pcc_write_wait_q); } return ret; }
static int send_pcc_cmd(u16 cmd) { int ret = -EIO; struct acpi_pcct_shared_memory *generic_comm_base = (struct acpi_pcct_shared_memory *) pcc_comm_addr; static ktime_t last_cmd_cmpl_time, last_mpar_reset; static int mpar_count; unsigned int time_delta; /* * For CMD_WRITE we know for a fact the caller should have checked * the channel before writing to PCC space */ if (cmd == CMD_READ) { ret = check_pcc_chan(); if (ret) return ret; } /* * Handle the Minimum Request Turnaround Time(MRTT) * "The minimum amount of time that OSPM must wait after the completion * of a command before issuing the next command, in microseconds" */ if (pcc_mrtt) { time_delta = ktime_us_delta(ktime_get(), last_cmd_cmpl_time); if (pcc_mrtt > time_delta) udelay(pcc_mrtt - time_delta); } /* * Handle the non-zero Maximum Periodic Access Rate(MPAR) * "The maximum number of periodic requests that the subspace channel can * support, reported in commands per minute. 0 indicates no limitation." * * This parameter should be ideally zero or large enough so that it can * handle maximum number of requests that all the cores in the system can * collectively generate. If it is not, we will follow the spec and just * not send the request to the platform after hitting the MPAR limit in * any 60s window */ if (pcc_mpar) { if (mpar_count == 0) { time_delta = ktime_ms_delta(ktime_get(), last_mpar_reset); if (time_delta < 60 * MSEC_PER_SEC) { pr_debug("PCC cmd not sent due to MPAR limit"); return -EIO; } last_mpar_reset = ktime_get(); mpar_count = pcc_mpar; } mpar_count--; } /* Write to the shared comm region. */ writew_relaxed(cmd, &generic_comm_base->command); /* Flip CMD COMPLETE bit */ writew_relaxed(0, &generic_comm_base->status); /* Ring doorbell */ ret = mbox_send_message(pcc_channel, &cmd); if (ret < 0) { pr_err("Err sending PCC mbox message. cmd:%d, ret:%d\n", cmd, ret); return ret; } /* * For READs we need to ensure the cmd completed to ensure * the ensuing read()s can proceed. For WRITEs we dont care * because the actual write()s are done before coming here * and the next READ or WRITE will check if the channel * is busy/free at the entry of this call. * * If Minimum Request Turnaround Time is non-zero, we need * to record the completion time of both READ and WRITE * command for proper handling of MRTT, so we need to check * for pcc_mrtt in addition to CMD_READ */ if (cmd == CMD_READ || pcc_mrtt) { ret = check_pcc_chan(); if (pcc_mrtt) last_cmd_cmpl_time = ktime_get(); } mbox_client_txdone(pcc_channel, ret); return ret; }