iPXE
Functions | Variables
intelx.c File Reference

Intel 10 Gigabit Ethernet network card driver. More...

#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/netdevice.h>
#include <ipxe/ethernet.h>
#include <ipxe/if_ether.h>
#include <ipxe/iobuf.h>
#include <ipxe/malloc.h>
#include <ipxe/pci.h>
#include "intelx.h"

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static int intelx_try_fetch_mac (struct intel_nic *intel, unsigned int ral0, uint8_t *hw_addr)
 Try to fetch initial MAC address.
static int intelx_fetch_mac (struct intel_nic *intel, uint8_t *hw_addr)
 Fetch initial MAC address.
static int intelx_reset (struct intel_nic *intel)
 Reset hardware.
static void intelx_check_link (struct net_device *netdev)
 Check link state.
static int intelx_open (struct net_device *netdev)
 Open network device.
static void intelx_close (struct net_device *netdev)
 Close network device.
static void intelx_poll (struct net_device *netdev)
 Poll for completed and received packets.
static void intelx_irq (struct net_device *netdev, int enable)
 Enable or disable interrupts.
static int intelx_probe (struct pci_device *pci)
 Probe PCI device.
static void intelx_remove (struct pci_device *pci)
 Remove PCI device.

Variables

static struct net_device_operations intelx_operations
 Network device operations.
static struct pci_device_id intelx_nics []
 PCI device IDs.
struct pci_driver intelx_driver __pci_driver
 PCI driver.

Detailed Description

Intel 10 Gigabit Ethernet network card driver.

Definition in file intelx.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static int intelx_try_fetch_mac ( struct intel_nic *  intel,
unsigned int  ral0,
uint8_t hw_addr 
) [static]

Try to fetch initial MAC address.

Parameters:
intelIntel device
ral0RAL0 register address
hw_addrHardware address to fill in
Return values:
rcReturn status code

Definition at line 60 of file intelx.c.

References cpu_to_le32, DBGC, ENOENT, ETH_ALEN, eth_ntoa(), intel_receive_address::high, INTELX_RAH0, INTELX_RAL0, is_valid_ether_addr(), intel_receive_address::low, memcpy(), intel_receive_address::raw, and readl().

Referenced by intelx_fetch_mac().

                                                     {
        union intel_receive_address mac;

        /* Read current address from RAL0/RAH0 */
        mac.reg.low = cpu_to_le32 ( readl ( intel->regs + ral0 ) );
        mac.reg.high = cpu_to_le32 ( readl ( intel->regs + ral0 +
                                             ( INTELX_RAH0 - INTELX_RAL0 ) ) );

        /* Use current address if valid */
        if ( is_valid_ether_addr ( mac.raw ) ) {
                DBGC ( intel, "INTEL %p has autoloaded MAC address %s at "
                       "%#05x\n", intel, eth_ntoa ( mac.raw ), ral0 );
                memcpy ( hw_addr, mac.raw, ETH_ALEN );
                return 0;
        }

        return -ENOENT;
}
static int intelx_fetch_mac ( struct intel_nic *  intel,
uint8_t hw_addr 
) [static]

Fetch initial MAC address.

Parameters:
intelIntel device
hw_addrHardware address to fill in
Return values:
rcReturn status code

Definition at line 87 of file intelx.c.

References DBGC, ENOENT, INTELX_RAL0, INTELX_RAL0_ALT, intelx_try_fetch_mac(), and rc.

Referenced by intelx_probe().

                                                                          {
        int rc;

        /* Try to fetch address from INTELX_RAL0 */
        if ( ( rc = intelx_try_fetch_mac ( intel, INTELX_RAL0,
                                           hw_addr ) ) == 0 ) {
                return 0;
        }

        /* Try to fetch address from INTELX_RAL0_ALT */
        if ( ( rc = intelx_try_fetch_mac ( intel, INTELX_RAL0_ALT,
                                           hw_addr ) ) == 0 ) {
                return 0;
        }

        DBGC ( intel, "INTEL %p has no MAC address to use\n", intel );
        return -ENOENT;
}
static int intelx_reset ( struct intel_nic *  intel) [static]

Reset hardware.

Parameters:
intelIntel device
Return values:
rcReturn status code

Definition at line 119 of file intelx.c.

References ctrl, DBGC, INTELX_CTRL, INTELX_CTRL_LRST, INTELX_CTRL_RST, INTELX_RESET_DELAY_MS, mdelay(), readl(), and writel().

Referenced by intelx_close(), intelx_probe(), and intelx_remove().

                                                    {
        uint32_t ctrl;

        /* Perform a global software reset */
        ctrl = readl ( intel->regs + INTELX_CTRL );
        writel ( ( ctrl | INTELX_CTRL_RST | INTELX_CTRL_LRST ),
                 intel->regs + INTELX_CTRL );
        mdelay ( INTELX_RESET_DELAY_MS );

        DBGC ( intel, "INTEL %p reset (ctrl %08x)\n", intel, ctrl );
        return 0;
}
static void intelx_check_link ( struct net_device netdev) [static]

Check link state.

Parameters:
netdevNetwork device

Definition at line 144 of file intelx.c.

References DBGC, INTELX_LINKS, INTELX_LINKS_UP, netdev_link_down(), netdev_link_up(), net_device::priv, and readl().

Referenced by intelx_open(), intelx_poll(), and intelx_probe().

                                                            {
        struct intel_nic *intel = netdev->priv;
        uint32_t links;

        /* Read link status */
        links = readl ( intel->regs + INTELX_LINKS );
        DBGC ( intel, "INTEL %p link status is %08x\n", intel, links );

        /* Update network device */
        if ( links & INTELX_LINKS_UP ) {
                netdev_link_up ( netdev );
        } else {
                netdev_link_down ( netdev );
        }
}
static int intelx_open ( struct net_device netdev) [static]

Open network device.

Parameters:
netdevNetwork device
Return values:
rcReturn status code

Definition at line 173 of file intelx.c.

