iPXE
Data Structures | Defines | Functions | Variables
snpnet.c File Reference

SNP NIC driver. More...

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <ipxe/iobuf.h>
#include <ipxe/netdevice.h>
#include <ipxe/ethernet.h>
#include <ipxe/vsprintf.h>
#include <ipxe/efi/efi.h>
#include <ipxe/efi/Protocol/SimpleNetwork.h>
#include <ipxe/efi/efi_driver.h>
#include <ipxe/efi/efi_utils.h>
#include "snpnet.h"

Go to the source code of this file.

Data Structures

struct  snp_nic
 An SNP NIC. More...

Defines

#define SNP_RX_QUOTA   4
 Maximum number of received packets per poll.

Functions

 FILE_LICENCE (GPL2_OR_LATER)
static const char * snpnet_mac_text (EFI_MAC_ADDRESS *mac, size_t len)
 Format SNP MAC address (for debugging)
static void snpnet_dump_mode (struct net_device *netdev)
 Dump SNP mode information (for debugging)
static void snpnet_check_link (struct net_device *netdev)
 Check link state.
static int snpnet_transmit (struct net_device *netdev, struct io_buffer *iobuf)
 Transmit packet.
static void snpnet_poll_tx (struct net_device *netdev)
 Poll for completed packets.
static void snpnet_poll_rx (struct net_device *netdev)
 Poll for received packets.
static void snpnet_poll (struct net_device *netdev)
 Poll for completed packets.
static int snpnet_rx_filters (struct net_device *netdev)
 Set receive filters.
static int snpnet_open (struct net_device *netdev)
 Open network device.
static void snpnet_close (struct net_device *netdev)
 Close network device.
int snpnet_start (struct efi_device *efidev)
 Attach driver to device.
void snpnet_stop (struct efi_device *efidev)
 Detach driver from device.

Variables

static struct net_device_operations snpnet_operations
 SNP network device operations.

Detailed Description

SNP NIC driver.

Definition in file snpnet.c.


Define Documentation

#define SNP_RX_QUOTA   4

Maximum number of received packets per poll.

Definition at line 65 of file snpnet.c.

Referenced by snpnet_poll_rx().


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER  )
static const char* snpnet_mac_text ( EFI_MAC_ADDRESS mac,
size_t  len 
) [static]

Format SNP MAC address (for debugging)

Parameters:
macMAC address
lenLength of MAC address
Return values:
textMAC address as text

Definition at line 74 of file snpnet.c.

References EFI_MAC_ADDRESS::Addr, len, and ssnprintf().

Referenced by snpnet_dump_mode().

                                                                         {
        static char buf[ sizeof ( *mac ) * 3 /* "xx:" or "xx\0" */ ];
        size_t used = 0;
        unsigned int i;

        for ( i = 0 ; i < len ; i++ ) {
                used += ssnprintf ( &buf[used], ( sizeof ( buf ) - used ),
                                    "%s%02x", ( used ? ":" : "" ),
                                    mac->Addr[i] );
        }
        return buf;
}
static void snpnet_dump_mode ( struct net_device netdev) [static]

Dump SNP mode information (for debugging)

Parameters:
netdevNetwork device

Definition at line 92 of file snpnet.c.

