david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

Kill off hotplug.h and just make net devices normal reference-counted

structures.

DHCP still broken and #if 0'd out.
This commit is contained in:
Michael Brown 2007-06-27 14:48:31 +01:00
parent e381714c07
commit f77815f2b1
16 changed files with 112 additions and 256 deletions

View File

@ -675,7 +675,7 @@ int undinet_probe ( struct undi_device *undi ) {
undinet_call ( undinic, PXENV_STOP_UNDI, &stop_undi, undinet_call ( undinic, PXENV_STOP_UNDI, &stop_undi,
sizeof ( stop_undi ) ); sizeof ( stop_undi ) );
err_start_undi: err_start_undi:
free_netdev ( netdev ); netdev_put ( netdev );
undi_set_drvdata ( undi, NULL ); undi_set_drvdata ( undi, NULL );
return rc; return rc;
} }
@ -710,7 +710,7 @@ void undinet_remove ( struct undi_device *undi ) {
undi->flags &= ~UNDI_FL_STARTED; undi->flags &= ~UNDI_FL_STARTED;
/* Free network device */ /* Free network device */
free_netdev ( netdev ); netdev_put ( netdev );
DBGC ( undinic, "UNDINIC %p removed\n", undinic ); DBGC ( undinic, "UNDINIC %p removed\n", undinic );
} }

View File

@ -1,45 +0,0 @@
/*
* Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <assert.h>
#include <gpxe/hotplug.h>
/** @file
*
* Hotplug support
*
*/
/**
* Forget all persistent references to an object
*
* @v list List of persistent references
*/
void forget_references ( struct list_head *list ) {
struct reference *ref;
struct reference *ref_tmp;
list_for_each_entry_safe ( ref, ref_tmp, list, list ) {
ref->forget ( ref );
}
/* The list had really better be empty by now, otherwise we're
* screwed.
*/
assert ( list_empty ( list ) );
}

View File

@ -90,13 +90,13 @@ int legacy_probe ( void *hwdev,
nic.node_addr = netdev->ll_addr; nic.node_addr = netdev->ll_addr;
if ( ! probe ( &nic, hwdev ) ) { if ( ! probe ( &nic, hwdev ) ) {
free_netdev ( netdev ); netdev_put ( netdev );
return -ENODEV; return -ENODEV;
} }
if ( ( rc = register_netdev ( netdev ) ) != 0 ) { if ( ( rc = register_netdev ( netdev ) ) != 0 ) {
disable ( &nic, hwdev ); disable ( &nic, hwdev );
free_netdev ( netdev ); netdev_put ( netdev );
return rc; return rc;
} }
@ -116,7 +116,7 @@ void legacy_remove ( void *hwdev,
unregister_netdev ( netdev ); unregister_netdev ( netdev );
disable ( nic, hwdev ); disable ( nic, hwdev );
free_netdev ( netdev ); netdev_put ( netdev );
legacy_registered = 0; legacy_registered = 0;
} }

View File

