mirror of https://github.com/ipxe/ipxe.git
Make open() and close() an official part of the netdevice API.
Call netdevice's poll() and transmit() methods only when device is open.pull/1/head
parent
d4894f0127
commit
0c03bb5a9a
|
@ -56,6 +56,14 @@ static void legacy_poll ( struct net_device *netdev ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int legacy_open ( struct net_device *netdev __unused ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void legacy_close ( struct net_device *netdev __unused ) {
|
||||||
|
/* Nothing to do */
|
||||||
|
}
|
||||||
|
|
||||||
int legacy_probe ( struct pci_device *pci,
|
int legacy_probe ( struct pci_device *pci,
|
||||||
const struct pci_device_id *id __unused,
|
const struct pci_device_id *id __unused,
|
||||||
int ( * probe ) ( struct nic *nic,
|
int ( * probe ) ( struct nic *nic,
|
||||||
|
@ -74,6 +82,8 @@ int legacy_probe ( struct pci_device *pci,
|
||||||
memset ( &nic, 0, sizeof ( nic ) );
|
memset ( &nic, 0, sizeof ( nic ) );
|
||||||
pci_set_drvdata ( pci, netdev );
|
pci_set_drvdata ( pci, netdev );
|
||||||
|
|
||||||
|
netdev->open = legacy_open;
|
||||||
|
netdev->close = legacy_close;
|
||||||
netdev->transmit = legacy_transmit;
|
netdev->transmit = legacy_transmit;
|
||||||
netdev->poll = legacy_poll;
|
netdev->poll = legacy_poll;
|
||||||
nic.node_addr = netdev->ll_addr;
|
nic.node_addr = netdev->ll_addr;
|
||||||
|
|
|
@ -185,6 +185,20 @@ static void pnic_irq ( struct net_device *netdev, irq_action_t action ) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
OPEN - Open network device
|
||||||
|
***************************************************************************/
|
||||||
|
static int pnic_open ( struct net_device *netdev __unused ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
CLOSE - Close network device
|
||||||
|
***************************************************************************/
|
||||||
|
static void pnic_close ( struct net_device *netdev __unused ) {
|
||||||
|
/* Nothing to do */
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
DISABLE - Turn off ethernet interface
|
DISABLE - Turn off ethernet interface
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
@ -238,6 +252,8 @@ static int pnic_probe ( struct pci_device *pci,
|
||||||
netdev->ll_addr, ETH_ALEN, NULL );
|
netdev->ll_addr, ETH_ALEN, NULL );
|
||||||
|
|
||||||
/* Point to NIC specific routines */
|
/* Point to NIC specific routines */
|
||||||
|
netdev->open = pnic_open;
|
||||||
|
netdev->close = pnic_close;
|
||||||
netdev->poll = pnic_poll;
|
netdev->poll = pnic_poll;
|
||||||
netdev->transmit = pnic_transmit;
|
netdev->transmit = pnic_transmit;
|
||||||
|
|
||||||
|
|
|
@ -542,8 +542,8 @@ static int rtl_probe ( struct pci_device *pci,
|
||||||
nvs_read ( &rtl->eeprom.nvs, EE_MAC, netdev->ll_addr, ETH_ALEN );
|
nvs_read ( &rtl->eeprom.nvs, EE_MAC, netdev->ll_addr, ETH_ALEN );
|
||||||
|
|
||||||
/* Point to NIC specific routines */
|
/* Point to NIC specific routines */
|
||||||
// netdev->open = rtl_open;
|
netdev->open = rtl_open;
|
||||||
// netdev->close = rtl_close;
|
netdev->close = rtl_close;
|
||||||
netdev->transmit = rtl_transmit;
|
netdev->transmit = rtl_transmit;
|
||||||
netdev->poll = rtl_poll;
|
netdev->poll = rtl_poll;
|
||||||
|
|
||||||
|
@ -558,10 +558,6 @@ static int rtl_probe ( struct pci_device *pci,
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
#warning "Hack alert"
|
|
||||||
rtl_open ( netdev );
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
@ -584,10 +580,6 @@ static void rtl_remove ( struct pci_device *pci ) {
|
||||||
struct net_device *netdev = pci_get_drvdata ( pci );
|
struct net_device *netdev = pci_get_drvdata ( pci );
|
||||||
struct rtl8139_nic *rtl = netdev->priv;
|
struct rtl8139_nic *rtl = netdev->priv;
|
||||||
|
|
||||||
|
|
||||||
#warning "Hack alert"
|
|
||||||
rtl_close ( netdev );
|
|
||||||
|
|
||||||
if ( rtl->nvo.nvs )
|
if ( rtl->nvo.nvs )
|
||||||
nvo_unregister ( &rtl->nvo );
|
nvo_unregister ( &rtl->nvo );
|
||||||
unregister_netdev ( netdev );
|
unregister_netdev ( netdev );
|
||||||
|
|
|
@ -142,6 +142,23 @@ struct net_device {
|
||||||
/** List of persistent reference holders */
|
/** List of persistent reference holders */
|
||||||
struct list_head references;
|
struct list_head references;
|
||||||
|
|
||||||
|
/** Open network device
|
||||||
|
*
|
||||||
|
* @v netdev Network device
|
||||||
|
* @ret rc Return status code
|
||||||
|
*
|
||||||
|
* This method should allocate RX packet buffers and enable
|
||||||
|
* the hardware to start transmitting and receiving packets.
|
||||||
|
*/
|
||||||
|
int ( * open ) ( struct net_device *netdev );
|
||||||
|
/** Close network device
|
||||||
|
*
|
||||||
|
* @v netdev Network device
|
||||||
|
*
|
||||||
|
* This method should stop the flow of packets, and free up
|
||||||
|
* any packets that are currently in the device's TX queue.
|
||||||
|
*/
|
||||||
|
void ( * close ) ( struct net_device *netdev );
|
||||||
/** Transmit packet
|
/** Transmit packet
|
||||||
*
|
*
|
||||||
* @v netdev Network device
|
* @v netdev Network device
|
||||||
|
@ -154,6 +171,9 @@ struct net_device {
|
||||||
* Ownership of the packet buffer is transferred to the @c
|
* Ownership of the packet buffer is transferred to the @c
|
||||||
* net_device, which must eventually call free_pkb() to
|
* net_device, which must eventually call free_pkb() to
|
||||||
* release the buffer.
|
* release the buffer.
|
||||||
|
*
|
||||||
|
* This method is guaranteed to be called only when the device
|
||||||
|
* is open.
|
||||||
*/
|
*/
|
||||||
int ( * transmit ) ( struct net_device *netdev, struct pk_buff *pkb );
|
int ( * transmit ) ( struct net_device *netdev, struct pk_buff *pkb );
|
||||||
/** Poll for received packet
|
/** Poll for received packet
|
||||||
|
@ -163,6 +183,9 @@ struct net_device {
|
||||||
* This method should cause the hardware to check for received
|
* This method should cause the hardware to check for received
|
||||||
* packets. Any received packets should be delivered via
|
* packets. Any received packets should be delivered via
|
||||||
* netdev_rx().
|
* netdev_rx().
|
||||||
|
*
|
||||||
|
* This method is guaranteed to be called only when the device
|
||||||
|
* is open.
|
||||||
*/
|
*/
|
||||||
void ( * poll ) ( struct net_device *netdev );
|
void ( * poll ) ( struct net_device *netdev );
|
||||||
|
|
||||||
|
@ -174,6 +197,11 @@ struct net_device {
|
||||||
*/
|
*/
|
||||||
uint8_t ll_addr[MAX_LL_ADDR_LEN];
|
uint8_t ll_addr[MAX_LL_ADDR_LEN];
|
||||||
|
|
||||||
|
/** Current device state
|
||||||
|
*
|
||||||
|
* This is the bitwise-OR of zero or more NETDEV_XXX constants.
|
||||||
|
*/
|
||||||
|
unsigned int state;
|
||||||
/** Received packet queue */
|
/** Received packet queue */
|
||||||
struct list_head rx_queue;
|
struct list_head rx_queue;
|
||||||
|
|
||||||
|
@ -181,6 +209,9 @@ struct net_device {
|
||||||
void *priv;
|
void *priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Network device is open */
|
||||||
|
#define NETDEV_OPEN 0x0001
|
||||||
|
|
||||||
/** Declare a link-layer protocol */
|
/** Declare a link-layer protocol */
|
||||||
#define __ll_protocol __table ( ll_protocols, 01 )
|
#define __ll_protocol __table ( ll_protocols, 01 )
|
||||||
|
|
||||||
|
@ -209,6 +240,8 @@ extern int netdev_poll ( struct net_device *netdev );
|
||||||
extern struct pk_buff * netdev_rx_dequeue ( struct net_device *netdev );
|
extern struct pk_buff * netdev_rx_dequeue ( struct net_device *netdev );
|
||||||
extern struct net_device * alloc_netdev ( size_t priv_size );
|
extern struct net_device * alloc_netdev ( size_t priv_size );
|
||||||
extern int register_netdev ( struct net_device *netdev );
|
extern int register_netdev ( struct net_device *netdev );
|
||||||
|
extern int netdev_open ( 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 );
|
extern void free_netdev ( struct net_device *netdev );
|
||||||
extern struct net_device * next_netdev ( void );
|
extern struct net_device * next_netdev ( void );
|
||||||
|
|
|
@ -54,6 +54,12 @@ static LIST_HEAD ( net_devices );
|
||||||
int netdev_tx ( struct net_device *netdev, struct pk_buff *pkb ) {
|
int netdev_tx ( struct net_device *netdev, struct pk_buff *pkb ) {
|
||||||
DBG ( "%s transmitting %p+%zx\n", netdev_name ( netdev ),
|
DBG ( "%s transmitting %p+%zx\n", netdev_name ( netdev ),
|
||||||
pkb->data, pkb_len ( pkb ) );
|
pkb->data, pkb_len ( pkb ) );
|
||||||
|
|
||||||
|
if ( ! ( netdev->state & NETDEV_OPEN ) ) {
|
||||||
|
free_pkb ( pkb );
|
||||||
|
return -ENETUNREACH;
|
||||||
|
}
|
||||||
|
|
||||||
return netdev->transmit ( netdev, pkb );
|
return netdev->transmit ( netdev, pkb );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +106,7 @@ int net_tx ( struct pk_buff *pkb, struct net_device *netdev,
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
int net_rx ( struct pk_buff *pkb, struct net_device *netdev,
|
int net_rx ( struct pk_buff *pkb, struct net_device *netdev,
|
||||||
uint16_t net_proto, const void *ll_source ) {
|
uint16_t net_proto, const void *ll_source ) {
|
||||||
struct net_protocol *net_protocol;
|
struct net_protocol *net_protocol;
|
||||||
|
|
||||||
/* Hand off to network-layer protocol, if any */
|
/* Hand off to network-layer protocol, if any */
|
||||||
|
@ -125,7 +131,10 @@ int net_rx ( struct pk_buff *pkb, struct net_device *netdev,
|
||||||
* packets will be added to the RX packet queue via netdev_rx().
|
* packets will be added to the RX packet queue via netdev_rx().
|
||||||
*/
|
*/
|
||||||
int netdev_poll ( struct net_device *netdev ) {
|
int netdev_poll ( struct net_device *netdev ) {
|
||||||
netdev->poll ( netdev );
|
|
||||||
|
if ( netdev->state & NETDEV_OPEN )
|
||||||
|
netdev->poll ( netdev );
|
||||||
|
|
||||||
return ( ! list_empty ( &netdev->rx_queue ) );
|
return ( ! list_empty ( &netdev->rx_queue ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,15 +195,46 @@ int register_netdev ( struct net_device *netdev ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregister network device
|
* Open network device
|
||||||
*
|
*
|
||||||
* @v netdev Network device
|
* @v netdev Network device
|
||||||
*
|
* @ret rc Return status code
|
||||||
* Removes the network device from the list of network devices.
|
|
||||||
*/
|
*/
|
||||||
void unregister_netdev ( struct net_device *netdev ) {
|
int netdev_open ( struct net_device *netdev ) {
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Do nothing if device is already open */
|
||||||
|
if ( netdev->state & NETDEV_OPEN )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
DBG ( "%s opening\n", netdev_name ( netdev ) );
|
||||||
|
|
||||||
|
/* Open the device */
|
||||||
|
if ( ( rc = netdev->open ( netdev ) ) != 0 )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* Mark as opened */
|
||||||
|
netdev->state |= NETDEV_OPEN;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close network device
|
||||||
|
*
|
||||||
|
* @v netdev Network device
|
||||||
|
*/
|
||||||
|
void netdev_close ( struct net_device *netdev ) {
|
||||||
struct pk_buff *pkb;
|
struct pk_buff *pkb;
|
||||||
|
|
||||||
|
/* Do nothing if device is already closed */
|
||||||
|
if ( ! ( netdev->state & NETDEV_OPEN ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
DBG ( "%s closing\n", netdev_name ( netdev ) );
|
||||||
|
|
||||||
|
/* Close the device */
|
||||||
|
netdev->close ( netdev );
|
||||||
|
|
||||||
/* Discard any packets in the RX queue */
|
/* Discard any packets in the RX queue */
|
||||||
while ( ( pkb = netdev_rx_dequeue ( netdev ) ) ) {
|
while ( ( pkb = netdev_rx_dequeue ( netdev ) ) ) {
|
||||||
DBG ( "%s discarding %p+%zx\n", netdev_name ( netdev ),
|
DBG ( "%s discarding %p+%zx\n", netdev_name ( netdev ),
|
||||||
|
@ -202,6 +242,22 @@ void unregister_netdev ( struct net_device *netdev ) {
|
||||||
free_pkb ( pkb );
|
free_pkb ( pkb );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Mark as closed */
|
||||||
|
netdev->state &= ~NETDEV_OPEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister network device
|
||||||
|
*
|
||||||
|
* @v netdev Network device
|
||||||
|
*
|
||||||
|
* Removes the network device from the list of network devices.
|
||||||
|
*/
|
||||||
|
void unregister_netdev ( struct net_device *netdev ) {
|
||||||
|
|
||||||
|
/* Ensure device is closed */
|
||||||
|
netdev_close ( netdev );
|
||||||
|
|
||||||
/* Kill off any persistent references to this device */
|
/* Kill off any persistent references to this device */
|
||||||
forget_references ( &netdev->references );
|
forget_references ( &netdev->references );
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,9 @@
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
#include <vsprintf.h>
|
#include <vsprintf.h>
|
||||||
|
#include <gpxe/netdevice.h>
|
||||||
#include <gpxe/autoboot.h>
|
#include <gpxe/autoboot.h>
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
|
@ -30,11 +32,21 @@ void test_dhcp ( struct net_device *netdev );
|
||||||
|
|
||||||
void autoboot ( void ) {
|
void autoboot ( void ) {
|
||||||
struct net_device *netdev;
|
struct net_device *netdev;
|
||||||
|
int rc;
|
||||||
|
|
||||||
netdev = next_netdev ();
|
netdev = next_netdev ();
|
||||||
if ( netdev ) {
|
if ( ! netdev ) {
|
||||||
test_dhcp ( netdev );
|
|
||||||
} else {
|
|
||||||
printf ( "No network device found\n" );
|
printf ( "No network device found\n" );
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( ( rc = netdev_open ( netdev ) ) != 0 ) {
|
||||||
|
printf ( "Could not open %s: %s\n", netdev_name ( netdev ),
|
||||||
|
strerror ( rc ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
test_dhcp ( netdev );
|
||||||
|
|
||||||
|
netdev_close ( netdev );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue