]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[intelxl] Update driver to use DMA API
authorMichael Brown <mcb30@ipxe.org>
Tue, 17 Nov 2020 01:26:21 +0000 (01:26 +0000)
committerMichael Brown <mcb30@ipxe.org>
Sat, 21 Nov 2020 13:35:11 +0000 (13:35 +0000)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/drivers/net/intelxl.c
src/drivers/net/intelxl.h
src/drivers/net/intelxlvf.c

index d929f48cd2a2dd006416810206aecd81150d935f..578d6ff02825ffd95a0166487844b6f2f6b16500 100644 (file)
@@ -34,7 +34,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #include <ipxe/if_ether.h>
 #include <ipxe/vlan.h>
 #include <ipxe/iobuf.h>
-#include <ipxe/malloc.h>
 #include <ipxe/pci.h>
 #include <ipxe/version.h>
 #include "intelxl.h"
@@ -136,20 +135,35 @@ int intelxl_msix_enable ( struct intelxl_nic *intelxl,
                          struct pci_device *pci ) {
        int rc;
 
+       /* Map dummy target location */
+       if ( ( rc = dma_map ( intelxl->dma, virt_to_phys ( &intelxl->msix.msg ),
+                             sizeof ( intelxl->msix.msg ), DMA_RX,
+                             &intelxl->msix.map ) ) != 0 ) {
+               DBGC ( intelxl, "INTELXL %p could not map MSI-X target: %s\n",
+                      intelxl, strerror ( rc ) );
+               goto err_map;
+       }
+
        /* Enable MSI-X capability */
-       if ( ( rc = pci_msix_enable ( pci, &intelxl->msix ) ) != 0 ) {
+       if ( ( rc = pci_msix_enable ( pci, &intelxl->msix.cap ) ) != 0 ) {
                DBGC ( intelxl, "INTELXL %p could not enable MSI-X: %s\n",
                       intelxl, strerror ( rc ) );
-               return rc;
+               goto err_enable;
        }
 
        /* Configure interrupt zero to write to dummy location */
-       pci_msix_map ( &intelxl->msix, 0, virt_to_bus ( &intelxl->msg ), 0 );
+       pci_msix_map ( &intelxl->msix.cap, 0, intelxl->msix.map.addr, 0 );
 
        /* Enable dummy interrupt zero */
-       pci_msix_unmask ( &intelxl->msix, 0 );
+       pci_msix_unmask ( &intelxl->msix.cap, 0 );
 
        return 0;
+
+       pci_msix_disable ( pci, &intelxl->msix.cap );
+ err_enable:
+       dma_unmap ( intelxl->dma, &intelxl->msix.map );
+ err_map:
+       return rc;
 }
 
 /**
@@ -162,10 +176,13 @@ void intelxl_msix_disable ( struct intelxl_nic *intelxl,
                            struct pci_device *pci ) {
 
        /* Disable dummy interrupt zero */
-       pci_msix_mask ( &intelxl->msix, 0 );
+       pci_msix_mask ( &intelxl->msix.cap, 0 );
 
        /* Disable MSI-X capability */
-       pci_msix_disable ( pci, &intelxl->msix );
+       pci_msix_disable ( pci, &intelxl->msix.cap );
+
+       /* Unmap dummy target location */
+       dma_unmap ( intelxl->dma, &intelxl->msix.map );
 }
 
 /******************************************************************************
@@ -197,22 +214,38 @@ static int intelxl_alloc_admin ( struct intelxl_nic *intelxl,
        size_t len = ( sizeof ( admin->desc[0] ) * INTELXL_ADMIN_NUM_DESC );
 
        /* Allocate admin queue */
-       admin->buf = malloc_phys ( ( buf_len + len ), INTELXL_ALIGN );
+       admin->buf = dma_alloc ( intelxl->dma, ( buf_len + len ),
+                                INTELXL_ALIGN, &admin->map );
        if ( ! admin->buf )
                return -ENOMEM;
        admin->desc = ( ( ( void * ) admin->buf ) + buf_len );
 
-       DBGC ( intelxl, "INTELXL %p A%cQ is at [%08llx,%08llx) buf "
-              "[%08llx,%08llx)\n", intelxl,
+       DBGC ( intelxl, "INTELXL %p A%cQ is at [%08lx,%08lx) buf "
+              "[%08lx,%08lx)\n", intelxl,
               ( ( admin == &intelxl->command ) ? 'T' : 'R' ),
-              ( ( unsigned long long ) virt_to_bus ( admin->desc ) ),
-              ( ( unsigned long long ) ( virt_to_bus ( admin->desc ) + len ) ),
-              ( ( unsigned long long ) virt_to_bus ( admin->buf ) ),
-              ( ( unsigned long long ) ( virt_to_bus ( admin->buf ) +
-                                         buf_len ) ) );
+              virt_to_phys ( admin->desc ),
+              ( virt_to_phys ( admin->desc ) + len ),
+              virt_to_phys ( admin->buf ),
+              ( virt_to_phys ( admin->buf ) + buf_len ) );
        return 0;
 }
 
