diff options
author | Michael Brown <mcb30@ipxe.org> | 2020-11-17 01:26:21 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2020-11-21 13:35:11 +0000 |
commit | 03314e8da9a3c387e9bbcf3830e6517377768de4 (patch) | |
tree | 3bd743ff3ae4f7b14c945df019ac2cf66f6ac1d7 | |
parent | 76a7bfe939b4b6ea88690e8c6960c65d57c01b5e (diff) | |
download | ipxe-03314e8da9a3c387e9bbcf3830e6517377768de4.tar.gz |
[intelxl] Update driver to use DMA API
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r-- | src/drivers/net/intelxl.c | 244 | ||||
-rw-r--r-- | src/drivers/net/intelxl.h | 53 | ||||
-rw-r--r-- | src/drivers/net/intelxlvf.c | 39 |
3 files changed, 215 insertions, 121 deletions
diff --git a/src/drivers/net/intelxl.c b/src/drivers/net/intelxl.c index d929f48cd..578d6ff02 100644 --- a/src/drivers/net/intelxl.c +++ b/src/drivers/net/intelxl.c @@ -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,23 +214,39 @@ 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 * * @v intelxl Intel device @@ -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 | diff --git a/src/drivers/net/intelxl.h b/src/drivers/net/intelxl.h index ef9152f6e..cffc0da96 100644 --- a/src/drivers/net/intelxl.h +++ b/src/drivers/net/intelxl.h @@ -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 ); diff --git a/src/drivers/net/intelxlvf.c b/src/drivers/net/intelxlvf.c index 83e484c8d..dc2e3bf4e 100644 --- a/src/drivers/net/intelxlvf.c +++ b/src/drivers/net/intelxlvf.c @@ -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 */ |