Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/xe/pf: Add helpers for VF GGTT migration data handling

In an upcoming change, the VF GGTT migration data will be handled as
part of VF control state machine. Add the necessary helpers to allow the
migration data transfer to/from the HW GGTT resource.

Reviewed-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Link: https://patch.msgid.link/20251112132220.516975-18-michal.winiarski@intel.com
Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>

+171
+104
drivers/gpu/drm/xe/xe_ggtt.c
··· 151 151 ggtt_update_access_counter(ggtt); 152 152 } 153 153 154 + static u64 xe_ggtt_get_pte(struct xe_ggtt *ggtt, u64 addr) 155 + { 156 + xe_tile_assert(ggtt->tile, !(addr & XE_PTE_MASK)); 157 + xe_tile_assert(ggtt->tile, addr < ggtt->size); 158 + 159 + return readq(&ggtt->gsm[addr >> XE_PTE_SHIFT]); 160 + } 161 + 154 162 static void xe_ggtt_clear(struct xe_ggtt *ggtt, u64 start, u64 size) 155 163 { 156 164 u16 pat_index = tile_to_xe(ggtt->tile)->pat.idx[XE_CACHE_WB]; ··· 241 233 static const struct xe_ggtt_pt_ops xelp_pt_ops = { 242 234 .pte_encode_flags = xelp_ggtt_pte_flags, 243 235 .ggtt_set_pte = xe_ggtt_set_pte, 236 + .ggtt_get_pte = xe_ggtt_get_pte, 244 237 }; 245 238 246 239 static const struct xe_ggtt_pt_ops xelpg_pt_ops = { 247 240 .pte_encode_flags = xelpg_ggtt_pte_flags, 248 241 .ggtt_set_pte = xe_ggtt_set_pte, 242 + .ggtt_get_pte = xe_ggtt_get_pte, 249 243 }; 250 244 251 245 static const struct xe_ggtt_pt_ops xelpg_pt_wa_ops = { 252 246 .pte_encode_flags = xelpg_ggtt_pte_flags, 253 247 .ggtt_set_pte = xe_ggtt_set_pte_and_flush, 248 + .ggtt_get_pte = xe_ggtt_get_pte, 254 249 }; 255 250 256 251 static void __xe_ggtt_init_early(struct xe_ggtt *ggtt, u32 reserved) ··· 709 698 } 710 699 711 700 /** 701 + * xe_ggtt_node_pt_size() - Get the size of page table entries needed to map a GGTT node. 702 + * @node: the &xe_ggtt_node 703 + * 704 + * Return: GGTT node page table entries size in bytes. 705 + */ 706 + size_t xe_ggtt_node_pt_size(const struct xe_ggtt_node *node) 707 + { 708 + if (!node) 709 + return 0; 710 + 711 + return node->base.size / XE_PAGE_SIZE * sizeof(u64); 712 + } 713 + 714 + /** 712 715 * xe_ggtt_map_bo - Map the BO into GGTT 713 716 * @ggtt: the &xe_ggtt where node will be mapped 714 717 * @node: the &xe_ggtt_node where this BO is mapped ··· 955 930 xe_ggtt_assign_locked(node->ggtt, &node->base, vfid); 956 931 mutex_unlock(&node->ggtt->lock); 957 932 } 933 + 934 + /** 935 + * xe_ggtt_node_save() - Save a &xe_ggtt_node to a buffer. 936 + * @node: the &xe_ggtt_node to be saved 937 + * @dst: destination buffer 938 + * @size: destination buffer size in bytes 939 + * @vfid: VF identifier 940 + * 941 + * Return: 0 on success or a negative error code on failure. 942 + */ 943 + int xe_ggtt_node_save(struct xe_ggtt_node *node, void *dst, size_t size, u16 vfid) 944 + { 945 + struct xe_ggtt *ggtt; 946 + u64 start, end; 947 + u64 *buf = dst; 948 + u64 pte; 949 + 950 + if (!node) 951 + return -ENOENT; 952 + 953 + guard(mutex)(&node->ggtt->lock); 954 + 955 + if (xe_ggtt_node_pt_size(node) != size) 956 + return -EINVAL; 957 + 958 + ggtt = node->ggtt; 959 + start = node->base.start; 960 + end = start + node->base.size - 1; 961 + 962 + while (start < end) { 963 + pte = ggtt->pt_ops->ggtt_get_pte(ggtt, start); 964 + if (vfid != u64_get_bits(pte, GGTT_PTE_VFID)) 965 + return -EPERM; 966 + 967 + *buf++ = u64_replace_bits(pte, 0, GGTT_PTE_VFID); 968 + start += XE_PAGE_SIZE; 969 + } 970 + 971 + return 0; 972 + } 973 + 974 + /** 975 + * xe_ggtt_node_load() - Load a &xe_ggtt_node from a buffer. 976 + * @node: the &xe_ggtt_node to be loaded 977 + * @src: source buffer 978 + * @size: source buffer size in bytes 979 + * @vfid: VF identifier 980 + * 981 + * Return: 0 on success or a negative error code on failure. 982 + */ 983 + int xe_ggtt_node_load(struct xe_ggtt_node *node, const void *src, size_t size, u16 vfid) 984 + { 985 + u64 vfid_pte = xe_encode_vfid_pte(vfid); 986 + const u64 *buf = src; 987 + struct xe_ggtt *ggtt; 988 + u64 start, end; 989 + 990 + if (!node) 991 + return -ENOENT; 992 + 993 + guard(mutex)(&node->ggtt->lock); 994 + 995 + if (xe_ggtt_node_pt_size(node) != size) 996 + return -EINVAL; 997 + 998 + ggtt = node->ggtt; 999 + start = node->base.start; 1000 + end = start + node->base.size - 1; 1001 + 1002 + while (start < end) { 1003 + vfid_pte = u64_replace_bits(*buf++, vfid, GGTT_PTE_VFID); 1004 + ggtt->pt_ops->ggtt_set_pte(ggtt, start, vfid_pte); 1005 + start += XE_PAGE_SIZE; 1006 + } 1007 + xe_ggtt_invalidate(ggtt); 1008 + 1009 + return 0; 1010 + } 1011 + 958 1012 #endif 959 1013 960 1014 /**
+3
drivers/gpu/drm/xe/xe_ggtt.h
··· 29 29 u32 size, u32 align, u32 mm_flags); 30 30 void xe_ggtt_node_remove(struct xe_ggtt_node *node, bool invalidate); 31 31 bool xe_ggtt_node_allocated(const struct xe_ggtt_node *node); 32 + size_t xe_ggtt_node_pt_size(const struct xe_ggtt_node *node); 32 33 void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_ggtt_node *node, 33 34 struct xe_bo *bo, u16 pat_index); 34 35 void xe_ggtt_map_bo_unlocked(struct xe_ggtt *ggtt, struct xe_bo *bo); ··· 44 43 45 44 #ifdef CONFIG_PCI_IOV 46 45 void xe_ggtt_assign(const struct xe_ggtt_node *node, u16 vfid); 46 + int xe_ggtt_node_save(struct xe_ggtt_node *node, void *dst, size_t size, u16 vfid); 47 + int xe_ggtt_node_load(struct xe_ggtt_node *node, const void *src, size_t size, u16 vfid); 47 48 #endif 48 49 49 50 #ifndef CONFIG_LOCKDEP
+2
drivers/gpu/drm/xe/xe_ggtt_types.h
··· 78 78 u64 (*pte_encode_flags)(struct xe_bo *bo, u16 pat_index); 79 79 /** @ggtt_set_pte: Directly write into GGTT's PTE */ 80 80 void (*ggtt_set_pte)(struct xe_ggtt *ggtt, u64 addr, u64 pte); 81 + /** @ggtt_get_pte: Directly read from GGTT's PTE */ 82 + u64 (*ggtt_get_pte)(struct xe_ggtt *ggtt, u64 addr); 81 83 }; 82 84 83 85 #endif
+57
drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c
··· 726 726 return xe_gt_sriov_pf_config_bulk_set_ggtt(gt, vfid, num_vfs, fair); 727 727 } 728 728 729 + /** 730 + * xe_gt_sriov_pf_config_ggtt_save() - Save a VF provisioned GGTT data into a buffer. 731 + * @gt: the &xe_gt 732 + * @vfid: VF identifier (can't be 0) 733 + * @buf: the GGTT data destination buffer (or NULL to query the buf size) 734 + * @size: the size of the buffer (or 0 to query the buf size) 735 + * 736 + * This function can only be called on PF. 737 + * 738 + * Return: size of the buffer needed to save GGTT data if querying, 739 + * 0 on successful save or a negative error code on failure. 740 + */ 741 + ssize_t xe_gt_sriov_pf_config_ggtt_save(struct xe_gt *gt, unsigned int vfid, 742 + void *buf, size_t size) 743 + { 744 + struct xe_ggtt_node *node; 745 + 746 + xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); 747 + xe_gt_assert(gt, vfid); 748 + xe_gt_assert(gt, !(!buf ^ !size)); 749 + 750 + guard(mutex)(xe_gt_sriov_pf_master_mutex(gt)); 751 + 752 + node = pf_pick_vf_config(gt, vfid)->ggtt_region; 753 + 754 + if (!buf) 755 + return xe_ggtt_node_pt_size(node); 756 + 757 + return xe_ggtt_node_save(node, buf, size, vfid); 758 + } 759 + 760 + /** 761 + * xe_gt_sriov_pf_config_ggtt_restore() - Restore a VF provisioned GGTT data from a buffer. 762 + * @gt: the &xe_gt 763 + * @vfid: VF identifier (can't be 0) 764 + * @buf: the GGTT data source buffer 765 + * @size: the size of the buffer 766 + * 767 + * This function can only be called on PF. 768 + * 769 + * Return: 0 on success or a negative error code on failure. 770 + */ 771 + int xe_gt_sriov_pf_config_ggtt_restore(struct xe_gt *gt, unsigned int vfid, 772 + const void *buf, size_t size) 773 + { 774 + struct xe_ggtt_node *node; 775 + 776 + xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); 777 + xe_gt_assert(gt, vfid); 778 + 779 + guard(mutex)(xe_gt_sriov_pf_master_mutex(gt)); 780 + 781 + node = pf_pick_vf_config(gt, vfid)->ggtt_region; 782 + 783 + return xe_ggtt_node_load(node, buf, size, vfid); 784 + } 785 + 729 786 static u32 pf_get_min_spare_ctxs(struct xe_gt *gt) 730 787 { 731 788 /* XXX: preliminary */
+5
drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h
··· 71 71 int xe_gt_sriov_pf_config_restore(struct xe_gt *gt, unsigned int vfid, 72 72 const void *buf, size_t size); 73 73 74 + ssize_t xe_gt_sriov_pf_config_ggtt_save(struct xe_gt *gt, unsigned int vfid, 75 + void *buf, size_t size); 76 + int xe_gt_sriov_pf_config_ggtt_restore(struct xe_gt *gt, unsigned int vfid, 77 + const void *buf, size_t size); 78 + 74 79 bool xe_gt_sriov_pf_config_is_empty(struct xe_gt *gt, unsigned int vfid); 75 80 76 81 int xe_gt_sriov_pf_config_init(struct xe_gt *gt);