1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright 2023, Intel Corporation. 4 */ 5 6 #include <drm/intel/i915_hdcp_interface.h> 7 8 #include "gem/i915_gem_region.h" 9 #include "gt/intel_gt.h" 10 #include "gt/uc/intel_gsc_uc_heci_cmd_submit.h" 11 #include "i915_drv.h" 12 #include "i915_utils.h" 13 #include "intel_hdcp_gsc.h" 14 #include "intel_hdcp_gsc_message.h" 15 16 struct intel_hdcp_gsc_message { 17 struct i915_vma *vma; 18 void *hdcp_cmd_in; 19 void *hdcp_cmd_out; 20 }; 21 22 bool intel_hdcp_gsc_cs_required(struct intel_display *display) 23 { 24 return DISPLAY_VER(display) >= 14; 25 } 26 27 bool intel_hdcp_gsc_check_status(struct intel_display *display) 28 { 29 struct drm_i915_private *i915 = to_i915(display->drm); 30 struct intel_gt *gt = i915->media_gt; 31 struct intel_gsc_uc *gsc = gt ? >->uc.gsc : NULL; 32 33 if (!gsc || !intel_uc_fw_is_running(&gsc->fw)) { 34 drm_dbg_kms(display->drm, 35 "GSC components required for HDCP2.2 are not ready\n"); 36 return false; 37 } 38 39 return true; 40 } 41 42 /*This function helps allocate memory for the command that we will send to gsc cs */ 43 static int intel_hdcp_gsc_initialize_message(struct drm_i915_private *i915, 44 struct intel_hdcp_gsc_message *hdcp_message) 45 { 46 struct intel_gt *gt = i915->media_gt; 47 struct drm_i915_gem_object *obj = NULL; 48 struct i915_vma *vma = NULL; 49 void *cmd_in, *cmd_out; 50 int err; 51 52 /* allocate object of two page for HDCP command memory and store it */ 53 obj = i915_gem_object_create_shmem(i915, 2 * PAGE_SIZE); 54 55 if (IS_ERR(obj)) { 56 drm_err(&i915->drm, "Failed to allocate HDCP streaming command!\n"); 57 return PTR_ERR(obj); 58 } 59 60 cmd_in = i915_gem_object_pin_map_unlocked(obj, intel_gt_coherent_map_type(gt, obj, true)); 61 if (IS_ERR(cmd_in)) { 62 drm_err(&i915->drm, "Failed to map gsc message page!\n"); 63 err = PTR_ERR(cmd_in); 64 goto out_unpin; 65 } 66 67 cmd_out = cmd_in + PAGE_SIZE; 68 69 vma = i915_vma_instance(obj, >->ggtt->vm, NULL); 70 if (IS_ERR(vma)) { 71 err = PTR_ERR(vma); 72 goto out_unmap; 73 } 74 75 err = i915_vma_pin(vma, 0, 0, PIN_GLOBAL | PIN_HIGH); 76 if (err) 77 goto out_unmap; 78 79 memset(cmd_in, 0, obj->base.size); 80 81 hdcp_message->hdcp_cmd_in = cmd_in; 82 hdcp_message->hdcp_cmd_out = cmd_out; 83 hdcp_message->vma = vma; 84 85 return 0; 86 87 out_unmap: 88 i915_gem_object_unpin_map(obj); 89 out_unpin: 90 i915_gem_object_put(obj); 91 return err; 92 } 93 94 static const struct i915_hdcp_ops gsc_hdcp_ops = { 95 .initiate_hdcp2_session = intel_hdcp_gsc_initiate_session, 96 .verify_receiver_cert_prepare_km = 97 intel_hdcp_gsc_verify_receiver_cert_prepare_km, 98 .verify_hprime = intel_hdcp_gsc_verify_hprime, 99 .store_pairing_info = intel_hdcp_gsc_store_pairing_info, 100 .initiate_locality_check = intel_hdcp_gsc_initiate_locality_check, 101 .verify_lprime = intel_hdcp_gsc_verify_lprime, 102 .get_session_key = intel_hdcp_gsc_get_session_key, 103 .repeater_check_flow_prepare_ack = 104 intel_hdcp_gsc_repeater_check_flow_prepare_ack, 105 .verify_mprime = intel_hdcp_gsc_verify_mprime, 106 .enable_hdcp_authentication = intel_hdcp_gsc_enable_authentication, 107 .close_hdcp_session = intel_hdcp_gsc_close_session, 108 }; 109 110 static int intel_hdcp_gsc_hdcp2_init(struct intel_display *display) 111 { 112 struct drm_i915_private *i915 = to_i915(display->drm); 113 struct intel_hdcp_gsc_message *hdcp_message; 114 int ret; 115 116 hdcp_message = kzalloc(sizeof(*hdcp_message), GFP_KERNEL); 117 118 if (!hdcp_message) 119 return -ENOMEM; 120 121 /* 122 * NOTE: No need to lock the comp mutex here as it is already 123 * going to be taken before this function called 124 */ 125 display->hdcp.hdcp_message = hdcp_message; 126 ret = intel_hdcp_gsc_initialize_message(i915, hdcp_message); 127 128 if (ret) 129 drm_err(display->drm, "Could not initialize hdcp_message\n"); 130 131 return ret; 132 } 133 134 static void intel_hdcp_gsc_free_message(struct intel_display *display) 135 { 136 struct intel_hdcp_gsc_message *hdcp_message = 137 display->hdcp.hdcp_message; 138 139 hdcp_message->hdcp_cmd_in = NULL; 140 hdcp_message->hdcp_cmd_out = NULL; 141 i915_vma_unpin_and_release(&hdcp_message->vma, I915_VMA_RELEASE_MAP); 142 kfree(hdcp_message); 143 } 144 145 int intel_hdcp_gsc_init(struct intel_display *display) 146 { 147 struct i915_hdcp_arbiter *data; 148 int ret; 149 150 data = kzalloc(sizeof(struct i915_hdcp_arbiter), GFP_KERNEL); 151 if (!data) 152 return -ENOMEM; 153 154 mutex_lock(&display->hdcp.hdcp_mutex); 155 display->hdcp.arbiter = data; 156 display->hdcp.arbiter->hdcp_dev = display->drm->dev; 157 display->hdcp.arbiter->ops = &gsc_hdcp_ops; 158 ret = intel_hdcp_gsc_hdcp2_init(display); 159 mutex_unlock(&display->hdcp.hdcp_mutex); 160 161 return ret; 162 } 163 164 void intel_hdcp_gsc_fini(struct intel_display *display) 165 { 166 intel_hdcp_gsc_free_message(display); 167 kfree(display->hdcp.arbiter); 168 } 169 170 static int intel_gsc_send_sync(struct drm_i915_private *i915, 171 struct intel_gsc_mtl_header *header_in, 172 struct intel_gsc_mtl_header *header_out, 173 u64 addr_in, u64 addr_out, 174 size_t msg_out_len) 175 { 176 struct intel_gt *gt = i915->media_gt; 177 int ret; 178 179 ret = intel_gsc_uc_heci_cmd_submit_packet(>->uc.gsc, addr_in, 180 header_in->message_size, 181 addr_out, 182 msg_out_len + sizeof(*header_out)); 183 if (ret) { 184 drm_err(&i915->drm, "failed to send gsc HDCP msg (%d)\n", ret); 185 return ret; 186 } 187 188 /* 189 * Checking validity marker and header status to see if some error has 190 * blocked us from sending message to gsc cs 191 */ 192 if (header_out->validity_marker != GSC_HECI_VALIDITY_MARKER) { 193 drm_err(&i915->drm, "invalid validity marker\n"); 194 return -EINVAL; 195 } 196 197 if (header_out->status != 0) { 198 drm_err(&i915->drm, "header status indicates error %d\n", 199 header_out->status); 200 return -EINVAL; 201 } 202 203 if (header_out->flags & GSC_OUTFLAG_MSG_PENDING) { 204 header_in->gsc_message_handle = header_out->gsc_message_handle; 205 return -EAGAIN; 206 } 207 208 return 0; 209 } 210 211 /* 212 * This function can now be used for sending requests and will also handle 213 * receipt of reply messages hence no different function of message retrieval 214 * is required. We will initialize intel_hdcp_gsc_message structure then add 215 * gsc cs memory header as stated in specs after which the normal HDCP payload 216 * will follow 217 */ 218 ssize_t intel_hdcp_gsc_msg_send(struct drm_i915_private *i915, u8 *msg_in, 219 size_t msg_in_len, u8 *msg_out, 220 size_t msg_out_len) 221 { 222 struct intel_gt *gt = i915->media_gt; 223 struct intel_gsc_mtl_header *header_in, *header_out; 224 const size_t max_msg_size = PAGE_SIZE - sizeof(*header_in); 225 struct intel_hdcp_gsc_message *hdcp_message; 226 u64 addr_in, addr_out, host_session_id; 227 u32 reply_size, msg_size_in, msg_size_out; 228 int ret, tries = 0; 229 230 if (!intel_uc_uses_gsc_uc(>->uc)) 231 return -ENODEV; 232 233 if (msg_in_len > max_msg_size || msg_out_len > max_msg_size) 234 return -ENOSPC; 235 236 msg_size_in = msg_in_len + sizeof(*header_in); 237 msg_size_out = msg_out_len + sizeof(*header_out); 238 hdcp_message = i915->display.hdcp.hdcp_message; 239 header_in = hdcp_message->hdcp_cmd_in; 240 header_out = hdcp_message->hdcp_cmd_out; 241 addr_in = i915_ggtt_offset(hdcp_message->vma); 242 addr_out = addr_in + PAGE_SIZE; 243 244 memset(header_in, 0, msg_size_in); 245 memset(header_out, 0, msg_size_out); 246 get_random_bytes(&host_session_id, sizeof(u64)); 247 intel_gsc_uc_heci_cmd_emit_mtl_header(header_in, HECI_MEADDRESS_HDCP, 248 msg_size_in, host_session_id); 249 memcpy(hdcp_message->hdcp_cmd_in + sizeof(*header_in), msg_in, msg_in_len); 250 251 /* 252 * Keep sending request in case the pending bit is set no need to add 253 * message handle as we are using same address hence loc. of header is 254 * same and it will contain the message handle. we will send the message 255 * 20 times each message 50 ms apart 256 */ 257 do { 258 ret = intel_gsc_send_sync(i915, header_in, header_out, addr_in, 259 addr_out, msg_out_len); 260 261 /* Only try again if gsc says so */ 262 if (ret != -EAGAIN) 263 break; 264 265 msleep(50); 266 267 } while (++tries < 20); 268 269 if (ret) 270 goto err; 271 272 /* we use the same mem for the reply, so header is in the same loc */ 273 reply_size = header_out->message_size - sizeof(*header_out); 274 if (reply_size > msg_out_len) { 275 drm_warn(&i915->drm, "caller with insufficient HDCP reply size %u (%d)\n", 276 reply_size, (u32)msg_out_len); 277 reply_size = msg_out_len; 278 } else if (reply_size != msg_out_len) { 279 drm_dbg_kms(&i915->drm, "caller unexpected HCDP reply size %u (%d)\n", 280 reply_size, (u32)msg_out_len); 281 } 282 283 memcpy(msg_out, hdcp_message->hdcp_cmd_out + sizeof(*header_out), msg_out_len); 284 285 err: 286 return ret; 287 } 288