References EFI_SIMPLE_NETWORK_MODE::BroadcastAddress, EFI_SIMPLE_NETWORK_MODE::CurrentAddress, DBG_EXTRA, DBGC2, EFI_SIMPLE_NETWORK_MODE::HwAddressSize, EFI_SIMPLE_NETWORK_MODE::IfType, EFI_SIMPLE_NETWORK_MODE::MacAddressChangeable, EFI_SIMPLE_NETWORK_MODE::MaxMCastFilterCount, EFI_SIMPLE_NETWORK_MODE::MaxPacketSize, EFI_SIMPLE_NETWORK_MODE::MCastFilter, EFI_SIMPLE_NETWORK_MODE::MCastFilterCount, EFI_SIMPLE_NETWORK_MODE::MediaHeaderSize, EFI_SIMPLE_NETWORK_MODE::MediaPresent, EFI_SIMPLE_NETWORK_MODE::MediaPresentSupported, _EFI_SIMPLE_NETWORK_PROTOCOL::Mode, EFI_SIMPLE_NETWORK_MODE::MultipleTxSupported, net_device::name, netdev_priv(), EFI_SIMPLE_NETWORK_MODE::NvRamAccessSize, EFI_SIMPLE_NETWORK_MODE::NvRamSize, EFI_SIMPLE_NETWORK_MODE::PermanentAddress, EFI_SIMPLE_NETWORK_MODE::ReceiveFilterMask, EFI_SIMPLE_NETWORK_MODE::ReceiveFilterSetting, snp_nic::snp, snpnet_mac_text(), and EFI_SIMPLE_NETWORK_MODE::State.

Referenced by snpnet_open().

                                                           {
        struct snp_nic *snp = netdev_priv ( netdev );
        EFI_SIMPLE_NETWORK_MODE *mode = snp->snp->Mode;
        size_t mac_len = mode->HwAddressSize;
        unsigned int i;

        /* Do nothing unless debugging is enabled */
        if ( ! DBG_EXTRA )
                return;

        DBGC2 ( snp, "SNP %s st %d type %d hdr %d pkt %d rxflt %#x/%#x%s "
                "nvram %d acc %d mcast %d/%d\n", netdev->name, mode->State,
                mode->IfType, mode->MediaHeaderSize, mode->MaxPacketSize,
                mode->ReceiveFilterSetting, mode->ReceiveFilterMask,
                ( mode->MultipleTxSupported ? " multitx" : "" ),
                mode->NvRamSize, mode->NvRamAccessSize,
                mode->MCastFilterCount, mode->MaxMCastFilterCount );
        DBGC2 ( snp, "SNP %s hw %s", netdev->name,
                snpnet_mac_text ( &mode->PermanentAddress, mac_len ) );
        DBGC2 ( snp, " addr %s%s",
                snpnet_mac_text ( &mode->CurrentAddress, mac_len ),
                ( mode->MacAddressChangeable ? "" : "(f)" ) );
        DBGC2 ( snp, " bcast %s\n",
                snpnet_mac_text ( &mode->BroadcastAddress, mac_len ) );
        for ( i = 0 ; i < mode->MCastFilterCount ; i++ ) {
                DBGC2 ( snp, "SNP %s mcast %s\n", netdev->name,
                        snpnet_mac_text ( &mode->MCastFilter[i], mac_len ) );
        }
        DBGC2 ( snp, "SNP %s media %s\n", netdev->name,
                ( mode->MediaPresentSupported ?
                  ( mode->MediaPresent ? "present" : "not present" ) :
                  "presence not supported" ) );
}
static void snpnet_check_link ( struct net_device netdev) [static]

Check link state.

Parameters:
netdevNetwork device

Definition at line 131 of file snpnet.c.

References EFI_SIMPLE_NETWORK_MODE::MediaPresent, EFI_SIMPLE_NETWORK_MODE::MediaPresentSupported, _EFI_SIMPLE_NETWORK_PROTOCOL::Mode, netdev_link_down(), netdev_link_ok(), netdev_link_up(), netdev_priv(), and snp_nic::snp.

Referenced by snpnet_poll(), and snpnet_start().

                                                            {
        struct snp_nic *snp = netdev_priv ( netdev );
        EFI_SIMPLE_NETWORK_MODE *mode = snp->snp->Mode;

        /* Do nothing unless media presence detection is supported */
        if ( ! mode->MediaPresentSupported )
                return;

        /* Report any link status change */
        if ( mode->MediaPresent && ( ! netdev_link_ok ( netdev ) ) ) {
                netdev_link_up ( netdev );
        } else if ( ( ! mode->MediaPresent ) && netdev_link_ok ( netdev ) ) {
                netdev_link_down ( netdev );
        }
}
static int snpnet_transmit ( struct net_device netdev,
struct io_buffer iobuf 
) [static]

