Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/driver/linux_net/drivers/net/ethernet/sfc/net_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -1291,13 +1291,15 @@ struct efx_arfs_rule {
/**
* struct efx_async_filter_insertion - Request to asynchronously insert a filter
* @net_dev: Reference to the netdevice
* @net_dev_tracker: reference tracker entry for @net_dev
* @spec: The filter to insert
* @work: Workitem for this request
* @rxq_index: Identifies the channel for which this request was made
* @flow_id: Identifies the kernel-side flow for which this request was made
*/
struct efx_async_filter_insertion {
struct net_device *net_dev;
netdevice_tracker net_dev_tracker;
struct efx_filter_spec spec;
struct work_struct work;
u16 rxq_index;
Expand Down
6 changes: 3 additions & 3 deletions src/driver/linux_net/drivers/net/ethernet/sfc/rx_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -1845,7 +1845,7 @@ static void efx_filter_rfs_work(struct work_struct *data)

/* Release references */
clear_bit(slot_idx, &efx->rps_slot_map);
dev_put(req->net_dev);
netdev_put(req->net_dev, &req->net_dev_tracker);

return;
}
Expand Down Expand Up @@ -1908,7 +1908,8 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
}

/* Queue the request */
dev_hold(req->net_dev = net_dev);
req->net_dev = net_dev;
netdev_hold(req->net_dev, &req->net_dev_tracker, GFP_ATOMIC);
INIT_WORK(&req->work, efx_filter_rfs_work);
req->rxq_index = rxq_index;
req->flow_id = flow_id;
Expand Down Expand Up @@ -1965,4 +1966,3 @@ bool __efx_filter_rfs_expire(struct efx_channel *channel, unsigned int quota)
}

