myri10ge.c File Reference

#include <stdint.h>
#include <byteswap.h>
#include <errno.h>
#include <gpxe/ethernet.h>
#include <gpxe/if_ether.h>
#include <gpxe/iobuf.h>
#include <gpxe/malloc.h>
#include <gpxe/netdevice.h>
#include <gpxe/pci.h>
#include <gpxe/timer.h>
#include "myri10ge_mcp.h"

Go to the source code of this file.

Data Structures

struct  myri10ge_dma_buffers
struct  myri10ge_private

Defines

#define MYRI10GE_TRANSMIT_WRAP   1U
#define MYRI10GE_RECEIVE_WRAP   7U
#define MYRI10GE_RECEIVE_COMPLETION_WRAP   31U
#define DBG2_RINGS(priv)
#define VS_ADDR   ( vs + 0x18 )
#define VS_DATA   ( vs + 0x14 )
#define VS_MODE   ( vs + 0x10 )
#define VS_MODE_READ32   0x3
#define VS_MODE_LOCATE   0x8
#define VS_LOCATE_STRING_SPECS   0x3
#define TRY(prefix, base, suffix)

Functions

 FILE_LICENCE (GPL2_ONLY)
static int myri10ge_pci_probe (struct pci_device *, const struct pci_device_id *)
static void myri10ge_pci_remove (struct pci_device *)
static void myri10ge_net_close (struct net_device *)
static void myri10ge_net_irq (struct net_device *, int enable)
static int myri10ge_net_open (struct net_device *)
static void myri10ge_net_poll (struct net_device *)
static int myri10ge_net_transmit (struct net_device *, struct io_buffer *)
static struct myri10ge_privatemyri10ge_priv (struct net_device *nd)
static void myri10ge_post_receive (struct myri10ge_private *priv, struct io_buffer *iob)
static int myri10ge_command (struct myri10ge_private *priv, uint32 cmd, uint32 data[3])
static void myri10ge_interrupt_handler (struct net_device *netdev)
static int mac_address_from_string_specs (struct pci_device *pci, uint8 mac[ETH_ALEN])
static int myri10ge_pci_probe (struct pci_device *pci, const struct pci_device_id *id __unused)

Variables

static struct pci_device_id myri10ge_nics []
struct pci_driver myri10ge_driver __pci_driver


Define Documentation

#define MYRI10GE_TRANSMIT_WRAP   1U

Definition at line 107 of file myri10ge.c.

Referenced by myri10ge_interrupt_handler(), and myri10ge_net_transmit().

#define MYRI10GE_RECEIVE_WRAP   7U

#define MYRI10GE_RECEIVE_COMPLETION_WRAP   31U

Definition at line 109 of file myri10ge.c.

Referenced by myri10ge_net_poll().

#define DBG2_RINGS ( priv   ) 

Value:

DBG2 ( "tx %x/%x rx %x/%x in %s() \n",                          \
               ( priv ) ->transmits_done, ( priv ) -> transmits_posted, \
               ( priv ) ->receives_done, ( priv ) -> receives_posted,   \
               __FUNCTION__ )

Definition at line 181 of file myri10ge.c.

Referenced by myri10ge_net_close(), myri10ge_net_open(), myri10ge_net_poll(), and myri10ge_net_transmit().

#define VS_ADDR   ( vs + 0x18 )

Definition at line 384 of file myri10ge.c.

Referenced by mac_address_from_string_specs().

#define VS_DATA   ( vs + 0x14 )

Definition at line 385 of file myri10ge.c.

Referenced by mac_address_from_string_specs().

#define VS_MODE   ( vs + 0x10 )

Definition at line 386 of file myri10ge.c.

Referenced by mac_address_from_string_specs().

#define VS_MODE_READ32   0x3

Definition at line 387 of file myri10ge.c.

Referenced by mac_address_from_string_specs().

#define VS_MODE_LOCATE   0x8

Definition at line 388 of file myri10ge.c.

Referenced by mac_address_from_string_specs().

#define VS_LOCATE_STRING_SPECS   0x3

Definition at line 389 of file myri10ge.c.

Referenced by mac_address_from_string_specs().

#define TRY ( prefix,
base,
suffix   ) 

Value:

do {            \
                rc = myri10ge_command ( priv,           \
                                        MXGEFW_         \
                                        ## prefix       \
                                        ## base         \
                                        ## suffix,      \
                                        data );         \
                if ( rc ) {                             \
                        dbg = #base;                    \
                        goto abort_with_dma;            \
                }                                       \
        } while ( 0 )

Referenced by myri10ge_net_open().


Function Documentation

FILE_LICENCE ( GPL2_ONLY   ) 

static int myri10ge_pci_probe ( struct pci_device ,
const struct pci_device_id  
) [static]

static void myri10ge_pci_remove ( struct pci_device pci  )  [static]

Definition at line 576 of file myri10ge.c.

References DBGP, netdev, netdev_nullify(), netdev_put(), pci_get_drvdata(), and unregister_netdev().