Transmit packet.

Parameters:
netdevNetwork device
iobufI/O buffer
Return values:
rcReturn status code

Definition at line 154 of file snpnet.c.

References io_buffer::data, DBGC, EEFI, iob_len(), net_device::name, netdev_priv(), netdev_tx_defer(), NULL, rc, snp_nic::snp, strerror(), _EFI_SIMPLE_NETWORK_PROTOCOL::Transmit, and snp_nic::txbuf.

                                                       {
        struct snp_nic *snp = netdev_priv ( netdev );
        EFI_STATUS efirc;
        int rc;

        /* Defer the packet if there is already a transmission in progress */
        if ( snp->txbuf ) {
                netdev_tx_defer ( netdev, iobuf );
                return 0;
        }

        /* Transmit packet */
        if ( ( efirc = snp->snp->Transmit ( snp->snp, 0, iob_len ( iobuf ),
                                            iobuf->data, NULL, NULL,
                                            NULL ) ) != 0 ) {
                rc = -EEFI ( efirc );
                DBGC ( snp, "SNP %s could not transmit: %s\n",
                       netdev->name, strerror ( rc ) );
                return rc;
        }
        snp->txbuf = iobuf;

        return 0;
}
static void snpnet_poll_tx ( struct net_device netdev) [static]

Poll for completed packets.

Parameters:
netdevNetwork device

Definition at line 185 of file snpnet.c.

References DBGC, EEFI, EPIPE, _EFI_SIMPLE_NETWORK_PROTOCOL::GetStatus, net_device::name, netdev_rx_err(), netdev_tx_complete(), netdev_tx_err(), NULL, net_device::priv, rc, snp_nic::snp, strerror(), snp_nic::txbuf, and VOID.

Referenced by snpnet_poll().

                                                         {
        struct snp_nic *snp = netdev->priv;
        struct io_buffer *iobuf;
        UINT32 irq;
        VOID *txbuf;
        EFI_STATUS efirc;
        int rc;

        /* Get status */
        txbuf = NULL;
        if ( ( efirc = snp->snp->GetStatus ( snp->snp, &irq, &txbuf ) ) != 0 ) {
                rc = -EEFI ( efirc );
                DBGC ( snp, "SNP %s could not get status: %s\n",
                       netdev->name, strerror ( rc ) );
                netdev_rx_err ( netdev, NULL, rc );
                return;
        }

        /* Do nothing unless we have a completion */
        if ( ! txbuf )
                return;

        /* Sanity check */
        if ( ! snp->txbuf ) {
                DBGC ( snp, "SNP %s reported spurious TX completion\n",
                       netdev->name );
                netdev_tx_err ( netdev, NULL, -EPIPE );
                return;
        }

        /* Complete transmission */
        iobuf = snp->txbuf;
        snp->txbuf = NULL;
        netdev_tx_complete ( netdev, iobuf );
}
static void snpnet_poll_rx ( struct net_device netdev) [static]

Poll for received packets.

Parameters:
netdevNetwork device

Definition at line 226 of file snpnet.c.

References alloc_iob(), io_buffer::data, DBGC, EEFI, EFI_NOT_READY, iob_put, iob_tailroom(), len, snp_nic::mtu, net_device::name, netdev_rx(), netdev_rx_err(), NULL, net_device::priv, rc, _EFI_SIMPLE_NETWORK_PROTOCOL::Receive, snp_nic::rxbuf, snp_nic::snp, SNP_RX_QUOTA, and strerror().

