[PATCH 02/13] drm/i915/guc: Update MMIO based communication

Daniele Ceraolo Spurio daniele.ceraolospurio at intel.com
Wed Jun 9 01:03:18 UTC 2021


<snip>

>>>    #endif /* _ABI_GUC_COMMUNICATION_MMIO_ABI_H */
>>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
>>> b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
>>> index f147cb389a20..b773567cb080 100644
>>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
>>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
>>> @@ -376,29 +376,27 @@ void intel_guc_fini(struct intel_guc *guc)
>>>    /*
>>>     * This function implements the MMIO based host to GuC interface.
>>>     */
>>> -int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32
>>> len,
>>> +int intel_guc_send_mmio(struct intel_guc *guc, const u32 *request,
>>> u32 len,
>>>                u32 *response_buf, u32 response_buf_size)
>>>    {
>>> +    struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
>>>        struct intel_uncore *uncore = guc_to_gt(guc)->uncore;
>>> -    u32 status;
>>> +    u32 header;
>>>        int i;
>>>        int ret;
>>>          GEM_BUG_ON(!len);
>>>        GEM_BUG_ON(len > guc->send_regs.count);
>>>    -    /* We expect only action code */
>>> -    GEM_BUG_ON(*action & ~INTEL_GUC_MSG_CODE_MASK);
>>> -
>>> -    /* If CT is available, we expect to use MMIO only during
>>> init/fini */
>>> -    GEM_BUG_ON(*action !=
>>> INTEL_GUC_ACTION_REGISTER_COMMAND_TRANSPORT_BUFFER &&
>>> -           *action !=
>>> INTEL_GUC_ACTION_DEREGISTER_COMMAND_TRANSPORT_BUFFER);
>>> +    GEM_BUG_ON(FIELD_GET(GUC_HXG_MSG_0_ORIGIN, request[0]) !=
>>> GUC_HXG_ORIGIN_HOST);
>>> +    GEM_BUG_ON(FIELD_GET(GUC_HXG_MSG_0_TYPE, request[0]) !=
>>> GUC_HXG_TYPE_REQUEST);
>>>          mutex_lock(&guc->send_mutex);
>>>        intel_uncore_forcewake_get(uncore, guc->send_regs.fw_domains);
>>>    +retry:
>>>        for (i = 0; i < len; i++)
>>> -        intel_uncore_write(uncore, guc_send_reg(guc, i), action[i]);
>>> +        intel_uncore_write(uncore, guc_send_reg(guc, i), request[i]);
>>>          intel_uncore_posting_read(uncore, guc_send_reg(guc, i - 1));
>>>    @@ -410,30 +408,74 @@ int intel_guc_send_mmio(struct intel_guc *guc,
>>> const u32 *action, u32 len,
>>>         */
>>>        ret = __intel_wait_for_register_fw(uncore,
>>>                           guc_send_reg(guc, 0),
>>> -                       INTEL_GUC_MSG_TYPE_MASK,
>>> -                       INTEL_GUC_MSG_TYPE_RESPONSE <<
>>> -                       INTEL_GUC_MSG_TYPE_SHIFT,
>>> -                       10, 10, &status);
>>> -    /* If GuC explicitly returned an error, convert it to -EIO */
>>> -    if (!ret && !INTEL_GUC_MSG_IS_RESPONSE_SUCCESS(status))
>>> -        ret = -EIO;
>>> +                       GUC_HXG_MSG_0_ORIGIN,
>>> +                       FIELD_PREP(GUC_HXG_MSG_0_ORIGIN,
>>> +                              GUC_HXG_ORIGIN_GUC),
>>> +                       10, 10, &header);
>>> +    if (unlikely(ret)) {
>>> +timeout:
>>> +        drm_err(&i915->drm, "mmio request %#x: no reply %x\n",
>>> +            request[0], header);
>>> +        goto out;
>>> +    }
>>>    -    if (ret) {
>>> -        DRM_ERROR("MMIO: GuC action %#x failed with error %d %#x\n",
>>> -              action[0], ret, status);
>>> +    if (FIELD_GET(GUC_HXG_MSG_0_TYPE, header) ==
>>> GUC_HXG_TYPE_NO_RESPONSE_BUSY) {
>>> +#define done ({ header = intel_uncore_read(uncore, guc_send_reg(guc,
>>> 0)); \
>>> +        FIELD_GET(GUC_HXG_MSG_0_ORIGIN, header) != GUC_HXG_ORIGIN_GUC
>>> || \
>>> +        FIELD_GET(GUC_HXG_MSG_0_TYPE, header) !=
>>> GUC_HXG_TYPE_NO_RESPONSE_BUSY; })
>>> +
>>> +        ret = wait_for(done, 1000);
>>> +        if (unlikely(ret))
>>> +            goto timeout;
>>> +        if (unlikely(FIELD_GET(GUC_HXG_MSG_0_ORIGIN, header) !=
>>> +                       GUC_HXG_ORIGIN_GUC))
>>> +            goto proto;
>>> +#undef done
>>> +    }
>>> +
>>> +    if (FIELD_GET(GUC_HXG_MSG_0_TYPE, header) ==
>>> GUC_HXG_TYPE_NO_RESPONSE_RETRY) {
>>> +        u32 reason = FIELD_GET(GUC_HXG_RETRY_MSG_0_REASON, header);
>>> +
>>> +        drm_dbg(&i915->drm, "mmio request %#x: retrying, reason %u\n",
>>> +            request[0], reason);
>>> +        goto retry;
>>> +    }
>>> +
>>> +    if (FIELD_GET(GUC_HXG_MSG_0_TYPE, header) ==
>>> GUC_HXG_TYPE_RESPONSE_FAILURE) {
>>> +        u32 hint = FIELD_GET(GUC_HXG_FAILURE_MSG_0_HINT, header);
>>> +        u32 error = FIELD_GET(GUC_HXG_FAILURE_MSG_0_ERROR, header);
>>> +
>>> +        drm_err(&i915->drm, "mmio request %#x: failure %x/%u\n",
>>> +            request[0], error, hint);
>>> +        ret = -ENXIO;
>>> +        goto out;
>>> +    }
>>> +
>>> +    if (FIELD_GET(GUC_HXG_MSG_0_TYPE, header) !=
>>> GUC_HXG_TYPE_RESPONSE_SUCCESS) {
>>> +proto:
>>> +        drm_err(&i915->drm, "mmio request %#x: unexpected reply %#x\n",
>>> +            request[0], header);
>>> +        ret = -EPROTO;
>>>            goto out;
>>>        }
>>>          if (response_buf) {
>>> -        int count = min(response_buf_size, guc->send_regs.count - 1);
>>> +        int count = min(response_buf_size, guc->send_regs.count);
>>>    -        for (i = 0; i < count; i++)
>>> +        GEM_BUG_ON(!count);
>>> +
>>> +        response_buf[0] = header;
>>> +
>>> +        for (i = 1; i < count; i++)
>>>                response_buf[i] = intel_uncore_read(uncore,
>>> -                                guc_send_reg(guc, i + 1));
>>> -    }
>>> +                                guc_send_reg(guc, i));
>> This could use a note in the commit message to remark that we have no
>> users for the returned data yet and therefore nothing will break if we
>> change what we return through it.
> I hope this will do the work:
>
> "Since some of the new MMIO actions may use DATA0 from MMIO HXG
> response, we must update intel_guc_send_mmio() to copy full response,
> including HXG header. There will be no impact to existing users as all
> of them are only relying just on return code."

Yes it does.

Daniele

>
>> Apart from the nits, the logic looks good to me.
>> Daniele
>>
>>>    -    /* Use data from the GuC response as our return value */
>>> -    ret = INTEL_GUC_MSG_TO_DATA(status);
>>> +        /* Use number of copied dwords as our return value */
>>> +        ret = count;
>>> +    } else {
>>> +        /* Use data from the GuC response as our return value */
>>> +        ret = FIELD_GET(GUC_HXG_RESPONSE_MSG_0_DATA0, header);
>>> +    }
>>>      out:
>>>        intel_uncore_forcewake_put(uncore, guc->send_regs.fw_domains);



More information about the dri-devel mailing list