References intel_receive_address::high, intel_create_ring(), intel_destroy_ring(), intel_refill_rx(), intelx_check_link(), INTELX_DCA_RXCTRL, INTELX_DCA_RXCTRL_MUST_BE_ZERO, INTELX_DMATXCTL, INTELX_DMATXCTL_TE, INTELX_FCTRL, INTELX_FCTRL_BAM, INTELX_FCTRL_MPE, INTELX_FCTRL_UPE, INTELX_HLREG0, INTELX_HLREG0_JUMBOEN, INTELX_IVAR, INTELX_IVAR_RX0_DEFAULT, INTELX_IVAR_RX0_VALID, INTELX_IVAR_TX0_DEFAULT, INTELX_IVAR_TX0_VALID, INTELX_MAXFRS, INTELX_MAXFRS_MFS_DEFAULT, INTELX_MAXFRS_MFS_MASK, INTELX_RAH0, INTELX_RAH0_ALT, INTELX_RAH0_AV, INTELX_RAL0, INTELX_RAL0_ALT, INTELX_RDRXCTL, INTELX_RDRXCTL_SECRC, INTELX_RXCTRL, INTELX_RXCTRL_RXEN, INTELX_SRRCTL, INTELX_SRRCTL_BSIZE_DEFAULT, INTELX_SRRCTL_BSIZE_MASK, le32_to_cpu, net_device::ll_addr, intel_receive_address::low, memcpy(), memset(), net_device::priv, intel_receive_address::raw, rc, readl(), and writel().

                                                     {
        struct intel_nic *intel = netdev->priv;
        union intel_receive_address mac;
        uint32_t ral0;
        uint32_t rah0;
        uint32_t dmatxctl;
        uint32_t fctrl;
        uint32_t srrctl;
        uint32_t hlreg0;
        uint32_t maxfrs;
        uint32_t rdrxctl;
        uint32_t rxctrl;
        uint32_t dca_rxctrl;
        int rc;

        /* Create transmit descriptor ring */
        if ( ( rc = intel_create_ring ( intel, &intel->tx ) ) != 0 )
                goto err_create_tx;

        /* Create receive descriptor ring */
        if ( ( rc = intel_create_ring ( intel, &intel->rx ) ) != 0 )
                goto err_create_rx;

        /* Program MAC address */
        memset ( &mac, 0, sizeof ( mac ) );
        memcpy ( mac.raw, netdev->ll_addr, sizeof ( mac.raw ) );
        ral0 = le32_to_cpu ( mac.reg.low );
        rah0 = ( le32_to_cpu ( mac.reg.high ) | INTELX_RAH0_AV );
        writel ( ral0, intel->regs + INTELX_RAL0 );
        writel ( rah0, intel->regs + INTELX_RAH0 );
        writel ( ral0, intel->regs + INTELX_RAL0_ALT );
        writel ( rah0, intel->regs + INTELX_RAH0_ALT );

        /* Allocate interrupt vectors */
        writel ( ( INTELX_IVAR_RX0_DEFAULT | INTELX_IVAR_RX0_VALID |
                   INTELX_IVAR_TX0_DEFAULT | INTELX_IVAR_TX0_VALID ),
                 intel->regs + INTELX_IVAR );

        /* Enable transmitter  */
        dmatxctl = readl ( intel->regs + INTELX_DMATXCTL );
        dmatxctl |= INTELX_DMATXCTL_TE;
        writel ( dmatxctl, intel->regs + INTELX_DMATXCTL );

        /* Configure receive filter */
        fctrl = readl ( intel->regs + INTELX_FCTRL );
        fctrl |= ( INTELX_FCTRL_BAM | INTELX_FCTRL_UPE | INTELX_FCTRL_MPE );
        writel ( fctrl, intel->regs + INTELX_FCTRL );

        /* Configure receive buffer sizes */
        srrctl = readl ( intel->regs + INTELX_SRRCTL );
        srrctl &= ~INTELX_SRRCTL_BSIZE_MASK;
        srrctl |= INTELX_SRRCTL_BSIZE_DEFAULT;
        writel ( srrctl, intel->regs + INTELX_SRRCTL );

        /* Configure jumbo frames.  Required to allow the extra 4-byte
         * headroom for VLANs, since we don't use the hardware's
         * native VLAN offload.
         */
        hlreg0 = readl ( intel->regs + INTELX_HLREG0 );
        hlreg0 |= INTELX_HLREG0_JUMBOEN;
        writel ( hlreg0, intel->regs + INTELX_HLREG0 );

        /* Configure frame size */
        maxfrs = readl ( intel->regs + INTELX_MAXFRS );
        maxfrs &= ~INTELX_MAXFRS_MFS_MASK;
        maxfrs |= INTELX_MAXFRS_MFS_DEFAULT;
        writel ( maxfrs, intel->regs + INTELX_MAXFRS );

        /* Configure receive DMA */
        rdrxctl = readl ( intel->regs + INTELX_RDRXCTL );
        rdrxctl |= INTELX_RDRXCTL_SECRC;
        writel ( rdrxctl, intel->regs + INTELX_RDRXCTL );

        /* Clear "must-be-zero" bit for direct cache access (DCA).  We
         * leave DCA disabled anyway, but if we do not clear this bit
         * then the received packets contain garbage data.
         */
        dca_rxctrl = readl ( intel->regs + INTELX_DCA_RXCTRL );
        dca_rxctrl &= ~INTELX_DCA_RXCTRL_MUST_BE_ZERO;
        writel ( dca_rxctrl, intel->regs + INTELX_DCA_RXCTRL );

        /* Enable receiver */
        rxctrl = readl ( intel->regs + INTELX_RXCTRL );
        rxctrl |= INTELX_RXCTRL_RXEN;
        writel ( rxctrl, intel->regs + INTELX_RXCTRL );

        /* Fill receive ring */
        intel_refill_rx ( intel );

        /* Update link state */
        intelx_check_link ( netdev );

        return 0;

        intel_destroy_ring ( intel, &intel->rx );
 err_create_rx:
        intel_destroy_ring ( intel, &intel->tx );
 err_create_tx:
        return rc;
}
static void intelx_close ( struct net_device netdev) [static]

Close network device.

Parameters:
netdevNetwork device

Definition at line 279 of file intelx.c.

References intel_destroy_ring(), intel_empty_rx(), INTELX_DMATXCTL, INTELX_DMATXCTL_TE, intelx_reset(), INTELX_RXCTRL, INTELX_RXCTRL_RXEN, net_device::priv, readl(), and writel().

                                                       {
        struct intel_nic *intel = netdev->priv;
        uint32_t rxctrl;
        uint32_t dmatxctl;

        /* Disable receiver */
        rxctrl = readl ( intel->regs + INTELX_RXCTRL );
        rxctrl &= ~INTELX_RXCTRL_RXEN;
        writel ( rxctrl, intel->regs + INTELX_RXCTRL );

        /* Disable transmitter  */
        dmatxctl = readl ( intel->regs + INTELX_DMATXCTL );
        dmatxctl &= ~INTELX_DMATXCTL_TE;
        writel ( dmatxctl, intel->regs + INTELX_DMATXCTL );

        /* Destroy receive descriptor ring */
        intel_destroy_ring ( intel, &intel->rx );

        /* Discard any unused receive buffers */
        intel_empty_rx ( intel );

        /* Destroy transmit descriptor ring */
        intel_destroy_ring ( intel, &intel->tx );

        /* Reset the NIC, to flush the transmit and receive FIFOs */
        intelx_reset ( intel );
}
static void intelx_poll ( struct net_device netdev) [static]

