diff options
| -rw-r--r-- | drivers/net/ethernet/sfc/efx.c | 77 | ||||
| -rw-r--r-- | drivers/net/ethernet/sfc/falcon.c | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/sfc/mcdi.c | 4 | ||||
| -rw-r--r-- | drivers/net/ethernet/sfc/net_driver.h | 10 |
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 | ||
| 1120 | static LIST_HEAD(efx_primary_list); | ||
| 1121 | static LIST_HEAD(efx_unassociated_list); | ||
| 1122 | |||
| 1123 | static 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 | |||
| 1130 | static 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 | |||
| 1175 | static 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. */ |
| 1121 | static int efx_init_io(struct efx_nic *efx) | 1192 | static 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 | ||
| 2228 | fail_registered: | 2301 | fail_registered: |
| 2229 | rtnl_lock(); | 2302 | rtnl_lock(); |
| 2303 | efx_dissociate(efx); | ||
| 2230 | unregister_netdevice(net_dev); | 2304 | unregister_netdevice(net_dev); |
| 2231 | fail_locked: | 2305 | fail_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; |
