/* Caller must hold the device mutex. */ int kgsl_pwrctrl_wake(struct kgsl_device *device) { int status = KGSL_SUCCESS; struct kgsl_pwrctrl *pwr = &device->pwrctrl; BUG_ON(!mutex_is_locked(&device->mutex)); if (device->state == KGSL_STATE_SUSPEND) return status; KGSL_DRV_INFO("GRP_CLK= %lu BUS CLK= %lu\n", kgsl_get_clkrate(pwr->grp_clk), kgsl_get_clkrate(pwr->ebi1_clk)); /* Turn on the core clocks */ status = kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_CLK_ON); if (device->state != KGSL_STATE_NAP) { kgsl_pwrctrl_axi(device, KGSL_PWRFLAGS_AXI_ON); } /* Enable state before turning on irq */ device->state = KGSL_STATE_ACTIVE; KGSL_DRV_WARN("state -> ACTIVE, device %d\n", device->id); kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_IRQ_ON); /* Re-enable HW access */ mod_timer(&device->idle_timer, jiffies + FIRST_TIMEOUT); KGSL_DRV_VDBG("<-- kgsl_yamato_wake(). Return value %d\n", status); wake_lock(&device->idle_wakelock); return status; }
/* Caller must hold the device mutex. */ int kgsl_pwrctrl_sleep(struct kgsl_device *device) { struct kgsl_pwrctrl *pwr = &device->pwrctrl; KGSL_DRV_INFO("device %d, current state= %d, resquested change= %d!!\n", device->id, device->state, device->requested_state); KGSL_DRV_INFO("GRP_CLK= %lu BUS CLK= %lu\n", kgsl_get_clkrate(pwr->grp_clk), kgsl_get_clkrate(pwr->ebi1_clk)); /* Work through the legal state transitions */ if (device->requested_state == KGSL_STATE_NAP) { if (device->ftbl.device_isidle(device)) goto nap; } else if (device->requested_state == KGSL_STATE_SLEEP) { if (device->state == KGSL_STATE_NAP || device->ftbl.device_isidle(device)) goto sleep; } device->requested_state = KGSL_STATE_NONE; return KGSL_FAILURE; sleep: kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_IRQ_OFF); kgsl_pwrctrl_axi(device, KGSL_PWRFLAGS_AXI_OFF); goto clk_off; nap: kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_IRQ_OFF); clk_off: kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_CLK_OFF); device->state = device->requested_state; device->requested_state = KGSL_STATE_NONE; wake_unlock(&device->idle_wakelock); KGSL_DRV_WARN("state -> NAP/SLEEP(%d), device %d\n", device->state, device->id); return KGSL_SUCCESS; }
/* Snapshot the Linux specific information */ static int snapshot_os(struct kgsl_device *device, void *snapshot, int remain, void *priv) { struct kgsl_snapshot_linux *header = snapshot; struct kgsl_pwrctrl *pwr = &device->pwrctrl; struct task_struct *task; pid_t pid; int hang = (int) priv; int ctxtcount = 0; int size = sizeof(*header); /* Figure out how many active contexts there are - these will * be appended on the end of the structure */ idr_for_each(&device->context_idr, snapshot_context_count, &ctxtcount); size += ctxtcount * sizeof(struct kgsl_snapshot_linux_context); /* Make sure there is enough room for the data */ if (remain < size) { SNAPSHOT_ERR_NOMEM(device, "OS"); return 0; } memset(header, 0, sizeof(*header)); header->osid = KGSL_SNAPSHOT_OS_LINUX; header->state = hang ? SNAPSHOT_STATE_HUNG : SNAPSHOT_STATE_RUNNING; /* Get the kernel build information */ strlcpy(header->release, utsname()->release, sizeof(header->release)); strlcpy(header->version, utsname()->version, sizeof(header->version)); /* Get the Unix time for the timestamp */ header->seconds = get_seconds(); /* Remember the power information */ header->power_flags = pwr->power_flags; header->power_level = pwr->active_pwrlevel; header->power_interval_timeout = pwr->interval_timeout; header->grpclk = kgsl_get_clkrate(pwr->grp_clks[0]); header->busclk = kgsl_get_clkrate(pwr->ebi1_clk); /* Future proof for per-context timestamps */ header->current_context = -1; /* Get the current PT base */ header->ptbase = kgsl_mmu_get_current_ptbase(device); /* And the PID for the task leader */ pid = header->pid = kgsl_mmu_get_ptname_from_ptbase(header->ptbase); task = find_task_by_vpid(pid); if (task) get_task_comm(header->comm, task); header->ctxtcount = ctxtcount; /* append information for each context */ _ctxtptr = snapshot + sizeof(*header); idr_for_each(&device->context_idr, snapshot_context_info, NULL); /* Return the size of the data segment */ return size; }