@ -206,7 +206,7 @@ static void pnic_remove ( struct pci_device *pci ) {
unregister_netdev ( netdev ); unregister_netdev ( netdev );
pnic_command ( pnic, PNIC_CMD_RESET, NULL, 0, NULL, 0, NULL ); pnic_command ( pnic, PNIC_CMD_RESET, NULL, 0, NULL, 0, NULL );
free_netdev ( netdev ); netdev_put ( netdev );
} }
/************************************************************************** /**************************************************************************
@ -220,20 +220,18 @@ static int pnic_probe ( struct pci_device *pci,
uint16_t status; uint16_t status;
int rc; int rc;
/* Fix up PCI device */
adjust_pci_device ( pci );
/* Allocate net device */ /* Allocate net device */
netdev = alloc_etherdev ( sizeof ( *pnic ) ); netdev = alloc_etherdev ( sizeof ( *pnic ) );
if ( ! netdev ) { if ( ! netdev )
rc = -ENOMEM; return -ENOMEM;
goto err;
}
pnic = netdev->priv; pnic = netdev->priv;
pci_set_drvdata ( pci, netdev ); pci_set_drvdata ( pci, netdev );
netdev->dev = &pci->dev; netdev->dev = &pci->dev;
pnic->ioaddr = pci->ioaddr; pnic->ioaddr = pci->ioaddr;
/* Fix up PCI device */
adjust_pci_device ( pci );
/* API version check */ /* API version check */
status = pnic_command_quiet ( pnic, PNIC_CMD_API_VER, NULL, 0, status = pnic_command_quiet ( pnic, PNIC_CMD_API_VER, NULL, 0,
&api_version, &api_version,
@ -264,7 +262,7 @@ static int pnic_probe ( struct pci_device *pci,
err: err:
/* Free net device */ /* Free net device */
free_netdev ( netdev ); netdev_put ( netdev );
return rc; return rc;
} }

View File

@ -501,25 +501,22 @@ static void rtl_irq(struct nic *nic, irq_action_t action)
static int rtl_probe ( struct pci_device *pci, static int rtl_probe ( struct pci_device *pci,
const struct pci_device_id *id __unused ) { const struct pci_device_id *id __unused ) {
struct net_device *netdev; struct net_device *netdev;
struct rtl8139_nic *rtl = NULL; struct rtl8139_nic *rtl;
int registered_netdev = 0;
int rc; int rc;
/* Fix up PCI device */
adjust_pci_device ( pci );
/* Allocate net device */ /* Allocate net device */
netdev = alloc_etherdev ( sizeof ( *rtl ) ); netdev = alloc_etherdev ( sizeof ( *rtl ) );
if ( ! netdev ) { if ( ! netdev )
rc = -ENOMEM; return -ENOMEM;
goto err;
}
rtl = netdev->priv; rtl = netdev->priv;
pci_set_drvdata ( pci, netdev ); pci_set_drvdata ( pci, netdev );
netdev->dev = &pci->dev; netdev->dev = &pci->dev;
memset ( rtl, 0, sizeof ( *rtl ) ); memset ( rtl, 0, sizeof ( *rtl ) );
rtl->ioaddr = pci->ioaddr; rtl->ioaddr = pci->ioaddr;
/* Fix up PCI device */
adjust_pci_device ( pci );
/* Reset the NIC, set up EEPROM access and read MAC address */ /* Reset the NIC, set up EEPROM access and read MAC address */
rtl_reset ( rtl ); rtl_reset ( rtl );
rtl_init_eeprom ( rtl ); rtl_init_eeprom ( rtl );
@ -533,25 +530,21 @@ static int rtl_probe ( struct pci_device *pci,
/* Register network device */ /* Register network device */
if ( ( rc = register_netdev ( netdev ) ) != 0 ) if ( ( rc = register_netdev ( netdev ) ) != 0 )
goto err; goto err_register_netdev;
registered_netdev = 1;
/* Register non-volatile storage */ /* Register non-volatile storage */
if ( rtl->nvo.nvs ) { if ( rtl->nvo.nvs ) {
if ( ( rc = nvo_register ( &rtl->nvo ) ) != 0 ) if ( ( rc = nvo_register ( &rtl->nvo ) ) != 0 )
goto err; goto err_register_nvo;
} }
return 0; return 0;
err: err_register_nvo:
/* Disable NIC */
if ( rtl )
rtl_reset ( rtl );
if ( registered_netdev )
unregister_netdev ( netdev ); unregister_netdev ( netdev );
/* Free net device */ err_register_netdev:
free_netdev ( netdev ); rtl_reset ( rtl );
netdev_put ( netdev );
return rc; return rc;
} }
@ -568,7 +561,7 @@ static void rtl_remove ( struct pci_device *pci ) {
nvo_unregister ( &rtl->nvo ); nvo_unregister ( &rtl->nvo );
unregister_netdev ( netdev ); unregister_netdev ( netdev );
rtl_reset ( rtl ); rtl_reset ( rtl );
free_netdev ( netdev ); netdev_put ( netdev );
} }
static struct pci_device_id rtl8139_nics[] = { static struct pci_device_id rtl8139_nics[] = {

View File

@ -13,7 +13,6 @@
#include <gpxe/retry.h> #include <gpxe/retry.h>
#include <gpxe/async.h> #include <gpxe/async.h>
#include <gpxe/ata.h> #include <gpxe/ata.h>
#include <gpxe/hotplug.h>
/** An AoE ATA command */ /** An AoE ATA command */
struct aoecmd { struct aoecmd {
@ -87,8 +86,6 @@ struct aoe_session {
/** Network device */ /** Network device */
struct net_device *netdev; struct net_device *netdev;
/** Reference to network device */
struct reference netdev_ref;
/** Major number */ /** Major number */
uint16_t major; uint16_t major;

View File

@ -13,7 +13,6 @@
#include <gpxe/udp.h> #include <gpxe/udp.h>
#include <gpxe/async.h> #include <gpxe/async.h>
#include <gpxe/retry.h> #include <gpxe/retry.h>
#include <gpxe/hotplug.h>
/** BOOTP/DHCP server port */ /** BOOTP/DHCP server port */
#define BOOTPS_PORT 67 #define BOOTPS_PORT 67
@ -449,6 +448,8 @@ struct dhcp_packet {
struct dhcp_option_block options[NUM_OPT_BLOCKS]; struct dhcp_option_block options[NUM_OPT_BLOCKS];
}; };
struct udp_connection {};
/** A DHCP session */ /** A DHCP session */
struct dhcp_session { struct dhcp_session {
/** UDP connection for this session */ /** UDP connection for this session */
@ -456,8 +457,6 @@ struct dhcp_session {
/** Network device being configured */ /** Network device being configured */
struct net_device *netdev; struct net_device *netdev;
/** Persistent reference to network device */
struct reference netdev_ref;
/** Options obtained from server */ /** Options obtained from server */
struct dhcp_option_block *options; struct dhcp_option_block *options;

View File

@ -1,58 +0,0 @@
#ifndef _GPXE_HOTPLUG_H
#define _GPXE_HOTPLUG_H
/** @file
*
* Hotplug support
*
*/
#include <gpxe/list.h>
/**
* A persistent reference to another data structure
*
* This data structure should be embedded within any data structure
* (the referrer) which holds a persistent reference to a separate,
* volatile data structure (the referee).
*/
struct reference {
/** List of persistent references */
struct list_head list;
/** Forget persistent reference
*
* @v ref Persistent reference
*
* This method is called immediately before the referred-to
* data structure is destroyed. The reference holder must
* forget all references to the referee before returning from
* this method.
*
* This method must also call ref_del() to remove the
* reference.
*/
void ( * forget ) ( struct reference *ref );
};
/**
* Add persistent reference
*
* @v ref Persistent reference
* @v list List of persistent references
*/
static inline void ref_add ( struct reference *ref, struct list_head *list ) {
list_add ( &ref->list, list );
}
/**
* Remove persistent reference
*
* @v ref Persistent reference
*/
static inline void ref_del ( struct reference *ref ) {
list_del ( &ref->list );
}
extern void forget_references ( struct list_head *list );
#endif /* _GPXE_HOTPLUG_H */

View File

@ -9,7 +9,6 @@
#include <ip.h> #include <ip.h>
#include <gpxe/retry.h> #include <gpxe/retry.h>
#include <gpxe/hotplug.h>
/* IP constants */ /* IP constants */
@ -44,8 +43,6 @@ struct ipv4_miniroute {
/** Network device */ /** Network device */
struct net_device *netdev; struct net_device *netdev;
/** Reference to network device */
struct reference netdev_ref;
/** IPv4 address */ /** IPv4 address */
struct in_addr address; struct in_addr address;

View File

@ -10,7 +10,7 @@
#include <stdint.h> #include <stdint.h>
#include <gpxe/list.h> #include <gpxe/list.h>
#include <gpxe/tables.h> #include <gpxe/tables.h>
#include <gpxe/hotplug.h> #include <gpxe/refcnt.h>
struct io_buffer; struct io_buffer;
struct net_device; struct net_device;
@ -137,14 +137,14 @@ struct ll_protocol {
* not just an Ethernet device. * not just an Ethernet device.
*/ */
struct net_device { struct net_device {
/** Reference counter */
struct refcnt refcnt;
/** List of network devices */ /** List of network devices */
struct list_head list; struct list_head list;
/** Name of this network device */ /** Name of this network device */
char name[8]; char name[8];
/** Underlying hardware device */ /** Underlying hardware device */
struct device *dev; struct device *dev;
/** List of persistent reference holders */
struct list_head references;
/** Open network device /** Open network device
* *
@ -251,6 +251,28 @@ static inline int have_netdevs ( void ) {
return ( ! list_empty ( &net_devices ) ); return ( ! list_empty ( &net_devices ) );
} }
/**
* Get reference to network device
*
* @v netdev Network device
* @ret netdev Network device
*/
static inline __attribute__ (( always_inline )) struct net_device *
netdev_get ( struct net_device *netdev ) {
ref_get ( &netdev->refcnt );
return netdev;
}
/**
* Drop reference to network device
*
* @v netdev Network device
*/
static inline __attribute__ (( always_inline )) void
netdev_put ( struct net_device *netdev ) {
ref_put ( &netdev->refcnt );
}
extern int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ); extern int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf );
void netdev_tx_complete ( struct net_device *netdev, struct io_buffer *iobuf ); void netdev_tx_complete ( struct net_device *netdev, struct io_buffer *iobuf );
void netdev_tx_complete_next ( struct net_device *netdev ); void netdev_tx_complete_next ( struct net_device *netdev );
@ -262,7 +284,6 @@ extern int register_netdev ( struct net_device *netdev );
extern int netdev_open ( struct net_device *netdev ); extern int netdev_open ( struct net_device *netdev );
extern void netdev_close ( struct net_device *netdev ); extern void netdev_close ( struct net_device *netdev );
extern void unregister_netdev ( struct net_device *netdev ); extern void unregister_netdev ( struct net_device *netdev );
extern void free_netdev ( struct net_device *netdev );
struct net_device * find_netdev ( const char *name ); struct net_device * find_netdev ( const char *name );
struct net_device * find_pci_netdev ( unsigned int busdevfn ); struct net_device * find_pci_netdev ( unsigned int busdevfn );

View File

@ -265,19 +265,6 @@ struct net_protocol aoe_protocol __net_protocol = {
.rx = aoe_rx, .rx = aoe_rx,
}; };
/**
* Forget reference to net_device
*
* @v ref Persistent reference
*/
static void aoe_forget_netdev ( struct reference *ref ) {
struct aoe_session *aoe
= container_of ( ref, struct aoe_session, netdev_ref );
aoe->netdev = NULL;
ref_del ( &aoe->netdev_ref );
}
/** /**
* Open AoE session * Open AoE session
* *
@ -288,8 +275,6 @@ void aoe_open ( struct aoe_session *aoe ) {
sizeof ( aoe->target ) ); sizeof ( aoe->target ) );
aoe->tag = AOE_TAG_MAGIC; aoe->tag = AOE_TAG_MAGIC;
aoe->timer.expired = aoe_timer_expired; aoe->timer.expired = aoe_timer_expired;
aoe->netdev_ref.forget = aoe_forget_netdev;
ref_add ( &aoe->netdev_ref, &aoe->netdev->references );
list_add ( &aoe->list, &aoe_sessions ); list_add ( &aoe->list, &aoe_sessions );
} }
@ -299,8 +284,6 @@ void aoe_open ( struct aoe_session *aoe ) {
* @v aoe AoE session * @v aoe AoE session
*/ */
void aoe_close ( struct aoe_session *aoe ) { void aoe_close ( struct aoe_session *aoe ) {
if ( aoe->netdev )
ref_del ( &aoe->netdev_ref );
list_del ( &aoe->list ); list_del ( &aoe->list );
} }

View File

@ -30,8 +30,6 @@ struct list_head ipv4_miniroutes = LIST_HEAD_INIT ( ipv4_miniroutes );
/** List of fragment reassembly buffers */ /** List of fragment reassembly buffers */
static LIST_HEAD ( frag_buffers ); static LIST_HEAD ( frag_buffers );
static void ipv4_forget_netdev ( struct reference *ref );
/** /**
* Add IPv4 minirouting table entry * Add IPv4 minirouting table entry
* *
@ -61,7 +59,7 @@ static struct ipv4_miniroute * add_ipv4_miniroute ( struct net_device *netdev,
} }
/* Record routing information */ /* Record routing information */
miniroute->netdev = netdev; miniroute->netdev = netdev_get ( netdev );
miniroute->address = address; miniroute->address = address;
miniroute->netmask = netmask; miniroute->netmask = netmask;
miniroute->gateway = gateway; miniroute->gateway = gateway;
@ -75,10 +73,6 @@ static struct ipv4_miniroute * add_ipv4_miniroute ( struct net_device *netdev,
list_add ( &miniroute->list, &ipv4_miniroutes ); list_add ( &miniroute->list, &ipv4_miniroutes );
} }
/* Record reference to net_device */
miniroute->netdev_ref.forget = ipv4_forget_netdev;
ref_add ( &miniroute->netdev_ref, &netdev->references );
return miniroute; return miniroute;
} }
@ -95,23 +89,11 @@ static void del_ipv4_miniroute ( struct ipv4_miniroute *miniroute ) {
DBG ( "gw %s ", inet_ntoa ( miniroute->gateway ) ); DBG ( "gw %s ", inet_ntoa ( miniroute->gateway ) );
DBG ( "via %s\n", miniroute->netdev->name ); DBG ( "via %s\n", miniroute->netdev->name );
ref_del ( &miniroute->netdev_ref ); netdev_put ( miniroute->netdev );
list_del ( &miniroute->list ); list_del ( &miniroute->list );
free ( miniroute ); free ( miniroute );
} }
/**
* Forget reference to net_device
*
* @v ref Persistent reference
*/
static void ipv4_forget_netdev ( struct reference *ref ) {
struct ipv4_miniroute *miniroute
= container_of ( ref, struct ipv4_miniroute, netdev_ref );
del_ipv4_miniroute ( miniroute );
}
/** /**
* Add IPv4 interface * Add IPv4 interface
* *

View File

@ -32,8 +32,6 @@ struct ipv6_miniroute {
/* Network device */ /* Network device */
struct net_device *netdev; struct net_device *netdev;
/** Reference to network device */
struct reference netdev_ref;
/* Destination prefix */ /* Destination prefix */
struct in6_addr prefix; struct in6_addr prefix;
@ -48,8 +46,6 @@ struct ipv6_miniroute {
/** List of IPv6 miniroutes */ /** List of IPv6 miniroutes */
static LIST_HEAD ( miniroutes ); static LIST_HEAD ( miniroutes );
static void ipv6_forget_netdev ( struct reference *ref );
/** /**
* Add IPv6 minirouting table entry * Add IPv6 minirouting table entry
* *
@ -69,7 +65,7 @@ static struct ipv6_miniroute * add_ipv6_miniroute ( struct net_device *netdev,
miniroute = malloc ( sizeof ( *miniroute ) ); miniroute = malloc ( sizeof ( *miniroute ) );
if ( miniroute ) { if ( miniroute ) {
/* Record routing information */ /* Record routing information */
miniroute->netdev = netdev; miniroute->netdev = netdev_get ( netdev );
miniroute->prefix = prefix; miniroute->prefix = prefix;
miniroute->prefix_len = prefix_len; miniroute->prefix_len = prefix_len;
miniroute->address = address; miniroute->address = address;
@ -81,10 +77,6 @@ static struct ipv6_miniroute * add_ipv6_miniroute ( struct net_device *netdev,
} else { } else {
list_add ( &miniroute->list, &miniroutes ); list_add ( &miniroute->list, &miniroutes );
} }
/* Record reference to net_device */
miniroute->netdev_ref.forget = ipv6_forget_netdev;
ref_add ( &miniroute->netdev_ref, &netdev->references );
} }
return miniroute; return miniroute;
@ -96,23 +88,11 @@ static struct ipv6_miniroute * add_ipv6_miniroute ( struct net_device *netdev,
* @v miniroute Routing table entry * @v miniroute Routing table entry
*/ */
static void del_ipv6_miniroute ( struct ipv6_miniroute *miniroute ) { static void del_ipv6_miniroute ( struct ipv6_miniroute *miniroute ) {
ref_del ( &miniroute->netdev_ref ); netdev_put ( miniroute->netdev );
list_del ( &miniroute->list ); list_del ( &miniroute->list );
free ( miniroute ); free ( miniroute );
} }
/**
* Forget reference to net_device
*
* @v ref Persistent reference
*/
static void ipv6_forget_netdev ( struct reference *ref ) {
struct ipv6_miniroute *miniroute
= container_of ( ref, struct ipv6_miniroute, netdev_ref );
del_ipv6_miniroute ( miniroute );
}
/** /**
* Add IPv6 interface * Add IPv6 interface
* *

View File

@ -115,6 +115,19 @@ void netdev_tx_complete_next ( struct net_device *netdev ) {
} }
} }
/**
* Flush device's transmit queue
*
* @v netdev Network device
*/
static void netdev_tx_flush ( struct net_device *netdev ) {
/* Discard any packets in the TX queue */
while ( ! list_empty ( &netdev->tx_queue ) ) {
netdev_tx_complete_next ( netdev );
}
}
/** /**
* Add packet to receive queue * Add packet to receive queue
* *
@ -168,6 +181,36 @@ struct io_buffer * netdev_rx_dequeue ( struct net_device *netdev ) {
return NULL; return NULL;
} }
/**
* Flush device's receive queue
*
* @v netdev Network device
*/
static void netdev_rx_flush ( struct net_device *netdev ) {
struct io_buffer *iobuf;
/* Discard any packets in the RX queue */
while ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
DBGC ( netdev, "NETDEV %p discarding received %p\n",
netdev, iobuf );
free_iob ( iobuf );
}
}
/**
* Free network device
*
* @v refcnt Network device reference counter
*/
static void free_netdev ( struct refcnt *refcnt ) {
struct net_device *netdev =
container_of ( refcnt, struct net_device, refcnt );
netdev_tx_flush ( netdev );
netdev_rx_flush ( netdev );
free ( netdev );
}
/** /**
* Allocate network device * Allocate network device
* *
@ -184,7 +227,7 @@ struct net_device * alloc_netdev ( size_t priv_size ) {
netdev = malloc ( total_len ); netdev = malloc ( total_len );
if ( netdev ) { if ( netdev ) {
memset ( netdev, 0, total_len ); memset ( netdev, 0, total_len );
INIT_LIST_HEAD ( &netdev->references ); netdev->refcnt.free = free_netdev;
INIT_LIST_HEAD ( &netdev->tx_queue ); INIT_LIST_HEAD ( &netdev->tx_queue );
INIT_LIST_HEAD ( &netdev->rx_queue ); INIT_LIST_HEAD ( &netdev->rx_queue );
netdev->priv = ( ( ( void * ) netdev ) + sizeof ( *netdev ) ); netdev->priv = ( ( ( void * ) netdev ) + sizeof ( *netdev ) );
@ -209,6 +252,7 @@ int register_netdev ( struct net_device *netdev ) {
ifindex++ ); ifindex++ );
/* Add to device list */ /* Add to device list */
netdev_get ( netdev );
list_add_tail ( &netdev->list, &net_devices ); list_add_tail ( &netdev->list, &net_devices );
DBGC ( netdev, "NETDEV %p registered as %s (phys %s hwaddr %s)\n", DBGC ( netdev, "NETDEV %p registered as %s (phys %s hwaddr %s)\n",
netdev, netdev->name, netdev->dev->name, netdev, netdev->name, netdev->dev->name,
@ -247,7 +291,6 @@ int netdev_open ( struct net_device *netdev ) {
* @v netdev Network device * @v netdev Network device
*/ */
void netdev_close ( struct net_device *netdev ) { void netdev_close ( struct net_device *netdev ) {
struct io_buffer *iobuf;
/* Do nothing if device is already closed */ /* Do nothing if device is already closed */
if ( ! ( netdev->state & NETDEV_OPEN ) ) if ( ! ( netdev->state & NETDEV_OPEN ) )
@ -258,17 +301,9 @@ void netdev_close ( struct net_device *netdev ) {
/* Close the device */ /* Close the device */
netdev->close ( netdev ); netdev->close ( netdev );
/* Discard any packets in the TX queue */ /* Flush TX and RX queues */
while ( ! list_empty ( &netdev->tx_queue ) ) { netdev_tx_flush ( netdev );
netdev_tx_complete_next ( netdev ); netdev_rx_flush ( netdev );
}
/* Discard any packets in the RX queue */
while ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
DBGC ( netdev, "NETDEV %p discarding received %p\n",
netdev, iobuf );
free_iob ( iobuf );
}
/* Mark as closed */ /* Mark as closed */
netdev->state &= ~NETDEV_OPEN; netdev->state &= ~NETDEV_OPEN;
@ -286,23 +321,12 @@ void unregister_netdev ( struct net_device *netdev ) {
/* Ensure device is closed */ /* Ensure device is closed */
netdev_close ( netdev ); netdev_close ( netdev );
/* Kill off any persistent references to this device */
forget_references ( &netdev->references );
/* Remove from device list */ /* Remove from device list */
list_del ( &netdev->list ); list_del ( &netdev->list );
netdev_put ( netdev );
DBGC ( netdev, "NETDEV %p unregistered\n", netdev ); DBGC ( netdev, "NETDEV %p unregistered\n", netdev );
} }
/**
* Free network device
*
* @v netdev Network device
*/
void free_netdev ( struct net_device *netdev ) {
free ( netdev );
}
/** /**
* Get network device by name * Get network device by name
* *

View File

@ -493,6 +493,8 @@ udp_to_dhcp ( struct udp_connection *conn ) {
return container_of ( conn, struct dhcp_session, udp ); return container_of ( conn, struct dhcp_session, udp );
} }
#if 0
/** /**
* Mark DHCP session as complete * Mark DHCP session as complete
* *
@ -515,9 +517,6 @@ static void dhcp_done ( struct dhcp_session *dhcp, int rc ) {
/* Close UDP connection */ /* Close UDP connection */
udp_close ( &dhcp->udp ); udp_close ( &dhcp->udp );
/* Release reference on net device */
ref_del ( &dhcp->netdev_ref );
/* Mark async operation as complete */ /* Mark async operation as complete */
async_done ( &dhcp->async, rc ); async_done ( &dhcp->async, rc );
} }
@ -705,19 +704,6 @@ static struct udp_operations dhcp_udp_operations = {
.newdata = dhcp_newdata, .newdata = dhcp_newdata,
}; };
/**
* Forget reference to net_device
*
* @v ref Persistent reference
*/
static void dhcp_forget_netdev ( struct reference *ref ) {
struct dhcp_session *dhcp
= container_of ( ref, struct dhcp_session, netdev_ref );
/* Kill DHCP session immediately */
dhcp_done ( dhcp, -ENETUNREACH );
}
/** /**
* Initiate DHCP on a network interface * Initiate DHCP on a network interface
* *
@ -742,13 +728,12 @@ int start_dhcp ( struct dhcp_session *dhcp, struct async *parent ) {
if ( ( rc = udp_open ( &dhcp->udp, htons ( BOOTPC_PORT ) ) ) != 0 ) if ( ( rc = udp_open ( &dhcp->udp, htons ( BOOTPC_PORT ) ) ) != 0 )
return rc; return rc;
/* Add persistent reference to net device */
dhcp->netdev_ref.forget = dhcp_forget_netdev;
ref_add ( &dhcp->netdev_ref, &dhcp->netdev->references );
/* Proof of concept: just send a single DHCPDISCOVER */ /* Proof of concept: just send a single DHCPDISCOVER */
dhcp_send_request ( dhcp ); dhcp_send_request ( dhcp );
async_init ( &dhcp->async, &default_async_operations, parent ); async_init ( &dhcp->async, &default_async_operations, parent );
return 0; return 0;
} }
#endif