Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 81e696b5 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'nfp-flower-tc-block-support-and-nfp-PCI-updates'



Jakub Kicinski says:

====================
nfp: flower tc block support and nfp PCI updates

This series improves the nfp PCIe code by making use of the new
pcie_print_link_status() helper and resetting NFP locks when
driver loads.  This can help us avoid lock ups after host crashes
and is rebooted with PCIe reset or when kdump kernel is loaded.

The flower changes come from John, he says:

This patchset fixes offload issues when multiple repr netdevs are bound to
a tc block and filter rules added. Previously the rule would be passed to
the reprs and would be rejected in all but the first as the cookie value
will indicate a duplicate. The first patch extends the flow lookup
function to consider both host context and ingress netdev along with the
cookie value. This means that a rule with a given cookie can exist
multiple times assuming the ingress netdev is different. The host context
ensures that stats from fw are associated with the correct instance of the
rule.

The second patch protects against rejecting add/del/stat messages when a
rule has a repr as both an ingress port and an egress dev. In such cases a
callback can be triggered twice (once for ingress and once for egress)
and can lead to duplicate rule detection or incorrect double calls.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c77bbc64 c50647d3
Loading
Loading
Loading
Loading
+7 −2
Original line number Original line Diff line number Diff line
@@ -47,6 +47,7 @@
struct net_device;
struct net_device;
struct nfp_app;
struct nfp_app;


#define NFP_FL_STATS_CTX_DONT_CARE	cpu_to_be32(0xffffffff)
#define NFP_FL_STATS_ENTRY_RS		BIT(20)
#define NFP_FL_STATS_ENTRY_RS		BIT(20)
#define NFP_FL_STATS_ELEM_RS		4
#define NFP_FL_STATS_ELEM_RS		4
#define NFP_FL_REPEATED_HASH_MAX	BIT(17)
#define NFP_FL_REPEATED_HASH_MAX	BIT(17)
@@ -189,9 +190,11 @@ struct nfp_fl_payload {
	spinlock_t lock; /* lock stats */
	spinlock_t lock; /* lock stats */
	struct nfp_fl_stats stats;
	struct nfp_fl_stats stats;
	__be32 nfp_tun_ipv4_addr;
	__be32 nfp_tun_ipv4_addr;
	struct net_device *ingress_dev;
	char *unmasked_data;
	char *unmasked_data;
	char *mask_data;
	char *mask_data;
	char *action_data;
	char *action_data;
	bool ingress_offload;
};
};