00577 {
00578         struct net_device       *netdev;
00579 
00580         DBGP ( "myri10ge_pci_remove\n" );
00581         netdev = pci_get_drvdata ( pci );
00582 
00583         unregister_netdev ( netdev );
00584         netdev_nullify ( netdev );
00585         netdev_put ( netdev );
00586 }

static void myri10ge_net_close ( struct net_device netdev  )  [static]

Definition at line 599 of file myri10ge.c.

References DBG2_RINGS, DBGP, myri10ge_private::dma, free_dma(), free_iob(), memset(), MXGEFW_CMD_RESET, myri10ge_command(), myri10ge_net_irq(), myri10ge_priv(), MYRI10GE_RECEIVE_WRAP, priv, myri10ge_private::receive_iob, myri10ge_private::receives_done, and myri10ge_private::receives_posted.

Referenced by myri10ge_pci_probe().

00600 {
00601         struct myri10ge_private *priv;
00602         uint32                   data[3];
00603 
00604         DBGP ( "myri10ge_net_close\n" );
00605         priv = myri10ge_priv ( netdev );
00606 
00607         /* disable interrupts */
00608 
00609         myri10ge_net_irq ( netdev, 0 );
00610 
00611         /* Reset the NIC interface, so we won't get any more events from
00612            the NIC. */
00613 
00614         myri10ge_command ( priv, MXGEFW_CMD_RESET, data );
00615 
00616         /* Free receive buffers that were never filled. */
00617 
00618         while ( priv->receives_done != priv->receives_posted ) {
00619                 free_iob ( priv->receive_iob[priv->receives_done
00620                                              & MYRI10GE_RECEIVE_WRAP] );
00621                 ++priv->receives_done;
00622         }
00623 
00624         /* Release DMAable memory. */
00625 
00626         free_dma ( priv->dma, sizeof ( *priv->dma ) );
00627 
00628         /* Erase all state from the open. */
00629 
00630         memset ( priv, 0, sizeof ( *priv ) );
00631 
00632         DBG2_RINGS ( priv );
00633 }

static void myri10ge_net_irq ( struct net_device netdev,
int  enable 
) [static]

Definition at line 643 of file myri10ge.c.

References DBGP, net_device::dev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE, pci_read_config_word(), and pci_write_config_word().

Referenced by myri10ge_net_close(), myri10ge_net_open(), and myri10ge_pci_probe().

00644 {
00645         struct pci_device       *pci_dev;
00646         uint16                   val;
00647 
00648         DBGP ( "myri10ge_net_irq\n" );
00649         pci_dev = ( struct pci_device * ) netdev->dev;
00650 
00651         /* Adjust the Interrupt Disable bit in the Command register of the
00652            PCI Device. */
00653 
00654         pci_read_config_word ( pci_dev, PCI_COMMAND, &val );
00655         if ( enable )
00656                 val &= ~PCI_COMMAND_INTX_DISABLE;
00657         else
00658                 val |= PCI_COMMAND_INTX_DISABLE;
00659         pci_write_config_word ( pci_dev, PCI_COMMAND, val );
00660 }

static int myri10ge_net_open ( struct net_device netdev  )  [static]

Definition at line 671 of file myri10ge.c.

References alloc_iob(), myri10ge_private::command, DBG, DBG2_RINGS, DBGP, net_device::dev, myri10ge_private::dma, ENOMEM, EPROTO, ETH_FRAME_LEN, free_dma(), free_iob(), iob_reserve, myri10ge_private::irq_claim, myri10ge_dma_buffers::irq_data, myri10ge_private::irq_deassert, net_device::ll_addr, malloc_dma(), pci_device::membase, memset(), MXGEFW_CMD_SET_INTRQ_SIZE_FLAG_NO_STRICT_SIZE_CHECK, MXGEFW_ETH_CMD, MXGEFW_PAD, myri10ge_net_irq(), myri10ge_post_receive(), myri10ge_priv(), MYRI10GE_RECEIVE_WRAP, phys_to_virt(), priv, myri10ge_dma_buffers::receive_completion, myri10ge_private::receive_iob, myri10ge_private::receive_post_ring, myri10ge_private::receive_post_ring_wrap, myri10ge_private::receives_posted, RESET, RX_RING, strerror(), myri10ge_private::transmit_ring, myri10ge_private::transmit_ring_wrap, TRY, and virt_to_bus().

Referenced by myri10ge_pci_probe().

