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