| 186 | } |
| 187 | |
| 188 | void |
| 189 | __vhost_log_cache_sync(struct virtio_net *dev, struct vhost_virtqueue *vq) |
| 190 | { |
| 191 | unsigned long *log_base; |
| 192 | int i; |
| 193 | |
| 194 | if (unlikely(!dev->log_base)) |
| 195 | return; |
| 196 | |
| 197 | /* No cache, nothing to sync */ |
| 198 | if (unlikely(!vq->log_cache)) |
| 199 | return; |
| 200 | |
| 201 | rte_atomic_thread_fence(rte_memory_order_release); |
| 202 | |
| 203 | log_base = (unsigned long *)(uintptr_t)dev->log_base; |
| 204 | |
| 205 | for (i = 0; i < vq->log_cache_nb_elem; i++) { |
| 206 | struct log_cache_entry *elem = vq->log_cache + i; |
| 207 | |
| 208 | #if defined(RTE_TOOLCHAIN_GCC) && (GCC_VERSION < 70100) |
| 209 | /* |
| 210 | * '__sync' builtins are deprecated, but 'rte_atomic' ones |
| 211 | * are sub-optimized in older GCC versions. |
| 212 | */ |
| 213 | __sync_fetch_and_or(log_base + elem->offset, elem->val); |
| 214 | #else |
| 215 | rte_atomic_fetch_or_explicit( |
| 216 | (unsigned long __rte_atomic *)(log_base + elem->offset), |
| 217 | elem->val, rte_memory_order_relaxed); |
| 218 | #endif |
| 219 | } |
| 220 | |
| 221 | rte_atomic_thread_fence(rte_memory_order_release); |
| 222 | |
| 223 | vq->log_cache_nb_elem = 0; |
| 224 | } |
| 225 | |
| 226 | static __rte_always_inline void |
| 227 | vhost_log_cache_page(struct virtio_net *dev, struct vhost_virtqueue *vq, |
no test coverage detected