aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/sfc/efx.c77
-rw-r--r--drivers/net/ethernet/sfc/falcon.c2
-rw-r--r--drivers/net/ethernet/sfc/mcdi.c4
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h10
4 files changed, 93 insertions, 0 deletions
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 5745a9fd034e..d6a927021523 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1117,6 +1117,77 @@ static void efx_remove_port(struct efx_nic *efx)
1117 * 1117 *
1118 **************************************************************************/ 1118 **************************************************************************/
1119 1119
1120static LIST_HEAD(efx_primary_list);
1121static LIST_HEAD(efx_unassociated_list);
1122
1123static bool efx_same_controller(struct efx_nic *left, struct efx_nic *right)
1124{
1125 return left->type == right->type &&
1126 left->vpd_sn && right->vpd_sn &&
1127 !strcmp(left->vpd_sn, right->vpd_sn);
1128}
1129
1130static void efx_associate(struct efx_nic *efx)
1131{
1132 struct efx_nic *other, *next;
1133
1134 if (efx->primary == efx) {
1135 /* Adding primary function; look for secondaries */
1136
1137 netif_dbg(efx, probe, efx->net_dev, "adding to primary list\n");
1138 list_add_tail(&efx->node, &efx_primary_list);
1139
1140 list_for_each_entry_safe(other, next, &efx_unassociated_list,
1141 node) {
1142 if (efx_same_controller(efx, other)) {
1143 list_del(&other->node);
1144 netif_dbg(other, probe, other->net_dev,
1145 "moving to secondary list of %s %s\n",
1146 pci_name(efx->pci_dev),
1147 efx->net_dev->name);
1148 list_add_tail(&other->node,
1149 &efx->secondary_list);
1150 other->primary = efx;
1151 }
1152 }
1153 } else {
1154 /* Adding secondary function; look for primary */
1155
1156 list_for_each_entry(other, &efx_primary_list, node) {
1157 if (efx_same_controller(efx, other)) {
1158 netif_dbg(efx, probe, efx->net_dev,
1159 "adding to secondary list of %s %s\n",
1160 pci_name(other->pci_dev),
1161 other->net_dev->name);
1162 list_add_tail(&efx->node,
1163 &other->secondary_list);
1164 efx->primary = other;
1165 return;
1166 }
1167 }
1168
1169 netif_dbg(efx, probe, efx->net_dev,
1170 "adding to unassociated list\n");
1171 list_add_tail(&efx->node, &efx_unassociated_list);
1172 }
1173}
1174
1175static void efx_dissociate(struct efx_nic *efx)
1176{
1177 struct efx_nic *other, *next;
1178
1179 list_del(&efx->node);
1180 efx->primary = NULL;
1181
1182 list_for_each_entry_safe(other, next, &efx->secondary_list, node) {
1183 list_del(&other->node);
1184 netif_dbg(other, probe, other->net_dev,
1185 "moving to unassociated list\n");
1186 list_add_tail(&other->node, &efx_unassociated_list);
1187 other->primary = NULL;
1188 }
1189}
1190
1120/* This configures the PCI device to enable I/O and DMA. */ 1191/* This configures the PCI device to enable I/O and DMA. */
1121static int efx_init_io(struct efx_nic *efx) 1192static int efx_init_io(struct efx_nic *efx)
1122{ 1193{
@@ -2214,6 +2285,8 @@ static int efx_register_netdev(struct efx_nic *efx)
2214 efx_init_tx_queue_core_txq(tx_queue); 2285 efx_init_tx_queue_core_txq(tx_queue);
2215 } 2286 }
2216 2287
2288 efx_associate(efx);
2289
2217 rtnl_unlock(); 2290 rtnl_unlock();
2218 2291
2219 rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_type); 2292 rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_type);
@@ -2227,6 +2300,7 @@ static int efx_register_netdev(struct efx_nic *efx)
2227 2300
2228fail_registered: 2301fail_registered:
2229 rtnl_lock(); 2302 rtnl_lock();
2303 efx_dissociate(efx);
2230 unregister_netdevice(net_dev); 2304 unregister_netdevice(net_dev);
2231fail_locked: 2305fail_locked:
2232 efx->state = STATE_UNINIT; 2306 efx->state = STATE_UNINIT;
@@ -2568,6 +2642,8 @@ static int efx_init_struct(struct efx_nic *efx,
2568 int i; 2642 int i;
2569 2643
2570 /* Initialise common structures */ 2644 /* Initialise common structures */
2645 INIT_LIST_HEAD(&efx->node);
2646 INIT_LIST_HEAD(&efx->secondary_list);
2571 spin_lock_init(&efx->biu_lock); 2647 spin_lock_init(&efx->biu_lock);
2572#ifdef CONFIG_SFC_MTD 2648#ifdef CONFIG_SFC_MTD
2573 INIT_LIST_HEAD(&efx->mtd_list); 2649 INIT_LIST_HEAD(&efx->mtd_list);
@@ -2674,6 +2750,7 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
2674 2750
2675 /* Mark the NIC as fini, then stop the interface */ 2751 /* Mark the NIC as fini, then stop the interface */
2676 rtnl_lock(); 2752 rtnl_lock();
2753 efx_dissociate(efx);
2677 dev_close(efx->net_dev); 2754 dev_close(efx->net_dev);
2678 efx_disable_interrupts(efx); 2755 efx_disable_interrupts(efx);
2679 rtnl_unlock(); 2756 rtnl_unlock();
diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c
index 4a9e05c82e2a..76699f4e6e04 100644
--- a/drivers/net/ethernet/sfc/falcon.c
+++ b/drivers/net/ethernet/sfc/falcon.c
@@ -2247,6 +2247,8 @@ static int falcon_probe_nic(struct efx_nic *efx)
2247 struct falcon_board *board; 2247 struct falcon_board *board;
2248 int rc; 2248 int rc;
2249 2249
2250 efx->primary = efx; /* only one usable function per controller */
2251
2250 /* Allocate storage for hardware specific data */ 2252 /* Allocate storage for hardware specific data */
2251 nic_data = kzalloc(sizeof(*nic_data), GFP_KERNEL); 2253 nic_data = kzalloc(sizeof(*nic_data), GFP_KERNEL);
2252 if (!nic_data) 2254 if (!nic_data)
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
index 540f57915d6f..0d5d7b5325e8 100644
--- a/drivers/net/ethernet/sfc/mcdi.c
+++ b/drivers/net/ethernet/sfc/mcdi.c
@@ -102,6 +102,10 @@ int efx_mcdi_init(struct efx_nic *efx)
102 netif_err(efx, probe, efx->net_dev, 102 netif_err(efx, probe, efx->net_dev,
103 "Host already registered with MCPU\n"); 103 "Host already registered with MCPU\n");
104 104
105 if (efx->mcdi->fn_flags &
106 (1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_PRIMARY))
107 efx->primary = efx;
108
105 return 0; 109 return 0;
106} 110}
107 111
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index be8a616a1649..653b8782c956 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -657,6 +657,13 @@ struct vfdi_status;
657 * struct efx_nic - an Efx NIC 657 * struct efx_nic - an Efx NIC
658 * @name: Device name (net device name or bus id before net device registered) 658 * @name: Device name (net device name or bus id before net device registered)
659 * @pci_dev: The PCI device 659 * @pci_dev: The PCI device
660 * @node: List node for maintaning primary/secondary function lists
661 * @primary: &struct efx_nic instance for the primary function of this
662 * controller. May be the same structure, and may be %NULL if no
663 * primary function is bound. Serialised by rtnl_lock.
664 * @secondary_list: List of &struct efx_nic instances for the secondary PCI
665 * functions of the controller, if this is for the primary function.
666 * Serialised by rtnl_lock.
660 * @type: Controller type attributes 667 * @type: Controller type attributes
661 * @legacy_irq: IRQ number 668 * @legacy_irq: IRQ number
662 * @workqueue: Workqueue for port reconfigures and the HW monitor. 669 * @workqueue: Workqueue for port reconfigures and the HW monitor.
@@ -786,6 +793,9 @@ struct efx_nic {
786 /* The following fields should be written very rarely */ 793 /* The following fields should be written very rarely */
787 794
788 char name[IFNAMSIZ]; 795 char name[IFNAMSIZ];
796 struct list_head node;
797 struct efx_nic *primary;
798 struct list_head secondary_list;
789 struct pci_dev *pci_dev; 799 struct pci_dev *pci_dev;
790 unsigned int port_num; 800 unsigned int port_num;
791 const struct efx_nic_type *type; 801 const struct efx_nic_type *type;