| 298 | } |
| 299 | |
| 300 | static int |
| 301 | virtio_alloc_queue_headers(struct virtqueue *vq, int numa_node, const char *name) |
| 302 | { |
| 303 | char hdr_name[VIRTQUEUE_MAX_NAME_SZ]; |
| 304 | const struct rte_memzone **hdr_mz; |
| 305 | rte_iova_t *hdr_mem; |
| 306 | ssize_t size; |
| 307 | int queue_type; |
| 308 | |
| 309 | queue_type = virtio_get_queue_type(vq->hw, vq->vq_queue_index); |
| 310 | switch (queue_type) { |
| 311 | case VTNET_TQ: |
| 312 | /* |
| 313 | * For each xmit packet, allocate a virtio_net_hdr |
| 314 | * and indirect ring elements |
| 315 | */ |
| 316 | size = vq->vq_nentries * sizeof(struct virtio_tx_region); |
| 317 | hdr_mz = &vq->txq.hdr_mz; |
| 318 | hdr_mem = &vq->txq.hdr_mem; |
| 319 | break; |
| 320 | case VTNET_CQ: |
| 321 | /* Allocate a page for control vq command, data and status */ |
| 322 | size = rte_mem_page_size(); |
| 323 | hdr_mz = &vq->cq.hdr_mz; |
| 324 | hdr_mem = &vq->cq.hdr_mem; |
| 325 | break; |
| 326 | case VTNET_RQ: |
| 327 | /* fallthrough */ |
| 328 | default: |
| 329 | return 0; |
| 330 | } |
| 331 | |
| 332 | snprintf(hdr_name, sizeof(hdr_name), "%s_hdr", name); |
| 333 | *hdr_mz = rte_memzone_reserve_aligned(hdr_name, size, numa_node, |
| 334 | RTE_MEMZONE_IOVA_CONTIG, RTE_CACHE_LINE_SIZE); |
| 335 | if (*hdr_mz == NULL) { |
| 336 | if (rte_errno == EEXIST) |
| 337 | *hdr_mz = rte_memzone_lookup(hdr_name); |
| 338 | if (*hdr_mz == NULL) |
| 339 | return -ENOMEM; |
| 340 | } |
| 341 | |
| 342 | memset((*hdr_mz)->addr, 0, size); |
| 343 | |
| 344 | if (vq->hw->use_va) |
| 345 | *hdr_mem = (uintptr_t)(*hdr_mz)->addr; |
| 346 | else |
| 347 | *hdr_mem = (uintptr_t)(*hdr_mz)->iova; |
| 348 | |
| 349 | return 0; |
| 350 | } |
| 351 | |
| 352 | static void |
| 353 | virtio_free_queue_headers(struct virtqueue *vq) |
no test coverage detected