00672 {
00673         const char              *dbg;   /* printed upon error return */
00674         int                      rc;
00675         struct io_buffer        *iob;
00676         struct myri10ge_private *priv;
00677         uint32                   data[3];
00678         struct pci_device       *pci_dev;
00679         void                    *membase;
00680 
00681         DBGP ( "myri10ge_net_open\n" );
00682         priv    = myri10ge_priv ( netdev );
00683         pci_dev = ( struct pci_device * ) netdev->dev;
00684         membase = phys_to_virt ( pci_dev->membase );
00685 
00686         /* Compute address for passing commands to the firmware. */
00687 
00688         priv->command = membase + MXGEFW_ETH_CMD;
00689 
00690         /* Ensure interrupts are disabled. */
00691 
00692         myri10ge_net_irq ( netdev, 0 );
00693 
00694         /* Allocate cleared DMAable buffers. */
00695 
00696         priv->dma = malloc_dma ( sizeof ( *priv->dma ) , 128 );
00697         if ( !priv->dma ) {
00698                 rc = -ENOMEM;
00699                 dbg = "DMA";
00700                 goto abort_with_nothing;
00701         }
00702         memset ( priv->dma, 0, sizeof ( *priv->dma ) );
00703 
00704         /* Simplify following code. */
00705 
00706 #define TRY( prefix, base, suffix ) do {                \
00707                 rc = myri10ge_command ( priv,           \
00708                                         MXGEFW_         \
00709                                         ## prefix       \
00710                                         ## base         \
00711                                         ## suffix,      \
00712                                         data );         \
00713                 if ( rc ) {                             \
00714                         dbg = #base;                    \
00715                         goto abort_with_dma;            \
00716                 }                                       \
00717         } while ( 0 )
00718 
00719         /* Send a reset command to the card to see if it is alive,
00720            and to reset its queue state. */
00721 
00722         TRY ( CMD_, RESET , );
00723 
00724         /* Set the interrupt queue size. */
00725 
00726         data[0] = ( sizeof ( priv->dma->receive_completion )
00727                     | MXGEFW_CMD_SET_INTRQ_SIZE_FLAG_NO_STRICT_SIZE_CHECK );
00728         TRY ( CMD_SET_ , INTRQ_SIZE , );
00729 
00730         /* Set the interrupt queue DMA address. */
00731 
00732         data[0] = virt_to_bus ( &priv->dma->receive_completion );
00733         data[1] = 0;
00734         TRY ( CMD_SET_, INTRQ_DMA, );
00735 
00736         /* Get the NIC interrupt claim address. */
00737 
00738         TRY ( CMD_GET_, IRQ_ACK, _OFFSET );
00739         priv->irq_claim = membase + data[0];
00740 
00741         /* Get the NIC interrupt assert address. */
00742 
00743         TRY ( CMD_GET_, IRQ_DEASSERT, _OFFSET );
00744         priv->irq_deassert = membase + data[0];
00745 
00746         /* Disable interrupt coalescing, which is inappropriate for the
00747            minimal buffering we provide. */
00748 
00749         TRY ( CMD_GET_, INTR_COAL, _DELAY_OFFSET );
00750         * ( ( uint32 * ) ( membase + data[0] ) ) = 0;
00751 
00752         /* Set the NIC mac address. */
00753 
00754         data[0] = ( netdev->ll_addr[0] << 24
00755                     | netdev->ll_addr[1] << 16
00756                     | netdev->ll_addr[2] << 8
00757                     | netdev->ll_addr[3] );
00758         data[1] = ( ( netdev->ll_addr[4] << 8 )
00759                      | netdev->ll_addr[5] );
00760         TRY ( SET_ , MAC_ADDRESS , );
00761 
00762         /* Enable multicast receives, because some gPXE clients don't work
00763            without multicast. . */
00764 
00765         TRY ( ENABLE_ , ALLMULTI , );
00766 
00767         /* Disable Ethernet flow control, so the NIC cannot deadlock the
00768            network under any circumstances. */
00769 
00770         TRY ( DISABLE_ , FLOW , _CONTROL );
00771 
00772         /* Compute transmit ring sizes. */
00773 
00774         data[0] = 0;            /* slice 0 */
00775         TRY ( CMD_GET_, SEND_RING, _SIZE );
00776         priv->transmit_ring_wrap
00777                 = data[0] / sizeof ( mcp_kreq_ether_send_t ) - 1;
00778         if ( priv->transmit_ring_wrap
00779              & ( priv->transmit_ring_wrap + 1 ) ) {
00780                 rc = -EPROTO;
00781                 dbg = "TX_RING";
00782                 goto abort_with_dma;
00783         }
00784 
00785         /* Compute receive ring sizes. */
00786 
00787         data[0] = 0;            /* slice 0 */
00788         TRY ( CMD_GET_ , RX_RING , _SIZE );
00789         priv->receive_post_ring_wrap = data[0] / sizeof ( mcp_dma_addr_t ) - 1;
00790         if ( priv->receive_post_ring_wrap
00791              & ( priv->receive_post_ring_wrap + 1 ) ) {
00792                 rc = -EPROTO;
00793                 dbg = "RX_RING";
00794                 goto abort_with_dma;
00795         }
00796 
00797         /* Get NIC transmit ring address. */
00798 
00799         data[0] = 0;            /* slice 0. */
00800         TRY ( CMD_GET_, SEND, _OFFSET );
00801         priv->transmit_ring = membase + data[0];
00802 
00803         /* Get the NIC receive ring address. */
00804 
00805         data[0] = 0;            /* slice 0. */
00806         TRY ( CMD_GET_, SMALL_RX, _OFFSET );
00807         priv->receive_post_ring = membase + data[0];
00808 
00809         /* Set the Nic MTU. */
00810 
00811         data[0] = ETH_FRAME_LEN;
00812         TRY ( CMD_SET_, MTU, );
00813 
00814         /* Tell the NIC our buffer sizes. ( We use only small buffers, so we
00815            set both buffer sizes to the same value, which will force all
00816            received frames to use small buffers. ) */
00817 
00818         data[0] = MXGEFW_PAD + ETH_FRAME_LEN;
00819         TRY ( CMD_SET_, SMALL_BUFFER, _SIZE );
00820         data[0] = MXGEFW_PAD + ETH_FRAME_LEN;
00821         TRY ( CMD_SET_, BIG_BUFFER, _SIZE );
00822 
00823         /* Tell firmware where to DMA IRQ data */
00824 
00825         data[0] = virt_to_bus ( &priv->dma->irq_data );
00826         data[1] = 0;
00827         data[2] = sizeof ( priv->dma->irq_data );
00828         TRY ( CMD_SET_, STATS_DMA_V2, );
00829 
00830         /* Post receives. */
00831 
00832         while ( priv->receives_posted <= MYRI10GE_RECEIVE_WRAP ) {
00833 
00834                 /* Reserve 2 extra bytes at the start of packets, since
00835                    the firmware always skips the first 2 bytes of the buffer
00836                    so TCP headers will be aligned. */
00837 
00838                 iob = alloc_iob ( MXGEFW_PAD + ETH_FRAME_LEN );
00839                 if ( !iob ) {
00840                         rc = -ENOMEM;
00841                         dbg = "alloc_iob";
00842                         goto abort_with_receives_posted;
00843                 }
00844                 iob_reserve ( iob, MXGEFW_PAD );
00845                 myri10ge_post_receive ( priv, iob );
00846         }
00847 
00848         /* Bring up the link. */
00849 
00850         TRY ( CMD_, ETHERNET_UP, );
00851 
00852         DBG2_RINGS ( priv );
00853         return 0;
00854 
00855 abort_with_receives_posted:
00856         while ( priv->receives_posted-- )
00857                 free_iob ( priv->receive_iob[priv->receives_posted] );
00858 abort_with_dma:
00859         /* Because the link is not up, we don't have to reset the NIC here. */
00860         free_dma ( priv->dma, sizeof ( *priv->dma ) );
00861 abort_with_nothing:
00862         /* Erase all signs of the failed open. */
00863         memset ( priv, 0, sizeof ( *priv ) );
00864         DBG ( "%s: %s\n", dbg, strerror ( rc ) );
00865         return ( rc );
00866 }

