@@ -1084,6 +1084,80 @@ long xe_bo_shrink(struct ttm_operation_ctx *ctx, struct ttm_buffer_object *bo,
10841084 return lret ;
10851085}
10861086
1087+ /**
1088+ * xe_bo_notifier_prepare_pinned() - Prepare a pinned VRAM object to be backed
1089+ * up in system memory.
1090+ * @bo: The buffer object to prepare.
1091+ *
1092+ * On successful completion, the object backup pages are allocated. Expectation
1093+ * is that this is called from the PM notifier, prior to suspend/hibernation.
1094+ *
1095+ * Return: 0 on success. Negative error code on failure.
1096+ */
1097+ int xe_bo_notifier_prepare_pinned (struct xe_bo * bo )
1098+ {
1099+ struct xe_device * xe = ttm_to_xe_device (bo -> ttm .bdev );
1100+ struct xe_bo * backup ;
1101+ int ret = 0 ;
1102+
1103+ xe_bo_lock (bo , false);
1104+
1105+ xe_assert (xe , !bo -> backup_obj );
1106+
1107+ /*
1108+ * Since this is called from the PM notifier we might have raced with
1109+ * someone unpinning this after we dropped the pinned list lock and
1110+ * grabbing the above bo lock.
1111+ */
1112+ if (!xe_bo_is_pinned (bo ))
1113+ goto out_unlock_bo ;
1114+
1115+ if (!xe_bo_is_vram (bo ))
1116+ goto out_unlock_bo ;
1117+
1118+ if (bo -> flags & XE_BO_FLAG_PINNED_NORESTORE )
1119+ goto out_unlock_bo ;
1120+
1121+ backup = ___xe_bo_create_locked (xe , NULL , NULL , bo -> ttm .base .resv , NULL , bo -> size ,
1122+ DRM_XE_GEM_CPU_CACHING_WB , ttm_bo_type_kernel ,
1123+ XE_BO_FLAG_SYSTEM | XE_BO_FLAG_NEEDS_CPU_ACCESS |
1124+ XE_BO_FLAG_PINNED );
1125+ if (IS_ERR (backup )) {
1126+ ret = PTR_ERR (backup );
1127+ goto out_unlock_bo ;
1128+ }
1129+
1130+ backup -> parent_obj = xe_bo_get (bo ); /* Released by bo_destroy */
1131+ ttm_bo_pin (& backup -> ttm );
1132+ bo -> backup_obj = backup ;
1133+
1134+ out_unlock_bo :
1135+ xe_bo_unlock (bo );
1136+ return ret ;
1137+ }
1138+
1139+ /**
1140+ * xe_bo_notifier_unprepare_pinned() - Undo the previous prepare operation.
1141+ * @bo: The buffer object to undo the prepare for.
1142+ *
1143+ * Always returns 0. The backup object is removed, if still present. Expectation
1144+ * it that this called from the PM notifier when undoing the prepare step.
1145+ *
1146+ * Return: Always returns 0.
1147+ */
1148+ int xe_bo_notifier_unprepare_pinned (struct xe_bo * bo )
1149+ {
1150+ xe_bo_lock (bo , false);
1151+ if (bo -> backup_obj ) {
1152+ ttm_bo_unpin (& bo -> backup_obj -> ttm );
1153+ xe_bo_put (bo -> backup_obj );
1154+ bo -> backup_obj = NULL ;
1155+ }
1156+ xe_bo_unlock (bo );
1157+
1158+ return 0 ;
1159+ }
1160+
10871161/**
10881162 * xe_bo_evict_pinned() - Evict a pinned VRAM object to system memory
10891163 * @bo: The buffer object to move.
@@ -1098,7 +1172,8 @@ long xe_bo_shrink(struct ttm_operation_ctx *ctx, struct ttm_buffer_object *bo,
10981172int xe_bo_evict_pinned (struct xe_bo * bo )
10991173{
11001174 struct xe_device * xe = ttm_to_xe_device (bo -> ttm .bdev );
1101- struct xe_bo * backup ;
1175+ struct xe_bo * backup = bo -> backup_obj ;
1176+ bool backup_created = false;
11021177 bool unmap = false;
11031178 int ret = 0 ;
11041179
@@ -1120,15 +1195,18 @@ int xe_bo_evict_pinned(struct xe_bo *bo)
11201195 if (bo -> flags & XE_BO_FLAG_PINNED_NORESTORE )
11211196 goto out_unlock_bo ;
11221197
1123- backup = ___xe_bo_create_locked (xe , NULL , NULL , bo -> ttm .base .resv , NULL , bo -> size ,
1124- DRM_XE_GEM_CPU_CACHING_WB , ttm_bo_type_kernel ,
1125- XE_BO_FLAG_SYSTEM | XE_BO_FLAG_NEEDS_CPU_ACCESS |
1126- XE_BO_FLAG_PINNED );
1127- if (IS_ERR (backup )) {
1128- ret = PTR_ERR (backup );
1129- goto out_unlock_bo ;
1198+ if (!backup ) {
1199+ backup = ___xe_bo_create_locked (xe , NULL , NULL , bo -> ttm .base .resv , NULL , bo -> size ,
1200+ DRM_XE_GEM_CPU_CACHING_WB , ttm_bo_type_kernel ,
1201+ XE_BO_FLAG_SYSTEM | XE_BO_FLAG_NEEDS_CPU_ACCESS |
1202+ XE_BO_FLAG_PINNED );
1203+ if (IS_ERR (backup )) {
1204+ ret = PTR_ERR (backup );
1205+ goto out_unlock_bo ;
1206+ }
1207+ backup -> parent_obj = xe_bo_get (bo ); /* Released by bo_destroy */
1208+ backup_created = true;
11301209 }
1131- backup -> parent_obj = xe_bo_get (bo ); /* Released by bo_destroy */
11321210
11331211 if (xe_bo_is_user (bo ) || (bo -> flags & XE_BO_FLAG_PINNED_LATE_RESTORE )) {
11341212 struct xe_migrate * migrate ;
@@ -1175,11 +1253,12 @@ int xe_bo_evict_pinned(struct xe_bo *bo)
11751253 bo -> size );
11761254 }
11771255
1178- bo -> backup_obj = backup ;
1256+ if (!bo -> backup_obj )
1257+ bo -> backup_obj = backup ;
11791258
11801259out_backup :
11811260 xe_bo_vunmap (backup );
1182- if (ret )
1261+ if (ret && backup_created )
11831262 xe_bo_put (backup );
11841263out_unlock_bo :
11851264 if (unmap )
@@ -1215,9 +1294,11 @@ int xe_bo_restore_pinned(struct xe_bo *bo)
12151294
12161295 xe_bo_lock (bo , false);
12171296
1218- ret = ttm_bo_validate (& backup -> ttm , & backup -> placement , & ctx );
1219- if (ret )
1220- goto out_backup ;
1297+ if (!xe_bo_is_pinned (backup )) {
1298+ ret = ttm_bo_validate (& backup -> ttm , & backup -> placement , & ctx );
1299+ if (ret )
1300+ goto out_unlock_bo ;
1301+ }
12211302
12221303 if (xe_bo_is_user (bo ) || (bo -> flags & XE_BO_FLAG_PINNED_LATE_RESTORE )) {
12231304 struct xe_migrate * migrate ;
@@ -1257,7 +1338,7 @@ int xe_bo_restore_pinned(struct xe_bo *bo)
12571338 if (iosys_map_is_null (& bo -> vmap )) {
12581339 ret = xe_bo_vmap (bo );
12591340 if (ret )
1260- goto out_unlock_bo ;
1341+ goto out_backup ;
12611342 unmap = true;
12621343 }
12631344
@@ -1269,8 +1350,11 @@ int xe_bo_restore_pinned(struct xe_bo *bo)
12691350
12701351out_backup :
12711352 xe_bo_vunmap (backup );
1272- if (!bo -> backup_obj )
1353+ if (!bo -> backup_obj ) {
1354+ if (xe_bo_is_pinned (backup ))
1355+ ttm_bo_unpin (& backup -> ttm );
12731356 xe_bo_put (backup );
1357+ }
12741358out_unlock_bo :
12751359 if (unmap )
12761360 xe_bo_vunmap (bo );
@@ -2304,6 +2388,13 @@ void xe_bo_unpin(struct xe_bo *bo)
23042388 xe_assert (xe , !list_empty (& bo -> pinned_link ));
23052389 list_del_init (& bo -> pinned_link );
23062390 spin_unlock (& xe -> pinned .lock );
2391+
2392+ if (bo -> backup_obj ) {
2393+ if (xe_bo_is_pinned (bo -> backup_obj ))
2394+ ttm_bo_unpin (& bo -> backup_obj -> ttm );
2395+ xe_bo_put (bo -> backup_obj );
2396+ bo -> backup_obj = NULL ;
2397+ }
23072398 }
23082399 ttm_bo_unpin (& bo -> ttm );
23092400 if (bo -> ttm .ttm && ttm_tt_is_populated (bo -> ttm .ttm ))
0 commit comments