+/**
+ * Get DMA address for admin descriptor or buffer entry
+ *
+ * @v admin            Admin queue
+ * @v addr             Virtual address
+ * @ret addr           DMA address
+ */
+static physaddr_t intelxl_admin_address ( struct intelxl_admin *admin,
+                                         void *addr ) {
+       size_t offset;
+
+       /* Calculate offset within mapped area */
+       offset = ( addr - ( ( void * ) admin->buf ) );
+       return ( admin->map.addr + offset );
+}
+
 /**
  * Enable admin queue
  *
@@ -237,7 +270,7 @@ static void intelxl_enable_admin ( struct intelxl_nic *intelxl,
        admin->index = 0;
 
        /* Program queue address */
-       address = virt_to_bus ( admin->desc );
+       address = intelxl_admin_address ( admin, admin->desc );
        writel ( ( address & 0xffffffffUL ), admin_regs + regs->bal );
        if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) {
                writel ( ( ( ( uint64_t ) address ) >> 32 ),
@@ -273,13 +306,13 @@ static void intelxl_disable_admin ( struct intelxl_nic *intelxl,
  * @v intelxl          Intel device
  * @v admin            Admin queue
  */
-static void intelxl_free_admin ( struct intelxl_nic *intelxl __unused,
+static void intelxl_free_admin ( struct intelxl_nic *intelxl,
                                 struct intelxl_admin *admin ) {
        size_t buf_len = ( sizeof ( admin->buf[0] ) * INTELXL_ADMIN_NUM_DESC );
        size_t len = ( sizeof ( admin->desc[0] ) * INTELXL_ADMIN_NUM_DESC );
 
        /* Free queue */
-       free_phys ( admin->buf, ( buf_len + len ) );
+       dma_free ( intelxl->dma, admin->buf, ( buf_len + len ), &admin->map );
 }
 
 /**
@@ -332,7 +365,7 @@ static void intelxl_admin_event_init ( struct intelxl_nic *intelxl,
        /* Initialise descriptor */
        evt = &admin->desc[ index % INTELXL_ADMIN_NUM_DESC ];
        buf = &admin->buf[ index % INTELXL_ADMIN_NUM_DESC ];
-       address = virt_to_bus ( buf );
+       address = intelxl_admin_address ( admin, buf );
        evt->flags = cpu_to_le16 ( INTELXL_ADMIN_FL_BUF );
        evt->len = cpu_to_le16 ( sizeof ( *buf ) );
        evt->params.buffer.high = cpu_to_le32 ( address >> 32 );
@@ -377,7 +410,7 @@ int intelxl_admin_command ( struct intelxl_nic *intelxl ) {
 
        /* Populate data buffer address if applicable */
        if ( cmd->flags & cpu_to_le16 ( INTELXL_ADMIN_FL_BUF ) ) {
-               address = virt_to_bus ( buf );
+               address = intelxl_admin_address ( admin, buf );
                cmd->params.buffer.high = cpu_to_le32 ( address >> 32 );
                cmd->params.buffer.low = cpu_to_le32 ( address & 0xffffffffUL );
        }
@@ -924,16 +957,15 @@ void intelxl_close_admin ( struct intelxl_nic *intelxl ) {
  */
 int intelxl_alloc_ring ( struct intelxl_nic *intelxl,
                         struct intelxl_ring *ring ) {
-       physaddr_t address;
        int rc;
 
        /* Allocate descriptor ring */
-       ring->desc.raw = malloc_phys ( ring->len, INTELXL_ALIGN );
+       ring->desc.raw = dma_alloc ( intelxl->dma, ring->len, INTELXL_ALIGN,
+                                    &ring->map );
        if ( ! ring->desc.raw ) {
                rc = -ENOMEM;
                goto err_alloc;
        }
-       address = virt_to_bus ( ring->desc.raw );
 
        /* Initialise descriptor ring */
        memset ( ring->desc.raw, 0, ring->len );
@@ -945,14 +977,14 @@ int intelxl_alloc_ring ( struct intelxl_nic *intelxl,
        ring->prod = 0;
        ring->cons = 0;
 
-       DBGC ( intelxl, "INTELXL %p ring %06x is at [%08llx,%08llx)\n",
+       DBGC ( intelxl, "INTELXL %p ring %06x is at [%08lx,%08lx)\n",
               intelxl, ( ring->reg + ring->tail ),
-              ( ( unsigned long long ) address ),
-              ( ( unsigned long long ) address + ring->len ) );
+              virt_to_phys ( ring->desc.raw ),
+              ( virt_to_phys ( ring->desc.raw ) + ring->len ) );
 
        return 0;
 
-       free_phys ( ring->desc.raw, ring->len );
+       dma_free ( intelxl->dma, ring->desc.raw, ring->len, &ring->map );
  err_alloc:
        return rc;
 }
@@ -963,11 +995,11 @@ int intelxl_alloc_ring ( struct intelxl_nic *intelxl,
  * @v intelxl          Intel device
  * @v ring             Descriptor ring
  */
-void intelxl_free_ring ( struct intelxl_nic *intelxl __unused,
+void intelxl_free_ring ( struct intelxl_nic *intelxl,
                         struct intelxl_ring *ring ) {
 
        /* Free descriptor ring */
-       free_phys ( ring->desc.raw, ring->len );
+       dma_free ( intelxl->dma, ring->desc.raw, ring->len, &ring->map );
        ring->desc.raw = NULL;
 }
 
@@ -1235,7 +1267,6 @@ static int intelxl_disable_ring ( struct intelxl_nic *intelxl,
  */
 static int intelxl_create_ring ( struct intelxl_nic *intelxl,
                                 struct intelxl_ring *ring ) {
-       physaddr_t address;
        int rc;
 
        /* Allocate descriptor ring */
@@ -1243,8 +1274,7 @@ static int intelxl_create_ring ( struct intelxl_nic *intelxl,
                goto err_alloc;
 
        /* Program queue context */
-       address = virt_to_bus ( ring->desc.raw );
-       if ( ( rc = ring->context ( intelxl, address ) ) != 0 )
+       if ( ( rc = ring->context ( intelxl, ring->map.addr ) ) != 0 )
                goto err_context;
 
        /* Enable ring */
@@ -1289,61 +1319,75 @@ static void intelxl_destroy_ring ( struct intelxl_nic *intelxl,
 static void intelxl_refill_rx ( struct intelxl_nic *intelxl ) {
        struct intelxl_rx_data_descriptor *rx;
        struct io_buffer *iobuf;
+       struct dma_mapping *map;
        unsigned int rx_idx;
        unsigned int rx_tail;
-       physaddr_t address;
        unsigned int refilled = 0;
 
        /* Refill ring */
-       while ( ( intelxl->rx.prod - intelxl->rx.cons ) < INTELXL_RX_FILL ) {
+       while ( ( intelxl->rx.ring.prod -
+                 intelxl->rx.ring.cons ) < INTELXL_RX_FILL ) {
+
+               /* Get next receive descriptor */
+               rx_idx = ( intelxl->rx.ring.prod % INTELXL_RX_NUM_DESC );
+               rx = &intelxl->rx.ring.desc.rx[rx_idx].data;
+               map = &intelxl->rx.map[rx_idx];
+               assert ( intelxl->rx.iobuf[rx_idx] == NULL );
 
                /* Allocate I/O buffer */
-               iobuf = alloc_iob ( intelxl->mfs );
+               iobuf = dma_alloc_rx_iob ( intelxl->dma, intelxl->mfs, map );
                if ( ! iobuf ) {
                        /* Wait for next refill */
                        break;
                }
+               intelxl->rx.iobuf[rx_idx] = iobuf;
 
-               /* Get next receive descriptor */
-               rx_idx = ( intelxl->rx.prod++ % INTELXL_RX_NUM_DESC );
-               rx = &intelxl->rx.desc.rx[rx_idx].data;
+               /* Update producer index */
+               intelxl->rx.ring.prod++;
 
                /* Populate receive descriptor */
-               address = virt_to_bus ( iobuf->data );
-               rx->address = cpu_to_le64 ( address );
+               rx->address = cpu_to_le64 ( map->addr );
                rx->flags = 0;
 
-               /* Record I/O buffer */
-               assert ( intelxl->rx_iobuf[rx_idx] == NULL );
-               intelxl->rx_iobuf[rx_idx] = iobuf;
-
-               DBGC2 ( intelxl, "INTELXL %p RX %d is [%llx,%llx)\n", intelxl,
-                       rx_idx, ( ( unsigned long long ) address ),
-                       ( ( unsigned long long ) address + intelxl->mfs ) );
+               DBGC2 ( intelxl, "INTELXL %p RX %d is [%08lx,%08lx)\n",
+                       intelxl, rx_idx, virt_to_phys ( iobuf->data ),
+                       ( virt_to_phys ( iobuf->data ) +  intelxl->mfs ) );
                refilled++;
        }
 
        /* Push descriptors to card, if applicable */
        if ( refilled ) {
                wmb();
-               rx_tail = ( intelxl->rx.prod % INTELXL_RX_NUM_DESC );
-               writel ( rx_tail, ( intelxl->regs + intelxl->rx.tail ) );
+               rx_tail = ( intelxl->rx.ring.prod % INTELXL_RX_NUM_DESC );
+               writel ( rx_tail, ( intelxl->regs + intelxl->rx.ring.tail ) );
        }
 }
 
 /**
- * Discard unused receive I/O buffers
+ * Flush unused I/O buffers
  *
  * @v intelxl          Intel device
+ *
+ * Discard any unused receive I/O buffers and unmap any incomplete
+ * transmit I/O buffers.
  */
-void intelxl_empty_rx ( struct intelxl_nic *intelxl ) {
+void intelxl_flush ( struct intelxl_nic *intelxl ) {
        unsigned int i;
+       unsigned int tx_idx;
 
        /* Discard any unused receive buffers */
        for ( i = 0 ; i < INTELXL_RX_NUM_DESC ; i++ ) {
-               if ( intelxl->rx_iobuf[i] )
-                       free_iob ( intelxl->rx_iobuf[i] );
-               intelxl->rx_iobuf[i] = NULL;
+               if ( intelxl->rx.iobuf[i] ) {
+                       dma_unmap ( intelxl->dma, &intelxl->rx.map[i] );
+                       free_iob ( intelxl->rx.iobuf[i] );
+               }
+               intelxl->rx.iobuf[i] = NULL;
+       }
+
+       /* Unmap incomplete transmit buffers */
+       for ( i = intelxl->tx.ring.cons ; i != intelxl->tx.ring.prod ; i++ ) {
+               tx_idx = ( i % INTELXL_TX_NUM_DESC );
+               dma_unmap ( intelxl->dma, &intelxl->tx.map[tx_idx] );
        }
 }
 
@@ -1384,7 +1428,7 @@ static int intelxl_open ( struct net_device *netdev ) {
        /* Associate transmit queue to PF */
        writel ( ( INTELXL_QXX_CTL_PFVF_Q_PF |
                   INTELXL_QXX_CTL_PFVF_PF_INDX ( intelxl->pf ) ),
-                ( intelxl->regs + intelxl->tx.reg + INTELXL_QXX_CTL ) );
+                ( intelxl->regs + intelxl->tx.ring.reg + INTELXL_QXX_CTL ) );
 
        /* Clear transmit pre queue disable */
        queue = ( intelxl->base + intelxl->queue );
@@ -1396,11 +1440,11 @@ static int intelxl_open ( struct net_device *netdev ) {
        writel ( 0, ( intelxl->regs + INTELXL_QTX_HEAD ( intelxl->queue ) ) );
 
        /* Create receive descriptor ring */
-       if ( ( rc = intelxl_create_ring ( intelxl, &intelxl->rx ) ) != 0 )
+       if ( ( rc = intelxl_create_ring ( intelxl, &intelxl->rx.ring ) ) != 0 )
                goto err_create_rx;
 
        /* Create transmit descriptor ring */
-       if ( ( rc = intelxl_create_ring ( intelxl, &intelxl->tx ) ) != 0 )
+       if ( ( rc = intelxl_create_ring ( intelxl, &intelxl->tx.ring ) ) != 0 )
                goto err_create_tx;
 
        /* Fill receive ring */
@@ -1418,9 +1462,9 @@ static int intelxl_open ( struct net_device *netdev ) {
                   INTELXL_GLLAN_TXPRE_QDIS_QINDX ( queue ) ),
                 ( intelxl->regs + INTELXL_GLLAN_TXPRE_QDIS ( queue ) ) );
        udelay ( INTELXL_QUEUE_PRE_DISABLE_DELAY_US );
-       intelxl_destroy_ring ( intelxl, &intelxl->tx );
+       intelxl_destroy_ring ( intelxl, &intelxl->tx.ring );
  err_create_tx:
-       intelxl_destroy_ring ( intelxl, &intelxl->rx );
+       intelxl_destroy_ring ( intelxl, &intelxl->rx.ring );
  err_create_rx:
        return rc;
 }
@@ -1448,13 +1492,13 @@ static void intelxl_close ( struct net_device *netdev ) {
        udelay ( INTELXL_QUEUE_PRE_DISABLE_DELAY_US );
 
        /* Destroy transmit descriptor ring */
-       intelxl_destroy_ring ( intelxl, &intelxl->tx );
+       intelxl_destroy_ring ( intelxl, &intelxl->tx.ring );
 
        /* Destroy receive descriptor ring */
-       intelxl_destroy_ring ( intelxl, &intelxl->rx );
+       intelxl_destroy_ring ( intelxl, &intelxl->rx.ring );
 
-       /* Discard any unused receive buffers */
-       intelxl_empty_rx ( intelxl );
+       /* Flush unused buffers */
+       intelxl_flush ( intelxl );
 }
 
 /**
@@ -1467,36 +1511,45 @@ static void intelxl_close ( struct net_device *netdev ) {
 int intelxl_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
        struct intelxl_nic *intelxl = netdev->priv;
        struct intelxl_tx_data_descriptor *tx;
+       struct dma_mapping *map;
        unsigned int tx_idx;
        unsigned int tx_tail;
-       physaddr_t address;
        size_t len;
+       int rc;
 
        /* Get next transmit descriptor */
-       if ( ( intelxl->tx.prod - intelxl->tx.cons ) >= INTELXL_TX_FILL ) {
+       if ( ( intelxl->tx.ring.prod -
+              intelxl->tx.ring.cons ) >= INTELXL_TX_FILL ) {
                DBGC ( intelxl, "INTELXL %p out of transmit descriptors\n",
                       intelxl );
                return -ENOBUFS;
        }
-       tx_idx = ( intelxl->tx.prod++ % INTELXL_TX_NUM_DESC );
-       tx_tail = ( intelxl->tx.prod % INTELXL_TX_NUM_DESC );
-       tx = &intelxl->tx.desc.tx[tx_idx].data;
+       tx_idx = ( intelxl->tx.ring.prod % INTELXL_TX_NUM_DESC );
+       tx = &intelxl->tx.ring.desc.tx[tx_idx].data;
+       map = &intelxl->tx.map[tx_idx];
+
+       /* Map I/O buffer */
+       if ( ( rc = dma_map_tx_iob ( intelxl->dma, iobuf, map ) ) != 0 )
+               return rc;
+
+       /* Update producer index */
+       intelxl->tx.ring.prod++;
 
        /* Populate transmit descriptor */
-       address = virt_to_bus ( iobuf->data );
        len = iob_len ( iobuf );
-       tx->address = cpu_to_le64 ( address );
+       tx->address = cpu_to_le64 ( map->addr );
        tx->len = cpu_to_le32 ( INTELXL_TX_DATA_LEN ( len ) );
        tx->flags = cpu_to_le32 ( INTELXL_TX_DATA_DTYP | INTELXL_TX_DATA_EOP |
                                  INTELXL_TX_DATA_RS | INTELXL_TX_DATA_JFDI );
        wmb();
 
        /* Notify card that there are packets ready to transmit */
-       writel ( tx_tail, ( intelxl->regs + intelxl->tx.tail ) );
+       tx_tail = ( intelxl->tx.ring.prod % INTELXL_TX_NUM_DESC );
+       writel ( tx_tail, ( intelxl->regs + intelxl->tx.ring.tail ) );
 
-       DBGC2 ( intelxl, "INTELXL %p TX %d is [%llx,%llx)\n", intelxl, tx_idx,
-               ( ( unsigned long long ) address ),
-               ( ( unsigned long long ) address + len ) );
+       DBGC2 ( intelxl, "INTELXL %p TX %d is [%08lx,%08lx)\n",
+               intelxl, tx_idx, virt_to_phys ( iobuf->data ),
+               ( virt_to_phys ( iobuf->data ) + len ) );
        return 0;
 }
 
@@ -1511,11 +1564,11 @@ static void intelxl_poll_tx ( struct net_device *netdev ) {
        unsigned int tx_idx;
 
        /* Check for completed packets */
-       while ( intelxl->tx.cons != intelxl->tx.prod ) {
+       while ( intelxl->tx.ring.cons != intelxl->tx.ring.prod ) {
 
                /* Get next transmit descriptor */
-               tx_idx = ( intelxl->tx.cons % INTELXL_TX_NUM_DESC );
-               tx_wb = &intelxl->tx.desc.tx[tx_idx].wb;
+               tx_idx = ( intelxl->tx.ring.cons % INTELXL_TX_NUM_DESC );
+               tx_wb = &intelxl->tx.ring.desc.tx[tx_idx].wb;
 
                /* Stop if descriptor is still in use */
                if ( ! ( tx_wb->flags & INTELXL_TX_WB_FL_DD ) )
@@ -1523,9 +1576,12 @@ static void intelxl_poll_tx ( struct net_device *netdev ) {
                DBGC2 ( intelxl, "INTELXL %p TX %d complete\n",
                        intelxl, tx_idx );
 
+               /* Unmap I/O buffer */
+               dma_unmap ( intelxl->dma, &intelxl->tx.map[tx_idx] );
+
                /* Complete TX descriptor */
                netdev_tx_complete_next ( netdev );
-               intelxl->tx.cons++;
+               intelxl->tx.ring.cons++;
        }
 }
 
@@ -1543,19 +1599,22 @@ static void intelxl_poll_rx ( struct net_device *netdev ) {
        size_t len;
 
        /* Check for received packets */
-       while ( intelxl->rx.cons != intelxl->rx.prod ) {
+       while ( intelxl->rx.ring.cons != intelxl->rx.ring.prod ) {
 
                /* Get next receive descriptor */
-               rx_idx = ( intelxl->rx.cons % INTELXL_RX_NUM_DESC );
-               rx_wb = &intelxl->rx.desc.rx[rx_idx].wb;
+               rx_idx = ( intelxl->rx.ring.cons % INTELXL_RX_NUM_DESC );
+               rx_wb = &intelxl->rx.ring.desc.rx[rx_idx].wb;
 
                /* Stop if descriptor is still in use */
                if ( ! ( rx_wb->flags & cpu_to_le32 ( INTELXL_RX_WB_FL_DD ) ) )
                        return;
 
+               /* Unmap I/O buffer */
+               dma_unmap ( intelxl->dma, &intelxl->rx.map[rx_idx] );
+
                /* Populate I/O buffer */
-               iobuf = intelxl->rx_iobuf[rx_idx];
-               intelxl->rx_iobuf[rx_idx] = NULL;
+               iobuf = intelxl->rx.iobuf[rx_idx];
+               intelxl->rx.iobuf[rx_idx] = NULL;
                len = INTELXL_RX_WB_LEN ( le32_to_cpu ( rx_wb->len ) );
                iob_put ( iobuf, len );
 
@@ -1577,7 +1636,7 @@ static void intelxl_poll_rx ( struct net_device *netdev ) {
                                "%zd)\n", intelxl, rx_idx, len );
                        vlan_netdev_rx ( netdev, tag, iobuf );
                }
-               intelxl->rx.cons++;
+               intelxl->rx.ring.cons++;
        }
 }
 
@@ -1659,16 +1718,17 @@ static int intelxl_probe ( struct pci_device *pci ) {
        pci_set_drvdata ( pci, netdev );
        netdev->dev = &pci->dev;
        memset ( intelxl, 0, sizeof ( *intelxl ) );
+       intelxl->dma = &pci->dma;
        intelxl->intr = INTELXL_PFINT_DYN_CTL0;
        intelxl_init_admin ( &intelxl->command, INTELXL_ADMIN_CMD,
                             &intelxl_admin_offsets );
        intelxl_init_admin ( &intelxl->event, INTELXL_ADMIN_EVT,
                             &intelxl_admin_offsets );
-       intelxl_init_ring ( &intelxl->tx, INTELXL_TX_NUM_DESC,
-                           sizeof ( intelxl->tx.desc.tx[0] ),
+       intelxl_init_ring ( &intelxl->tx.ring, INTELXL_TX_NUM_DESC,
+                           sizeof ( intelxl->tx.ring.desc.tx[0] ),
                            intelxl_context_tx );
-       intelxl_init_ring ( &intelxl->rx, INTELXL_RX_NUM_DESC,
-                           sizeof ( intelxl->rx.desc.rx[0] ),
+       intelxl_init_ring ( &intelxl->rx.ring, INTELXL_RX_NUM_DESC,
+                           sizeof ( intelxl->rx.ring.desc.rx[0] ),
                            intelxl_context_rx );
 
        /* Fix up PCI device */
@@ -1725,10 +1785,10 @@ static int intelxl_probe ( struct pci_device *pci ) {
                goto err_admin_promisc;
 
        /* Configure queue register addresses */
-       intelxl->tx.reg = INTELXL_QTX ( intelxl->queue );
-       intelxl->tx.tail = ( intelxl->tx.reg + INTELXL_QXX_TAIL );
-       intelxl->rx.reg = INTELXL_QRX ( intelxl->queue );
-       intelxl->rx.tail = ( intelxl->rx.reg + INTELXL_QXX_TAIL );
+       intelxl->tx.ring.reg = INTELXL_QTX ( intelxl->queue );
+       intelxl->tx.ring.tail = ( intelxl->tx.ring.reg + INTELXL_QXX_TAIL );
+       intelxl->rx.ring.reg = INTELXL_QRX ( intelxl->queue );
+       intelxl->rx.ring.tail = ( intelxl->rx.ring.reg + INTELXL_QXX_TAIL );
 
        /* Configure interrupt causes */
        writel ( ( INTELXL_QINT_TQCTL_NEXTQ_INDX_NONE |
index ef9152f6e35632b7dfdde0959a99ada01d32df7e..cffc0da968fec8f76243214852ea088b798ca155 100644 (file)
@@ -12,6 +12,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #include <stdint.h>
 #include <ipxe/if_ether.h>
 #include <ipxe/pcimsix.h>
+#include <ipxe/dma.h>
 
 struct intelxl_nic;
 
@@ -562,6 +563,8 @@ struct intelxl_admin {
        struct intelxl_admin_descriptor *desc;
        /** Data buffers */
        union intelxl_admin_buffer *buf;
+       /** DMA mapping */
+       struct dma_mapping map;
        /** Queue index */
        unsigned int index;
 
@@ -866,6 +869,8 @@ struct intelxl_ring {
                /** Raw data */
                void *raw;
        } desc;
+       /** Descriptor ring DMA mapping */
+       struct dma_mapping map;
        /** Producer index */
        unsigned int prod;
        /** Consumer index */
@@ -1025,10 +1030,40 @@ union intelxl_receive_address {
        uint8_t raw[ETH_ALEN];
 };
 
+/** Transmit ring */
+struct intelxl_tx_ring {
+       /** Descriptor ring */
+       struct intelxl_ring ring;
+       /** DMA mappings */
+       struct dma_mapping map[INTELXL_TX_NUM_DESC];
+};
+
+/** Receive ring */
+struct intelxl_rx_ring {
+       /** Descriptor ring */
+       struct intelxl_ring ring;
+       /** I/O buffers */
+       struct io_buffer *iobuf[INTELXL_RX_NUM_DESC];
+       /** DMA mappings */
+       struct dma_mapping map[INTELXL_RX_NUM_DESC];
+};
+
+/** MSI-X interrupt */
+struct intelxl_msix {
+       /** PCI capability */
+       struct pci_msix cap;
+       /** MSI-X dummy interrupt target */
+       uint32_t msg;
+       /** DMA mapping for dummy interrupt target */
+       struct dma_mapping map;
+};
+
 /** An Intel 40Gigabit network card */
 struct intelxl_nic {
        /** Registers */
        void *regs;
+       /** DMA device */
+       struct dma_device *dma;
        /** Maximum frame size */
        size_t mfs;
 
@@ -1046,12 +1081,10 @@ struct intelxl_nic {
        unsigned int qset;
        /** Interrupt control register */
        unsigned int intr;
-       /** MSI-X capability */
-       struct pci_msix msix;
-       /** MSI-X dummy interrupt target */
-       uint32_t msg;
        /** PCI Express capability offset */
        unsigned int exp;
+       /** MSI-X interrupt */
+       struct intelxl_msix msix;
 
        /** Admin command queue */
        struct intelxl_admin command;
@@ -1065,12 +1098,10 @@ struct intelxl_nic {
        /** Current VF event data buffer */
        union intelxl_admin_buffer vbuf;
 
-       /** Transmit descriptor ring */
-       struct intelxl_ring tx;
-       /** Receive descriptor ring */
-       struct intelxl_ring rx;
-       /** Receive I/O buffers */
-       struct io_buffer *rx_iobuf[INTELXL_RX_NUM_DESC];
+       /** Transmit ring */
+       struct intelxl_tx_ring tx;
+       /** Receive ring */
+       struct intelxl_rx_ring rx;
 };
 
 extern int intelxl_msix_enable ( struct intelxl_nic *intelxl,
@@ -1090,7 +1121,7 @@ extern int intelxl_alloc_ring ( struct intelxl_nic *intelxl,
                                struct intelxl_ring *ring );
 extern void intelxl_free_ring ( struct intelxl_nic *intelxl,
                                struct intelxl_ring *ring );
-extern void intelxl_empty_rx ( struct intelxl_nic *intelxl );
+extern void intelxl_flush ( struct intelxl_nic *intelxl );
 extern int intelxl_transmit ( struct net_device *netdev,
                              struct io_buffer *iobuf );
 extern void intelxl_poll ( struct net_device *netdev );
index 83e484c8d154c2908dc453de884ba7f0fd01f429..dc2e3bf4e51bef76e1221fdd88448517ba6881a7 100644 (file)
@@ -298,9 +298,9 @@ void intelxlvf_admin_event ( struct net_device *netdev,
                if ( intelxl->vret != 0 ) {
                        DBGC ( intelxl, "INTELXL %p admin VF command %#x "
                               "error %d\n", intelxl, vopcode, intelxl->vret );
-                       DBGC_HDA ( intelxl, virt_to_bus ( evt ), evt,
+                       DBGC_HDA ( intelxl, virt_to_phys ( evt ), evt,
                                   sizeof ( *evt ) );
-                       DBGC_HDA ( intelxl, virt_to_bus ( buf ), buf,
+                       DBGC_HDA ( intelxl, virt_to_phys ( buf ), buf,
                                   le16_to_cpu ( evt->len ) );
                }
                return;
@@ -314,8 +314,10 @@ void intelxlvf_admin_event ( struct net_device *netdev,
        default:
                DBGC ( intelxl, "INTELXL %p unrecognised VF event %#x:\n",
                       intelxl, vopcode );
-               DBGC_HDA ( intelxl, 0, evt, sizeof ( *evt ) );
-               DBGC_HDA ( intelxl, 0, buf, le16_to_cpu ( evt->len ) );
+               DBGC_HDA ( intelxl, virt_to_phys ( evt ), evt,
+                          sizeof ( *evt ) );
+               DBGC_HDA ( intelxl, virt_to_phys ( buf ), buf,
+                          le16_to_cpu ( evt->len ) );
                break;
        }
 }
@@ -378,12 +380,12 @@ static int intelxlvf_admin_configure ( struct net_device *netdev ) {
        buf->cfg.count = cpu_to_le16 ( 1 );
        buf->cfg.tx.vsi = cpu_to_le16 ( intelxl->vsi );
        buf->cfg.tx.count = cpu_to_le16 ( INTELXL_TX_NUM_DESC );
-       buf->cfg.tx.base = cpu_to_le64 ( virt_to_bus ( intelxl->tx.desc.raw ) );
+       buf->cfg.tx.base = cpu_to_le64 ( intelxl->tx.ring.map.addr );
        buf->cfg.rx.vsi = cpu_to_le16 ( intelxl->vsi );
        buf->cfg.rx.count = cpu_to_le32 ( INTELXL_RX_NUM_DESC );
        buf->cfg.rx.len = cpu_to_le32 ( intelxl->mfs );
        buf->cfg.rx.mfs = cpu_to_le32 ( intelxl->mfs );
-       buf->cfg.rx.base = cpu_to_le64 ( virt_to_bus ( intelxl->rx.desc.raw ) );
+       buf->cfg.rx.base = cpu_to_le64 ( intelxl->rx.ring.map.addr );
 
        /* Issue command */
        if ( ( rc = intelxlvf_admin_command ( netdev ) ) != 0 )
@@ -497,11 +499,11 @@ static int intelxlvf_open ( struct net_device *netdev ) {
                           INTELXL_ALIGN - 1 ) & ~( INTELXL_ALIGN - 1 ) );
 
        /* Allocate transmit descriptor ring */
-       if ( ( rc = intelxl_alloc_ring ( intelxl, &intelxl->tx ) ) != 0 )
+       if ( ( rc = intelxl_alloc_ring ( intelxl, &intelxl->tx.ring ) ) != 0 )
                goto err_alloc_tx;
 
        /* Allocate receive descriptor ring */
-       if ( ( rc = intelxl_alloc_ring ( intelxl, &intelxl->rx ) ) != 0 )
+       if ( ( rc = intelxl_alloc_ring ( intelxl, &intelxl->rx.ring ) ) != 0 )
                goto err_alloc_rx;
 
        /* Configure queues */
@@ -527,9 +529,9 @@ static int intelxlvf_open ( struct net_device *netdev ) {
  err_enable:
  err_irq_map:
  err_configure:
-       intelxl_free_ring ( intelxl, &intelxl->rx );
+       intelxl_free_ring ( intelxl, &intelxl->rx.ring );
  err_alloc_rx:
-       intelxl_free_ring ( intelxl, &intelxl->tx );
+       intelxl_free_ring ( intelxl, &intelxl->tx.ring );
  err_alloc_tx:
        return rc;
 }
@@ -550,13 +552,13 @@ static void intelxlvf_close ( struct net_device *netdev ) {
        }
 
        /* Free receive descriptor ring */
-       intelxl_free_ring ( intelxl, &intelxl->rx );
+       intelxl_free_ring ( intelxl, &intelxl->rx.ring );
 
        /* Free transmit descriptor ring */
-       intelxl_free_ring ( intelxl, &intelxl->tx );
+       intelxl_free_ring ( intelxl, &intelxl->tx.ring );
 
-       /* Discard any unused receive buffers */
-       intelxl_empty_rx ( intelxl );
+       /* Flush unused buffers */
+       intelxl_flush ( intelxl );
 }
 
 /** Network device operations */
@@ -596,16 +598,17 @@ static int intelxlvf_probe ( struct pci_device *pci ) {
        pci_set_drvdata ( pci, netdev );
        netdev->dev = &pci->dev;
        memset ( intelxl, 0, sizeof ( *intelxl ) );
+       intelxl->dma = &pci->dma;
        intelxl->intr = INTELXLVF_VFINT_DYN_CTL0;
        intelxl_init_admin ( &intelxl->command, INTELXLVF_ADMIN,
                             &intelxlvf_admin_command_offsets );
        intelxl_init_admin ( &intelxl->event, INTELXLVF_ADMIN,
                             &intelxlvf_admin_event_offsets );
-       intelxlvf_init_ring ( &intelxl->tx, INTELXL_TX_NUM_DESC,
-                             sizeof ( intelxl->tx.desc.tx[0] ),
+       intelxlvf_init_ring ( &intelxl->tx.ring, INTELXL_TX_NUM_DESC,
+                             sizeof ( intelxl->tx.ring.desc.tx[0] ),
                              INTELXLVF_QTX_TAIL );
-       intelxlvf_init_ring ( &intelxl->rx, INTELXL_RX_NUM_DESC,
-                             sizeof ( intelxl->rx.desc.rx[0] ),
+       intelxlvf_init_ring ( &intelxl->rx.ring, INTELXL_RX_NUM_DESC,
+                             sizeof ( intelxl->rx.ring.desc.rx[0] ),
                              INTELXLVF_QRX_TAIL );
 
        /* Fix up PCI device */