Referenced by snpnet_poll().

                                                         {
        struct snp_nic *snp = netdev->priv;
        UINTN len;
        unsigned int quota;
        EFI_STATUS efirc;
        int rc;

        /* Retrieve up to SNP_RX_QUOTA packets */
        for ( quota = SNP_RX_QUOTA ; quota ; quota-- ) {

                /* Allocate buffer, if required */
                if ( ! snp->rxbuf ) {
                        snp->rxbuf = alloc_iob ( snp->mtu );
                        if ( ! snp->rxbuf ) {
                                /* Leave for next poll */
                                break;
                        }
                }

                /* Receive packet */
                len = iob_tailroom ( snp->rxbuf );
                if ( ( efirc = snp->snp->Receive ( snp->snp, NULL, &len,
                                                   snp->rxbuf->data, NULL,
                                                   NULL, NULL ) ) != 0 ) {

                        /* EFI_NOT_READY is just the usual "no packet"
                         * status indication; ignore it.
                         */
                        if ( efirc == EFI_NOT_READY )
                                break;

                        /* Anything else is an error */
                        rc = -EEFI ( efirc );
                        DBGC ( snp, "SNP %s could not receive: %s\n",
                               netdev->name, strerror ( rc ) );
                        netdev_rx_err ( netdev, NULL, rc );
                        break;
                }

                /* Hand off to network stack */
                iob_put ( snp->rxbuf, len );
                netdev_rx ( netdev, snp->rxbuf );
                snp->rxbuf = NULL;
        }
}
static void snpnet_poll ( struct net_device netdev) [static]

Poll for completed packets.

Parameters:
netdevNetwork device

Definition at line 277 of file snpnet.c.

References snpnet_check_link(), snpnet_poll_rx(), and snpnet_poll_tx().

                                                      {

        /* Process any TX completions */
        snpnet_poll_tx ( netdev );

        /* Process any RX completions */
        snpnet_poll_rx ( netdev );

        /* Check for link state changes */
        snpnet_check_link ( netdev );
}
static int snpnet_rx_filters ( struct net_device netdev) [static]

Set receive filters.

Parameters:
netdevNetwork device
Return values:
rcReturn status code

Definition at line 295 of file snpnet.c.

References DBGC, EEFI, EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST, EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST, EFI_SIMPLE_NETWORK_RECEIVE_UNICAST, _EFI_SIMPLE_NETWORK_PROTOCOL::Mode, net_device::name, NULL, net_device::priv, rc, EFI_SIMPLE_NETWORK_MODE::ReceiveFilterMask, _EFI_SIMPLE_NETWORK_PROTOCOL::ReceiveFilters, EFI_SIMPLE_NETWORK_MODE::ReceiveFilterSetting, snp_nic::snp, strerror(), and TRUE.

Referenced by snpnet_open().

                                                           {
        struct snp_nic *snp = netdev->priv;
        UINT32 filters[] = {
                snp->snp->Mode->ReceiveFilterMask,
                ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
                  EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
                  EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST ),
                ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
                  EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST ),
                ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST ),
        };
        unsigned int i;
        EFI_STATUS efirc;
        int rc;

        /* Try possible receive filters in turn */
        for ( i = 0; i < ( sizeof ( filters ) / sizeof ( filters[0] ) ); i++ ) {
                efirc = snp->snp->ReceiveFilters ( snp->snp, filters[i],
                                                   0, TRUE, 0, NULL );
                if ( efirc == 0 )
                        return 0;
                rc = -EEFI ( efirc );
                DBGC ( snp, "SNP %s could not set receive filters %#02x (have "
                       "%#02x): %s\n", netdev->name, filters[i],
                       snp->snp->Mode->ReceiveFilterSetting, strerror ( rc ) );
        }

        return rc;
}
static int snpnet_open ( struct net_device netdev) [static]

Open network device.

Parameters:
netdevNetwork device
Return values:
rcReturn status code

Definition at line 331 of file snpnet.c.

