2025-01-20 09:27:15 -08:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2024, Microsoft Corporation. All rights reserved.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _MANA_SHADOW_QUEUE_H_
|
|
|
|
#define _MANA_SHADOW_QUEUE_H_
|
|
|
|
|
|
|
|
struct shadow_wqe_header {
|
|
|
|
u16 opcode;
|
|
|
|
u16 error_code;
|
|
|
|
u32 posted_wqe_size;
|
|
|
|
u64 wr_id;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ud_rq_shadow_wqe {
|
|
|
|
struct shadow_wqe_header header;
|
|
|
|
u32 byte_len;
|
|
|
|
u32 src_qpn;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ud_sq_shadow_wqe {
|
|
|
|
struct shadow_wqe_header header;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct shadow_queue {
|
|
|
|
/* Unmasked producer index, Incremented on wqe posting */
|
|
|
|
u64 prod_idx;
|
|
|
|
/* Unmasked consumer index, Incremented on cq polling */
|
|
|
|
u64 cons_idx;
|
|
|
|
/* Unmasked index of next-to-complete (from HW) shadow WQE */
|
|
|
|
u64 next_to_complete_idx;
|
|
|
|
/* queue size in wqes */
|
|
|
|
u32 length;
|
|
|
|
/* distance between elements in bytes */
|
|
|
|
u32 stride;
|
|
|
|
/* ring buffer holding wqes */
|
|
|
|
void *buffer;
|
|
|
|
};
|
|
|
|
|
|
|
|
static inline int create_shadow_queue(struct shadow_queue *queue, uint32_t length, uint32_t stride)
|
|
|
|
{
|
2025-03-06 22:49:06 +03:00
|
|
|
queue->buffer = kvmalloc_array(length, stride, GFP_KERNEL);
|
2025-01-20 09:27:15 -08:00
|
|
|
if (!queue->buffer)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
queue->length = length;
|
|
|
|
queue->stride = stride;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void destroy_shadow_queue(struct shadow_queue *queue)
|
|
|
|
{
|
|
|
|
kvfree(queue->buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool shadow_queue_full(struct shadow_queue *queue)
|
|
|
|
{
|
|
|
|
return (queue->prod_idx - queue->cons_idx) >= queue->length;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool shadow_queue_empty(struct shadow_queue *queue)
|
|
|
|
{
|
|
|
|
return queue->prod_idx == queue->cons_idx;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void *
|
|
|
|
shadow_queue_get_element(const struct shadow_queue *queue, u64 unmasked_index)
|
|
|
|
{
|
|
|
|
u32 index = unmasked_index % queue->length;
|
|
|
|
|
|
|
|
return ((u8 *)queue->buffer + index * queue->stride);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void *
|
|
|
|
shadow_queue_producer_entry(struct shadow_queue *queue)
|
|
|
|
{
|
|
|
|
return shadow_queue_get_element(queue, queue->prod_idx);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void *
|
|
|
|
shadow_queue_get_next_to_consume(const struct shadow_queue *queue)
|
|
|
|
{
|
|
|
|
if (queue->cons_idx == queue->next_to_complete_idx)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return shadow_queue_get_element(queue, queue->cons_idx);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void *
|
|
|
|
shadow_queue_get_next_to_complete(struct shadow_queue *queue)
|
|
|
|
{
|
|
|
|
if (queue->next_to_complete_idx == queue->prod_idx)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return shadow_queue_get_element(queue, queue->next_to_complete_idx);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void shadow_queue_advance_producer(struct shadow_queue *queue)
|
|
|
|
{
|
|
|
|
queue->prod_idx++;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void shadow_queue_advance_consumer(struct shadow_queue *queue)
|
|
|
|
{
|
|
|
|
queue->cons_idx++;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void shadow_queue_advance_next_to_complete(struct shadow_queue *queue)
|
|
|
|
{
|
|
|
|
queue->next_to_complete_idx++;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|