static void myri10ge_net_poll ( struct net_device netdev  )  [static]

Definition at line 877 of file myri10ge.c.

References alloc_iob(), DBG, DBG2_RINGS, DBGP, myri10ge_private::dma, ETH_FRAME_LEN, iob_put, iob_reserve, mcp_slot::length, MXGEFW_PAD, myri10ge_interrupt_handler(), myri10ge_post_receive(), myri10ge_priv(), MYRI10GE_RECEIVE_COMPLETION_WRAP, MYRI10GE_RECEIVE_WRAP, netdev_rx(), ntohs, priv, myri10ge_dma_buffers::receive_completion, myri10ge_private::receive_iob, myri10ge_private::receives_done, myri10ge_private::receives_posted, and wmb.

Referenced by myri10ge_pci_probe().

00878 {
00879         struct io_buffer                *iob;
00880         struct io_buffer                *replacement;
00881         struct myri10ge_dma_buffers     *dma;
00882         struct myri10ge_private         *priv;
00883         unsigned int                     length;
00884         unsigned int                     orig_receives_posted;
00885 
00886         DBGP ( "myri10ge_net_poll\n" );
00887         priv = myri10ge_priv ( netdev );
00888         dma  = priv->dma;
00889 
00890         /* Process any pending interrupt. */
00891 
00892         myri10ge_interrupt_handler ( netdev );
00893 
00894         /* Pass up received frames, but limit ourselves to receives posted
00895            before this function was called, so we cannot livelock if
00896            receives are arriving faster than we process them. */
00897 
00898         orig_receives_posted = priv->receives_posted;
00899         while ( priv->receives_done != orig_receives_posted ) {
00900 
00901                 /* Stop if there is no pending receive. */
00902 
00903                 length = ntohs ( dma->receive_completion
00904                                  [priv->receives_done
00905                                   & MYRI10GE_RECEIVE_COMPLETION_WRAP]
00906                                  .length );
00907                 if ( length == 0 )
00908                         break;
00909 
00910                 /* Allocate a replacement buffer.  If none is available,
00911                    stop passing up packets until a buffer is available.
00912 
00913                    Reserve 2 extra bytes at the start of packets, since
00914                    the firmware always skips the first 2 bytes of the buffer
00915                    so TCP headers will be aligned. */
00916 
00917                 replacement = alloc_iob ( MXGEFW_PAD + ETH_FRAME_LEN );
00918                 if ( !replacement ) {
00919                         DBG ( "NO RX BUF\n" );
00920                         break;
00921                 }
00922                 iob_reserve ( replacement, MXGEFW_PAD );
00923 
00924                 /* Pass up the received frame. */
00925 
00926                 iob = priv->receive_iob[priv->receives_done
00927                                         & MYRI10GE_RECEIVE_WRAP];
00928                 iob_put ( iob, length );
00929                 netdev_rx ( netdev, iob );
00930 
00931                 /* We have consumed the packet, so clear the receive
00932                    notification. */
00933 
00934                 dma->receive_completion [priv->receives_done
00935                                          & MYRI10GE_RECEIVE_COMPLETION_WRAP]
00936                         .length = 0;
00937                 wmb();
00938 
00939                 /* Replace the passed-up I/O buffer. */
00940 
00941                 myri10ge_post_receive ( priv, replacement );
00942                 ++priv->receives_done;
00943                 DBG2_RINGS ( priv );
00944         }
00945 }