References DBGC, EEFI, FALSE, _EFI_SIMPLE_NETWORK_PROTOCOL::Initialize, net_device::ll_addr, mac, net_device::name, net_device::priv, rc, snp_nic::snp, snpnet_dump_mode(), snpnet_rx_filters(), _EFI_SIMPLE_NETWORK_PROTOCOL::StationAddress, and strerror().

                                                     {
        struct snp_nic *snp = netdev->priv;
        EFI_MAC_ADDRESS *mac = ( ( void * ) netdev->ll_addr );
        EFI_STATUS efirc;
        int rc;

        /* Try setting MAC address (before initialising) */
        if ( ( efirc = snp->snp->StationAddress ( snp->snp, FALSE, mac ) ) !=0){
                rc = -EEFI ( efirc );
                DBGC ( snp, "SNP %s could not set station address before "
                       "initialising: %s\n", netdev->name, strerror ( rc ) );
                /* Ignore error */
        }

        /* Initialise NIC */
        if ( ( efirc = snp->snp->Initialize ( snp->snp, 0, 0 ) ) != 0 ) {
                rc = -EEFI ( efirc );
                snpnet_dump_mode ( netdev );
                DBGC ( snp, "SNP %s could not initialise: %s\n",
                       netdev->name, strerror ( rc ) );
                return rc;
        }

        /* Try setting MAC address (after initialising) */
        if ( ( efirc = snp->snp->StationAddress ( snp->snp, FALSE, mac ) ) !=0){
                rc = -EEFI ( efirc );
                DBGC ( snp, "SNP %s could not set station address after "
                       "initialising: %s\n", netdev->name, strerror ( rc ) );
                /* Ignore error */
        }

        /* Set receive filters */
        if ( ( rc = snpnet_rx_filters ( netdev ) ) != 0 ) {
                /* Ignore error */
        }

        /* Dump mode information (for debugging) */
        snpnet_dump_mode ( netdev );

        return 0;
}
static void snpnet_close ( struct net_device netdev) [static]

Close network device.

Parameters:
netdevNetwork device

Definition at line 378 of file snpnet.c.

References DBGC, ECANCELED, EEFI, free_iob(), net_device::name, netdev_tx_complete_err(), NULL, net_device::priv, rc, snp_nic::rxbuf, _EFI_SIMPLE_NETWORK_PROTOCOL::Shutdown, snp_nic::snp, strerror(), and snp_nic::txbuf.

                                                       {
        struct snp_nic *snp = netdev->priv;
        EFI_STATUS efirc;
        int rc;

        /* Shut down NIC */
        if ( ( efirc = snp->snp->Shutdown ( snp->snp ) ) != 0 ) {
                rc = -EEFI ( efirc );
                DBGC ( snp, "SNP %s could not shut down: %s\n",
                       netdev->name, strerror ( rc ) );
                /* Nothing we can do about this */
        }

        /* Discard transmit buffer, if applicable */
        if ( snp->txbuf ) {
                netdev_tx_complete_err ( netdev, snp->txbuf, -ECANCELED );
                snp->txbuf = NULL;
        }

        /* Discard receive buffer, if applicable */
        if ( snp->rxbuf ) {
                free_iob ( snp->rxbuf );
                snp->rxbuf = NULL;
        }
}
int snpnet_start ( struct efi_device efidev)

Attach driver to device.

Parameters:
efidevEFI device
Return values:
rcReturn status code

Definition at line 418 of file snpnet.c.

