* Notify BIOS of existence of network device
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int pxe_notify ( struct net_device *netdev ) {
+static int pxe_notify ( struct net_device *netdev, void *priv __unused ) {
/* Do nothing if we already have a network device */
if ( pxe_netdev )
* Create per-netdevice GuestInfo settings
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int guestinfo_net_probe ( struct net_device *netdev ) {
+static int guestinfo_net_probe ( struct net_device *netdev,
+ void *priv __unused ) {
struct settings *settings;
int rc;
* Remove per-netdevice GuestInfo settings
*
* @v netdev Network device
+ * @v priv Private data
*/
-static void guestinfo_net_remove ( struct net_device *netdev ) {
+static void guestinfo_net_remove ( struct net_device *netdev,
+ void *priv __unused ) {
struct settings *parent = netdev_settings ( netdev );
struct settings *settings;
* Apply cached DHCPACK to network device, if applicable
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int cachedhcp_probe ( struct net_device *netdev ) {
+static int cachedhcp_probe ( struct net_device *netdev, void *priv __unused ) {
/* Apply cached DHCPACK to network device, if applicable */
return cachedhcp_apply ( &cached_dhcpack, netdev );
* Inhibit emulated PCI devices
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int netfront_net_probe ( struct net_device *netdev ) {
+static int netfront_net_probe ( struct net_device *netdev,
+ void *priv __unused ) {
struct netfront_nic *netfront;
/* Inhibit emulated PCI devices matching an existing netfront device */
struct net_driver {
/** Name */
const char *name;
+ /** Size of private data */
+ size_t priv_len;
/** Probe device
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
- int ( * probe ) ( struct net_device *netdev );
+ int ( * probe ) ( struct net_device *netdev, void *priv );
/** Notify of device or link state change
*
* @v netdev Network device
+ * @v priv Private data
*/
- void ( * notify ) ( struct net_device *netdev );
+ void ( * notify ) ( struct net_device *netdev, void *priv );
/** Remove device
*
* @v netdev Network device
+ * @v priv Private data
*/
- void ( * remove ) ( struct net_device *netdev );
+ void ( * remove ) ( struct net_device *netdev, void *priv );
};
/** Network driver table */
return ( netdev->state & NETDEV_RX_FROZEN );
}
+extern void * netdev_priv ( struct net_device *netdev,
+ struct net_driver *driver );
extern void netdev_rx_freeze ( struct net_device *netdev );
extern void netdev_rx_unfreeze ( struct net_device *netdev );
extern void netdev_link_err ( struct net_device *netdev, int rc );
* Create SNP device
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int efi_snp_probe ( struct net_device *netdev ) {
+static int efi_snp_probe ( struct net_device *netdev, void *priv __unused ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
struct efi_device *efidev;
struct efi_snp_device *snpdev;
* Handle SNP device or link state change
*
* @v netdev Network device
+ * @v priv Private data
*/
-static void efi_snp_notify ( struct net_device *netdev ) {
+static void efi_snp_notify ( struct net_device *netdev, void *priv __unused ) {
struct efi_snp_device *snpdev;
/* Locate SNP device */
* Destroy SNP device
*
* @v netdev Network device
+ * @v priv Private data
*/
-static void efi_snp_remove ( struct net_device *netdev ) {
+static void efi_snp_remove ( struct net_device *netdev, void *priv __unused ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
struct efi_snp_device *snpdev;
int leak = efi_shutdown_in_progress;
* Create FCoE port
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int fcoe_probe ( struct net_device *netdev ) {
+static int fcoe_probe ( struct net_device *netdev, void *priv __unused ) {
struct ll_protocol *ll_protocol = netdev->ll_protocol;
struct fcoe_port *fcoe;
int rc;
* Handle FCoE port device or link state change
*
* @v netdev Network device
+ * @v priv Private data
*/
-static void fcoe_notify ( struct net_device *netdev ) {
+static void fcoe_notify ( struct net_device *netdev, void *priv __unused ) {
struct fcoe_port *fcoe;
/* Sanity check */
* Destroy FCoE port
*
* @v netdev Network device
+ * @v priv Private data
*/
-static void fcoe_remove ( struct net_device *netdev ) {
+static void fcoe_remove ( struct net_device *netdev, void *priv __unused ) {
struct fcoe_port *fcoe;
/* Sanity check */
* Handle device or link status change
*
* @v netdev Network device
+ * @v priv Private data
*/
-static void xsigo_net_notify ( struct net_device *netdev ) {
+static void xsigo_net_notify ( struct net_device *netdev,
+ void *priv __unused ) {
struct xsigo_device *xdev;
struct ib_device *ibdev;
struct xsigo_manager *xcm;
* Register IPv6 link-local address settings
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int ipv6_register_settings ( struct net_device *netdev ) {
+static int ipv6_register_settings ( struct net_device *netdev,
+ void *priv __unused ) {
struct settings *parent = netdev_settings ( netdev );
struct ipv6_settings *ipv6set;
int rc;
* Create LLDP settings block
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int lldp_probe ( struct net_device *netdev ) {
+static int lldp_probe ( struct net_device *netdev, void *priv __unused ) {
struct lldp_settings *lldpset;
int rc;
* Update neighbour cache on network device state change or removal
*
* @v netdev Network device
+ * @v priv Private data
*/
-static void neighbour_flush ( struct net_device *netdev ) {
+static void neighbour_flush ( struct net_device *netdev, void *priv __unused ) {
struct neighbour *neighbour;
struct neighbour *tmp;
return 0;
}
+/**
+ * Get offset of network device driver private data
+ *
+ * @v driver Upper-layer driver, or NULL for device driver
+ * @ret offset Offset of driver private data
+ */
+static size_t netdev_priv_offset ( struct net_driver *driver ) {
+ struct net_device *netdev;
+ unsigned int num_configs;
+ size_t offset;
+
+ /* Allow space for network device */
+ offset = sizeof ( *netdev );
+
+ /* Allow space for configurations */
+ num_configs = table_num_entries ( NET_DEVICE_CONFIGURATORS );
+ offset += ( num_configs * sizeof ( netdev->configs[0] ) );
+
+ /* Place variable-length device driver private data at end */
+ if ( ! driver )
+ driver = table_end ( NET_DRIVERS );
+
+ /* Allow space for preceding upper-layer drivers' private data */
+ for_each_table_entry_continue_reverse ( driver, NET_DRIVERS ) {
+ offset += driver->priv_len;
+ }
+
+ /* Sanity check */
+ assert ( ( offset & ( sizeof ( void * ) - 1 ) ) == 0 );
+
+ return offset;
+}
+
+/**
+ * Get network device driver private data
+ *
+ * @v netdev Network device
+ * @v driver Upper-layer driver, or NULL for device driver
+ * @ret priv Driver private data
+ */
+void * netdev_priv ( struct net_device *netdev, struct net_driver *driver ) {
+
+ return ( ( ( void * ) netdev ) + netdev_priv_offset ( driver ) );
+}
+
/**
* Notify drivers of network device or link state change
*
*/
static void netdev_notify ( struct net_device *netdev ) {
struct net_driver *driver;
+ void *priv;
for_each_table_entry ( driver, NET_DRIVERS ) {
+ priv = netdev_priv ( netdev, driver );
if ( driver->notify )
- driver->notify ( netdev );
+ driver->notify ( netdev, priv );
}
}
struct net_device *netdev;
struct net_device_configurator *configurator;
struct net_device_configuration *config;
- unsigned int num_configs;
- size_t confs_len;
- size_t total_len;
- num_configs = table_num_entries ( NET_DEVICE_CONFIGURATORS );
- confs_len = ( num_configs * sizeof ( netdev->configs[0] ) );
- total_len = ( sizeof ( *netdev ) + confs_len + priv_len );
- netdev = zalloc ( total_len );
+ netdev = zalloc ( netdev_priv_offset ( NULL ) + priv_len );
if ( netdev ) {
ref_init ( &netdev->refcnt, free_netdev );
netdev->link_rc = -EUNKNOWN_LINK_STATUS;
&netdev->refcnt );
config++;
}
- netdev->priv = ( ( ( void * ) netdev ) + sizeof ( *netdev ) +
- confs_len );
+ netdev->priv = netdev_priv ( netdev, NULL );
}
return netdev;
}
struct net_device *duplicate;
unsigned int i;
uint32_t seed;
+ void *priv;
int rc;
/* Set initial link-layer address, if not already set */
/* Probe device */
for_each_table_entry ( driver, NET_DRIVERS ) {
- if ( driver->probe && ( rc = driver->probe ( netdev ) ) != 0 ) {
+ priv = netdev_priv ( netdev, driver );
+ if ( driver->probe &&
+ ( rc = driver->probe ( netdev, priv ) ) != 0 ) {
DBGC ( netdev, "NETDEV %s could not add %s device: "
"%s\n", netdev->name, driver->name,
strerror ( rc ) );
err_probe:
for_each_table_entry_continue_reverse ( driver, NET_DRIVERS ) {
+ priv = netdev_priv ( netdev, driver );
if ( driver->remove )
- driver->remove ( netdev );
+ driver->remove ( netdev, priv );
}
clear_settings ( netdev_settings ( netdev ) );
unregister_settings ( netdev_settings ( netdev ) );
*/
void unregister_netdev ( struct net_device *netdev ) {
struct net_driver *driver;
+ void *priv;
/* Ensure device is closed */
netdev_close ( netdev );
/* Remove device */
for_each_table_entry_reverse ( driver, NET_DRIVERS ) {
+ priv = netdev_priv ( netdev, driver );
if ( driver->remove )
- driver->remove ( netdev );
+ driver->remove ( netdev, priv );
}
/* Unregister per-netdev configuration settings */
* Create automatic VLAN device
*
* @v trunk Trunk network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int vlan_probe ( struct net_device *trunk ) {
+static int vlan_probe ( struct net_device *trunk, void *priv __unused ) {
int rc;
/* Do nothing unless an automatic VLAN exists */
* Handle trunk network device link state change
*
* @v trunk Trunk network device
+ * @v priv Private data
*/
-static void vlan_notify ( struct net_device *trunk ) {
+static void vlan_notify ( struct net_device *trunk, void *priv __unused ) {
struct net_device *netdev;
struct vlan_device *vlan;
* Destroy all VLAN devices for a given trunk
*
* @v trunk Trunk network device
+ * @v priv Private data
*/
-static void vlan_remove ( struct net_device *trunk ) {
+static void vlan_remove ( struct net_device *trunk, void *priv __unused ) {
/* Remove all VLAN devices attached to this trunk, safe
* against arbitrary net device removal.