Lines Matching full:gsc
29 * GSC proxy:
30 * The GSC uC needs to communicate with the CSME to perform certain operations.
31 * Since the GSC can't perform this communication directly on platforms where it
33 * GSC to CSME and back. The proxy flow must be manually started after the GSC
34 * is loaded to signal to GSC that we're ready to handle its messages and allow
35 * it to query its init data from CSME; GSC will then trigger an HECI2 interrupt
38 * 1 - Xe submits a request to GSC asking for the message to CSME
39 * 2 - GSC replies with the proxy header + payload for CSME
40 * 3 - Xe sends the reply from GSC as-is to CSME via the mei proxy component
41 * 4 - CSME replies with the proxy header + payload for GSC
42 * 5 - Xe submits a request to GSC with the reply from CSME
43 * 6 - GSC replies either with a new header + payload (same as step 2, so we
61 gsc_to_gt(struct xe_gsc *gsc) in gsc_to_gt() argument
63 return container_of(gsc, struct xe_gt, uc.gsc); in gsc_to_gt()
66 bool xe_gsc_proxy_init_done(struct xe_gsc *gsc) in xe_gsc_proxy_init_done() argument
68 struct xe_gt *gt = gsc_to_gt(gsc); in xe_gsc_proxy_init_done()
75 int xe_gsc_wait_for_proxy_init_done(struct xe_gsc *gsc) in xe_gsc_wait_for_proxy_init_done() argument
77 struct xe_gt *gt = gsc_to_gt(gsc); in xe_gsc_wait_for_proxy_init_done()
86 static void __gsc_proxy_irq_rmw(struct xe_gsc *gsc, u32 clr, u32 set) in __gsc_proxy_irq_rmw() argument
88 struct xe_gt *gt = gsc_to_gt(gsc); in __gsc_proxy_irq_rmw()
96 static void gsc_proxy_irq_clear(struct xe_gsc *gsc) in gsc_proxy_irq_clear() argument
99 __gsc_proxy_irq_rmw(gsc, 0, HECI_H_CSR_IS); in gsc_proxy_irq_clear()
102 static void gsc_proxy_irq_toggle(struct xe_gsc *gsc, bool enabled) in gsc_proxy_irq_toggle() argument
107 __gsc_proxy_irq_rmw(gsc, clr, set); in gsc_proxy_irq_toggle()
110 static int proxy_send_to_csme(struct xe_gsc *gsc, u32 size) in proxy_send_to_csme() argument
112 struct xe_gt *gt = gsc_to_gt(gsc); in proxy_send_to_csme()
113 struct i915_gsc_proxy_component *comp = gsc->proxy.component; in proxy_send_to_csme()
116 ret = comp->ops->send(comp->mei_dev, gsc->proxy.to_csme, size); in proxy_send_to_csme()
122 ret = comp->ops->recv(comp->mei_dev, gsc->proxy.from_csme, GSC_PROXY_BUFFER_SIZE); in proxy_send_to_csme()
131 static int proxy_send_to_gsc(struct xe_gsc *gsc, u32 size) in proxy_send_to_gsc() argument
133 struct xe_gt *gt = gsc_to_gt(gsc); in proxy_send_to_gsc()
134 u64 addr_in = xe_bo_ggtt_addr(gsc->proxy.bo); in proxy_send_to_gsc()
138 /* the message must contain at least the gsc and proxy headers */ in proxy_send_to_gsc()
140 xe_gt_err(gt, "Invalid GSC proxy message size: %u\n", size); in proxy_send_to_gsc()
144 err = xe_gsc_pkt_submit_kernel(gsc, addr_in, size, in proxy_send_to_gsc()
147 xe_gt_err(gt, "Failed to submit gsc proxy rq (%pe)\n", ERR_PTR(err)); in proxy_send_to_gsc()
193 "GSC proxy error: s=0x%x[0x%x], d=0x%x[0x%x], t=%u, l=0x%x, st=0x%x\n", in validate_proxy_header()
221 static int proxy_query(struct xe_gsc *gsc) in proxy_query() argument
223 struct xe_gt *gt = gsc_to_gt(gsc); in proxy_query()
225 struct xe_gsc_proxy_header *to_csme_hdr = gsc->proxy.to_csme; in proxy_query()
226 void *to_csme_payload = gsc->proxy.to_csme + PROXY_HDR_SIZE; in proxy_query()
232 wr_offset = xe_gsc_emit_header(xe, &gsc->proxy.to_gsc, 0, in proxy_query()
234 wr_offset = emit_proxy_header(xe, &gsc->proxy.to_gsc, wr_offset); in proxy_query()
240 * Poison the GSC response header space to make sure we don't in proxy_query()
243 xe_gsc_poison_header(xe, &gsc->proxy.from_gsc, 0); in proxy_query()
245 /* send proxy message to GSC */ in proxy_query()
246 ret = proxy_send_to_gsc(gsc, size); in proxy_query()
250 /* check the reply from GSC */ in proxy_query()
251 ret = xe_gsc_read_out_header(xe, &gsc->proxy.from_gsc, 0, in proxy_query()
254 xe_gt_err(gt, "Invalid gsc header in proxy reply (%pe)\n", in proxy_query()
259 /* copy the proxy header reply from GSC */ in proxy_query()
260 xe_map_memcpy_from(xe, to_csme_hdr, &gsc->proxy.from_gsc, in proxy_query()
272 /* make sure the GSC-to-CSME proxy header is sane */ in proxy_query()
278 xe_gt_err(gt, "invalid GSC to CSME proxy header! (%pe)\n", in proxy_query()
285 xe_map_memcpy_from(xe, to_csme_payload, &gsc->proxy.from_gsc, in proxy_query()
288 /* send the GSC message to the CSME */ in proxy_query()
289 ret = proxy_send_to_csme(gsc, size + PROXY_HDR_SIZE); in proxy_query()
296 xe_gt_err(gt, "CSME to GSC proxy msg too small: 0x%x\n", size); in proxy_query()
301 /* make sure the CSME-to-GSC proxy header is sane */ in proxy_query()
302 ret = validate_proxy_header(gt, gsc->proxy.from_csme, in proxy_query()
307 xe_gt_err(gt, "invalid CSME to GSC proxy header! %d\n", ret); in proxy_query()
311 /* Emit a new header for sending the reply to the GSC */ in proxy_query()
312 wr_offset = xe_gsc_emit_header(xe, &gsc->proxy.to_gsc, 0, in proxy_query()
315 /* copy the CSME reply and update the total msg size to include the GSC header */ in proxy_query()
316 xe_map_memcpy_to(xe, &gsc->proxy.to_gsc, wr_offset, gsc->proxy.from_csme, size); in proxy_query()
325 int xe_gsc_proxy_request_handler(struct xe_gsc *gsc) in xe_gsc_proxy_request_handler() argument
327 struct xe_gt *gt = gsc_to_gt(gsc); in xe_gsc_proxy_request_handler()
331 if (!gsc->proxy.component_added) in xe_gsc_proxy_request_handler()
334 /* when GSC is loaded, we can queue this before the component is bound */ in xe_gsc_proxy_request_handler()
336 if (gsc->proxy.component) in xe_gsc_proxy_request_handler()
342 mutex_lock(&gsc->proxy.mutex); in xe_gsc_proxy_request_handler()
343 if (!gsc->proxy.component) { in xe_gsc_proxy_request_handler()
344 xe_gt_err(gt, "GSC proxy component not bound!\n"); in xe_gsc_proxy_request_handler()
351 gsc_proxy_irq_clear(gsc); in xe_gsc_proxy_request_handler()
352 err = proxy_query(gsc); in xe_gsc_proxy_request_handler()
354 mutex_unlock(&gsc->proxy.mutex); in xe_gsc_proxy_request_handler()
358 void xe_gsc_proxy_irq_handler(struct xe_gsc *gsc, u32 iir) in xe_gsc_proxy_irq_handler() argument
360 struct xe_gt *gt = gsc_to_gt(gsc); in xe_gsc_proxy_irq_handler()
365 if (!gsc->proxy.component) { in xe_gsc_proxy_irq_handler()
366 xe_gt_err(gt, "GSC proxy irq received without the component being bound!\n"); in xe_gsc_proxy_irq_handler()
370 spin_lock(&gsc->lock); in xe_gsc_proxy_irq_handler()
371 gsc->work_actions |= GSC_ACTION_SW_PROXY; in xe_gsc_proxy_irq_handler()
372 spin_unlock(&gsc->lock); in xe_gsc_proxy_irq_handler()
374 queue_work(gsc->wq, &gsc->work); in xe_gsc_proxy_irq_handler()
382 struct xe_gsc *gsc = >->uc.gsc; in xe_gsc_proxy_component_bind() local
384 mutex_lock(&gsc->proxy.mutex); in xe_gsc_proxy_component_bind()
385 gsc->proxy.component = data; in xe_gsc_proxy_component_bind()
386 gsc->proxy.component->mei_dev = mei_kdev; in xe_gsc_proxy_component_bind()
387 mutex_unlock(&gsc->proxy.mutex); in xe_gsc_proxy_component_bind()
397 struct xe_gsc *gsc = >->uc.gsc; in xe_gsc_proxy_component_unbind() local
399 xe_gsc_wait_for_worker_completion(gsc); in xe_gsc_proxy_component_unbind()
401 mutex_lock(&gsc->proxy.mutex); in xe_gsc_proxy_component_unbind()
402 gsc->proxy.component = NULL; in xe_gsc_proxy_component_unbind()
403 mutex_unlock(&gsc->proxy.mutex); in xe_gsc_proxy_component_unbind()
411 static int proxy_channel_alloc(struct xe_gsc *gsc) in proxy_channel_alloc() argument
413 struct xe_gt *gt = gsc_to_gt(gsc); in proxy_channel_alloc()
429 gsc->proxy.bo = bo; in proxy_channel_alloc()
430 gsc->proxy.to_gsc = IOSYS_MAP_INIT_OFFSET(&bo->vmap, 0); in proxy_channel_alloc()
431 gsc->proxy.from_gsc = IOSYS_MAP_INIT_OFFSET(&bo->vmap, GSC_PROXY_BUFFER_SIZE); in proxy_channel_alloc()
432 gsc->proxy.to_csme = csme; in proxy_channel_alloc()
433 gsc->proxy.from_csme = csme + GSC_PROXY_BUFFER_SIZE; in proxy_channel_alloc()
440 struct xe_gsc *gsc = arg; in xe_gsc_proxy_remove() local
441 struct xe_gt *gt = gsc_to_gt(gsc); in xe_gsc_proxy_remove()
445 if (!gsc->proxy.component_added) in xe_gsc_proxy_remove()
452 xe_gt_err(gt, "failed to get forcewake to disable GSC interrupts\n"); in xe_gsc_proxy_remove()
455 gsc_proxy_irq_toggle(gsc, false); in xe_gsc_proxy_remove()
460 xe_gsc_wait_for_worker_completion(gsc); in xe_gsc_proxy_remove()
463 gsc->proxy.component_added = false; in xe_gsc_proxy_remove()
467 * xe_gsc_proxy_init() - init objects and MEI component required by GSC proxy
468 * @gsc: the GSC uC
472 int xe_gsc_proxy_init(struct xe_gsc *gsc) in xe_gsc_proxy_init() argument
475 struct xe_gt *gt = gsc_to_gt(gsc); in xe_gsc_proxy_init()
479 mutex_init(&gsc->proxy.mutex); in xe_gsc_proxy_init()
482 xe_gt_info(gt, "can't init GSC proxy due to missing mei component\n"); in xe_gsc_proxy_init()
488 xe_gt_err(gt, "unexpected GSC proxy init on tile %u\n", tile->id); in xe_gsc_proxy_init()
492 err = proxy_channel_alloc(gsc); in xe_gsc_proxy_init()
503 gsc->proxy.component_added = true; in xe_gsc_proxy_init()
505 return devm_add_action_or_reset(xe->drm.dev, xe_gsc_proxy_remove, gsc); in xe_gsc_proxy_init()
510 * @gsc: the GSC uC
514 int xe_gsc_proxy_start(struct xe_gsc *gsc) in xe_gsc_proxy_start() argument
518 /* enable the proxy interrupt in the GSC shim layer */ in xe_gsc_proxy_start()
519 gsc_proxy_irq_toggle(gsc, true); in xe_gsc_proxy_start()
523 * notify the GSC that we're ready to support the proxy flow. in xe_gsc_proxy_start()
525 err = xe_gsc_proxy_request_handler(gsc); in xe_gsc_proxy_start()
529 if (!xe_gsc_proxy_init_done(gsc)) { in xe_gsc_proxy_start()
530 xe_gt_err(gsc_to_gt(gsc), "GSC FW reports proxy init not completed\n"); in xe_gsc_proxy_start()