struct nfp_fl_stats_frame {
struct nfp_fl_stats_frame {
@@ -216,12 +219,14 @@ int nfp_flower_compile_action(struct tc_cls_flower_offload *flow,
			      struct nfp_fl_payload *nfp_flow);
			      struct nfp_fl_payload *nfp_flow);
int nfp_compile_flow_metadata(struct nfp_app *app,
int nfp_compile_flow_metadata(struct nfp_app *app,
			      struct tc_cls_flower_offload *flow,
			      struct tc_cls_flower_offload *flow,
			      struct nfp_fl_payload *nfp_flow);
			      struct nfp_fl_payload *nfp_flow,
			      struct net_device *netdev);
int nfp_modify_flow_metadata(struct nfp_app *app,
int nfp_modify_flow_metadata(struct nfp_app *app,
			     struct nfp_fl_payload *nfp_flow);
			     struct nfp_fl_payload *nfp_flow);


struct nfp_fl_payload *
struct nfp_fl_payload *
nfp_flower_search_fl_table(struct nfp_app *app, unsigned long tc_flower_cookie);
nfp_flower_search_fl_table(struct nfp_app *app, unsigned long tc_flower_cookie,
			   struct net_device *netdev, __be32 host_ctx);
struct nfp_fl_payload *
struct nfp_fl_payload *
nfp_flower_remove_fl_table(struct nfp_app *app, unsigned long tc_flower_cookie);
nfp_flower_remove_fl_table(struct nfp_app *app, unsigned long tc_flower_cookie);


+12 −8
Original line number Original line Diff line number Diff line
@@ -99,14 +99,18 @@ static int nfp_get_stats_entry(struct nfp_app *app, u32 *stats_context_id)


/* Must be called with either RTNL or rcu_read_lock */
/* Must be called with either RTNL or rcu_read_lock */
struct nfp_fl_payload *
struct nfp_fl_payload *
nfp_flower_search_fl_table(struct nfp_app *app, unsigned long tc_flower_cookie)
nfp_flower_search_fl_table(struct nfp_app *app, unsigned long tc_flower_cookie,
			   struct net_device *netdev, __be32 host_ctx)
{
{
	struct nfp_flower_priv *priv = app->priv;
	struct nfp_flower_priv *priv = app->priv;
	struct nfp_fl_payload *flower_entry;
	struct nfp_fl_payload *flower_entry;


	hash_for_each_possible_rcu(priv->flow_table, flower_entry, link,
	hash_for_each_possible_rcu(priv->flow_table, flower_entry, link,
				   tc_flower_cookie)
				   tc_flower_cookie)
		if (flower_entry->tc_flower_cookie == tc_flower_cookie)
		if (flower_entry->tc_flower_cookie == tc_flower_cookie &&
		    (!netdev || flower_entry->ingress_dev == netdev) &&
		    (host_ctx == NFP_FL_STATS_CTX_DONT_CARE ||
		     flower_entry->meta.host_ctx_id == host_ctx))
			return flower_entry;
			return flower_entry;


	return NULL;
	return NULL;
@@ -121,13 +125,11 @@ nfp_flower_update_stats(struct nfp_app *app, struct nfp_fl_stats_frame *stats)
	flower_cookie = be64_to_cpu(stats->stats_cookie);
	flower_cookie = be64_to_cpu(stats->stats_cookie);


	rcu_read_lock();
	rcu_read_lock();
	nfp_flow = nfp_flower_search_fl_table(app, flower_cookie);
	nfp_flow = nfp_flower_search_fl_table(app, flower_cookie, NULL,
					      stats->stats_con_id);
	if (!nfp_flow)
	if (!nfp_flow)
		goto exit_rcu_unlock;
		goto exit_rcu_unlock;


	if (nfp_flow->meta.host_ctx_id != stats->stats_con_id)
		goto exit_rcu_unlock;

	spin_lock(&nfp_flow->lock);
	spin_lock(&nfp_flow->lock);
	nfp_flow->stats.pkts += be32_to_cpu(stats->pkt_count);
	nfp_flow->stats.pkts += be32_to_cpu(stats->pkt_count);
	nfp_flow->stats.bytes += be64_to_cpu(stats->byte_count);
	nfp_flow->stats.bytes += be64_to_cpu(stats->byte_count);
@@ -317,7 +319,8 @@ nfp_check_mask_remove(struct nfp_app *app, char *mask_data, u32 mask_len,


int nfp_compile_flow_metadata(struct nfp_app *app,
int nfp_compile_flow_metadata(struct nfp_app *app,
			      struct tc_cls_flower_offload *flow,
			      struct tc_cls_flower_offload *flow,
			      struct nfp_fl_payload *nfp_flow)
			      struct nfp_fl_payload *nfp_flow,
			      struct net_device *netdev)
{
{
	struct nfp_flower_priv *priv = app->priv;
	struct nfp_flower_priv *priv = app->priv;
	struct nfp_fl_payload *check_entry;
	struct nfp_fl_payload *check_entry;
@@ -348,7 +351,8 @@ int nfp_compile_flow_metadata(struct nfp_app *app,
	nfp_flow->stats.bytes = 0;
	nfp_flow->stats.bytes = 0;
	nfp_flow->stats.used = jiffies;
	nfp_flow->stats.used = jiffies;


	check_entry = nfp_flower_search_fl_table(app, flow->cookie);
	check_entry = nfp_flower_search_fl_table(app, flow->cookie, netdev,
						 NFP_FL_STATS_CTX_DONT_CARE);
	if (check_entry) {
	if (check_entry) {
		if (nfp_release_stats_entry(app, stats_cxt))
		if (nfp_release_stats_entry(app, stats_cxt))
			return -EINVAL;
			return -EINVAL;
+40 −10
Original line number Original line Diff line number Diff line
@@ -345,7 +345,7 @@ nfp_flower_calculate_key_layers(struct nfp_app *app,
}
}


static struct nfp_fl_payload *
static struct nfp_fl_payload *
nfp_flower_allocate_new(struct nfp_fl_key_ls *key_layer)
nfp_flower_allocate_new(struct nfp_fl_key_ls *key_layer, bool egress)
{
{
	struct nfp_fl_payload *flow_pay;
	struct nfp_fl_payload *flow_pay;


@@ -371,6 +371,8 @@ nfp_flower_allocate_new(struct nfp_fl_key_ls *key_layer)
	flow_pay->meta.flags = 0;
	flow_pay->meta.flags = 0;
	spin_lock_init(&flow_pay->lock);
	spin_lock_init(&flow_pay->lock);


	flow_pay->ingress_offload = !egress;

	return flow_pay;
	return flow_pay;


err_free_mask:
err_free_mask:
@@ -402,8 +404,20 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev,
	struct nfp_flower_priv *priv = app->priv;
	struct nfp_flower_priv *priv = app->priv;
	struct nfp_fl_payload *flow_pay;
	struct nfp_fl_payload *flow_pay;
	struct nfp_fl_key_ls *key_layer;
	struct nfp_fl_key_ls *key_layer;
	struct net_device *ingr_dev;
	int err;
	int err;


	ingr_dev = egress ? NULL : netdev;
	flow_pay = nfp_flower_search_fl_table(app, flow->cookie, ingr_dev,
					      NFP_FL_STATS_CTX_DONT_CARE);
	if (flow_pay) {
		/* Ignore as duplicate if it has been added by different cb. */
		if (flow_pay->ingress_offload && egress)
			return 0;
		else
			return -EOPNOTSUPP;
	}

	key_layer = kmalloc(sizeof(*key_layer), GFP_KERNEL);
	key_layer = kmalloc(sizeof(*key_layer), GFP_KERNEL);
	if (!key_layer)
	if (!key_layer)
		return -ENOMEM;
		return -ENOMEM;
@@ -413,12 +427,14 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev,
	if (err)
	if (err)
		goto err_free_key_ls;
		goto err_free_key_ls;


	flow_pay = nfp_flower_allocate_new(key_layer);
	flow_pay = nfp_flower_allocate_new(key_layer, egress);
	if (!flow_pay) {
	if (!flow_pay) {
		err = -ENOMEM;
		err = -ENOMEM;
		goto err_free_key_ls;
		goto err_free_key_ls;
	}
	}


	flow_pay->ingress_dev = egress ? NULL : netdev;

	err = nfp_flower_compile_flow_match(flow, key_layer, netdev, flow_pay,
	err = nfp_flower_compile_flow_match(flow, key_layer, netdev, flow_pay,
					    tun_type);
					    tun_type);
	if (err)
	if (err)
@@ -428,7 +444,8 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev,
	if (err)
	if (err)
		goto err_destroy_flow;
		goto err_destroy_flow;


	err = nfp_compile_flow_metadata(app, flow, flow_pay);
	err = nfp_compile_flow_metadata(app, flow, flow_pay,
					flow_pay->ingress_dev);
	if (err)
	if (err)
		goto err_destroy_flow;
		goto err_destroy_flow;


@@ -462,6 +479,7 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev,
 * @app:	Pointer to the APP handle
 * @app:	Pointer to the APP handle
 * @netdev:	netdev structure.
 * @netdev:	netdev structure.
 * @flow:	TC flower classifier offload structure
 * @flow:	TC flower classifier offload structure
 * @egress:	Netdev is the egress dev.
 *
 *
 * Removes a flow from the repeated hash structure and clears the
 * Removes a flow from the repeated hash structure and clears the
 * action payload.
 * action payload.
@@ -470,15 +488,18 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev,
 */
 */
static int
static int
nfp_flower_del_offload(struct nfp_app *app, struct net_device *netdev,
nfp_flower_del_offload(struct nfp_app *app, struct net_device *netdev,
		       struct tc_cls_flower_offload *flow)
		       struct tc_cls_flower_offload *flow, bool egress)
{
{
	struct nfp_port *port = nfp_port_from_netdev(netdev);
	struct nfp_port *port = nfp_port_from_netdev(netdev);
	struct nfp_fl_payload *nfp_flow;
	struct nfp_fl_payload *nfp_flow;
	struct net_device *ingr_dev;
	int err;
	int err;


	nfp_flow = nfp_flower_search_fl_table(app, flow->cookie);
	ingr_dev = egress ? NULL : netdev;
	nfp_flow = nfp_flower_search_fl_table(app, flow->cookie, ingr_dev,
					      NFP_FL_STATS_CTX_DONT_CARE);
	if (!nfp_flow)
	if (!nfp_flow)
		return -ENOENT;
		return egress ? 0 : -ENOENT;


	err = nfp_modify_flow_metadata(app, nfp_flow);
	err = nfp_modify_flow_metadata(app, nfp_flow);
	if (err)
	if (err)
@@ -505,7 +526,9 @@ nfp_flower_del_offload(struct nfp_app *app, struct net_device *netdev,
/**
/**
 * nfp_flower_get_stats() - Populates flow stats obtained from hardware.
 * nfp_flower_get_stats() - Populates flow stats obtained from hardware.
 * @app:	Pointer to the APP handle
 * @app:	Pointer to the APP handle
 * @netdev:	Netdev structure.
 * @flow:	TC flower classifier offload structure
 * @flow:	TC flower classifier offload structure
 * @egress:	Netdev is the egress dev.
 *
 *
 * Populates a flow statistics structure which which corresponds to a
 * Populates a flow statistics structure which which corresponds to a
 * specific flow.
 * specific flow.
@@ -513,14 +536,21 @@ nfp_flower_del_offload(struct nfp_app *app, struct net_device *netdev,
 * Return: negative value on error, 0 if stats populated successfully.
 * Return: negative value on error, 0 if stats populated successfully.
 */
 */
static int
static int
nfp_flower_get_stats(struct nfp_app *app, struct tc_cls_flower_offload *flow)
nfp_flower_get_stats(struct nfp_app *app, struct net_device *netdev,
		     struct tc_cls_flower_offload *flow, bool egress)
{
{
	struct nfp_fl_payload *nfp_flow;
	struct nfp_fl_payload *nfp_flow;
	struct net_device *ingr_dev;


	nfp_flow = nfp_flower_search_fl_table(app, flow->cookie);
	ingr_dev = egress ? NULL : netdev;
	nfp_flow = nfp_flower_search_fl_table(app, flow->cookie, ingr_dev,
					      NFP_FL_STATS_CTX_DONT_CARE);
	if (!nfp_flow)
	if (!nfp_flow)
		return -EINVAL;
		return -EINVAL;


	if (nfp_flow->ingress_offload && egress)
		return 0;

	spin_lock_bh(&nfp_flow->lock);
	spin_lock_bh(&nfp_flow->lock);
	tcf_exts_stats_update(flow->exts, nfp_flow->stats.bytes,
	tcf_exts_stats_update(flow->exts, nfp_flow->stats.bytes,
			      nfp_flow->stats.pkts, nfp_flow->stats.used);
			      nfp_flow->stats.pkts, nfp_flow->stats.used);
@@ -543,9 +573,9 @@ nfp_flower_repr_offload(struct nfp_app *app, struct net_device *netdev,
	case TC_CLSFLOWER_REPLACE:
	case TC_CLSFLOWER_REPLACE:
		return nfp_flower_add_offload(app, netdev, flower, egress);
		return nfp_flower_add_offload(app, netdev, flower, egress);
	case TC_CLSFLOWER_DESTROY:
	case TC_CLSFLOWER_DESTROY:
		return nfp_flower_del_offload(app, netdev, flower);
		return nfp_flower_del_offload(app, netdev, flower, egress);
	case TC_CLSFLOWER_STATS:
	case TC_CLSFLOWER_STATS:
		return nfp_flower_get_stats(app, flower);
		return nfp_flower_get_stats(app, netdev, flower, egress);
	}
	}


	return -EOPNOTSUPP;
	return -EOPNOTSUPP;
+5 −0
Original line number Original line Diff line number Diff line
@@ -486,6 +486,10 @@ static int nfp_pci_probe(struct pci_dev *pdev,
		goto err_disable_msix;
		goto err_disable_msix;
	}
	}


	err = nfp_resource_table_init(pf->cpp);
	if (err)
		goto err_cpp_free;

	pf->hwinfo = nfp_hwinfo_read(pf->cpp);
	pf->hwinfo = nfp_hwinfo_read(pf->cpp);


	dev_info(&pdev->dev, "Assembly: %s%s%s-%s CPLD: %s\n",
	dev_info(&pdev->dev, "Assembly: %s%s%s-%s CPLD: %s\n",
@@ -548,6 +552,7 @@ static int nfp_pci_probe(struct pci_dev *pdev,
	vfree(pf->dumpspec);
	vfree(pf->dumpspec);
err_hwinfo_free:
err_hwinfo_free:
	kfree(pf->hwinfo);
	kfree(pf->hwinfo);
err_cpp_free:
	nfp_cpp_free(pf->cpp);
	nfp_cpp_free(pf->cpp);
err_disable_msix:
err_disable_msix:
	destroy_workqueue(pf->wq);
	destroy_workqueue(pf->wq);
+2 −0
Original line number Original line Diff line number Diff line
@@ -94,6 +94,8 @@ int nfp_nsp_read_sensors(struct nfp_nsp *state, unsigned int sensor_mask,
/* MAC Statistics Accumulator */
/* MAC Statistics Accumulator */
#define NFP_RESOURCE_MAC_STATISTICS	"mac.stat"
#define NFP_RESOURCE_MAC_STATISTICS	"mac.stat"


int nfp_resource_table_init(struct nfp_cpp *cpp);

struct nfp_resource *
struct nfp_resource *
nfp_resource_acquire(struct nfp_cpp *cpp, const char *name);
nfp_resource_acquire(struct nfp_cpp *cpp, const char *name);


Loading