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

Configure Feed

Select the types of activity you want to include in your feed.

virtio: introduce virtio_map container union

Following patch will introduce the mapping operations for virtio
device. In order to achieve this, besides the dma device, virtio core
needs to support a transport or device specific mapping metadata as well.
So this patch introduces a union container of a dma device. The idea
is the allow the transport layer to pass device specific mapping
metadata which will be used as a parameter for the virtio mapping
operations. For the transport or device that is using DMA, dma device
is still being used.

Signed-off-by: Jason Wang <jasowang@redhat.com>
Message-Id: <20250821064641.5025-5-jasowang@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Tested-by: Lei Yang <leiyang@redhat.com>
Reviewed-by: Eugenio Pérez <eperezma@redhat.com>

authored by

Jason Wang and committed by
Michael S. Tsirkin
b16060c5 b41cb3bc

+66 -56
+53 -51
drivers/virtio/virtio_ring.c
··· 210 210 /* DMA, allocation, and size information */ 211 211 bool we_own_ring; 212 212 213 - /* Device used for doing DMA */ 214 - struct device *dma_dev; 213 + union virtio_map map; 215 214 216 215 #ifdef DEBUG 217 216 /* They're supposed to lock for us. */ ··· 306 307 307 308 static void *vring_alloc_queue(struct virtio_device *vdev, size_t size, 308 309 dma_addr_t *dma_handle, gfp_t flag, 309 - struct device *dma_dev) 310 + union virtio_map map) 310 311 { 311 312 if (vring_use_map_api(vdev)) { 312 - return dma_alloc_coherent(dma_dev, size, 313 + return dma_alloc_coherent(map.dma_dev, size, 313 314 dma_handle, flag); 314 315 } else { 315 316 void *queue = alloc_pages_exact(PAGE_ALIGN(size), flag); ··· 340 341 341 342 static void vring_free_queue(struct virtio_device *vdev, size_t size, 342 343 void *queue, dma_addr_t dma_handle, 343 - struct device *dma_dev) 344 + union virtio_map map) 344 345 { 345 346 if (vring_use_map_api(vdev)) 346 - dma_free_coherent(dma_dev, size, queue, dma_handle); 347 + dma_free_coherent(map.dma_dev, size, queue, dma_handle); 347 348 else 348 349 free_pages_exact(queue, PAGE_ALIGN(size)); 349 350 } ··· 355 356 */ 356 357 static struct device *vring_dma_dev(const struct vring_virtqueue *vq) 357 358 { 358 - return vq->dma_dev; 359 + return vq->map.dma_dev; 359 360 } 360 361 361 362 /* Map one sg entry. */ ··· 1055 1056 } 1056 1057 1057 1058 static void vring_free_split(struct vring_virtqueue_split *vring_split, 1058 - struct virtio_device *vdev, struct device *dma_dev) 1059 + struct virtio_device *vdev, 1060 + union virtio_map map) 1059 1061 { 1060 1062 vring_free_queue(vdev, vring_split->queue_size_in_bytes, 1061 1063 vring_split->vring.desc, 1062 1064 vring_split->queue_dma_addr, 1063 - dma_dev); 1065 + map); 1064 1066 1065 1067 kfree(vring_split->desc_state); 1066 1068 kfree(vring_split->desc_extra); ··· 1072 1072 u32 num, 1073 1073 unsigned int vring_align, 1074 1074 bool may_reduce_num, 1075 - struct device *dma_dev) 1075 + union virtio_map map) 1076 1076 { 1077 1077 void *queue = NULL; 1078 1078 dma_addr_t dma_addr; ··· 1088 1088 queue = vring_alloc_queue(vdev, vring_size(num, vring_align), 1089 1089 &dma_addr, 1090 1090 GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO, 1091 - dma_dev); 1091 + map); 1092 1092 if (queue) 1093 1093 break; 1094 1094 if (!may_reduce_num) ··· 1102 1102 /* Try to get a single page. You are my only hope! */ 1103 1103 queue = vring_alloc_queue(vdev, vring_size(num, vring_align), 1104 1104 &dma_addr, GFP_KERNEL | __GFP_ZERO, 1105 - dma_dev); 1105 + map); 1106 1106 } 1107 1107 if (!queue) 1108 1108 return -ENOMEM; ··· 1126 1126 bool (*notify)(struct virtqueue *), 1127 1127 void (*callback)(struct virtqueue *), 1128 1128 const char *name, 1129 - struct device *dma_dev) 1129 + union virtio_map map) 1130 1130 { 1131 1131 struct vring_virtqueue *vq; 1132 1132 int err; ··· 1149 1149 #else 1150 1150 vq->broken = false; 1151 1151 #endif 1152 - vq->dma_dev = dma_dev; 1152 + vq->map = map; 1153 1153 vq->use_map_api = vring_use_map_api(vdev); 1154 1154 1155 1155 vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) && ··· 1187 1187 bool (*notify)(struct virtqueue *), 1188 1188 void (*callback)(struct virtqueue *), 1189 1189 const char *name, 1190 - struct device *dma_dev) 1190 + union virtio_map map) 1191 1191 { 1192 1192 struct vring_virtqueue_split vring_split = {}; 1193 1193 struct virtqueue *vq; 1194 1194 int err; 1195 1195 1196 1196 err = vring_alloc_queue_split(&vring_split, vdev, num, vring_align, 1197 - may_reduce_num, dma_dev); 1197 + may_reduce_num, map); 1198 1198 if (err) 1199 1199 return NULL; 1200 1200 1201 1201 vq = __vring_new_virtqueue_split(index, &vring_split, vdev, weak_barriers, 1202 - context, notify, callback, name, dma_dev); 1202 + context, notify, callback, name, map); 1203 1203 if (!vq) { 1204 - vring_free_split(&vring_split, vdev, dma_dev); 1204 + vring_free_split(&vring_split, vdev, map); 1205 1205 return NULL; 1206 1206 } 1207 1207 ··· 1220 1220 err = vring_alloc_queue_split(&vring_split, vdev, num, 1221 1221 vq->split.vring_align, 1222 1222 vq->split.may_reduce_num, 1223 - vring_dma_dev(vq)); 1223 + vq->map); 1224 1224 if (err) 1225 1225 goto err; 1226 1226 ··· 1238 1238 return 0; 1239 1239 1240 1240 err_state_extra: 1241 - vring_free_split(&vring_split, vdev, vring_dma_dev(vq)); 1241 + vring_free_split(&vring_split, vdev, vq->map); 1242 1242 err: 1243 1243 virtqueue_reinit_split(vq); 1244 1244 return -ENOMEM; ··· 1947 1947 1948 1948 static void vring_free_packed(struct vring_virtqueue_packed *vring_packed, 1949 1949 struct virtio_device *vdev, 1950 - struct device *dma_dev) 1950 + union virtio_map map) 1951 1951 { 1952 1952 if (vring_packed->vring.desc) 1953 1953 vring_free_queue(vdev, vring_packed->ring_size_in_bytes, 1954 1954 vring_packed->vring.desc, 1955 1955 vring_packed->ring_dma_addr, 1956 - dma_dev); 1956 + map); 1957 1957 1958 1958 if (vring_packed->vring.driver) 1959 1959 vring_free_queue(vdev, vring_packed->event_size_in_bytes, 1960 1960 vring_packed->vring.driver, 1961 1961 vring_packed->driver_event_dma_addr, 1962 - dma_dev); 1962 + map); 1963 1963 1964 1964 if (vring_packed->vring.device) 1965 1965 vring_free_queue(vdev, vring_packed->event_size_in_bytes, 1966 1966 vring_packed->vring.device, 1967 1967 vring_packed->device_event_dma_addr, 1968 - dma_dev); 1968 + map); 1969 1969 1970 1970 kfree(vring_packed->desc_state); 1971 1971 kfree(vring_packed->desc_extra); ··· 1973 1973 1974 1974 static int vring_alloc_queue_packed(struct vring_virtqueue_packed *vring_packed, 1975 1975 struct virtio_device *vdev, 1976 - u32 num, struct device *dma_dev) 1976 + u32 num, union virtio_map map) 1977 1977 { 1978 1978 struct vring_packed_desc *ring; 1979 1979 struct vring_packed_desc_event *driver, *device; ··· 1985 1985 ring = vring_alloc_queue(vdev, ring_size_in_bytes, 1986 1986 &ring_dma_addr, 1987 1987 GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO, 1988 - dma_dev); 1988 + map); 1989 1989 if (!ring) 1990 1990 goto err; 1991 1991 ··· 1998 1998 driver = vring_alloc_queue(vdev, event_size_in_bytes, 1999 1999 &driver_event_dma_addr, 2000 2000 GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO, 2001 - dma_dev); 2001 + map); 2002 2002 if (!driver) 2003 2003 goto err; 2004 2004 ··· 2009 2009 device = vring_alloc_queue(vdev, event_size_in_bytes, 2010 2010 &device_event_dma_addr, 2011 2011 GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO, 2012 - dma_dev); 2012 + map); 2013 2013 if (!device) 2014 2014 goto err; 2015 2015 ··· 2021 2021 return 0; 2022 2022 2023 2023 err: 2024 - vring_free_packed(vring_packed, vdev, dma_dev); 2024 + vring_free_packed(vring_packed, vdev, map); 2025 2025 return -ENOMEM; 2026 2026 } 2027 2027 ··· 2097 2097 bool (*notify)(struct virtqueue *), 2098 2098 void (*callback)(struct virtqueue *), 2099 2099 const char *name, 2100 - struct device *dma_dev) 2100 + union virtio_map map) 2101 2101 { 2102 2102 struct vring_virtqueue *vq; 2103 2103 int err; ··· 2120 2120 vq->broken = false; 2121 2121 #endif 2122 2122 vq->packed_ring = true; 2123 - vq->dma_dev = dma_dev; 2123 + vq->map = map; 2124 2124 vq->use_map_api = vring_use_map_api(vdev); 2125 2125 2126 2126 vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) && ··· 2158 2158 bool (*notify)(struct virtqueue *), 2159 2159 void (*callback)(struct virtqueue *), 2160 2160 const char *name, 2161 - struct device *dma_dev) 2161 + union virtio_map map) 2162 2162 { 2163 2163 struct vring_virtqueue_packed vring_packed = {}; 2164 2164 struct virtqueue *vq; 2165 2165 2166 - if (vring_alloc_queue_packed(&vring_packed, vdev, num, dma_dev)) 2166 + if (vring_alloc_queue_packed(&vring_packed, vdev, num, map)) 2167 2167 return NULL; 2168 2168 2169 2169 vq = __vring_new_virtqueue_packed(index, &vring_packed, vdev, weak_barriers, 2170 - context, notify, callback, name, dma_dev); 2170 + context, notify, callback, name, map); 2171 2171 if (!vq) { 2172 - vring_free_packed(&vring_packed, vdev, dma_dev); 2172 + vring_free_packed(&vring_packed, vdev, map); 2173 2173 return NULL; 2174 2174 } 2175 2175 ··· 2185 2185 struct virtio_device *vdev = _vq->vdev; 2186 2186 int err; 2187 2187 2188 - if (vring_alloc_queue_packed(&vring_packed, vdev, num, vring_dma_dev(vq))) 2188 + if (vring_alloc_queue_packed(&vring_packed, vdev, num, vq->map)) 2189 2189 goto err_ring; 2190 2190 2191 2191 err = vring_alloc_state_extra_packed(&vring_packed); ··· 2202 2202 return 0; 2203 2203 2204 2204 err_state_extra: 2205 - vring_free_packed(&vring_packed, vdev, vring_dma_dev(vq)); 2205 + vring_free_packed(&vring_packed, vdev, vq->map); 2206 2206 err_ring: 2207 2207 virtqueue_reinit_packed(vq); 2208 2208 return -ENOMEM; ··· 2434 2434 struct vring_virtqueue *vq = to_vvq(_vq); 2435 2435 2436 2436 if (vq->use_map_api) 2437 - return vring_dma_dev(vq); 2437 + return vq->map.dma_dev; 2438 2438 else 2439 2439 return NULL; 2440 2440 } ··· 2719 2719 void (*callback)(struct virtqueue *), 2720 2720 const char *name) 2721 2721 { 2722 + union virtio_map map = {.dma_dev = vdev->dev.parent}; 2722 2723 2723 2724 if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED)) 2724 2725 return vring_create_virtqueue_packed(index, num, vring_align, 2725 2726 vdev, weak_barriers, may_reduce_num, 2726 - context, notify, callback, name, vdev->dev.parent); 2727 + context, notify, callback, name, map); 2727 2728 2728 2729 return vring_create_virtqueue_split(index, num, vring_align, 2729 2730 vdev, weak_barriers, may_reduce_num, 2730 - context, notify, callback, name, vdev->dev.parent); 2731 + context, notify, callback, name, map); 2731 2732 } 2732 2733 EXPORT_SYMBOL_GPL(vring_create_virtqueue); 2733 2734 2734 - struct virtqueue *vring_create_virtqueue_dma( 2735 + struct virtqueue *vring_create_virtqueue_map( 2735 2736 unsigned int index, 2736 2737 unsigned int num, 2737 2738 unsigned int vring_align, ··· 2743 2742 bool (*notify)(struct virtqueue *), 2744 2743 void (*callback)(struct virtqueue *), 2745 2744 const char *name, 2746 - struct device *dma_dev) 2745 + union virtio_map map) 2747 2746 { 2748 2747 2749 2748 if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED)) 2750 2749 return vring_create_virtqueue_packed(index, num, vring_align, 2751 2750 vdev, weak_barriers, may_reduce_num, 2752 - context, notify, callback, name, dma_dev); 2751 + context, notify, callback, name, map); 2753 2752 2754 2753 return vring_create_virtqueue_split(index, num, vring_align, 2755 2754 vdev, weak_barriers, may_reduce_num, 2756 - context, notify, callback, name, dma_dev); 2755 + context, notify, callback, name, map); 2757 2756 } 2758 - EXPORT_SYMBOL_GPL(vring_create_virtqueue_dma); 2757 + EXPORT_SYMBOL_GPL(vring_create_virtqueue_map); 2759 2758 2760 2759 /** 2761 2760 * virtqueue_resize - resize the vring of vq ··· 2866 2865 const char *name) 2867 2866 { 2868 2867 struct vring_virtqueue_split vring_split = {}; 2868 + union virtio_map map = {.dma_dev = vdev->dev.parent}; 2869 2869 2870 2870 if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED)) { 2871 2871 struct vring_virtqueue_packed vring_packed = {}; ··· 2876 2874 return __vring_new_virtqueue_packed(index, &vring_packed, 2877 2875 vdev, weak_barriers, 2878 2876 context, notify, callback, 2879 - name, vdev->dev.parent); 2877 + name, map); 2880 2878 } 2881 2879 2882 2880 vring_init(&vring_split.vring, num, pages, vring_align); 2883 2881 return __vring_new_virtqueue_split(index, &vring_split, vdev, weak_barriers, 2884 2882 context, notify, callback, name, 2885 - vdev->dev.parent); 2883 + map); 2886 2884 } 2887 2885 EXPORT_SYMBOL_GPL(vring_new_virtqueue); 2888 2886 ··· 2896 2894 vq->packed.ring_size_in_bytes, 2897 2895 vq->packed.vring.desc, 2898 2896 vq->packed.ring_dma_addr, 2899 - vring_dma_dev(vq)); 2897 + vq->map); 2900 2898 2901 2899 vring_free_queue(vq->vq.vdev, 2902 2900 vq->packed.event_size_in_bytes, 2903 2901 vq->packed.vring.driver, 2904 2902 vq->packed.driver_event_dma_addr, 2905 - vring_dma_dev(vq)); 2903 + vq->map); 2906 2904 2907 2905 vring_free_queue(vq->vq.vdev, 2908 2906 vq->packed.event_size_in_bytes, 2909 2907 vq->packed.vring.device, 2910 2908 vq->packed.device_event_dma_addr, 2911 - vring_dma_dev(vq)); 2909 + vq->map); 2912 2910 2913 2911 kfree(vq->packed.desc_state); 2914 2912 kfree(vq->packed.desc_extra); ··· 2917 2915 vq->split.queue_size_in_bytes, 2918 2916 vq->split.vring.desc, 2919 2917 vq->split.queue_dma_addr, 2920 - vring_dma_dev(vq)); 2918 + vq->map); 2921 2919 } 2922 2920 } 2923 2921 if (!vq->packed_ring) {
+4 -2
drivers/virtio/virtio_vdpa.c
··· 139 139 struct vdpa_callback cb; 140 140 struct virtqueue *vq; 141 141 u64 desc_addr, driver_addr, device_addr; 142 + union virtio_map map = {0}; 142 143 /* Assume split virtqueue, switch to packed if necessary */ 143 144 struct vdpa_vq_state state = {0}; 144 145 u32 align, max_num, min_num = 1; ··· 186 185 dma_dev = ops->get_vq_dma_dev(vdpa, index); 187 186 else 188 187 dma_dev = vdpa_get_dma_dev(vdpa); 189 - vq = vring_create_virtqueue_dma(index, max_num, align, vdev, 188 + map.dma_dev = dma_dev; 189 + vq = vring_create_virtqueue_map(index, max_num, align, vdev, 190 190 true, may_reduce_num, ctx, 191 - notify, callback, name, dma_dev); 191 + notify, callback, name, map); 192 192 if (!vq) { 193 193 err = -ENOMEM; 194 194 goto error_new_virtqueue;
+5
include/linux/virtio.h
··· 41 41 void *priv; 42 42 }; 43 43 44 + union virtio_map { 45 + /* Device that performs DMA */ 46 + struct device *dma_dev; 47 + }; 48 + 44 49 int virtqueue_add_outbuf(struct virtqueue *vq, 45 50 struct scatterlist sg[], unsigned int num, 46 51 void *data,
+4 -3
include/linux/virtio_ring.h
··· 3 3 #define _LINUX_VIRTIO_RING_H 4 4 5 5 #include <asm/barrier.h> 6 + #include <linux/virtio.h> 6 7 #include <linux/irqreturn.h> 7 8 #include <uapi/linux/virtio_ring.h> 8 9 ··· 80 79 81 80 /* 82 81 * Creates a virtqueue and allocates the descriptor ring with per 83 - * virtqueue DMA device. 82 + * virtqueue mapping operations. 84 83 */ 85 - struct virtqueue *vring_create_virtqueue_dma(unsigned int index, 84 + struct virtqueue *vring_create_virtqueue_map(unsigned int index, 86 85 unsigned int num, 87 86 unsigned int vring_align, 88 87 struct virtio_device *vdev, ··· 92 91 bool (*notify)(struct virtqueue *vq), 93 92 void (*callback)(struct virtqueue *vq), 94 93 const char *name, 95 - struct device *dma_dev); 94 + union virtio_map map); 96 95 97 96 /* 98 97 * Creates a virtqueue with a standard layout but a caller-allocated