References alloc_etherdev(), EFI_SYSTEM_TABLE::BootServices, device::children, EFI_BOOT_SERVICES::CloseProtocol, EFI_SIMPLE_NETWORK_MODE::CurrentAddress, DBGC, DBGC_EFI_OPENERS, efi_device::dev, snp_nic::dev, net_device::dev, efi_device::device, device::driver_name, EEFI, efi_device_info(), efi_handle_name(), efi_image_handle, EFI_OPEN_PROTOCOL_BY_DRIVER, EFI_OPEN_PROTOCOL_EXCLUSIVE, efi_simple_network_protocol_guid, efi_systab, snp_nic::efidev, efidev_set_drvdata(), EfiSimpleNetworkInitialized, EfiSimpleNetworkStopped, ENOMEM, ENOTSUP, net_device::hw_addr, ll_protocol::hw_addr_len, EFI_SIMPLE_NETWORK_MODE::HwAddressSize, INIT_LIST_HEAD, list_add, list_del, net_device::ll_addr, ll_protocol::ll_addr_len, net_device::ll_protocol, EFI_SIMPLE_NETWORK_MODE::MaxPacketSize, EFI_SIMPLE_NETWORK_MODE::MediaHeaderSize, EFI_SIMPLE_NETWORK_MODE::MediaPresentSupported, memcpy(), _EFI_SIMPLE_NETWORK_PROTOCOL::Mode, snp_nic::mtu, net_device::name, netdev, netdev_init(), netdev_link_up(), netdev_nullify(), netdev_put(), EFI_BOOT_SERVICES::OpenProtocol, device::parent, EFI_SIMPLE_NETWORK_MODE::PermanentAddress, net_device::priv, rc, register_netdev(), _EFI_SIMPLE_NETWORK_PROTOCOL::Shutdown, device::siblings, snp_nic::snp, snpnet_check_link(), _EFI_SIMPLE_NETWORK_PROTOCOL::Start, EFI_SIMPLE_NETWORK_MODE::State, strerror(), and unregister_netdev().

                                               {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        EFI_HANDLE device = efidev->device;
        EFI_SIMPLE_NETWORK_MODE *mode;
        struct net_device *netdev;
        struct snp_nic *snp;
        void *interface;
        EFI_STATUS efirc;
        int rc;

        /* Open SNP protocol */
        if ( ( efirc = bs->OpenProtocol ( device,
                                          &efi_simple_network_protocol_guid,
                                          &interface, efi_image_handle, device,
                                          ( EFI_OPEN_PROTOCOL_BY_DRIVER |
                                            EFI_OPEN_PROTOCOL_EXCLUSIVE )))!=0){
                rc = -EEFI ( efirc );
                DBGC ( device, "SNP %s cannot open SNP protocol: %s\n",
                       efi_handle_name ( device ), strerror ( rc ) );
                DBGC_EFI_OPENERS ( device, device,
                                   &efi_simple_network_protocol_guid );
                goto err_open_protocol;
        }

        /* Allocate and initialise structure */
        netdev = alloc_etherdev ( sizeof ( *snp ) );
        if ( ! netdev ) {
                rc = -ENOMEM;
                goto err_alloc;
        }
        netdev_init ( netdev, &snpnet_operations );
        snp = netdev->priv;
        snp->efidev = efidev;
        snp->snp = interface;
        mode = snp->snp->Mode;
        efidev_set_drvdata ( efidev, netdev );

        /* Populate underlying device information */
        efi_device_info ( device, "SNP", &snp->dev );
        snp->dev.driver_name = "SNP";
        snp->dev.parent = &efidev->dev;
        list_add ( &snp->dev.siblings, &efidev->dev.children );
        INIT_LIST_HEAD ( &snp->dev.children );
        netdev->dev = &snp->dev;

        /* Bring to the Started state */
        if ( ( mode->State == EfiSimpleNetworkStopped ) &&
             ( ( efirc = snp->snp->Start ( snp->snp ) ) != 0 ) ) {
                rc = -EEFI ( efirc );
                DBGC ( device, "SNP %s could not start: %s\n",
                       efi_handle_name ( device ), strerror ( rc ) );
                goto err_start;
        }
        if ( ( mode->State == EfiSimpleNetworkInitialized ) &&
             ( ( efirc = snp->snp->Shutdown ( snp->snp ) ) != 0 ) ) {
                rc = -EEFI ( efirc );
                DBGC ( device, "SNP %s could not shut down: %s\n",
                       efi_handle_name ( device ), strerror ( rc ) );
                goto err_shutdown;
        }

        /* Populate network device parameters */
        if ( mode->HwAddressSize != netdev->ll_protocol->hw_addr_len ) {
                DBGC ( device, "SNP %s has invalid hardware address length "
                       "%d\n", efi_handle_name ( device ), mode->HwAddressSize);
                rc = -ENOTSUP;
                goto err_hw_addr_len;
        }
        memcpy ( netdev->hw_addr, &mode->PermanentAddress,
                 netdev->ll_protocol->hw_addr_len );
        if ( mode->HwAddressSize != netdev->ll_protocol->ll_addr_len ) {
                DBGC ( device, "SNP %s has invalid link-layer address length "
                       "%d\n", efi_handle_name ( device ), mode->HwAddressSize);
                rc = -ENOTSUP;
                goto err_ll_addr_len;
        }
        memcpy ( netdev->ll_addr, &mode->CurrentAddress,
                 netdev->ll_protocol->ll_addr_len );
        snp->mtu = ( snp->snp->Mode->MaxPacketSize +
                     snp->snp->Mode->MediaHeaderSize );

        /* Register network device */
        if ( ( rc = register_netdev ( netdev ) ) != 0 )
                goto err_register_netdev;
        DBGC ( device, "SNP %s registered as %s\n",
               efi_handle_name ( device ), netdev->name );

        /* Set initial link state */
        if ( snp->snp->Mode->MediaPresentSupported ) {
                snpnet_check_link ( netdev );
        } else {
                netdev_link_up ( netdev );
        }

        return 0;

        unregister_netdev ( netdev );
 err_register_netdev:
 err_ll_addr_len:
 err_hw_addr_len:
 err_shutdown:
 err_start:
        list_del ( &snp->dev.siblings );
        netdev_nullify ( netdev );
        netdev_put ( netdev );
 err_alloc:
        bs->CloseProtocol ( device, &efi_simple_network_protocol_guid,
                            efi_image_handle, device );
 err_open_protocol:
        return rc;
}
void snpnet_stop ( struct efi_device efidev)

