Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 1 | /* Copyright (c) 2017, The Linux Foundation. All rights reserved. |
| 2 | * |
| 3 | * This program is free software; you can redistribute it and/or modify |
| 4 | * it under the terms of the GNU General Public License version 2 and |
| 5 | * only version 2 as published by the Free Software Foundation. |
| 6 | * |
| 7 | * This program is distributed in the hope that it will be useful, |
| 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 10 | * GNU General Public License for more details. |
| 11 | */ |
| 12 | |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 13 | #include <linux/debugfs.h> |
| 14 | #include <linux/videodev2.h> |
| 15 | #include <linux/slab.h> |
| 16 | #include <linux/uaccess.h> |
| 17 | #include <media/cam_sync.h> |
| 18 | #include <media/cam_defs.h> |
| 19 | |
Gregory Bergschneider | 5164f3a | 2017-07-07 10:26:17 -0600 | [diff] [blame] | 20 | #include "cam_context.h" |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 21 | #include "cam_context_utils.h" |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 22 | #include "cam_mem_mgr.h" |
| 23 | #include "cam_node.h" |
Gregory Bergschneider | 5164f3a | 2017-07-07 10:26:17 -0600 | [diff] [blame] | 24 | #include "cam_req_mgr_util.h" |
| 25 | #include "cam_sync_api.h" |
| 26 | #include "cam_trace.h" |
Lakshmi Narayana Kalavala | adc6ce3 | 2017-07-17 17:19:11 -0700 | [diff] [blame] | 27 | #include "cam_debug_util.h" |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 28 | |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 29 | static inline int cam_context_validate_thread(void) |
| 30 | { |
| 31 | if (in_interrupt()) { |
| 32 | WARN(1, "Invalid execution context\n"); |
| 33 | return -EINVAL; |
| 34 | } |
| 35 | return 0; |
| 36 | } |
| 37 | |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 38 | int cam_context_buf_done_from_hw(struct cam_context *ctx, |
| 39 | void *done_event_data, uint32_t bubble_state) |
| 40 | { |
Sagar Gore | cdd6a5e | 2017-05-17 19:06:59 -0700 | [diff] [blame] | 41 | int j; |
Suresh Vankadara | 8e06cfb | 2017-06-13 16:27:08 +0530 | [diff] [blame] | 42 | int result; |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 43 | struct cam_ctx_request *req; |
| 44 | struct cam_hw_done_event_data *done = |
| 45 | (struct cam_hw_done_event_data *)done_event_data; |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 46 | int rc; |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 47 | |
Pavan Kumar Chilamkurthi | ca2295d | 2017-07-30 01:50:59 -0700 | [diff] [blame] | 48 | if (!ctx || !done) { |
| 49 | CAM_ERR(CAM_CTXT, "Invalid input params %pK %pK", ctx, done); |
| 50 | return -EINVAL; |
| 51 | } |
| 52 | |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 53 | rc = cam_context_validate_thread(); |
| 54 | if (rc) |
| 55 | return rc; |
| 56 | |
| 57 | spin_lock(&ctx->lock); |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 58 | if (list_empty(&ctx->active_req_list)) { |
Lakshmi Narayana Kalavala | adc6ce3 | 2017-07-17 17:19:11 -0700 | [diff] [blame] | 59 | CAM_ERR(CAM_CTXT, "no active request"); |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 60 | spin_unlock(&ctx->lock); |
Sagar Gore | cdd6a5e | 2017-05-17 19:06:59 -0700 | [diff] [blame] | 61 | return -EIO; |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 62 | } |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 63 | req = list_first_entry(&ctx->active_req_list, |
| 64 | struct cam_ctx_request, list); |
| 65 | |
Gregory Bergschneider | 5164f3a | 2017-07-07 10:26:17 -0600 | [diff] [blame] | 66 | trace_cam_buf_done("UTILS", ctx, req); |
| 67 | |
Sagar Gore | cdd6a5e | 2017-05-17 19:06:59 -0700 | [diff] [blame] | 68 | if (done->request_id != req->request_id) { |
Lakshmi Narayana Kalavala | adc6ce3 | 2017-07-17 17:19:11 -0700 | [diff] [blame] | 69 | CAM_ERR(CAM_CTXT, "mismatch: done req[%lld], active req[%lld]", |
Sagar Gore | cdd6a5e | 2017-05-17 19:06:59 -0700 | [diff] [blame] | 70 | done->request_id, req->request_id); |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 71 | spin_unlock(&ctx->lock); |
Sagar Gore | cdd6a5e | 2017-05-17 19:06:59 -0700 | [diff] [blame] | 72 | return -EIO; |
| 73 | } |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 74 | |
Sagar Gore | cdd6a5e | 2017-05-17 19:06:59 -0700 | [diff] [blame] | 75 | if (!req->num_out_map_entries) { |
Lakshmi Narayana Kalavala | adc6ce3 | 2017-07-17 17:19:11 -0700 | [diff] [blame] | 76 | CAM_ERR(CAM_CTXT, "no output fence to signal"); |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 77 | spin_unlock(&ctx->lock); |
Sagar Gore | cdd6a5e | 2017-05-17 19:06:59 -0700 | [diff] [blame] | 78 | return -EIO; |
| 79 | } |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 80 | |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 81 | /* |
| 82 | * since another thread may be adding/removing from active |
| 83 | * list, so hold the lock |
| 84 | */ |
Sagar Gore | cdd6a5e | 2017-05-17 19:06:59 -0700 | [diff] [blame] | 85 | list_del_init(&req->list); |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 86 | spin_unlock(&ctx->lock); |
Suresh Vankadara | 8e06cfb | 2017-06-13 16:27:08 +0530 | [diff] [blame] | 87 | if (!bubble_state) |
| 88 | result = CAM_SYNC_STATE_SIGNALED_SUCCESS; |
| 89 | else |
| 90 | result = CAM_SYNC_STATE_SIGNALED_ERROR; |
| 91 | |
Sagar Gore | cdd6a5e | 2017-05-17 19:06:59 -0700 | [diff] [blame] | 92 | for (j = 0; j < req->num_out_map_entries; j++) { |
Suresh Vankadara | 8e06cfb | 2017-06-13 16:27:08 +0530 | [diff] [blame] | 93 | cam_sync_signal(req->out_map_entries[j].sync_id, result); |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 94 | req->out_map_entries[j].sync_id = -1; |
| 95 | } |
| 96 | |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 97 | /* |
| 98 | * another thread may be adding/removing from free list, |
| 99 | * so hold the lock |
| 100 | */ |
| 101 | spin_lock(&ctx->lock); |
Sagar Gore | cdd6a5e | 2017-05-17 19:06:59 -0700 | [diff] [blame] | 102 | list_add_tail(&req->list, &ctx->free_req_list); |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 103 | req->ctx = NULL; |
| 104 | spin_unlock(&ctx->lock); |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 105 | |
Sagar Gore | cdd6a5e | 2017-05-17 19:06:59 -0700 | [diff] [blame] | 106 | return 0; |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 107 | } |
| 108 | |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 109 | static int cam_context_apply_req_to_hw(struct cam_ctx_request *req, |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 110 | struct cam_req_mgr_apply_request *apply) |
| 111 | { |
| 112 | int rc = 0; |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 113 | struct cam_context *ctx = req->ctx; |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 114 | struct cam_hw_config_args cfg; |
| 115 | |
| 116 | if (!ctx->hw_mgr_intf) { |
Lakshmi Narayana Kalavala | adc6ce3 | 2017-07-17 17:19:11 -0700 | [diff] [blame] | 117 | CAM_ERR(CAM_CTXT, "HW interface is not ready"); |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 118 | rc = -EFAULT; |
| 119 | goto end; |
| 120 | } |
| 121 | |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 122 | spin_lock(&ctx->lock); |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 123 | list_del_init(&req->list); |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 124 | list_add_tail(&req->list, &ctx->active_req_list); |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 125 | spin_unlock(&ctx->lock); |
| 126 | |
| 127 | cfg.ctxt_to_hw_map = ctx->ctxt_to_hw_map; |
| 128 | cfg.hw_update_entries = req->hw_update_entries; |
| 129 | cfg.num_hw_update_entries = req->num_hw_update_entries; |
| 130 | cfg.out_map_entries = req->out_map_entries; |
| 131 | cfg.num_out_map_entries = req->num_out_map_entries; |
Pavan Kumar Chilamkurthi | eb8833c | 2017-07-15 19:44:13 -0700 | [diff] [blame] | 132 | cfg.priv = req->req_priv; |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 133 | |
| 134 | rc = ctx->hw_mgr_intf->hw_config(ctx->hw_mgr_intf->hw_mgr_priv, &cfg); |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 135 | if (rc) { |
| 136 | spin_lock(&ctx->lock); |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 137 | list_del_init(&req->list); |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 138 | spin_unlock(&ctx->lock); |
| 139 | } |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 140 | |
| 141 | end: |
| 142 | return rc; |
| 143 | } |
| 144 | |
Suresh Vankadara | 8e06cfb | 2017-06-13 16:27:08 +0530 | [diff] [blame] | 145 | static void cam_context_sync_callback(int32_t sync_obj, int status, void *data) |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 146 | { |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 147 | struct cam_ctx_request *req = data; |
| 148 | struct cam_context *ctx = NULL; |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 149 | struct cam_req_mgr_apply_request apply; |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 150 | int rc; |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 151 | |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 152 | if (!req) { |
Pavan Kumar Chilamkurthi | ca2295d | 2017-07-30 01:50:59 -0700 | [diff] [blame] | 153 | CAM_ERR(CAM_CTXT, "Invalid input param"); |
| 154 | return; |
| 155 | } |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 156 | rc = cam_context_validate_thread(); |
| 157 | if (rc) |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 158 | return; |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 159 | |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 160 | ctx = req->ctx; |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 161 | req->num_in_acked++; |
| 162 | if (req->num_in_acked == req->num_in_map_entries) { |
| 163 | apply.request_id = req->request_id; |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 164 | /* |
| 165 | * take mutex to ensure that another thread does |
| 166 | * not flush the request while this |
| 167 | * thread is submitting it to h/w. The submit to |
| 168 | * h/w and adding to the active list should happen |
| 169 | * in a critical section which is provided by this |
| 170 | * mutex. |
| 171 | */ |
| 172 | mutex_lock(&ctx->sync_mutex); |
| 173 | if (!req->flushed) { |
| 174 | cam_context_apply_req_to_hw(req, &apply); |
| 175 | mutex_unlock(&ctx->sync_mutex); |
| 176 | } else { |
| 177 | mutex_unlock(&ctx->sync_mutex); |
| 178 | req->ctx = NULL; |
| 179 | req->flushed = 0; |
| 180 | spin_lock(&ctx->lock); |
| 181 | list_add_tail(&req->list, &ctx->free_req_list); |
| 182 | spin_unlock(&ctx->lock); |
| 183 | } |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 184 | } |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 185 | cam_context_putref(ctx); |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 186 | } |
| 187 | |
Suresh Vankadara | 8e06cfb | 2017-06-13 16:27:08 +0530 | [diff] [blame] | 188 | int32_t cam_context_release_dev_to_hw(struct cam_context *ctx, |
| 189 | struct cam_release_dev_cmd *cmd) |
| 190 | { |
Suresh Vankadara | 8e06cfb | 2017-06-13 16:27:08 +0530 | [diff] [blame] | 191 | struct cam_hw_release_args arg; |
Suresh Vankadara | 8e06cfb | 2017-06-13 16:27:08 +0530 | [diff] [blame] | 192 | |
Pavan Kumar Chilamkurthi | ca2295d | 2017-07-30 01:50:59 -0700 | [diff] [blame] | 193 | if (!ctx) { |
| 194 | CAM_ERR(CAM_CTXT, "Invalid input param"); |
| 195 | return -EINVAL; |
| 196 | } |
| 197 | |
Suresh Vankadara | d8905f4 | 2017-06-04 13:33:49 +0530 | [diff] [blame] | 198 | if ((!ctx->hw_mgr_intf) || (!ctx->hw_mgr_intf->hw_release)) { |
Lakshmi Narayana Kalavala | adc6ce3 | 2017-07-17 17:19:11 -0700 | [diff] [blame] | 199 | CAM_ERR(CAM_CTXT, "HW interface is not ready"); |
Suresh Vankadara | d8905f4 | 2017-06-04 13:33:49 +0530 | [diff] [blame] | 200 | return -EINVAL; |
Suresh Vankadara | 8e06cfb | 2017-06-13 16:27:08 +0530 | [diff] [blame] | 201 | } |
| 202 | |
Suresh Vankadara | d8905f4 | 2017-06-04 13:33:49 +0530 | [diff] [blame] | 203 | arg.ctxt_to_hw_map = ctx->ctxt_to_hw_map; |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 204 | arg.active_req = false; |
Suresh Vankadara | 8e06cfb | 2017-06-13 16:27:08 +0530 | [diff] [blame] | 205 | |
Suresh Vankadara | d8905f4 | 2017-06-04 13:33:49 +0530 | [diff] [blame] | 206 | ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv, &arg); |
| 207 | ctx->ctxt_to_hw_map = NULL; |
Suresh Vankadara | 8e06cfb | 2017-06-13 16:27:08 +0530 | [diff] [blame] | 208 | |
Soundrapandian Jeyaprakash | 8d16e27 | 2017-10-12 11:05:37 -0700 | [diff] [blame] | 209 | ctx->session_hdl = -1; |
| 210 | ctx->dev_hdl = -1; |
| 211 | ctx->link_hdl = -1; |
Suresh Vankadara | 8e06cfb | 2017-06-13 16:27:08 +0530 | [diff] [blame] | 212 | |
Suresh Vankadara | d8905f4 | 2017-06-04 13:33:49 +0530 | [diff] [blame] | 213 | return 0; |
Suresh Vankadara | 8e06cfb | 2017-06-13 16:27:08 +0530 | [diff] [blame] | 214 | } |
| 215 | |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 216 | int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx, |
| 217 | struct cam_config_dev_cmd *cmd) |
| 218 | { |
| 219 | int rc = 0; |
| 220 | struct cam_ctx_request *req = NULL; |
| 221 | struct cam_hw_prepare_update_args cfg; |
| 222 | uint64_t packet_addr; |
| 223 | struct cam_packet *packet; |
| 224 | size_t len = 0; |
| 225 | int32_t i = 0; |
| 226 | |
Pavan Kumar Chilamkurthi | ca2295d | 2017-07-30 01:50:59 -0700 | [diff] [blame] | 227 | if (!ctx || !cmd) { |
| 228 | CAM_ERR(CAM_CTXT, "Invalid input params %pK %pK", ctx, cmd); |
| 229 | rc = -EINVAL; |
| 230 | goto end; |
| 231 | } |
| 232 | |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 233 | if (!ctx->hw_mgr_intf) { |
Lakshmi Narayana Kalavala | adc6ce3 | 2017-07-17 17:19:11 -0700 | [diff] [blame] | 234 | CAM_ERR(CAM_CTXT, "HW interface is not ready"); |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 235 | rc = -EFAULT; |
| 236 | goto end; |
| 237 | } |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 238 | rc = cam_context_validate_thread(); |
| 239 | if (rc) |
| 240 | return rc; |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 241 | |
| 242 | spin_lock(&ctx->lock); |
| 243 | if (!list_empty(&ctx->free_req_list)) { |
| 244 | req = list_first_entry(&ctx->free_req_list, |
| 245 | struct cam_ctx_request, list); |
| 246 | list_del_init(&req->list); |
| 247 | } |
| 248 | spin_unlock(&ctx->lock); |
| 249 | |
| 250 | if (!req) { |
Lakshmi Narayana Kalavala | adc6ce3 | 2017-07-17 17:19:11 -0700 | [diff] [blame] | 251 | CAM_ERR(CAM_CTXT, "No more request obj free"); |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 252 | rc = -ENOMEM; |
| 253 | goto end; |
| 254 | } |
| 255 | |
| 256 | memset(req, 0, sizeof(*req)); |
| 257 | INIT_LIST_HEAD(&req->list); |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 258 | req->ctx = ctx; |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 259 | |
| 260 | /* for config dev, only memory handle is supported */ |
| 261 | /* map packet from the memhandle */ |
| 262 | rc = cam_mem_get_cpu_buf((int32_t) cmd->packet_handle, |
| 263 | (uint64_t *) &packet_addr, |
| 264 | &len); |
| 265 | if (rc != 0) { |
Lakshmi Narayana Kalavala | adc6ce3 | 2017-07-17 17:19:11 -0700 | [diff] [blame] | 266 | CAM_ERR(CAM_CTXT, "Can not get packet address"); |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 267 | rc = -EINVAL; |
| 268 | goto free_req; |
| 269 | } |
| 270 | |
| 271 | packet = (struct cam_packet *) (packet_addr + cmd->offset); |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 272 | |
| 273 | /* preprocess the configuration */ |
| 274 | memset(&cfg, 0, sizeof(cfg)); |
| 275 | cfg.packet = packet; |
| 276 | cfg.ctxt_to_hw_map = ctx->ctxt_to_hw_map; |
| 277 | cfg.max_hw_update_entries = CAM_CTX_CFG_MAX; |
| 278 | cfg.num_hw_update_entries = req->num_hw_update_entries; |
| 279 | cfg.hw_update_entries = req->hw_update_entries; |
| 280 | cfg.max_out_map_entries = CAM_CTX_CFG_MAX; |
| 281 | cfg.out_map_entries = req->out_map_entries; |
| 282 | cfg.max_in_map_entries = CAM_CTX_CFG_MAX; |
| 283 | cfg.in_map_entries = req->in_map_entries; |
| 284 | |
| 285 | rc = ctx->hw_mgr_intf->hw_prepare_update( |
| 286 | ctx->hw_mgr_intf->hw_mgr_priv, &cfg); |
| 287 | if (rc != 0) { |
Lakshmi Narayana Kalavala | adc6ce3 | 2017-07-17 17:19:11 -0700 | [diff] [blame] | 288 | CAM_ERR(CAM_CTXT, "Prepare config packet failed in HW layer"); |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 289 | rc = -EFAULT; |
| 290 | goto free_req; |
| 291 | } |
| 292 | req->num_hw_update_entries = cfg.num_hw_update_entries; |
| 293 | req->num_out_map_entries = cfg.num_out_map_entries; |
| 294 | req->num_in_map_entries = cfg.num_in_map_entries; |
| 295 | req->request_id = packet->header.request_id; |
| 296 | req->status = 1; |
| 297 | req->req_priv = cfg.priv; |
| 298 | |
| 299 | if (req->num_in_map_entries > 0) { |
| 300 | spin_lock(&ctx->lock); |
| 301 | list_add_tail(&req->list, &ctx->pending_req_list); |
| 302 | spin_unlock(&ctx->lock); |
| 303 | for (i = 0; i < req->num_in_map_entries; i++) { |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 304 | cam_context_getref(ctx); |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 305 | rc = cam_sync_register_callback( |
| 306 | cam_context_sync_callback, |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 307 | (void *)req, |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 308 | req->in_map_entries[i].sync_id); |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 309 | if (rc) { |
| 310 | CAM_ERR(CAM_CTXT, |
| 311 | "Failed register fence cb: %d ret = %d", |
| 312 | req->in_map_entries[i].sync_id, rc); |
| 313 | cam_context_putref(ctx); |
| 314 | goto free_req; |
| 315 | } |
Lakshmi Narayana Kalavala | adc6ce3 | 2017-07-17 17:19:11 -0700 | [diff] [blame] | 316 | CAM_DBG(CAM_CTXT, "register in fence cb: %d ret = %d", |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 317 | req->in_map_entries[i].sync_id, rc); |
| 318 | } |
| 319 | goto end; |
| 320 | } |
| 321 | |
| 322 | return rc; |
| 323 | |
| 324 | free_req: |
| 325 | spin_lock(&ctx->lock); |
| 326 | list_add_tail(&req->list, &ctx->free_req_list); |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 327 | req->ctx = NULL; |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 328 | spin_unlock(&ctx->lock); |
| 329 | end: |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 330 | return rc; |
| 331 | } |
| 332 | |
| 333 | int32_t cam_context_acquire_dev_to_hw(struct cam_context *ctx, |
| 334 | struct cam_acquire_dev_cmd *cmd) |
| 335 | { |
| 336 | int rc; |
| 337 | struct cam_hw_acquire_args param; |
| 338 | struct cam_create_dev_hdl req_hdl_param; |
| 339 | struct cam_hw_release_args release; |
| 340 | |
Pavan Kumar Chilamkurthi | ca2295d | 2017-07-30 01:50:59 -0700 | [diff] [blame] | 341 | if (!ctx || !cmd) { |
| 342 | CAM_ERR(CAM_CTXT, "Invalid input params %pK %pK", ctx, cmd); |
| 343 | rc = -EINVAL; |
| 344 | goto end; |
| 345 | } |
| 346 | |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 347 | if (!ctx->hw_mgr_intf) { |
Lakshmi Narayana Kalavala | adc6ce3 | 2017-07-17 17:19:11 -0700 | [diff] [blame] | 348 | CAM_ERR(CAM_CTXT, "HW interface is not ready"); |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 349 | rc = -EFAULT; |
| 350 | goto end; |
| 351 | } |
| 352 | |
Lakshmi Narayana Kalavala | adc6ce3 | 2017-07-17 17:19:11 -0700 | [diff] [blame] | 353 | CAM_DBG(CAM_CTXT, "ses hdl: %x, num_res: %d, type: %d, res: %lld", |
| 354 | cmd->session_handle, cmd->num_resources, cmd->handle_type, |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 355 | cmd->resource_hdl); |
| 356 | |
| 357 | if (cmd->num_resources > CAM_CTX_RES_MAX) { |
Lakshmi Narayana Kalavala | adc6ce3 | 2017-07-17 17:19:11 -0700 | [diff] [blame] | 358 | CAM_ERR(CAM_CTXT, "resource limit exceeded"); |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 359 | rc = -ENOMEM; |
| 360 | goto end; |
| 361 | } |
| 362 | |
| 363 | /* for now we only support user pointer */ |
| 364 | if (cmd->handle_type != 1) { |
Lakshmi Narayana Kalavala | adc6ce3 | 2017-07-17 17:19:11 -0700 | [diff] [blame] | 365 | CAM_ERR(CAM_CTXT, "Only user pointer is supported"); |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 366 | rc = -EINVAL; |
| 367 | goto end; |
| 368 | } |
| 369 | |
| 370 | /* fill in parameters */ |
| 371 | param.context_data = ctx; |
| 372 | param.event_cb = ctx->irq_cb_intf; |
| 373 | param.num_acq = cmd->num_resources; |
| 374 | param.acquire_info = cmd->resource_hdl; |
| 375 | |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 376 | /* call HW manager to reserve the resource */ |
| 377 | rc = ctx->hw_mgr_intf->hw_acquire(ctx->hw_mgr_intf->hw_mgr_priv, |
| 378 | ¶m); |
| 379 | if (rc != 0) { |
Lakshmi Narayana Kalavala | adc6ce3 | 2017-07-17 17:19:11 -0700 | [diff] [blame] | 380 | CAM_ERR(CAM_CTXT, "Acquire device failed"); |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 381 | goto end; |
| 382 | } |
| 383 | |
| 384 | ctx->ctxt_to_hw_map = param.ctxt_to_hw_map; |
| 385 | |
| 386 | /* if hw resource acquire successful, acquire dev handle */ |
| 387 | req_hdl_param.session_hdl = cmd->session_handle; |
| 388 | /* bridge is not ready for these flags. so false for now */ |
| 389 | req_hdl_param.v4l2_sub_dev_flag = 0; |
| 390 | req_hdl_param.media_entity_flag = 0; |
| 391 | req_hdl_param.priv = ctx; |
Soundrapandian Jeyaprakash | eb64e8e | 2017-08-11 18:44:14 -0700 | [diff] [blame] | 392 | req_hdl_param.ops = ctx->crm_ctx_intf; |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 393 | |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 394 | ctx->dev_hdl = cam_create_device_hdl(&req_hdl_param); |
| 395 | if (ctx->dev_hdl <= 0) { |
| 396 | rc = -EFAULT; |
Lakshmi Narayana Kalavala | adc6ce3 | 2017-07-17 17:19:11 -0700 | [diff] [blame] | 397 | CAM_ERR(CAM_CTXT, "Can not create device handle"); |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 398 | goto free_hw; |
| 399 | } |
| 400 | cmd->dev_handle = ctx->dev_hdl; |
| 401 | |
| 402 | /* store session information */ |
| 403 | ctx->session_hdl = cmd->session_handle; |
| 404 | |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 405 | return rc; |
| 406 | |
| 407 | free_hw: |
| 408 | release.ctxt_to_hw_map = ctx->ctxt_to_hw_map; |
| 409 | ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv, &release); |
| 410 | ctx->ctxt_to_hw_map = NULL; |
| 411 | end: |
| 412 | return rc; |
| 413 | } |
| 414 | |
| 415 | int32_t cam_context_start_dev_to_hw(struct cam_context *ctx, |
| 416 | struct cam_start_stop_dev_cmd *cmd) |
| 417 | { |
| 418 | int rc = 0; |
| 419 | struct cam_hw_start_args arg; |
| 420 | |
Pavan Kumar Chilamkurthi | ca2295d | 2017-07-30 01:50:59 -0700 | [diff] [blame] | 421 | if (!ctx || !cmd) { |
| 422 | CAM_ERR(CAM_CTXT, "Invalid input params %pK %pK", ctx, cmd); |
| 423 | rc = -EINVAL; |
| 424 | goto end; |
| 425 | } |
| 426 | |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 427 | if (!ctx->hw_mgr_intf) { |
Lakshmi Narayana Kalavala | adc6ce3 | 2017-07-17 17:19:11 -0700 | [diff] [blame] | 428 | CAM_ERR(CAM_CTXT, "HW interface is not ready"); |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 429 | rc = -EFAULT; |
| 430 | goto end; |
| 431 | } |
| 432 | |
| 433 | if ((cmd->session_handle != ctx->session_hdl) || |
| 434 | (cmd->dev_handle != ctx->dev_hdl)) { |
Lakshmi Narayana Kalavala | adc6ce3 | 2017-07-17 17:19:11 -0700 | [diff] [blame] | 435 | CAM_ERR(CAM_CTXT, "Invalid session hdl[%d], dev_handle[%d]", |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 436 | cmd->session_handle, cmd->dev_handle); |
| 437 | rc = -EPERM; |
| 438 | goto end; |
| 439 | } |
| 440 | |
| 441 | if (ctx->hw_mgr_intf->hw_start) { |
Pavan Kumar Chilamkurthi | ca2295d | 2017-07-30 01:50:59 -0700 | [diff] [blame] | 442 | arg.ctxt_to_hw_map = ctx->ctxt_to_hw_map; |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 443 | rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv, |
| 444 | &arg); |
| 445 | if (rc) { |
| 446 | /* HW failure. user need to clean up the resource */ |
Lakshmi Narayana Kalavala | adc6ce3 | 2017-07-17 17:19:11 -0700 | [diff] [blame] | 447 | CAM_ERR(CAM_CTXT, "Start HW failed"); |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 448 | goto end; |
| 449 | } |
| 450 | } |
| 451 | |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 452 | end: |
| 453 | return rc; |
| 454 | } |
| 455 | |
| 456 | int32_t cam_context_stop_dev_to_hw(struct cam_context *ctx) |
| 457 | { |
| 458 | int rc = 0; |
| 459 | uint32_t i; |
| 460 | struct cam_hw_stop_args stop; |
| 461 | struct cam_ctx_request *req; |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 462 | struct list_head temp_list; |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 463 | |
Pavan Kumar Chilamkurthi | ca2295d | 2017-07-30 01:50:59 -0700 | [diff] [blame] | 464 | if (!ctx) { |
| 465 | CAM_ERR(CAM_CTXT, "Invalid input param"); |
| 466 | rc = -EINVAL; |
| 467 | goto end; |
| 468 | } |
| 469 | |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 470 | if (!ctx->hw_mgr_intf) { |
Lakshmi Narayana Kalavala | adc6ce3 | 2017-07-17 17:19:11 -0700 | [diff] [blame] | 471 | CAM_ERR(CAM_CTXT, "HW interface is not ready"); |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 472 | rc = -EFAULT; |
| 473 | goto end; |
| 474 | } |
| 475 | |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 476 | rc = cam_context_validate_thread(); |
| 477 | if (rc) |
| 478 | goto end; |
| 479 | |
| 480 | /* |
| 481 | * flush pending requests, take the sync lock to synchronize with the |
| 482 | * sync callback thread so that the sync cb thread does not try to |
| 483 | * submit request to h/w while the request is being flushed |
| 484 | */ |
| 485 | mutex_lock(&ctx->sync_mutex); |
| 486 | INIT_LIST_HEAD(&temp_list); |
| 487 | spin_lock(&ctx->lock); |
| 488 | list_splice_init(&ctx->pending_req_list, &temp_list); |
| 489 | spin_unlock(&ctx->lock); |
| 490 | while (!list_empty(&temp_list)) { |
| 491 | req = list_first_entry(&temp_list, |
| 492 | struct cam_ctx_request, list); |
| 493 | list_del_init(&req->list); |
| 494 | req->flushed = 1; |
| 495 | for (i = 0; i < req->num_out_map_entries; i++) |
| 496 | if (req->out_map_entries[i].sync_id != -1) |
| 497 | cam_sync_signal(req->out_map_entries[i].sync_id, |
| 498 | CAM_SYNC_STATE_SIGNALED_ERROR); |
| 499 | } |
| 500 | mutex_unlock(&ctx->sync_mutex); |
| 501 | |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 502 | /* stop hw first */ |
| 503 | if (ctx->ctxt_to_hw_map) { |
| 504 | stop.ctxt_to_hw_map = ctx->ctxt_to_hw_map; |
| 505 | if (ctx->hw_mgr_intf->hw_stop) |
| 506 | ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv, |
| 507 | &stop); |
| 508 | } |
| 509 | |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 510 | /* |
| 511 | * flush active queue, at this point h/w layer below does not have any |
| 512 | * reference to requests in active queue. |
| 513 | */ |
| 514 | INIT_LIST_HEAD(&temp_list); |
| 515 | spin_lock(&ctx->lock); |
| 516 | list_splice_init(&ctx->active_req_list, &temp_list); |
| 517 | spin_unlock(&ctx->lock); |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 518 | |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 519 | while (!list_empty(&temp_list)) { |
| 520 | req = list_first_entry(&temp_list, |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 521 | struct cam_ctx_request, list); |
| 522 | list_del_init(&req->list); |
Lakshmi Narayana Kalavala | adc6ce3 | 2017-07-17 17:19:11 -0700 | [diff] [blame] | 523 | CAM_DBG(CAM_CTXT, "signal fence in active list. fence num %d", |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 524 | req->num_out_map_entries); |
| 525 | for (i = 0; i < req->num_out_map_entries; i++) |
| 526 | if (req->out_map_entries[i].sync_id != -1) |
| 527 | cam_sync_signal(req->out_map_entries[i].sync_id, |
| 528 | CAM_SYNC_STATE_SIGNALED_ERROR); |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 529 | /* |
| 530 | * The spin lock should be taken here to guard the free list, |
| 531 | * as sync cb thread could be adding a pending req to free list |
| 532 | */ |
| 533 | spin_lock(&ctx->lock); |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 534 | list_add_tail(&req->list, &ctx->free_req_list); |
Shubhraprakash Das | 45ca2fe | 2017-10-07 14:29:30 -0700 | [diff] [blame] | 535 | req->ctx = NULL; |
| 536 | spin_unlock(&ctx->lock); |
Lakshmi Narayana Kalavala | 85c4035 | 2017-05-15 16:19:13 -0700 | [diff] [blame] | 537 | } |
| 538 | |
| 539 | end: |
| 540 | return rc; |
| 541 | } |
| 542 | |