void nvhost_job_unpin(struct nvhost_job *job) { nvmap_unpin_handles(job->nvmap, job->unpins, job->num_unpins); memset(job->unpins, BAD_MAGIC, job->num_unpins * sizeof(struct nvmap_handle *)); }
/** * For all sync queue entries that have already finished according to the * current sync point registers: * - unpin & unref their mems * - pop their push buffer slots * - remove them from the sync queue * This is normally called from the host code's worker thread, but can be * called manually if necessary. * Must be called with the cdma lock held. */ static void update_cdma(struct nvhost_cdma *cdma) { bool signal = false; struct nvhost_master *dev = cdma_to_dev(cdma); BUG_ON(!cdma->running); /* * Walk the sync queue, reading the sync point registers as necessary, * to consume as many sync queue entries as possible without blocking */ for (;;) { u32 syncpt_id, syncpt_val; u32 timeout; struct nvhost_userctx_timeout *timeout_ref = NULL; unsigned int nr_slots, nr_handles; struct nvhost_syncpt *sp = &dev->syncpt; struct nvmap_handle **handles; struct nvmap_client *nvmap; u32 *sync; sync = sync_queue_head(&cdma->sync_queue); if (!sync) { if (cdma->event == CDMA_EVENT_SYNC_QUEUE_EMPTY) signal = true; break; } syncpt_id = sync[SQ_IDX_SYNCPT_ID]; syncpt_val = sync[SQ_IDX_SYNCPT_VAL]; timeout = sync[SQ_IDX_TIMEOUT]; timeout_ref = (struct nvhost_userctx_timeout *) sync[SQ_IDX_TIMEOUT_CTX]; BUG_ON(syncpt_id == NVSYNCPT_INVALID); /* Check whether this syncpt has completed, and bail if not */ if (!nvhost_syncpt_min_cmp(sp, syncpt_id, syncpt_val)) { /* Start timer on next pending syncpt */ if (timeout) { nvhost_cdma_start_timer(cdma, syncpt_id, syncpt_val, timeout_ref); } break; } /* Cancel timeout, when a buffer completes */ if (cdma->timeout.ctx_timeout) stop_cdma_timer(cdma); nr_slots = sync[SQ_IDX_NUM_SLOTS]; nr_handles = sync[SQ_IDX_NUM_HANDLES]; nvmap = (struct nvmap_client *)sync[SQ_IDX_NVMAP_CTX]; handles = (struct nvmap_handle **)&sync[SQ_IDX_HANDLES]; BUG_ON(!nvmap); /* Unpin the memory */ nvmap_unpin_handles(nvmap, handles, nr_handles); nvmap_client_put(nvmap); /* Pop push buffer slots */ if (nr_slots) { struct push_buffer *pb = &cdma->push_buffer; BUG_ON(!cdma_pb_op(cdma).pop_from); cdma_pb_op(cdma).pop_from(pb, nr_slots); if (cdma->event == CDMA_EVENT_PUSH_BUFFER_SPACE) signal = true; } dequeue_sync_queue_head(&cdma->sync_queue); if (cdma->event == CDMA_EVENT_SYNC_QUEUE_SPACE) signal = true; } /* Wake up CdmaWait() if the requested event happened */ if (signal) { cdma->event = CDMA_EVENT_NONE; up(&cdma->sem); } }