struct gve_events *events = &gve->events;
struct gve_irqs *irqs = &gve->irqs;
union gve_admin_command *cmd;
+ uint32_t doorbell;
unsigned int db_off;
unsigned int i;
int rc;
return rc;
/* Disable all interrupts */
+ doorbell = ( ( gve->mode & GVE_MODE_DQO ) ?
+ 0 : bswap_32 ( GVE_GQI_IRQ_DISABLE ) );
for ( i = 0 ; i < GVE_IRQ_COUNT ; i++ ) {
db_off = ( be32_to_cpu ( irqs->irq[i].db_idx ) *
sizeof ( uint32_t ) );
DBGC ( gve, "GVE %p IRQ %d doorbell +%#04x\n", gve, i, db_off );
irqs->db[i] = ( gve->db + db_off );
- writel ( bswap_32 ( GVE_IRQ_DISABLE ), irqs->db[i] );
+ writel ( doorbell, irqs->db[i] );
}
return 0;
queue->event = &gve->events.event[evt_idx];
assert ( queue->event->count == 0 );
+ /* Unmask dummy interrupt */
+ pci_msix_unmask ( &gve->msix, type->irq );
+
+ /* Rearm queue interrupt if applicable */
+ if ( gve->mode & GVE_MODE_DQO )
+ writel ( GVE_DQO_IRQ_REARM, gve->irqs.db[type->irq] );
+
return 0;
}
const struct gve_queue_type *type = queue->type;
int rc;
+ /* Mask dummy interrupt */
+ pci_msix_mask ( &gve->msix, type->irq );
+
/* Issue command */
if ( ( rc = gve_admin_simple ( gve, type->destroy, 0 ) ) != 0 )
return rc;
rmb();
tx->done++;
+ /* Re-arm interrupt */
+ writel ( GVE_DQO_IRQ_REARM, gve->irqs.db[GVE_TX_IRQ] );
+
/* Ignore non-packet completions */
if ( ( ! ( dqo->flags & GVE_DQO_TXF_PKT ) ) ||
( dqo->tag.count < 0 ) ) {
break;
rmb();
+ /* Re-arm interrupt */
+ writel ( GVE_DQO_IRQ_REARM, gve->irqs.db[GVE_RX_IRQ] );
+
/* Parse completion */
len = ( le16_to_cpu ( dqo->len ) &
( GVE_BUF_SIZE - 1 ) );
dma_set_mask_64bit ( gve->dma );
assert ( netdev->dma == NULL );
+ /* Configure dummy MSI-X interrupt */
+ if ( ( rc = pci_msix_enable ( pci, &gve->msix ) ) != 0 )
+ goto err_msix;
+
/* Allocate admin queue */
if ( ( rc = gve_admin_alloc ( gve ) ) != 0 )
goto err_admin;
gve_reset ( gve );
gve_admin_free ( gve );
err_admin:
+ pci_msix_disable ( pci, &gve->msix );
+ err_msix:
iounmap ( gve->db );
err_db:
iounmap ( gve->cfg );
/* Free admin queue */
gve_admin_free ( gve );
+ /* Disable dummy MSI-X interrupt */
+ pci_msix_disable ( pci, &gve->msix );
+
/* Unmap registers */
iounmap ( gve->db );
iounmap ( gve->cfg );
#include <stdint.h>
#include <ipxe/dma.h>
#include <ipxe/pci.h>
+#include <ipxe/pcimsix.h>
#include <ipxe/in.h>
#include <ipxe/process.h>
#include <ipxe/retry.h>
volatile uint32_t *db[GVE_IRQ_COUNT];
};
-/** Disable interrupts */
-#define GVE_IRQ_DISABLE 0x40000000UL
+/** Disable in-order queue interrupt */
+#define GVE_GQI_IRQ_DISABLE 0x40000000UL
+
+/** Rearm out-of-order queue interrupt */
+#define GVE_DQO_IRQ_REARM 0x00000019UL
/**
* Queue resources
struct net_device *netdev;
/** DMA device */
struct dma_device *dma;
+ /** Dummy MSI-X interrupt */
+ struct pci_msix msix;
/** Admin queue */
struct gve_admin admin;