static int myri10ge_net_transmit ( struct net_device netdev,
struct io_buffer iobuf 
) [static]

Definition at line 956 of file myri10ge.c.

References mcp_kreq_ether_send::addr_high, mcp_kreq_ether_send::addr_low, io_buffer::data, DBG, DBG2, DBG2_HD, DBG2_RINGS, DBGP, ENOBUFS, ETH_ZLEN, htonl, iob_len(), iob_pad(), MXGEFW_FLAGS_FIRST, MXGEFW_FLAGS_NO_TSO, MXGEFW_FLAGS_SMALL, myri10ge_priv(), MYRI10GE_TRANSMIT_WRAP, priv, myri10ge_private::transmit_iob, myri10ge_private::transmit_ring, myri10ge_private::transmit_ring_wrap, myri10ge_private::transmits_done, myri10ge_private::transmits_posted, virt_to_bus(), and wmb.

Referenced by myri10ge_pci_probe().

00958 {
00959         mcp_kreq_ether_send_t   *kreq;
00960         size_t                   len;
00961         struct myri10ge_private *priv;
00962         uint32                   transmits_posted;
00963 
00964         DBGP ( "myri10ge_net_transmit\n" );
00965         priv = myri10ge_priv ( netdev );
00966 
00967         /* Confirm space in the send ring. */
00968 
00969         transmits_posted = priv->transmits_posted;
00970         if ( transmits_posted - priv->transmits_done
00971              > MYRI10GE_TRANSMIT_WRAP ) {
00972                 DBG ( "TX ring full\n" );
00973                 return -ENOBUFS;
00974         }
00975 
00976         DBG2 ( "TX %p+%d ", iobuf->data, iob_len ( iobuf ) );
00977         DBG2_HD ( iobuf->data, 14 );
00978 
00979         /* Record the packet being transmitted, so we can later report
00980            send completion. */
00981 
00982         priv->transmit_iob[transmits_posted & MYRI10GE_TRANSMIT_WRAP] = iobuf;
00983 
00984         /* Copy and pad undersized frames, because the NIC does not pad,
00985            and we would rather copy small frames than do a gather. */
00986 
00987         len = iob_len ( iobuf );
00988         if ( len < ETH_ZLEN ) {
00989                 iob_pad ( iobuf, ETH_ZLEN );
00990                 len = ETH_ZLEN;
00991         }
00992 
00993         /* Enqueue the packet by writing a descriptor to the NIC.
00994            This is a bit tricky because the HW requires 32-bit writes,
00995            but the structure has smaller fields. */
00996 
00997         kreq = &priv->transmit_ring[transmits_posted
00998                                     & priv->transmit_ring_wrap];
00999         kreq->addr_high = 0;
01000         kreq->addr_low = htonl ( virt_to_bus ( iobuf->data ) );
01001         ( ( uint32 * ) kreq ) [2] = htonl (
01002                 0x0000 << 16     /* pseudo_header_offset */
01003                 | ( len & 0xFFFF ) /* length */
01004                 );
01005         wmb();
01006         ( ( uint32 * ) kreq ) [3] = htonl (
01007                 0x00 << 24      /* pad */
01008                 | 0x01 << 16    /* rdma_count */
01009                 | 0x00 << 8     /* cksum_offset */
01010                 | ( MXGEFW_FLAGS_SMALL
01011                     | MXGEFW_FLAGS_FIRST
01012                     | MXGEFW_FLAGS_NO_TSO ) /* flags */
01013                 );
01014         wmb();
01015 
01016         /* Mark the slot as consumed and return. */
01017 
01018         priv->transmits_posted = ++transmits_posted;
01019         DBG2_RINGS ( priv );
01020         return 0;
01021 }

static struct myri10ge_private* myri10ge_priv ( struct net_device nd  )  [static, read]

Definition at line 193 of file myri10ge.c.

Referenced by myri10ge_interrupt_handler(), myri10ge_net_close(), myri10ge_net_open(), myri10ge_net_poll(), myri10ge_net_transmit(), and myri10ge_pci_probe().

