mirror of
https://github.com/ipxe/ipxe
synced 2025-12-07 18:00:28 +03:00
[gve] Allow for descriptor and completion lengths to vary by mode
The descriptors and completions in the DQO operating mode are not the same sizes as the equivalent structures in the GQI operating mode. Allow the queue stride size to vary by operating mode (and therefore to be known only after reading the device descriptor and selecting the operating mode). Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -746,6 +746,7 @@ static void gve_create_rx_param ( struct gve_queue *queue, uint32_t qpl,
|
|||||||
*/
|
*/
|
||||||
static int gve_create_queue ( struct gve_nic *gve, struct gve_queue *queue ) {
|
static int gve_create_queue ( struct gve_nic *gve, struct gve_queue *queue ) {
|
||||||
const struct gve_queue_type *type = queue->type;
|
const struct gve_queue_type *type = queue->type;
|
||||||
|
const struct gve_queue_stride *stride = &queue->stride;
|
||||||
union gve_admin_command *cmd;
|
union gve_admin_command *cmd;
|
||||||
struct gve_buffer *buf;
|
struct gve_buffer *buf;
|
||||||
unsigned int db_off;
|
unsigned int db_off;
|
||||||
@@ -758,17 +759,17 @@ static int gve_create_queue ( struct gve_nic *gve, struct gve_queue *queue ) {
|
|||||||
/* Reset queue */
|
/* Reset queue */
|
||||||
queue->prod = 0;
|
queue->prod = 0;
|
||||||
queue->cons = 0;
|
queue->cons = 0;
|
||||||
memset ( queue->desc.raw, 0, ( queue->count * type->desc_len ) );
|
memset ( queue->desc.raw, 0, ( queue->count * stride->desc ) );
|
||||||
memset ( queue->cmplt.raw, 0, ( queue->count * type->cmplt_len ) );
|
memset ( queue->cmplt.raw, 0, ( queue->count * stride->cmplt ) );
|
||||||
for ( i = 0 ; i < queue->fill ; i++ )
|
for ( i = 0 ; i < queue->fill ; i++ )
|
||||||
queue->tag[i] = i;
|
queue->tag[i] = i;
|
||||||
|
|
||||||
/* Pre-populate descriptor offsets */
|
/* Pre-populate descriptor offsets */
|
||||||
buf = ( queue->desc.raw + type->desc_len - sizeof ( *buf ) );
|
buf = ( queue->desc.raw + stride->desc - sizeof ( *buf ) );
|
||||||
for ( i = 0 ; i < queue->count ; i++ ) {
|
for ( i = 0 ; i < queue->count ; i++ ) {
|
||||||
tag = ( i & ( queue->fill - 1 ) );
|
tag = ( i & ( queue->fill - 1 ) );
|
||||||
buf->addr = cpu_to_be64 ( gve_address ( queue, tag ) );
|
buf->addr = cpu_to_be64 ( gve_address ( queue, tag ) );
|
||||||
buf = ( ( ( void * ) buf ) + type->desc_len );
|
buf = ( ( ( void * ) buf ) + stride->desc );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Construct request */
|
/* Construct request */
|
||||||
@@ -963,10 +964,11 @@ gve_next ( unsigned int seq ) {
|
|||||||
*/
|
*/
|
||||||
static int gve_alloc_queue ( struct gve_nic *gve, struct gve_queue *queue ) {
|
static int gve_alloc_queue ( struct gve_nic *gve, struct gve_queue *queue ) {
|
||||||
const struct gve_queue_type *type = queue->type;
|
const struct gve_queue_type *type = queue->type;
|
||||||
|
struct gve_queue_stride *stride = &queue->stride;
|
||||||
struct dma_device *dma = gve->dma;
|
struct dma_device *dma = gve->dma;
|
||||||
size_t desc_len = ( queue->count * type->desc_len );
|
size_t desc_len;
|
||||||
size_t cmplt_len = ( queue->count * type->cmplt_len );
|
size_t cmplt_len;
|
||||||
size_t res_len = sizeof ( *queue->res );
|
size_t res_len;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Sanity checks */
|
/* Sanity checks */
|
||||||
@@ -978,6 +980,12 @@ static int gve_alloc_queue ( struct gve_nic *gve, struct gve_queue *queue ) {
|
|||||||
goto err_sanity;
|
goto err_sanity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set queue strides and calculate total lengths */
|
||||||
|
*stride = type->stride.gqi;
|
||||||
|
desc_len = ( queue->count * stride->desc );
|
||||||
|
cmplt_len = ( queue->count * stride->cmplt );
|
||||||
|
res_len = sizeof ( *queue->res );
|
||||||
|
|
||||||
/* Calculate maximum fill level */
|
/* Calculate maximum fill level */
|
||||||
assert ( ( type->fill & ( type->fill - 1 ) ) == 0 );
|
assert ( ( type->fill & ( type->fill - 1 ) ) == 0 );
|
||||||
queue->fill = type->fill;
|
queue->fill = type->fill;
|
||||||
@@ -1045,9 +1053,9 @@ static int gve_alloc_queue ( struct gve_nic *gve, struct gve_queue *queue ) {
|
|||||||
* @v queue Descriptor queue
|
* @v queue Descriptor queue
|
||||||
*/
|
*/
|
||||||
static void gve_free_queue ( struct gve_nic *gve, struct gve_queue *queue ) {
|
static void gve_free_queue ( struct gve_nic *gve, struct gve_queue *queue ) {
|
||||||
const struct gve_queue_type *type = queue->type;
|
const struct gve_queue_stride *stride = &queue->stride;
|
||||||
size_t desc_len = ( queue->count * type->desc_len );
|
size_t desc_len = ( queue->count * stride->desc );
|
||||||
size_t cmplt_len = ( queue->count * type->cmplt_len );
|
size_t cmplt_len = ( queue->count * stride->cmplt );
|
||||||
size_t res_len = sizeof ( *queue->res );
|
size_t res_len = sizeof ( *queue->res );
|
||||||
|
|
||||||
/* Free queue resources */
|
/* Free queue resources */
|
||||||
@@ -1570,7 +1578,11 @@ static const struct gve_queue_type gve_tx_type = {
|
|||||||
.qpl = GVE_TX_QPL,
|
.qpl = GVE_TX_QPL,
|
||||||
.irq = GVE_TX_IRQ,
|
.irq = GVE_TX_IRQ,
|
||||||
.fill = GVE_TX_FILL,
|
.fill = GVE_TX_FILL,
|
||||||
.desc_len = sizeof ( struct gve_gqi_tx_descriptor ),
|
.stride = {
|
||||||
|
.gqi = {
|
||||||
|
.desc = sizeof ( struct gve_gqi_tx_descriptor ),
|
||||||
|
},
|
||||||
|
},
|
||||||
.create = GVE_ADMIN_CREATE_TX,
|
.create = GVE_ADMIN_CREATE_TX,
|
||||||
.destroy = GVE_ADMIN_DESTROY_TX,
|
.destroy = GVE_ADMIN_DESTROY_TX,
|
||||||
};
|
};
|
||||||
@@ -1582,8 +1594,12 @@ static const struct gve_queue_type gve_rx_type = {
|
|||||||
.qpl = GVE_RX_QPL,
|
.qpl = GVE_RX_QPL,
|
||||||
.irq = GVE_RX_IRQ,
|
.irq = GVE_RX_IRQ,
|
||||||
.fill = GVE_RX_FILL,
|
.fill = GVE_RX_FILL,
|
||||||
.desc_len = sizeof ( struct gve_gqi_rx_descriptor ),
|
.stride = {
|
||||||
.cmplt_len = sizeof ( struct gve_gqi_rx_completion ),
|
.gqi = {
|
||||||
|
.desc = sizeof ( struct gve_gqi_rx_descriptor ),
|
||||||
|
.cmplt = sizeof ( struct gve_gqi_rx_completion ),
|
||||||
|
},
|
||||||
|
},
|
||||||
.create = GVE_ADMIN_CREATE_RX,
|
.create = GVE_ADMIN_CREATE_RX,
|
||||||
.destroy = GVE_ADMIN_DESTROY_RX,
|
.destroy = GVE_ADMIN_DESTROY_RX,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -622,6 +622,14 @@ struct gve_gqi_rx_completion {
|
|||||||
/** Padding at the start of all received packets */
|
/** Padding at the start of all received packets */
|
||||||
#define GVE_RX_PAD 2
|
#define GVE_RX_PAD 2
|
||||||
|
|
||||||
|
/** Queue strides */
|
||||||
|
struct gve_queue_stride {
|
||||||
|
/** Descriptor ring stride */
|
||||||
|
uint8_t desc;
|
||||||
|
/** Completion ring stride */
|
||||||
|
uint8_t cmplt;
|
||||||
|
};
|
||||||
|
|
||||||
/** A descriptor queue */
|
/** A descriptor queue */
|
||||||
struct gve_queue {
|
struct gve_queue {
|
||||||
/** Descriptor ring */
|
/** Descriptor ring */
|
||||||
@@ -654,6 +662,8 @@ struct gve_queue {
|
|||||||
|
|
||||||
/** Queue type */
|
/** Queue type */
|
||||||
const struct gve_queue_type *type;
|
const struct gve_queue_type *type;
|
||||||
|
/** Queue strides */
|
||||||
|
struct gve_queue_stride stride;
|
||||||
/** Number of descriptors (must be a power of two) */
|
/** Number of descriptors (must be a power of two) */
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
/** Maximum fill level (must be a power of two) */
|
/** Maximum fill level (must be a power of two) */
|
||||||
@@ -701,10 +711,11 @@ struct gve_queue_type {
|
|||||||
uint8_t irq;
|
uint8_t irq;
|
||||||
/** Maximum fill level */
|
/** Maximum fill level */
|
||||||
uint8_t fill;
|
uint8_t fill;
|
||||||
/** Descriptor size */
|
/** Queue strides */
|
||||||
uint8_t desc_len;
|
struct {
|
||||||
/** Completion size */
|
/** In-order queue strides */
|
||||||
uint8_t cmplt_len;
|
struct gve_queue_stride gqi;
|
||||||
|
} stride;
|
||||||
/** Command to create queue */
|
/** Command to create queue */
|
||||||
uint8_t create;
|
uint8_t create;
|
||||||
/** Command to destroy queue */
|
/** Command to destroy queue */
|
||||||
|
|||||||
Reference in New Issue
Block a user