*
  **************************************************************************/
 
+static LIST_HEAD(efx_primary_list);
+static LIST_HEAD(efx_unassociated_list);
+
+static bool efx_same_controller(struct efx_nic *left, struct efx_nic *right)
+{
+       return left->type == right->type &&
+               left->vpd_sn && right->vpd_sn &&
+               !strcmp(left->vpd_sn, right->vpd_sn);
+}
+
+static void efx_associate(struct efx_nic *efx)
+{
+       struct efx_nic *other, *next;
+
+       if (efx->primary == efx) {
+               /* Adding primary function; look for secondaries */
+
+               netif_dbg(efx, probe, efx->net_dev, "adding to primary list\n");
+               list_add_tail(&efx->node, &efx_primary_list);
+
+               list_for_each_entry_safe(other, next, &efx_unassociated_list,
+                                        node) {
+                       if (efx_same_controller(efx, other)) {
+                               list_del(&other->node);
+                               netif_dbg(other, probe, other->net_dev,
+                                         "moving to secondary list of %s %s\n",
+                                         pci_name(efx->pci_dev),
+                                         efx->net_dev->name);
+                               list_add_tail(&other->node,
+                                             &efx->secondary_list);
+                               other->primary = efx;
+                       }
+               }
+       } else {
+               /* Adding secondary function; look for primary */
+
+               list_for_each_entry(other, &efx_primary_list, node) {
+                       if (efx_same_controller(efx, other)) {
+                               netif_dbg(efx, probe, efx->net_dev,
+                                         "adding to secondary list of %s %s\n",
+                                         pci_name(other->pci_dev),
+                                         other->net_dev->name);
+                               list_add_tail(&efx->node,
+                                             &other->secondary_list);
+                               efx->primary = other;
+                               return;
+                       }
+               }
+
+               netif_dbg(efx, probe, efx->net_dev,
+                         "adding to unassociated list\n");
+               list_add_tail(&efx->node, &efx_unassociated_list);
+       }
+}
+
+static void efx_dissociate(struct efx_nic *efx)
+{
+       struct efx_nic *other, *next;
+
+       list_del(&efx->node);
+       efx->primary = NULL;
+
+       list_for_each_entry_safe(other, next, &efx->secondary_list, node) {
+               list_del(&other->node);
+               netif_dbg(other, probe, other->net_dev,
+                         "moving to unassociated list\n");
+               list_add_tail(&other->node, &efx_unassociated_list);
+               other->primary = NULL;
+       }
+}
+
 /* This configures the PCI device to enable I/O and DMA. */
 static int efx_init_io(struct efx_nic *efx)
 {
                        efx_init_tx_queue_core_txq(tx_queue);
        }
 
+       efx_associate(efx);
+
        rtnl_unlock();
 
        rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_type);
 
 fail_registered:
        rtnl_lock();
+       efx_dissociate(efx);
        unregister_netdevice(net_dev);
 fail_locked:
        efx->state = STATE_UNINIT;
        int i;
 
        /* Initialise common structures */
+       INIT_LIST_HEAD(&efx->node);
+       INIT_LIST_HEAD(&efx->secondary_list);
        spin_lock_init(&efx->biu_lock);
 #ifdef CONFIG_SFC_MTD
        INIT_LIST_HEAD(&efx->mtd_list);
 
        /* Mark the NIC as fini, then stop the interface */
        rtnl_lock();
+       efx_dissociate(efx);
        dev_close(efx->net_dev);
        efx_disable_interrupts(efx);
        rtnl_unlock();
 
  * struct efx_nic - an Efx NIC
  * @name: Device name (net device name or bus id before net device registered)
  * @pci_dev: The PCI device
+ * @node: List node for maintaning primary/secondary function lists
+ * @primary: &struct efx_nic instance for the primary function of this
+ *     controller.  May be the same structure, and may be %NULL if no
+ *     primary function is bound.  Serialised by rtnl_lock.
+ * @secondary_list: List of &struct efx_nic instances for the secondary PCI
+ *     functions of the controller, if this is for the primary function.
+ *     Serialised by rtnl_lock.
  * @type: Controller type attributes
  * @legacy_irq: IRQ number
  * @workqueue: Workqueue for port reconfigures and the HW monitor.
        /* The following fields should be written very rarely */
 
        char name[IFNAMSIZ];
+       struct list_head node;
+       struct efx_nic *primary;
+       struct list_head secondary_list;
        struct pci_dev *pci_dev;
        unsigned int port_num;
        const struct efx_nic_type *type;