00194 {
00195         /* Our private data always follows the network device in memory,
00196            since we use alloc_netdev() to allocate the storage. */
00197 
00198         return ( struct myri10ge_private * ) ( nd + 1 );
00199 }

static void myri10ge_post_receive ( struct myri10ge_private priv,
struct io_buffer iob 
) [static]

Definition at line 209 of file myri10ge.c.

References mcp_kreq_ether_recv::addr_high, mcp_kreq_ether_recv::addr_low, io_buffer::data, htonl, MYRI10GE_RECEIVE_WRAP, myri10ge_private::receive_iob, myri10ge_private::receive_post_ring, myri10ge_private::receive_post_ring_wrap, myri10ge_private::receives_posted, virt_to_bus(), and wmb.

Referenced by myri10ge_net_open(), and myri10ge_net_poll().

00211 {
00212         unsigned int             receives_posted;
00213         mcp_kreq_ether_recv_t   *request;
00214 
00215         /* Record the posted I/O buffer, to be passed to netdev_rx() on
00216            receive. */
00217 
00218         receives_posted = priv->receives_posted;
00219         priv->receive_iob[receives_posted & MYRI10GE_RECEIVE_WRAP] = iob;
00220 
00221         /* Post the receive. */
00222 
00223         request = &priv->receive_post_ring[receives_posted
00224                                            & priv->receive_post_ring_wrap];
00225         request->addr_high = 0;
00226         wmb();
00227         request->addr_low = htonl ( virt_to_bus ( iob->data ) );
00228         priv->receives_posted = ++receives_posted;
00229 }

static int myri10ge_command ( struct myri10ge_private priv,
uint32  cmd,
uint32  data[3] 
) [static]

Definition at line 239 of file myri10ge.c.

References mcp_cmd::cmd, myri10ge_private::command, myri10ge_dma_buffers::command_response, mcp_cmd_response::data, mcp_cmd::data0, mcp_cmd::data1, mcp_cmd::data2, DBG, DBGP, myri10ge_private::dma, EIO, ETIMEDOUT, mcp_dma_addr::high, htonl, mcp_dma_addr::low, ntohl, mcp_cmd::pad, mcp_cmd::response_addr, mcp_cmd_response::result, rmb, udelay(), virt_to_bus(), and wmb.

Referenced by myri10ge_net_close().

00242 {
00243         int                              i;
00244         mcp_cmd_t                       *command;
00245         uint32                           result;
00246         unsigned int                     slept_ms;
00247         volatile mcp_cmd_response_t     *response;
00248 
00249         DBGP ( "myri10ge_command ( ,%d, ) \n", cmd );
00250         command = priv->command;
00251         response = &priv->dma->command_response;
00252 
00253         /* Mark the command as incomplete. */
00254 
00255         response->result = 0xFFFFFFFF;
00256 
00257         /* Pass the command to the NIC. */
00258 
00259         command->cmd                = htonl ( cmd );
00260         command->data0              = htonl ( data[0] );
00261         command->data1              = htonl ( data[1] );
00262         command->data2              = htonl ( data[2] );
00263         command->response_addr.high = 0;
00264         command->response_addr.low
00265                 = htonl ( virt_to_bus ( &priv->dma->command_response ) );
00266         for ( i=0; i<36; i+=4 )
00267                 * ( uint32 * ) &command->pad[i] = 0;
00268         wmb();
00269         * ( uint32 * ) &command->pad[36] = 0;
00270 
00271         /* Wait up to 2 seconds for a response. */
00272 
00273         for ( slept_ms=0; slept_ms<2000; slept_ms++ ) {
00274                 result = response->result;
00275                 if ( result == 0 ) {
00276                         data[0] = ntohl ( response->data );
00277                         return 0;
00278                 } else if ( result != 0xFFFFFFFF ) {
00279                         DBG ( "cmd%d:0x%x\n",
00280                               cmd,
00281                               ntohl ( response->result ) );
00282                         return -EIO;
00283                 }
00284                 udelay ( 1000 );
00285                 rmb();
00286         }
00287         DBG ( "cmd%d:timed out\n", cmd );
00288         return -ETIMEDOUT;
00289 }

static void myri10ge_interrupt_handler ( struct net_device netdev  )  [static]

Definition at line 298 of file myri10ge.c.

References DBG2, myri10ge_private::dma, htonl, myri10ge_private::irq_claim, myri10ge_dma_buffers::irq_data, myri10ge_private::irq_deassert, mcp_irq_data::link_up, mb(), MXGEFW_LINK_UP, myri10ge_priv(), MYRI10GE_TRANSMIT_WRAP, netdev_link_down(), netdev_link_up(), netdev_tx_complete(), ntohl, priv, rmb, mcp_irq_data::send_done_count, mcp_irq_data::stats_updated, myri10ge_private::transmit_iob, myri10ge_private::transmits_done, mcp_irq_data::valid, and wmb.

Referenced by myri10ge_net_poll().

