aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2013-10-18 14:21:45 -0400
committerBen Hutchings <bhutchings@solarflare.com>2013-12-12 17:07:15 -0500
commit0bcf4a645fc027d05d15e79ce48b5893cff28082 (patch)
tree48f54ac160df82b66b4d0776a8247d1f8c21c8b1 /drivers/net/ethernet
parentef215e64760ef6bd756c2999e7c8cee95b98e30a (diff)
sfc: Associate primary and secondary functions of controller
The primary function of an EF10 controller will share its clock device with other functions in the same domain (which we call secondary functions). To this end, we need to associate functions on the same controller. We do not control probe order, so allow primary and secondary functions to appear in any order. Maintain global lists of all primary functions and of unassociated secondary functions, and a list of secondary functions on each primary function. Use the VPD serial number to tell whether functions are part of the same controller. VPD will not be readable by virtual functions, so this may need to be revisited later. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Diffstat (limited to 'drivers/net/ethernet')
-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;