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