00299 {
00300         struct myri10ge_private *priv;
00301         mcp_irq_data_t          *irq_data;
00302         uint8                    valid;
00303 
00304         priv = myri10ge_priv ( netdev );
00305         irq_data = &priv->dma->irq_data;
00306 
00307         /* Return if there was no interrupt. */
00308 
00309         rmb();
00310         valid = irq_data->valid;
00311         if ( !valid )
00312                 return;
00313         DBG2 ( "irq " );
00314 
00315         /* Tell the NIC to deassert the interrupt and clear
00316            irq_data->valid.*/
00317 
00318         *priv->irq_deassert = 0;        /* any value is OK. */
00319         mb();
00320 
00321         /* Handle any new receives. */
00322 
00323         if ( valid & 1 ) {
00324 
00325                 /* Pass the receive interrupt token back to the NIC. */
00326 
00327                 DBG2 ( "rx " );
00328                 *priv->irq_claim = htonl ( 3 );
00329                 wmb();
00330         }
00331 
00332         /* Handle any sent packet by freeing its I/O buffer, now that
00333            we know it has been DMAd. */
00334 
00335         if ( valid & 2 ) {
00336                 unsigned int nic_done_count;
00337 
00338                 DBG2 ( "snt " );
00339                 nic_done_count = ntohl ( priv->dma->irq_data.send_done_count );
00340                 while ( priv->transmits_done != nic_done_count ) {
00341                         struct io_buffer *iob;
00342 
00343                         iob = priv->transmit_iob [priv->transmits_done
00344                                                   & MYRI10GE_TRANSMIT_WRAP];
00345                         DBG2 ( "%p ", iob );
00346                         netdev_tx_complete ( netdev, iob );
00347                         ++priv->transmits_done;
00348                 }
00349         }
00350 
00351         /* Record any statistics update. */
00352 
00353         if ( irq_data->stats_updated ) {
00354 
00355                 /* Update the link status. */
00356 
00357                 DBG2 ( "stats " );
00358                 if ( ntohl ( irq_data->link_up ) == MXGEFW_LINK_UP )
00359                         netdev_link_up ( netdev );
00360                 else
00361                         netdev_link_down ( netdev );
00362 
00363                 /* Ignore all error counters from the NIC. */
00364         }
00365 
00366         /* Wait for the interrupt to be deasserted, as indicated by
00367            irq_data->valid, which is set by the NIC after the deassert. */
00368 
00369         DBG2 ( "wait " );
00370         do {
00371                 mb();
00372         } while ( irq_data->valid );
00373 
00374         /* Claim the interrupt to enable future interrupt generation. */
00375 
00376         DBG2 ( "claim\n" );
00377         * ( priv->irq_claim + 1 ) = htonl ( 3 );
00378         mb();
00379 }

static int mac_address_from_string_specs ( struct pci_device pci,
uint8  mac[ETH_ALEN] 
) [static]

Definition at line 400 of file myri10ge.c.

References DBG, DBG2, ENOTSUP, memcmp(), memcpy, ntohl, pci_find_capability(), pci_read_config_dword(), pci_write_config_byte(), pci_write_config_dword(), strtoul(), VS_ADDR, VS_DATA, VS_LOCATE_STRING_SPECS, VS_MODE, VS_MODE_LOCATE, and VS_MODE_READ32.

Referenced by myri10ge_pci_probe().

00402 {
00403         char string_specs[256];
00404         char *ptr, *limit;
00405         char *to = string_specs;
00406         uint32 addr;
00407         uint32 len;
00408         unsigned int vs;
00409         int mac_set = 0;
00410 
00411         /* Find the "vendor specific" capability. */
00412 
00413         vs = pci_find_capability ( pci, 9 );
00414         if ( vs == 0 ) {
00415                 DBG ( "no VS\n" );
00416                 return -ENOTSUP;
00417         }
00418 
00419         /* Locate the String specs in LANai SRAM. */
00420 
00421         pci_write_config_byte ( pci, VS_MODE, VS_MODE_LOCATE );
00422         pci_write_config_dword ( pci, VS_ADDR, VS_LOCATE_STRING_SPECS );
00423         pci_read_config_dword ( pci, VS_ADDR, &addr );
00424         pci_read_config_dword ( pci, VS_DATA, &len );
00425         DBG2 ( "ss@%x,%x\n", addr, len );
00426 
00427         /* Copy in the string specs.  Use 32-bit reads for performance. */
00428 
00429         if ( len > sizeof ( string_specs ) || ( len & 3 ) ) {
00430                 DBG ( "SS too big\n" );
00431                 return -ENOTSUP;
00432         }
00433 
00434         pci_write_config_byte ( pci, VS_MODE, VS_MODE_READ32 );
00435         while ( len >= 4 ) {
00436                 uint32 tmp;
00437 
00438                 pci_write_config_byte ( pci, VS_ADDR, addr );
00439                 pci_read_config_dword ( pci, VS_DATA, &tmp );
00440                 tmp = ntohl ( tmp );
00441                 memcpy ( to, &tmp, 4 );
00442                 to += 4;
00443                 addr += 4;
00444                 len -= 4;
00445         }
00446         pci_write_config_byte ( pci, VS_MODE, 0 );
00447 
00448         /* Parse the string specs. */
00449 
00450         DBG2 ( "STRING_SPECS:\n" );
00451         ptr = string_specs;
00452         limit = string_specs + sizeof ( string_specs );
00453         while ( *ptr != '\0' && ptr < limit ) {
00454                 DBG2 ( "%s\n", ptr );
00455                 if ( memcmp ( ptr, "MAC=", 4 ) == 0 ) {
00456                         unsigned int i;
00457 
00458                         ptr += 4;
00459                         for ( i=0; i<6; i++ ) {
00460                                 if ( ( ptr + 2 ) > limit ) {
00461                                         DBG ( "bad MAC addr\n" );
00462                                         return -ENOTSUP;
00463                                 }
00464                                 mac[i] = strtoul ( ptr, &ptr, 16 );
00465                                 ptr += 1;
00466                         }
00467                         mac_set = 1;
00468                 }
00469                 else
00470                         while ( ptr < limit && *ptr++ );
00471         }
00472 
00473         /* Verify we parsed all we need. */
00474 
00475         if ( !mac_set ) {
00476                 DBG ( "no MAC addr\n" );
00477                 return -ENOTSUP;
00478         }
00479 
00480         DBG2 ( "MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
00481                mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] );
00482 
00483         return 0;
00484 }