Detach driver from device.

Parameters:
efidevEFI device

Definition at line 535 of file snpnet.c.

References EFI_SYSTEM_TABLE::BootServices, EFI_BOOT_SERVICES::CloseProtocol, DBGC, snp_nic::dev, efi_device::device, EEFI, efi_handle_name(), efi_image_handle, efi_simple_network_protocol_guid, efi_systab, efidev_get_drvdata(), list_del, netdev_nullify(), netdev_put(), net_device::priv, rc, device::siblings, snp_nic::snp, _EFI_SIMPLE_NETWORK_PROTOCOL::Stop, strerror(), and unregister_netdev().

                                               {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        struct net_device *netdev = efidev_get_drvdata ( efidev );
        struct snp_nic *snp = netdev->priv;
        EFI_HANDLE device = efidev->device;
        EFI_STATUS efirc;
        int rc;

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

        /* Stop SNP protocol */
        if ( ( efirc = snp->snp->Stop ( snp->snp ) ) != 0 ) {
                rc = -EEFI ( efirc );
                DBGC ( device, "SNP %s could not stop: %s\n",
                       efi_handle_name ( device ), strerror ( rc ) );
                /* Nothing we can do about this */
        }

        /* Free network device */
        list_del ( &snp->dev.siblings );
        netdev_nullify ( netdev );
        netdev_put ( netdev );

        /* Close SNP protocol */
        bs->CloseProtocol ( device, &efi_simple_network_protocol_guid,
                            efi_image_handle, device );
}

Variable Documentation

Initial value:
 {
        .open = snpnet_open,
        .close = snpnet_close,
        .transmit = snpnet_transmit,
        .poll = snpnet_poll,
}

SNP network device operations.

Definition at line 405 of file snpnet.c.