[PATCH 2/2] drm/xe/guc: Add support for G2G communications

John Harrison john.c.harrison at intel.com
Tue Nov 19 00:53:18 UTC 2024


On 11/18/2024 08:34, Daniele Ceraolo Spurio wrote:
> <snip>
>
>>>
>>>> +}
>>>> +
>>>> +static bool xe_guc_g2g_wanted(struct xe_device *xe)
>>>> +{
>>>> +    /* Can't do GuC to GuC communication if there is only one GuC */
>>>> +    if (xe->info.gt_count <= 1)
>>>> +        return false;
>>>> +
>>>> +    /* No current user */
>>>> +    return false;
>>>> +}
>>>> +
>>>> +static int guc_g2g_alloc(struct xe_guc *guc)
>>>> +{
>>>> +    struct xe_gt *gt = guc_to_gt(guc);
>>>> +    struct xe_device *xe = gt_to_xe(gt);
>>>> +    struct xe_tile *tile = gt_to_tile(gt);
>>>> +    struct xe_bo *bo;
>>>> +    u32 g2g_size;
>>>> +
>>>> +    if (guc->g2g.bo)
>>>> +        return 0;
>>>> +
>>>> +    if (gt->info.id != 0) {
>>>> +        struct xe_gt *root_gt = xe_device_get_gt(xe, 0);
>>>> +        struct xe_guc *root_guc = &root_gt->uc.guc;
>>>> +        struct xe_bo *bo;
>>>> +
>>>> +        bo = xe_bo_get(root_guc->g2g.bo);
>>>> +        if (IS_ERR(bo))
>>>> +            return PTR_ERR(bo);
>>>> +
>>>> +        guc->g2g.bo = bo;
>>>> +        guc->g2g.owned = false;
>>>
>>> It doesn't look like you're actually using the "owned" variable 
>>> (which makes sense, because the BO is refcounted so it doesn't 
>>> matter which GuC it was originally allocated for)
>> Yeah, owned is only there for the selftest that comes later. But not 
>> including it now means the g2g structure only has a single entry, so 
>> really should not be a structure. Which suddenly makes the deltas for 
>> adding in owned later significantly larger!
>
> Can you explain why the selftest would need to know that? Can't review 
> it now if we can't see how it is supposed to be used.
Same as for below - so it can free and re-allocate as necessary.

>
>>
>> Having said that, as Matthew pointed out, the code is currently 
>> leaking reference counts as they are not auto-cleaned. So it does 
>> actually need a fini function which will use the owned field to 
>> decide whether to call put or not.
>
> Why? If you do a get() from every GuC then you need to do a put() from 
> every GuC, no need to check.
The root GT doesn't do a get. It has a reference automatically from 
having created the object. Same as all the other GuC related objects 
that get created but never have a get/put called on them.

John.

>
> Daniele
>
>>
>> John.
>>
>>
>>>
>>> Daniele
>>>
>>>> +        return 0;
>>>> +    }
>>>> +
>>>> +    g2g_size = guc_g2g_size(guc);
>>>> +    bo = xe_managed_bo_create_pin_map(xe, tile, g2g_size,
>>>> +                      XE_BO_FLAG_VRAM_IF_DGFX(tile) |
>>>> +                      XE_BO_FLAG_GGTT |
>>>> +                      XE_BO_FLAG_GGTT_ALL |
>>>> +                      XE_BO_FLAG_GGTT_INVALIDATE);
>>>> +    if (IS_ERR(bo))
>>>> +        return PTR_ERR(bo);
>>>> +
>>>> +    xe_map_memset(xe, &bo->vmap, 0, 0, g2g_size);
>>>> +    guc->g2g.bo = bo;
>>>> +    guc->g2g.owned = true;
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +
>>>> +static int guc_g2g_start(struct xe_guc *guc)
>>>> +{
>>>> +    struct xe_gt *far_gt, *gt = guc_to_gt(guc);
>>>> +    struct xe_device *xe = gt_to_xe(gt);
>>>> +    unsigned int i, j;
>>>> +    int t, err;
>>>> +    bool have_dev;
>>>> +
>>>> +    if (!guc->g2g.bo) {
>>>> +        int ret;
>>>> +
>>>> +        ret = guc_g2g_alloc(guc);
>>>> +        if (ret)
>>>> +            return ret;
>>>> +    }
>>>> +
>>>> +    /* GuC interface will need extending if more GT device types 
>>>> are ever created. */
>>>> +    xe_gt_assert(gt, (gt->info.type == XE_GT_TYPE_MAIN) || 
>>>> (gt->info.type == XE_GT_TYPE_MEDIA));
>>>> +
>>>> +    /* Channel numbering depends on whether there are multiple GTs 
>>>> per tile */
>>>> +    have_dev = xe->info.gt_count > xe->info.tile_count;
>>>> +
>>>> +    for_each_gt(far_gt, xe, i) {
>>>> +        u32 far_tile, far_dev;
>>>> +
>>>> +        if (far_gt->info.id == gt->info.id)
>>>> +            continue;
>>>> +
>>>> +        far_tile = gt_to_tile(far_gt)->id;
>>>> +        far_dev = G2G_DEV(far_gt);
>>>> +
>>>> +        for (t = 0; t < XE_G2G_TYPE_LIMIT; t++) {
>>>> +            err = guc_g2g_register(guc, far_gt, t, have_dev);
>>>> +            if (err) {
>>>> +                while (--t >= 0)
>>>> +                    guc_g2g_deregister(guc, far_tile, far_dev, t);
>>>> +                goto err_deregister;
>>>> +            }
>>>> +        }
>>>> +    }
>>>> +
>>>> +    return 0;
>>>> +
>>>> +err_deregister:
>>>> +    for_each_gt(far_gt, xe, j) {
>>>> +        u32 tile, dev;
>>>> +
>>>> +        if (far_gt->info.id == gt->info.id)
>>>> +            continue;
>>>> +
>>>> +        if (j >= i)
>>>> +            break;
>>>> +
>>>> +        tile = gt_to_tile(far_gt)->id;
>>>> +        dev = G2G_DEV(far_gt);
>>>> +
>>>> +        for (t = 0; t < XE_G2G_TYPE_LIMIT; t++)
>>>> +            guc_g2g_deregister(guc, tile, dev, t);
>>>> +    }
>>>> +
>>>> +    return err;
>>>> +}
>>>> +
>>>>   static void guc_fini_hw(void *arg)
>>>>   {
>>>>       struct xe_guc *guc = arg;
>>>> @@ -423,7 +688,16 @@ int xe_guc_init_post_hwconfig(struct xe_guc *guc)
>>>>     int xe_guc_post_load_init(struct xe_guc *guc)
>>>>   {
>>>> +    int ret;
>>>> +
>>>>       xe_guc_ads_populate_post_load(&guc->ads);
>>>> +
>>>> +    if (xe_guc_g2g_wanted(guc_to_xe(guc))) {
>>>> +        ret = guc_g2g_start(guc);
>>>> +        if (ret)
>>>> +            return ret;
>>>> +    }
>>>> +
>>>>       guc->submission_state.enabled = true;
>>>>         return 0;
>>>> diff --git a/drivers/gpu/drm/xe/xe_guc_types.h 
>>>> b/drivers/gpu/drm/xe/xe_guc_types.h
>>>> index fa75f57bf5da..83a41ebcdc91 100644
>>>> --- a/drivers/gpu/drm/xe/xe_guc_types.h
>>>> +++ b/drivers/gpu/drm/xe/xe_guc_types.h
>>>> @@ -64,6 +64,15 @@ struct xe_guc {
>>>>       struct xe_guc_pc pc;
>>>>       /** @dbm: GuC Doorbell Manager */
>>>>       struct xe_guc_db_mgr dbm;
>>>> +
>>>> +    /** @g2g: GuC to GuC communication state */
>>>> +    struct {
>>>> +        /** @g2g.bo: Storage for GuC to GuC communication channels */
>>>> +        struct xe_bo *bo;
>>>> +        /** @g2g.owned: Is the BO owned by this GT or just mapped 
>>>> in */
>>>> +        bool owned;
>>>> +    } g2g;
>>>> +
>>>>       /** @submission_state: GuC submission state */
>>>>       struct {
>>>>           /** @submission_state.idm: GuC context ID Manager */
>>>> @@ -79,6 +88,7 @@ struct xe_guc {
>>>>           /** @submission_state.fini_wq: submit fini wait queue */
>>>>           wait_queue_head_t fini_wq;
>>>>       } submission_state;
>>>> +
>>>>       /** @hwconfig: Hardware config state */
>>>>       struct {
>>>>           /** @hwconfig.bo: buffer object of the hardware config */
>>>
>>
>



More information about the Intel-xe mailing list