static int myri10ge_pci_probe ( struct pci_device pci,
const struct pci_device_id *id  __unused 
) [static]

Definition at line 500 of file myri10ge.c.

References adjust_pci_device(), alloc_etherdev(), DBG, DBGP, pci_device::dev, net_device::dev, ENOMEM, net_device::hw_addr, mac_address_from_string_specs(), myri10ge_net_close(), myri10ge_net_irq(), myri10ge_net_open(), myri10ge_net_poll(), myri10ge_net_transmit(), myri10ge_priv(), netdev, netdev_init(), netdev_nullify(), netdev_put(), net_device_operations::open, pci_set_drvdata(), priv, register_netdev(), and strerror().

00502 {
00503         static struct net_device_operations myri10ge_operations = {
00504                 .open     = myri10ge_net_open,
00505                 .close    = myri10ge_net_close,
00506                 .transmit = myri10ge_net_transmit,
00507                 .poll     = myri10ge_net_poll,
00508                 .irq      = myri10ge_net_irq
00509         };
00510 
00511         const char *dbg;
00512         int rc;
00513         struct net_device *netdev;
00514         struct myri10ge_private *priv;
00515 
00516         DBGP ( "myri10ge_pci_probe: " );
00517 
00518         netdev = alloc_etherdev ( sizeof ( *priv ) );
00519         if ( !netdev ) {
00520                 rc = -ENOMEM;
00521                 dbg = "alloc_etherdev";
00522                 goto abort_with_nothing;
00523         }
00524 
00525         netdev_init ( netdev, &myri10ge_operations );
00526         priv = myri10ge_priv ( netdev );
00527 
00528         pci_set_drvdata ( pci, netdev );
00529         netdev->dev = &pci->dev;
00530 
00531         /* Make sure interrupts are disabled. */
00532 
00533         myri10ge_net_irq ( netdev, 0 );
00534 
00535         /* Read the NIC HW address. */
00536 
00537         rc = mac_address_from_string_specs ( pci, netdev->hw_addr );
00538         if ( rc ) {
00539                 dbg = "mac_from_ss";
00540                 goto abort_with_netdev_init;
00541         }
00542         DBGP ( "mac " );
00543 
00544         /* Enable bus master, etc. */
00545 
00546         adjust_pci_device ( pci );
00547         DBGP ( "pci " );
00548 
00549         /* Register the initialized network device. */
00550 
00551         rc = register_netdev ( netdev );
00552         if ( rc ) {
00553                 dbg = "register_netdev";
00554                 goto abort_with_netdev_init;
00555         }
00556 
00557         DBGP ( "done\n" );
00558 
00559         return 0;
00560 
00561 abort_with_netdev_init:
00562         netdev_nullify ( netdev );
00563         netdev_put ( netdev );
00564 abort_with_nothing:
00565         DBG ( "%s:%s\n", dbg, strerror ( rc ) );
00566         return rc;
00567 }


Variable Documentation

struct pci_device_id myri10ge_nics[] [static]

Initial value:

 {
        
        PCI_ROM ( 0x14c1, 0x0008, "myri10ge", "Myricom 10Gb Ethernet Adapter", 0 ) ,
}

Definition at line 1023 of file myri10ge.c.

struct pci_driver myri10ge_driver __pci_driver

Initial value:

 {
        .ids      = myri10ge_nics,
        .id_count = ( sizeof ( myri10ge_nics ) / sizeof ( myri10ge_nics[0] ) ) ,
        .probe    = myri10ge_pci_probe,
        .remove   = myri10ge_pci_remove
}

Definition at line 1028 of file myri10ge.c.


Generated on Tue Apr 6 20:01:36 2010 for gPXE by  doxygen 1.5.7.1