In the future there will be situations where queues can accept either kernel allocated CBs or user allocated CBs, depending on different states. Therefore, instead of using a boolean variable of kernel/user allocated CB, we need to use a bitmask to indicate that, which will allow to combine the two options. Add a flag to the uapi so the user will be able to indicate whether the CB was allocated by kernel or by user. Of course the driver validates that.
Unified · Split
| @@ -568,9 +568,36 @@ static int validate_queue_index(struct hl_device *hdev, · 567 unmodified lines | |||
| 568 | return -EINVAL; | 568 | return -EINVAL; |
| 569 | } | 569 | } |
| 570 | 570 | ||
| 571 | *queue_type = hw_queue_prop->type; | 571 | /* When hw queue type isn't QUEUE_TYPE_HW, |
| 572 | *is_kernel_allocated_cb = !!hw_queue_prop->requires_kernel_cb; | 572 | * USER_ALLOC_CB flag shall be referred as "don't care". |
| 573 | */ | ||
| 574 | if (hw_queue_prop->type == QUEUE_TYPE_HW) { | ||
| 575 | if (chunk->cs_chunk_flags & HL_CS_CHUNK_FLAGS_USER_ALLOC_CB) { | ||
| 576 | if (!(hw_queue_prop->cb_alloc_flags & CB_ALLOC_USER)) { | ||
| 577 | dev_err(hdev->dev, | ||
| 578 | "Queue index %d doesn't support user CB\n", | ||
| 579 | chunk->queue_index); | ||
| 580 | return -EINVAL; | ||
| 581 | } | ||
| 573 | 582 | ||
| 583 | *is_kernel_allocated_cb = false; | ||
| 584 | } else { | ||
| 585 | if (!(hw_queue_prop->cb_alloc_flags & | ||
| 586 | CB_ALLOC_KERNEL)) { | ||
| 587 | dev_err(hdev->dev, | ||
| 588 | "Queue index %d doesn't support kernel CB\n", | ||
| 589 | chunk->queue_index); | ||
| 590 | return -EINVAL; | ||
| 591 | } | ||
| 592 | |||
| 593 | *is_kernel_allocated_cb = true; | ||
| 594 | } | ||
| 595 | } else { | ||
| 596 | *is_kernel_allocated_cb = !!(hw_queue_prop->cb_alloc_flags | ||
| 597 | & CB_ALLOC_KERNEL); | ||
| 598 | } | ||
| 599 | |||
| 600 | *queue_type = hw_queue_prop->type; | ||
| 574 | return 0; | 601 | return 0; |
| 575 | } | 602 | } |
| 576 | 603 | ||
| @@ -206,6 +206,17 @@ struct hl_outbound_pci_region { · 205 unmodified lines | |||
| 206 | u64 size; | 206 | u64 size; |
| 207 | }; | 207 | }; |
| 208 | 208 | ||
| 209 | /* | ||
| 210 | * enum queue_cb_alloc_flags - Indicates queue support for CBs that | ||
| 211 | * allocated by Kernel or by User | ||
| 212 | * @CB_ALLOC_KERNEL: support only CBs that allocated by Kernel | ||
| 213 | * @CB_ALLOC_USER: support only CBs that allocated by User | ||
| 214 | */ | ||
| 215 | enum queue_cb_alloc_flags { | ||
| 216 | CB_ALLOC_KERNEL = 0x1, | ||
| 217 | CB_ALLOC_USER = 0x2 | ||
| 218 | }; | ||
| 219 | |||
| 209 | /* | 220 | /* |
| 210 | * struct hl_hw_sob - H/W SOB info. | 221 | * struct hl_hw_sob - H/W SOB info. |
| 211 | * @hdev: habanalabs device structure. | 222 | * @hdev: habanalabs device structure. |
| @@ -223,16 +234,18 @@ struct hl_hw_sob { · 11 unmodified lines | |||
| 223 | /** | 234 | /** |
| 224 | * struct hw_queue_properties - queue information. | 235 | * struct hw_queue_properties - queue information. |
| 225 | * @type: queue type. | 236 | * @type: queue type. |
| 237 | * @queue_cb_alloc_flags: bitmap which indicates if the hw queue supports CB | ||
| 238 | * that allocated by the Kernel driver and therefore, | ||
| 239 | * a CB handle can be provided for jobs on this queue. | ||
| 240 | * Otherwise, a CB address must be provided. | ||
| 226 | * @driver_only: true if only the driver is allowed to send a job to this queue, | 241 | * @driver_only: true if only the driver is allowed to send a job to this queue, |
| 227 | * false otherwise. | 242 | * false otherwise. |
| 228 | * @requires_kernel_cb: true if a CB handle must be provided for jobs on this | ||
| 229 | * queue, false otherwise (a CB address must be provided). | ||
| 230 | * @supports_sync_stream: True if queue supports sync stream | 243 | * @supports_sync_stream: True if queue supports sync stream |
| 231 | */ | 244 | */ |
| 232 | struct hw_queue_properties { | 245 | struct hw_queue_properties { |
| 233 | enum hl_queue_type type; | 246 | enum hl_queue_type type; |
| 247 | enum queue_cb_alloc_flags cb_alloc_flags; | ||
| 234 | u8 driver_only; | 248 | u8 driver_only; |
| 235 | u8 requires_kernel_cb; | ||
| 236 | u8 supports_sync_stream; | 249 | u8 supports_sync_stream; |
| 237 | }; | 250 | }; |
| 238 | 251 | ||
| @@ -381,23 +381,28 @@ static int gaudi_get_fixed_properties(struct hl_device *hdev) · 380 unmodified lines | |||
| 381 | if (gaudi_queue_type[i] == QUEUE_TYPE_EXT) { | 381 | if (gaudi_queue_type[i] == QUEUE_TYPE_EXT) { |
| 382 | prop->hw_queues_props[i].type = QUEUE_TYPE_EXT; | 382 | prop->hw_queues_props[i].type = QUEUE_TYPE_EXT; |
| 383 | prop->hw_queues_props[i].driver_only = 0; | 383 | prop->hw_queues_props[i].driver_only = 0; |
| 384 | prop->hw_queues_props[i].requires_kernel_cb = 1; | ||
| 385 | prop->hw_queues_props[i].supports_sync_stream = 1; | 384 | prop->hw_queues_props[i].supports_sync_stream = 1; |
| 385 | prop->hw_queues_props[i].cb_alloc_flags = | ||
| 386 | CB_ALLOC_KERNEL; | ||
| 386 | num_sync_stream_queues++; | 387 | num_sync_stream_queues++; |
| 387 | } else if (gaudi_queue_type[i] == QUEUE_TYPE_CPU) { | 388 | } else if (gaudi_queue_type[i] == QUEUE_TYPE_CPU) { |
| 388 | prop->hw_queues_props[i].type = QUEUE_TYPE_CPU; | 389 | prop->hw_queues_props[i].type = QUEUE_TYPE_CPU; |
| 389 | prop->hw_queues_props[i].driver_only = 1; | 390 | prop->hw_queues_props[i].driver_only = 1; |
| 390 | prop->hw_queues_props[i].requires_kernel_cb = 0; | ||
| 391 | prop->hw_queues_props[i].supports_sync_stream = 0; | 391 | prop->hw_queues_props[i].supports_sync_stream = 0; |
| 392 | prop->hw_queues_props[i].cb_alloc_flags = | ||
| 393 | CB_ALLOC_KERNEL; | ||
| 392 | } else if (gaudi_queue_type[i] == QUEUE_TYPE_INT) { | 394 | } else if (gaudi_queue_type[i] == QUEUE_TYPE_INT) { |
| 393 | prop->hw_queues_props[i].type = QUEUE_TYPE_INT; | 395 | prop->hw_queues_props[i].type = QUEUE_TYPE_INT; |
| 394 | prop->hw_queues_props[i].driver_only = 0; | 396 | prop->hw_queues_props[i].driver_only = 0; |
| 395 | prop->hw_queues_props[i].requires_kernel_cb = 0; | 397 | prop->hw_queues_props[i].supports_sync_stream = 0; |
| 398 | prop->hw_queues_props[i].cb_alloc_flags = | ||
| 399 | CB_ALLOC_USER; | ||
| 396 | } else if (gaudi_queue_type[i] == QUEUE_TYPE_NA) { | 400 | } else if (gaudi_queue_type[i] == QUEUE_TYPE_NA) { |
| 397 | prop->hw_queues_props[i].type = QUEUE_TYPE_NA; | 401 | prop->hw_queues_props[i].type = QUEUE_TYPE_NA; |
| 398 | prop->hw_queues_props[i].driver_only = 0; | 402 | prop->hw_queues_props[i].driver_only = 0; |
| 399 | prop->hw_queues_props[i].requires_kernel_cb = 0; | ||
| 400 | prop->hw_queues_props[i].supports_sync_stream = 0; | 403 | prop->hw_queues_props[i].supports_sync_stream = 0; |
| 404 | prop->hw_queues_props[i].cb_alloc_flags = | ||
| 405 | CB_ALLOC_USER; | ||
| 401 | } | 406 | } |
| 402 | } | 407 | } |
| 403 | 408 | ||
| @@ -373,20 +373,20 @@ int goya_get_fixed_properties(struct hl_device *hdev) · 372 unmodified lines | |||
| 373 | for (i = 0 ; i < NUMBER_OF_EXT_HW_QUEUES ; i++) { | 373 | for (i = 0 ; i < NUMBER_OF_EXT_HW_QUEUES ; i++) { |
| 374 | prop->hw_queues_props[i].type = QUEUE_TYPE_EXT; | 374 | prop->hw_queues_props[i].type = QUEUE_TYPE_EXT; |
| 375 | prop->hw_queues_props[i].driver_only = 0; | 375 | prop->hw_queues_props[i].driver_only = 0; |
| 376 | prop->hw_queues_props[i].requires_kernel_cb = 1; | 376 | prop->hw_queues_props[i].cb_alloc_flags = CB_ALLOC_KERNEL; |
| 377 | } | 377 | } |
| 378 | 378 | ||
| 379 | for (; i < NUMBER_OF_EXT_HW_QUEUES + NUMBER_OF_CPU_HW_QUEUES ; i++) { | 379 | for (; i < NUMBER_OF_EXT_HW_QUEUES + NUMBER_OF_CPU_HW_QUEUES ; i++) { |
| 380 | prop->hw_queues_props[i].type = QUEUE_TYPE_CPU; | 380 | prop->hw_queues_props[i].type = QUEUE_TYPE_CPU; |
| 381 | prop->hw_queues_props[i].driver_only = 1; | 381 | prop->hw_queues_props[i].driver_only = 1; |
| 382 | prop->hw_queues_props[i].requires_kernel_cb = 0; | 382 | prop->hw_queues_props[i].cb_alloc_flags = CB_ALLOC_KERNEL; |
| 383 | } | 383 | } |
| 384 | 384 | ||
| 385 | for (; i < NUMBER_OF_EXT_HW_QUEUES + NUMBER_OF_CPU_HW_QUEUES + | 385 | for (; i < NUMBER_OF_EXT_HW_QUEUES + NUMBER_OF_CPU_HW_QUEUES + |
| 386 | NUMBER_OF_INT_HW_QUEUES; i++) { | 386 | NUMBER_OF_INT_HW_QUEUES; i++) { |
| 387 | prop->hw_queues_props[i].type = QUEUE_TYPE_INT; | 387 | prop->hw_queues_props[i].type = QUEUE_TYPE_INT; |
| 388 | prop->hw_queues_props[i].driver_only = 0; | 388 | prop->hw_queues_props[i].driver_only = 0; |
| 389 | prop->hw_queues_props[i].requires_kernel_cb = 0; | 389 | prop->hw_queues_props[i].cb_alloc_flags = CB_ALLOC_USER; |
| 390 | } | 390 | } |
| 391 | 391 | ||
| 392 | prop->completion_queues_count = NUMBER_OF_CMPLT_QUEUES; | 392 | prop->completion_queues_count = NUMBER_OF_CMPLT_QUEUES; |
| @@ -490,6 +490,22 @@ union hl_cb_args { · 489 unmodified lines | |||
| 490 | struct hl_cb_out out; | 490 | struct hl_cb_out out; |
| 491 | }; | 491 | }; |
| 492 | 492 | ||
| 493 | /* HL_CS_CHUNK_FLAGS_ values | ||
| 494 | * | ||
| 495 | * HL_CS_CHUNK_FLAGS_USER_ALLOC_CB: | ||
| 496 | * Indicates if the CB was allocated and mapped by userspace. | ||
| 497 | * User allocated CB is a command buffer allocated by the user, via malloc | ||
| 498 | * (or similar). After allocating the CB, the user invokes “memory ioctl” | ||
| 499 | * to map the user memory into a device virtual address. The user provides | ||
| 500 | * this address via the cb_handle field. The interface provides the | ||
| 501 | * ability to create a large CBs, Which aren’t limited to | ||
| 502 | * “HL_MAX_CB_SIZE”. Therefore, it increases the PCI-DMA queues | ||
| 503 | * throughput. This CB allocation method also reduces the use of Linux | ||
| 504 | * DMA-able memory pool. Which are limited and used by other Linux | ||
| 505 | * sub-systems. | ||
| 506 | */ | ||
| 507 | #define HL_CS_CHUNK_FLAGS_USER_ALLOC_CB 0x1 | ||
| 508 | |||
| 493 | /* | 509 | /* |
| 494 | * This structure size must always be fixed to 64-bytes for backward | 510 | * This structure size must always be fixed to 64-bytes for backward |
| 495 | * compatibility | 511 | * compatibility |