aboutsummaryrefslogtreecommitdiffstats
path: root/src/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers/net')
-rw-r--r--src/drivers/net/ecm.c5
-rw-r--r--src/drivers/net/netfront.c50
-rw-r--r--src/drivers/net/netfront.h5
3 files changed, 57 insertions, 3 deletions
diff --git a/src/drivers/net/ecm.c b/src/drivers/net/ecm.c
index 68ac962ab..ab1f98370 100644
--- a/src/drivers/net/ecm.c
+++ b/src/drivers/net/ecm.c
@@ -121,10 +121,9 @@ int ecm_fetch_mac ( struct usb_function *func,
}
/* Apply system-specific MAC address as current link-layer
- * address, if present and not already used.
+ * address, if present.
*/
- if ( ( ( rc = acpi_mac ( amac ) ) == 0 ) &&
- ! find_netdev_by_ll_addr ( &ethernet_protocol, amac ) ) {
+ if ( ( rc = acpi_mac ( amac ) ) == 0 ) {
memcpy ( netdev->ll_addr, amac, ETH_ALEN );
DBGC ( usb, "USB %s using system-specific MAC %s\n",
func->name, eth_ntoa ( netdev->ll_addr ) );
diff --git a/src/drivers/net/netfront.c b/src/drivers/net/netfront.c
index 1203e585c..7ddc7cdb9 100644
--- a/src/drivers/net/netfront.c
+++ b/src/drivers/net/netfront.c
@@ -59,6 +59,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
EUNIQ ( EINFO_EIO, ( -(status) & 0x1f ), \
EIO_NETIF_RSP_ERROR, EIO_NETIF_RSP_DROPPED )
+/** List of netfront devices */
+static LIST_HEAD ( netfront_devices );
+
/******************************************************************************
*
* XenStore interface
@@ -952,6 +955,7 @@ static int netfront_probe ( struct xen_device *xendev ) {
netdev->dev = &xendev->dev;
netfront = netdev->priv;
netfront->xendev = xendev;
+ netfront->netdev = netdev;
INIT_LIST_HEAD ( &netfront->rx_partial );
DBGC ( netfront, "NETFRONT %s backend=\"%s\" in domain %ld\n",
xendev->key, xendev->backend, xendev->backend_id );
@@ -991,9 +995,13 @@ static int netfront_probe ( struct xen_device *xendev ) {
/* Set initial link state */
netdev_link_down ( netdev );
+ /* Add to list of netfront devices */
+ list_add_tail ( &netfront->list, &netfront_devices );
+
xen_set_drvdata ( xendev, netdev );
return 0;
+ list_del ( &netfront->list );
unregister_netdev ( netdev );
err_register_netdev:
err_read_mac:
@@ -1015,6 +1023,9 @@ static void netfront_remove ( struct xen_device *xendev ) {
struct netfront_nic *netfront = netdev->priv;
struct xen_hypervisor *xen = xendev->xen;
+ /* Remove from list of netfront devices */
+ list_del ( &netfront->list );
+
/* Unregister network device */
unregister_netdev ( netdev );
@@ -1033,3 +1044,42 @@ struct xen_driver netfront_driver __xen_driver = {
.probe = netfront_probe,
.remove = netfront_remove,
};
+
+/******************************************************************************
+ *
+ * Emulated PCI device inhibitor
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Inhibit emulated PCI devices
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int netfront_net_probe ( struct net_device *netdev ) {
+ struct netfront_nic *netfront;
+
+ /* Inhibit emulated PCI devices matching an existing netfront device */
+ list_for_each_entry ( netfront, &netfront_devices, list ) {
+ if ( ( netdev->dev != netfront->netdev->dev ) &&
+ ( netdev->ll_protocol->ll_addr_len == ETH_ALEN ) &&
+ ( memcmp ( netdev->hw_addr, netfront->netdev->hw_addr,
+ ETH_ALEN ) == 0 ) ) {
+ DBGC ( netfront, "NETFRONT %s inhibiting emulated %s "
+ "%s (%s)\n", netfront->xendev->key,
+ netdev->dev->driver_name, netdev->name,
+ eth_ntoa ( netdev->hw_addr ) );
+ return -EEXIST;
+ }
+ }
+
+ return 0;
+}
+
+/** Emulated PCI device inhibitor driver */
+struct net_driver netfront_net_driver __net_driver = {
+ .name = "netfront",
+ .probe = netfront_net_probe,
+};
diff --git a/src/drivers/net/netfront.h b/src/drivers/net/netfront.h
index dca3ff1c5..de16d5291 100644
--- a/src/drivers/net/netfront.h
+++ b/src/drivers/net/netfront.h
@@ -159,6 +159,11 @@ struct netfront_nic {
/** Grant references */
grant_ref_t refs[NETFRONT_REF_COUNT];
+ /** Network device */
+ struct net_device *netdev;
+ /** List of netfront NICs */
+ struct list_head list;
+
/** Transmit ring */
struct netfront_ring tx;
/** Transmit front ring */