Poll for completed and received packets.

Parameters:
netdevNetwork device

Definition at line 312 of file intelx.c.

References ENOBUFS, intel_poll_rx(), intel_poll_tx(), intel_refill_rx(), intelx_check_link(), INTELX_EICR, INTELX_EIRQ_LSC, INTELX_EIRQ_RX0, INTELX_EIRQ_RXO, INTELX_EIRQ_TX0, netdev_rx_err(), NULL, net_device::priv, and readl().

                                                      {
        struct intel_nic *intel = netdev->priv;
        uint32_t eicr;

        /* Check for and acknowledge interrupts */
        eicr = readl ( intel->regs + INTELX_EICR );
        if ( ! eicr )
                return;

        /* Poll for TX completions, if applicable */
        if ( eicr & INTELX_EIRQ_TX0 )
                intel_poll_tx ( netdev );

        /* Poll for RX completions, if applicable */
        if ( eicr & ( INTELX_EIRQ_RX0 | INTELX_EIRQ_RXO ) )
                intel_poll_rx ( netdev );

        /* Report receive overruns */
        if ( eicr & INTELX_EIRQ_RXO )
                netdev_rx_err ( netdev, NULL, -ENOBUFS );

        /* Check link state, if applicable */
        if ( eicr & INTELX_EIRQ_LSC )
                intelx_check_link ( netdev );

        /* Refill RX ring */
        intel_refill_rx ( intel );
}
static void intelx_irq ( struct net_device netdev,
int  enable 
) [static]

Enable or disable interrupts.

Parameters:
netdevNetwork device
enableInterrupts should be enabled

Definition at line 347 of file intelx.c.

References INTELX_EIMC, INTELX_EIMS, INTELX_EIRQ_LSC, INTELX_EIRQ_RX0, INTELX_EIRQ_RXO, INTELX_EIRQ_TX0, net_device::priv, and writel().

                                                                 {
        struct intel_nic *intel = netdev->priv;
        uint32_t mask;

        mask = ( INTELX_EIRQ_LSC | INTELX_EIRQ_RXO | INTELX_EIRQ_TX0 |
                 INTELX_EIRQ_RX0 );
        if ( enable ) {
                writel ( mask, intel->regs + INTELX_EIMS );
        } else {
                writel ( mask, intel->regs + INTELX_EIMC );
        }
}
static int intelx_probe ( struct pci_device pci) [static]

Probe PCI device.

Parameters:
pciPCI device
Return values:
rcReturn status code

Definition at line 382 of file intelx.c.

References adjust_pci_device(), alloc_etherdev(), pci_device::busdevfn, pci_device::dev, net_device::dev, ENODEV, ENOMEM, net_device::hw_addr, INTEL_BAR_SIZE, intel_describe_rx(), intel_describe_tx(), INTEL_NUM_RX_DESC, INTEL_NUM_TX_DESC, intelx_check_link(), intelx_fetch_mac(), INTELX_RD, intelx_reset(), INTELX_TD, ioremap(), iounmap(), pci_device::membase, memset(), netdev, netdev_init(), netdev_nullify(), netdev_put(), PCI_FUNC, pci_set_drvdata(), net_device::priv, rc, register_netdev(), and unregister_netdev().

                                                   {
        struct net_device *netdev;
        struct intel_nic *intel;
        int rc;

        /* Allocate and initialise net device */
        netdev = alloc_etherdev ( sizeof ( *intel ) );
        if ( ! netdev ) {
                rc = -ENOMEM;
                goto err_alloc;
        }
        netdev_init ( netdev, &intelx_operations );
        intel = netdev->priv;
        pci_set_drvdata ( pci, netdev );
        netdev->dev = &pci->dev;
        memset ( intel, 0, sizeof ( *intel ) );
        intel->port = PCI_FUNC ( pci->busdevfn );
        intel_init_ring ( &intel->tx, INTEL_NUM_TX_DESC, INTELX_TD,
                          intel_describe_tx );
        intel_init_ring ( &intel->rx, INTEL_NUM_RX_DESC, INTELX_RD,
                          intel_describe_rx );

        /* Fix up PCI device */
        adjust_pci_device ( pci );

        /* Map registers */
        intel->regs = ioremap ( pci->membase, INTEL_BAR_SIZE );
        if ( ! intel->regs ) {
                rc = -ENODEV;
                goto err_ioremap;
        }

        /* Reset the NIC */
        if ( ( rc = intelx_reset ( intel ) ) != 0 )
                goto err_reset;

        /* Fetch MAC address */
        if ( ( rc = intelx_fetch_mac ( intel, netdev->hw_addr ) ) != 0 )
                goto err_fetch_mac;

        /* Register network device */
        if ( ( rc = register_netdev ( netdev ) ) != 0 )
                goto err_register_netdev;

        /* Set initial link state */
        intelx_check_link ( netdev );

        return 0;

        unregister_netdev ( netdev );
 err_register_netdev:
 err_fetch_mac:
        intelx_reset ( intel );
 err_reset:
        iounmap ( intel->regs );
 err_ioremap:
        netdev_nullify ( netdev );
        netdev_put ( netdev );
 err_alloc:
        return rc;
}
static void intelx_remove ( struct pci_device pci) [static]

Remove PCI device.

Parameters:
pciPCI device

Definition at line 449 of file intelx.c.

References intelx_reset(), iounmap(), netdev, netdev_nullify(), netdev_put(), pci_get_drvdata(), net_device::priv, and unregister_netdev().

                                                     {
        struct net_device *netdev = pci_get_drvdata ( pci );
        struct intel_nic *intel = netdev->priv;

        /* Unregister network device */
        unregister_netdev ( netdev );

        /* Reset the NIC */
        intelx_reset ( intel );

        /* Free network device */
        iounmap ( intel->regs );
        netdev_nullify ( netdev );
        netdev_put ( netdev );
}

Variable Documentation

Initial value:
 {
        .open           = intelx_open,
        .close          = intelx_close,
        .transmit       = intel_transmit,
        .poll           = intelx_poll,
        .irq            = intelx_irq,
}

Network device operations.

Definition at line 361 of file intelx.c.

struct pci_device_id intelx_nics[] [static]
Initial value:
 {
        PCI_ROM ( 0x8086, 0x10f7, "82599-kx4", "82599 (KX/KX4)", 0 ),
        PCI_ROM ( 0x8086, 0x10f8, "82599-combo-backplane", "82599 (combined backplane; KR/KX4/KX)", 0 ),
        PCI_ROM ( 0x8086, 0x10f9, "82599-cx4", "82599 (CX4)", 0 ),
        PCI_ROM ( 0x8086, 0x10fb, "82599-sfp", "82599 (SFI/SFP+)", 0 ),
        PCI_ROM ( 0x8086, 0x10fc, "82599-xaui", "82599 (XAUI/BX4)", 0 ),
        PCI_ROM ( 0x8086, 0x1528, "x540t", "X540-AT2/X540-BT2", 0 ),
        PCI_ROM ( 0x8086, 0x154d, "82599-sfp-sf2", "82599 (SFI/SFP+)", 0 ),
        PCI_ROM ( 0x8086, 0x1557, "82599en-sfp", "82599 (Single Port SFI Only)", 0 ),
        PCI_ROM ( 0x8086, 0x1560, "x540t1", "X540-AT2/X540-BT2 (with single port NVM)", 0 ),
        PCI_ROM ( 0x8086, 0x1563, "x550t2", "X550-T2", 0 ),
        PCI_ROM ( 0x8086, 0x15ab, "x552", "X552", 0 ),
        PCI_ROM ( 0x8086, 0x15e5, "x553", "X553", 0 ),
}

PCI device IDs.

Definition at line 466 of file intelx.c.

struct pci_driver intelx_driver __pci_driver
Initial value:
 {
        .ids = intelx_nics,
        .id_count = ( sizeof ( intelx_nics ) / sizeof ( intelx_nics[0] ) ),
        .probe = intelx_probe,
        .remove = intelx_remove,
}

PCI driver.

Definition at line 482 of file intelx.c.