#endif /* CONFIG_RFS_ACCEL */

Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,8 @@ static int efx_bind_neigh(struct efx_nic *efx,
EFX_TC_ERR_MSG(efx, extack, "Failed to lookup route for encap");
goto out_free;
}
dev_hold(neigh->egdev = dst->dev);
netdev_hold(neigh->egdev = dst->dev, &neigh->dev_tracker,
GFP_KERNEL_ACCOUNT);
neigh->ttl = ip6_dst_hoplimit(dst);
n = dst_neigh_lookup(dst, &flow6.daddr);
dst_release(dst);
Expand All @@ -223,7 +224,8 @@ static int efx_bind_neigh(struct efx_nic *efx,
EFX_TC_ERR_MSG(efx, extack, "Failed to lookup route for encap");
goto out_free;
}
dev_hold(neigh->egdev = rt->dst.dev);
netdev_hold(neigh->egdev = rt->dst.dev, &neigh->dev_tracker,
GFP_KERNEL_ACCOUNT);
neigh->ttl = ip4_dst_hoplimit(&rt->dst);
n = dst_neigh_lookup(&rt->dst, &flow4.daddr);
ip_rt_put(rt);
Expand All @@ -233,7 +235,7 @@ static int efx_bind_neigh(struct efx_nic *efx,
if (!n) {
rc = -ENETUNREACH;
EFX_TC_ERR_MSG(efx, extack, "Failed to lookup neighbour for encap");
dev_put(neigh->egdev);
netdev_put(neigh->egdev, &neigh->dev_tracker);
goto out_free;
}
refcount_set(&neigh->ref, 1);
Expand Down Expand Up @@ -273,7 +275,7 @@ static void efx_free_neigh(struct efx_neigh_binder *neigh)
rhashtable_remove_fast(&efx->tc->neigh_ht, &neigh->linkage,
efx_neigh_ht_params);
synchronize_rcu();
dev_put(neigh->egdev);
netdev_put(neigh->egdev, &neigh->dev_tracker);
put_net(neigh->net);
kfree(neigh);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
* @ttl: Time To Live associated with the route used
* @dying: set when egdev is going away, to skip further updates
* @egdev: egress device from the route lookup. Holds a reference
* @dev_tracker: reference tracker entry for @egdev
* @ref: counts encap actions referencing this entry
* @used: jiffies of last time traffic hit any encap action using this.
* When counter reads update this, a new neighbour event is sent to
Expand Down Expand Up @@ -53,6 +54,7 @@ struct efx_neigh_binder {
u8 ttl;
bool dying;
struct net_device *egdev;
netdevice_tracker dev_tracker;
refcount_t ref;
unsigned long used;
struct list_head users;
Expand Down
3 changes: 3 additions & 0 deletions src/driver/linux_resource/kernel_compat.sh
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ EFRM_HAVE_FOLLOW_PTE_VMA symtype follow_pte include/linux/mm.h int(struct vm_are

EFRM_HAVE_LINUX_TPH_H file include/linux/pci-tph.h

EFX_NEED_NETDEV_HOLD nsymbol netdev_hold include/linux/netdevice.h
EFX_HAVE_DEV_HOLD_TRACK symbol dev_hold_track include/linux/netdevice.h

# TODO move onload-related stuff from net kernel_compat
" | grep -E -v -e '^#' -e '^$' | sed 's/[ \t][ \t]*/:/g'
}
Expand Down
9 changes: 7 additions & 2 deletions src/driver/linux_resource/nondl_resource.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <ci/efrm/efrm_client.h>
#include <ci/efrm/nondl.h>
#include <linux/rtnetlink.h>
#include <linux/netdevice.h>

/* Maximum number of VIs we will try to create for each device. */
#define MAX_VIS 128
Expand Down Expand Up @@ -94,6 +95,9 @@ void efrm_nondl_unregister_driver(struct efrm_nondl_driver *driver)

rtnl_lock();

if (!nondl_driver)
goto out;

EFRM_ASSERT(nondl_driver == driver);

list_for_each_entry_safe_reverse(device, device_n, &driver->devices,
Expand All @@ -104,6 +108,7 @@ void efrm_nondl_unregister_driver(struct efrm_nondl_driver *driver)

nondl_driver = NULL;

out:
rtnl_unlock();
}
EXPORT_SYMBOL(efrm_nondl_unregister_driver);
Expand Down Expand Up @@ -132,7 +137,7 @@ int efrm_nondl_register_netdev(struct net_device *netdev,

INIT_LIST_HEAD(&device->node);

dev_hold(netdev);
netdev_hold(netdev, &device->netdev_tracker, GFP_KERNEL);
device->netdev = netdev;
device->n_vis = n_vis;
device->is_up = 1;
Expand All @@ -153,7 +158,7 @@ static void efrm_nondl_cleanup_netdev(struct efrm_nondl_device *device)
BUG_ON(device->driver);

list_del(&device->node);
dev_put(device->netdev);
netdev_put(device->netdev, &device->netdev_tracker);

kfree(device);
}
Expand Down
28 changes: 24 additions & 4 deletions src/driver/linux_resource/resource_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
#include "sfcaffinity.h"
#include <ci/driver/resource/linux_efhw_nic.h>
#include <ci/driver/resource/driverlink.h>
#include <linux/reboot.h>
#include "debugfs.h"

MODULE_AUTHOR("Solarflare Communications");
Expand Down Expand Up @@ -206,7 +207,7 @@ linux_efrm_nic_ctor(struct linux_efhw_nic *lnic, struct device *dev,
/* Tie the lifetime of the kernel's state to that of our own. */
if( dev )
get_device(dev);
dev_hold(net_dev);
netdev_hold(net_dev, &nic->net_dev_tracker, GFP_KERNEL);

rc = efhw_nic_ctor(nic, res_dim, dev_type, net_dev, dev);
if (rc < 0)
Expand Down Expand Up @@ -236,7 +237,7 @@ linux_efrm_nic_ctor(struct linux_efhw_nic *lnic, struct device *dev,
fail1:
if( dev )
put_device(dev);
dev_put(net_dev);
netdev_put(net_dev, &nic->net_dev_tracker);
return rc;
}

Expand All @@ -259,7 +260,7 @@ linux_efrm_nic_reclaim(struct linux_efhw_nic *lnic,

/* Replace the net & pci devs */
get_device(dev);
dev_hold(net_dev);
netdev_hold(net_dev, &nic->net_dev_tracker, GFP_KERNEL);
spin_lock_bh(&nic->pci_dev_lock);
old_dev = nic->dev;
nic->dev = dev;
Expand Down Expand Up @@ -506,7 +507,7 @@ efrm_nic_do_unplug(struct efhw_nic* nic, bool hard)
spin_unlock_bh(&nic->pci_dev_lock);

EFRM_ASSERT(net_dev != NULL);
dev_put(net_dev);
netdev_put(net_dev, &nic->net_dev_tracker);
put_device(dev);

return 0;
Expand Down Expand Up @@ -631,6 +632,21 @@ static void efrm_nic_del_all(void)
efrm_nic_del(linux_efhw_nic(nic));
}

static int sfc_resource_shutdown_notify(struct notifier_block *unused1,
unsigned long unused2, void *unused3)
{
/* Due to refcounting reasons in netdev, these must
* be called for the shutdown to happen without delays
*/
efrm_nondl_unregister();
efrm_nondl_shutdown();

return NOTIFY_DONE;
}

static struct notifier_block sfc_resource_shutdown_nb = {
.notifier_call = sfc_resource_shutdown_notify,
};

/****************************************************************************
*
Expand Down Expand Up @@ -683,6 +699,8 @@ static int init_sfc_resource(void)
efrm_install_sysfs_entries();
efrm_nondl_register();

register_reboot_notifier(&sfc_resource_shutdown_nb);

return 0;

failed_notifier:
Expand All @@ -705,6 +723,8 @@ static int init_sfc_resource(void)
****************************************************************************/
static void cleanup_sfc_resource(void)
{
unregister_reboot_notifier(&sfc_resource_shutdown_nb);

efrm_nondl_unregister();
efrm_remove_sysfs_entries();
efrm_nondl_shutdown();
Expand Down
26 changes: 26 additions & 0 deletions src/include/ci/driver/kernel_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -546,4 +546,30 @@ static inline int efrm_follow_pfn(struct vm_area_struct *vma,
}
#endif

#ifdef EFX_NEED_NETDEV_HOLD
#ifdef EFX_HAVE_DEV_HOLD_TRACK
/* Commit d62607c3fe45 ("net: rename reference+tracking helpers")
* renamed these.
*/
#define netdev_hold(_n, _t, _g) dev_hold_track(_n, _t, _g)
#define netdev_put(_n, _t) dev_put_track(_n, _t)
#else
/* This was introduced in the same commit that adds dev_hold_track */
typedef struct {} netdevice_tracker;

static inline void netdev_hold(struct net_device *dev,
netdevice_tracker *tracker __always_unused,
gfp_t gfp __always_unused)
{
dev_hold(dev);
}

static inline void netdev_put(struct net_device *dev,
netdevice_tracker *tracker __always_unused)
{
dev_put(dev);
}
#endif
#endif

#endif /* DRIVER_LINUX_RESOURCE_KERNEL_COMPAT_H */
2 changes: 2 additions & 0 deletions src/include/ci/efhw/efhw_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#ifndef __CI_EFHW_EFAB_TYPES_H__
#define __CI_EFHW_EFAB_TYPES_H__

#include <ci/driver/kernel_compat.h>
#include <ci/efhw/efhw_config.h>
#include <ci/efhw/hardware_sysdep.h>
#include <ci/efhw/iopage_types.h>
Expand Down Expand Up @@ -569,6 +570,7 @@ struct efhw_nic {
int index;

struct net_device *net_dev; /*!< Network device */
netdevice_tracker net_dev_tracker;
struct device *dev; /*!< HW device */
struct pci_dev *pci_dev; /*!< PCI device */
spinlock_t pci_dev_lock; /*!< Protects access to dev & net_dev */
Expand Down
2 changes: 2 additions & 0 deletions src/include/ci/efrm/nondl.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#define __EFRM_NONDL_H__

#include <linux/types.h>
#include <ci/driver/kernel_compat.h>


/* Non-driverlink network device.
Expand Down Expand Up @@ -43,6 +44,7 @@ struct efrm_nondl_device {
/* Network device currently associated with this non-driverlink
* device. */
struct net_device *netdev;
netdevice_tracker netdev_tracker;

/* Number of VIs we would like to create on this device. */
unsigned int n_vis;
Expand Down