diff --git a/drivers/net/ethernet/sfc/ef100.c b/drivers/net/ethernet/sfc/ef100.c index 96b99966ce25e84cbc52dc4748bb9ca08852729a..a77100239e7c280d30e5fb3337b81c52e3a981b7 100644 --- a/drivers/net/ethernet/sfc/ef100.c +++ b/drivers/net/ethernet/sfc/ef100.c @@ -423,6 +423,7 @@ static int ef100_pci_find_func_ctrl_window(struct efx_nic *efx, */ static void ef100_pci_remove(struct pci_dev *pci_dev) { + struct efx_probe_data *probe_data; struct efx_nic *efx; efx = pci_get_drvdata(pci_dev); @@ -448,6 +449,8 @@ static void ef100_pci_remove(struct pci_dev *pci_dev) pci_set_drvdata(pci_dev, NULL); efx_fini_struct(efx); free_netdev(efx->net_dev); + probe_data = container_of(efx, struct efx_probe_data, efx); + kfree(probe_data); pci_disable_pcie_error_reporting(pci_dev); }; @@ -455,16 +458,25 @@ static void ef100_pci_remove(struct pci_dev *pci_dev) static int ef100_pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *entry) { + struct efx_probe_data *probe_data, **probe_ptr; struct ef100_func_ctl_window fcw = { 0 }; struct net_device *net_dev; struct efx_nic *efx; int rc; - /* Allocate and initialise a struct net_device and struct efx_nic */ - net_dev = alloc_etherdev_mq(sizeof(*efx), EFX_MAX_CORE_TX_QUEUES); + /* Allocate probe data and struct efx_nic */ + probe_data = kzalloc(sizeof(*probe_data), GFP_KERNEL); + if (!probe_data) + return -ENOMEM; + probe_data->pci_dev = pci_dev; + efx = &probe_data->efx; + + /* Allocate and initialise a struct net_device */ + net_dev = alloc_etherdev_mq(sizeof(probe_data), EFX_MAX_CORE_TX_QUEUES); if (!net_dev) return -ENOMEM; - efx = efx_netdev_priv(net_dev); + probe_ptr = netdev_priv(net_dev); + *probe_ptr = probe_data; efx->type = (const struct efx_nic_type *)entry->driver_data; pci_set_drvdata(pci_dev, efx); diff --git a/drivers/net/ethernet/sfc/ef100_netdev.c b/drivers/net/ethernet/sfc/ef100_netdev.c index e833eaaf61b6318b6c17678af247b23d79f58d34..7a80979f4ab799658809dd05c19331bc7fa6c42b 100644 --- a/drivers/net/ethernet/sfc/ef100_netdev.c +++ b/drivers/net/ethernet/sfc/ef100_netdev.c @@ -243,7 +243,7 @@ int ef100_netdev_event(struct notifier_block *this, struct efx_nic *efx = container_of(this, struct efx_nic, netdev_notifier); struct net_device *net_dev = netdev_notifier_info_to_dev(ptr); - if (efx_netdev_priv(net_dev) == efx && event == NETDEV_CHANGENAME) + if (efx->net_dev == net_dev && event == NETDEV_CHANGENAME) ef100_update_name(efx); return NOTIFY_DONE; diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index f874835e1764c94648e3779670b2c1d7ff40d48c..c88e9de9dcd03096e17e6d49d7bad8af4f7d1f03 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -861,6 +861,7 @@ static void efx_pci_remove_main(struct efx_nic *efx) */ static void efx_pci_remove(struct pci_dev *pci_dev) { + struct efx_probe_data *probe_data; struct efx_nic *efx; efx = pci_get_drvdata(pci_dev); @@ -889,6 +890,8 @@ static void efx_pci_remove(struct pci_dev *pci_dev) efx_fini_struct(efx); free_netdev(efx->net_dev); + probe_data = container_of(efx, struct efx_probe_data, efx); + kfree(probe_data); pci_disable_pcie_error_reporting(pci_dev); }; @@ -1042,16 +1045,25 @@ static int efx_pci_probe_post_io(struct efx_nic *efx) static int efx_pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *entry) { + struct efx_probe_data *probe_data, **probe_ptr; struct net_device *net_dev; struct efx_nic *efx; int rc; - /* Allocate and initialise a struct net_device and struct efx_nic */ - net_dev = alloc_etherdev_mqs(sizeof(*efx), EFX_MAX_CORE_TX_QUEUES, - EFX_MAX_RX_QUEUES); + /* Allocate probe data and struct efx_nic */ + probe_data = kzalloc(sizeof(*probe_data), GFP_KERNEL); + if (!probe_data) + return -ENOMEM; + probe_data->pci_dev = pci_dev; + efx = &probe_data->efx; + + /* Allocate and initialise a struct net_device */ + net_dev = alloc_etherdev_mq(sizeof(probe_data), EFX_MAX_CORE_TX_QUEUES); if (!net_dev) return -ENOMEM; - efx = efx_netdev_priv(net_dev); + probe_ptr = netdev_priv(net_dev); + *probe_ptr = probe_data; + efx->net_dev = net_dev; efx->type = (const struct efx_nic_type *) entry->driver_data; efx->fixed_features |= NETIF_F_HIGHDMA; diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index df93ffd7092a397871ea83f8d1f0c926480a0d6e..2228c88a7f3146e4b4276f1d8acc68a877a49662 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -1166,9 +1166,22 @@ struct efx_nic { atomic_t n_rx_noskb_drops; }; +/** + * struct efx_probe_data - State after hardware probe + * @pci_dev: The PCI device + * @efx: Efx NIC details + */ +struct efx_probe_data { + struct pci_dev *pci_dev; + struct efx_nic efx; +}; + static inline struct efx_nic *efx_netdev_priv(struct net_device *dev) { - return netdev_priv(dev); + struct efx_probe_data **probe_ptr = netdev_priv(dev); + struct efx_probe_data *probe_data = *probe_ptr; + + return &probe_data->efx; } static inline int efx_dev_registered(struct efx_nic *efx)