Skip to content

Commit 81e696b

Browse files
committed
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: David S. Miller <[email protected]>
2 parents c77bbc6 + c50647d commit 81e696b

File tree

9 files changed

+173
-20
lines changed

9 files changed

+173
-20
lines changed

drivers/net/ethernet/netronome/nfp/flower/main.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
struct net_device;
4848
struct nfp_app;
4949

50+
#define NFP_FL_STATS_CTX_DONT_CARE cpu_to_be32(0xffffffff)
5051
#define NFP_FL_STATS_ENTRY_RS BIT(20)
5152
#define NFP_FL_STATS_ELEM_RS 4
5253
#define NFP_FL_REPEATED_HASH_MAX BIT(17)
@@ -189,9 +190,11 @@ struct nfp_fl_payload {
189190
spinlock_t lock; /* lock stats */
190191
struct nfp_fl_stats stats;
191192
__be32 nfp_tun_ipv4_addr;
193+
struct net_device *ingress_dev;
192194
char *unmasked_data;
193195
char *mask_data;
194196
char *action_data;
197+
bool ingress_offload;
195198
};
196199

197200
struct nfp_fl_stats_frame {
@@ -216,12 +219,14 @@ int nfp_flower_compile_action(struct tc_cls_flower_offload *flow,
216219
struct nfp_fl_payload *nfp_flow);
217220
int nfp_compile_flow_metadata(struct nfp_app *app,
218221
struct tc_cls_flower_offload *flow,
219-
struct nfp_fl_payload *nfp_flow);
222+
struct nfp_fl_payload *nfp_flow,
223+
struct net_device *netdev);
220224
int nfp_modify_flow_metadata(struct nfp_app *app,
221225
struct nfp_fl_payload *nfp_flow);
222226

223227
struct nfp_fl_payload *
224-
nfp_flower_search_fl_table(struct nfp_app *app, unsigned long tc_flower_cookie);
228+
nfp_flower_search_fl_table(struct nfp_app *app, unsigned long tc_flower_cookie,
229+
struct net_device *netdev, __be32 host_ctx);
225230
struct nfp_fl_payload *
226231
nfp_flower_remove_fl_table(struct nfp_app *app, unsigned long tc_flower_cookie);
227232

drivers/net/ethernet/netronome/nfp/flower/metadata.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,18 @@ static int nfp_get_stats_entry(struct nfp_app *app, u32 *stats_context_id)
9999

100100
/* Must be called with either RTNL or rcu_read_lock */
101101
struct nfp_fl_payload *
102-
nfp_flower_search_fl_table(struct nfp_app *app, unsigned long tc_flower_cookie)
102+
nfp_flower_search_fl_table(struct nfp_app *app, unsigned long tc_flower_cookie,
103+
struct net_device *netdev, __be32 host_ctx)
103104
{
104105
struct nfp_flower_priv *priv = app->priv;
105106
struct nfp_fl_payload *flower_entry;
106107

107108
hash_for_each_possible_rcu(priv->flow_table, flower_entry, link,
108109
tc_flower_cookie)
109-
if (flower_entry->tc_flower_cookie == tc_flower_cookie)
110+
if (flower_entry->tc_flower_cookie == tc_flower_cookie &&
111+
(!netdev || flower_entry->ingress_dev == netdev) &&
112+
(host_ctx == NFP_FL_STATS_CTX_DONT_CARE ||
113+
flower_entry->meta.host_ctx_id == host_ctx))
110114
return flower_entry;
111115

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

123127
rcu_read_lock();
124-
nfp_flow = nfp_flower_search_fl_table(app, flower_cookie);
128+
nfp_flow = nfp_flower_search_fl_table(app, flower_cookie, NULL,
129+
stats->stats_con_id);
125130
if (!nfp_flow)
126131
goto exit_rcu_unlock;
127132

128-
if (nfp_flow->meta.host_ctx_id != stats->stats_con_id)
129-
goto exit_rcu_unlock;
130-
131133
spin_lock(&nfp_flow->lock);
132134
nfp_flow->stats.pkts += be32_to_cpu(stats->pkt_count);
133135
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,
317319

318320
int nfp_compile_flow_metadata(struct nfp_app *app,
319321
struct tc_cls_flower_offload *flow,
320-
struct nfp_fl_payload *nfp_flow)
322+
struct nfp_fl_payload *nfp_flow,
323+
struct net_device *netdev)
321324
{
322325
struct nfp_flower_priv *priv = app->priv;
323326
struct nfp_fl_payload *check_entry;
@@ -348,7 +351,8 @@ int nfp_compile_flow_metadata(struct nfp_app *app,
348351
nfp_flow->stats.bytes = 0;
349352
nfp_flow->stats.used = jiffies;
350353

351-
check_entry = nfp_flower_search_fl_table(app, flow->cookie);
354+
check_entry = nfp_flower_search_fl_table(app, flow->cookie, netdev,
355+
NFP_FL_STATS_CTX_DONT_CARE);
352356
if (check_entry) {
353357
if (nfp_release_stats_entry(app, stats_cxt))
354358
return -EINVAL;

drivers/net/ethernet/netronome/nfp/flower/offload.c

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ nfp_flower_calculate_key_layers(struct nfp_app *app,
345345
}
346346

347347
static struct nfp_fl_payload *
348-
nfp_flower_allocate_new(struct nfp_fl_key_ls *key_layer)
348+
nfp_flower_allocate_new(struct nfp_fl_key_ls *key_layer, bool egress)
349349
{
350350
struct nfp_fl_payload *flow_pay;
351351

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

374+
flow_pay->ingress_offload = !egress;
375+
374376
return flow_pay;
375377

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

410+
ingr_dev = egress ? NULL : netdev;
411+
flow_pay = nfp_flower_search_fl_table(app, flow->cookie, ingr_dev,
412+
NFP_FL_STATS_CTX_DONT_CARE);
413+
if (flow_pay) {
414+
/* Ignore as duplicate if it has been added by different cb. */
415+
if (flow_pay->ingress_offload && egress)
416+
return 0;
417+
else
418+
return -EOPNOTSUPP;
419+
}
420+
407421
key_layer = kmalloc(sizeof(*key_layer), GFP_KERNEL);
408422
if (!key_layer)
409423
return -ENOMEM;
@@ -413,12 +427,14 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev,
413427
if (err)
414428
goto err_free_key_ls;
415429

416-
flow_pay = nfp_flower_allocate_new(key_layer);
430+
flow_pay = nfp_flower_allocate_new(key_layer, egress);
417431
if (!flow_pay) {
418432
err = -ENOMEM;
419433
goto err_free_key_ls;
420434
}
421435

436+
flow_pay->ingress_dev = egress ? NULL : netdev;
437+
422438
err = nfp_flower_compile_flow_match(flow, key_layer, netdev, flow_pay,
423439
tun_type);
424440
if (err)
@@ -428,7 +444,8 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev,
428444
if (err)
429445
goto err_destroy_flow;
430446

431-
err = nfp_compile_flow_metadata(app, flow, flow_pay);
447+
err = nfp_compile_flow_metadata(app, flow, flow_pay,
448+
flow_pay->ingress_dev);
432449
if (err)
433450
goto err_destroy_flow;
434451

@@ -462,6 +479,7 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev,
462479
* @app: Pointer to the APP handle
463480
* @netdev: netdev structure.
464481
* @flow: TC flower classifier offload structure
482+
* @egress: Netdev is the egress dev.
465483
*
466484
* Removes a flow from the repeated hash structure and clears the
467485
* action payload.
@@ -470,15 +488,18 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev,
470488
*/
471489
static int
472490
nfp_flower_del_offload(struct nfp_app *app, struct net_device *netdev,
473-
struct tc_cls_flower_offload *flow)
491+
struct tc_cls_flower_offload *flow, bool egress)
474492
{
475493
struct nfp_port *port = nfp_port_from_netdev(netdev);
476494
struct nfp_fl_payload *nfp_flow;
495+
struct net_device *ingr_dev;
477496
int err;
478497

479-
nfp_flow = nfp_flower_search_fl_table(app, flow->cookie);
498+
ingr_dev = egress ? NULL : netdev;
499+
nfp_flow = nfp_flower_search_fl_table(app, flow->cookie, ingr_dev,
500+
NFP_FL_STATS_CTX_DONT_CARE);
480501
if (!nfp_flow)
481-
return -ENOENT;
502+
return egress ? 0 : -ENOENT;
482503

483504
err = nfp_modify_flow_metadata(app, nfp_flow);
484505
if (err)
@@ -505,22 +526,31 @@ nfp_flower_del_offload(struct nfp_app *app, struct net_device *netdev,
505526
/**
506527
* nfp_flower_get_stats() - Populates flow stats obtained from hardware.
507528
* @app: Pointer to the APP handle
529+
* @netdev: Netdev structure.
508530
* @flow: TC flower classifier offload structure
531+
* @egress: Netdev is the egress dev.
509532
*
510533
* Populates a flow statistics structure which which corresponds to a
511534
* specific flow.
512535
*
513536
* Return: negative value on error, 0 if stats populated successfully.
514537
*/
515538
static int
516-
nfp_flower_get_stats(struct nfp_app *app, struct tc_cls_flower_offload *flow)
539+
nfp_flower_get_stats(struct nfp_app *app, struct net_device *netdev,
540+
struct tc_cls_flower_offload *flow, bool egress)
517541
{
518542
struct nfp_fl_payload *nfp_flow;
543+
struct net_device *ingr_dev;
519544

520-
nfp_flow = nfp_flower_search_fl_table(app, flow->cookie);
545+
ingr_dev = egress ? NULL : netdev;
546+
nfp_flow = nfp_flower_search_fl_table(app, flow->cookie, ingr_dev,
547+
NFP_FL_STATS_CTX_DONT_CARE);
521548
if (!nfp_flow)
522549
return -EINVAL;
523550

551+
if (nfp_flow->ingress_offload && egress)
552+
return 0;
553+
524554
spin_lock_bh(&nfp_flow->lock);
525555
tcf_exts_stats_update(flow->exts, nfp_flow->stats.bytes,
526556
nfp_flow->stats.pkts, nfp_flow->stats.used);
@@ -543,9 +573,9 @@ nfp_flower_repr_offload(struct nfp_app *app, struct net_device *netdev,
543573
case TC_CLSFLOWER_REPLACE:
544574
return nfp_flower_add_offload(app, netdev, flower, egress);
545575
case TC_CLSFLOWER_DESTROY:
546-
return nfp_flower_del_offload(app, netdev, flower);
576+
return nfp_flower_del_offload(app, netdev, flower, egress);
547577
case TC_CLSFLOWER_STATS:
548-
return nfp_flower_get_stats(app, flower);
578+
return nfp_flower_get_stats(app, netdev, flower, egress);
549579
}
550580

551581
return -EOPNOTSUPP;

drivers/net/ethernet/netronome/nfp/nfp_main.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,10 @@ static int nfp_pci_probe(struct pci_dev *pdev,
486486
goto err_disable_msix;
487487
}
488488

489+
err = nfp_resource_table_init(pf->cpp);
490+
if (err)
491+
goto err_cpp_free;
492+
489493
pf->hwinfo = nfp_hwinfo_read(pf->cpp);
490494

491495
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,
548552
vfree(pf->dumpspec);
549553
err_hwinfo_free:
550554
kfree(pf->hwinfo);
555+
err_cpp_free:
551556
nfp_cpp_free(pf->cpp);
552557
err_disable_msix:
553558
destroy_workqueue(pf->wq);

drivers/net/ethernet/netronome/nfp/nfpcore/nfp.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ int nfp_nsp_read_sensors(struct nfp_nsp *state, unsigned int sensor_mask,
9494
/* MAC Statistics Accumulator */
9595
#define NFP_RESOURCE_MAC_STATISTICS "mac.stat"
9696

97+
int nfp_resource_table_init(struct nfp_cpp *cpp);
98+
9799
struct nfp_resource *
98100
nfp_resource_acquire(struct nfp_cpp *cpp, const char *name);
99101

drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1330,6 +1330,7 @@ struct nfp_cpp *nfp_cpp_from_nfp6000_pcie(struct pci_dev *pdev)
13301330
/* Finished with card initialization. */
13311331
dev_info(&pdev->dev,
13321332
"Netronome Flow Processor NFP4000/NFP6000 PCIe Card Probe\n");
1333+
pcie_print_link_status(pdev);
13331334

13341335
nfp = kzalloc(sizeof(*nfp), GFP_KERNEL);
13351336
if (!nfp) {

drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpp.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,8 @@ void nfp_cpp_mutex_free(struct nfp_cpp_mutex *mutex);
295295
int nfp_cpp_mutex_lock(struct nfp_cpp_mutex *mutex);
296296
int nfp_cpp_mutex_unlock(struct nfp_cpp_mutex *mutex);
297297
int nfp_cpp_mutex_trylock(struct nfp_cpp_mutex *mutex);
298+
int nfp_cpp_mutex_reclaim(struct nfp_cpp *cpp, int target,
299+
unsigned long long address);
298300

299301
/**
300302
* nfp_cppcore_pcie_unit() - Get PCI Unit of a CPP handle

drivers/net/ethernet/netronome/nfp/nfpcore/nfp_mutex.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ static u32 nfp_mutex_unlocked(u16 interface)
5959
return (u32)interface << 16 | 0x0000;
6060
}
6161

62+
static u32 nfp_mutex_owner(u32 val)
63+
{
64+
return val >> 16;
65+
}
66+
6267
static bool nfp_mutex_is_locked(u32 val)
6368
{
6469
return (val & 0xffff) == 0x000f;
@@ -351,3 +356,43 @@ int nfp_cpp_mutex_trylock(struct nfp_cpp_mutex *mutex)
351356

352357
return nfp_mutex_is_locked(tmp) ? -EBUSY : -EINVAL;
353358
}
359+
360+
/**
361+
* nfp_cpp_mutex_reclaim() - Unlock mutex if held by local endpoint
362+
* @cpp: NFP CPP handle
363+
* @target: NFP CPP target ID (ie NFP_CPP_TARGET_CLS or NFP_CPP_TARGET_MU)
364+
* @address: Offset into the address space of the NFP CPP target ID
365+
*
366+
* Release lock if held by local system. Extreme care is advised, call only
367+
* when no local lock users can exist.
368+
*
369+
* Return: 0 if the lock was OK, 1 if locked by us, -errno on invalid mutex
370+
*/
371+
int nfp_cpp_mutex_reclaim(struct nfp_cpp *cpp, int target,
372+
unsigned long long address)
373+
{
374+
const u32 mur = NFP_CPP_ID(target, 3, 0); /* atomic_read */
375+
const u32 muw = NFP_CPP_ID(target, 4, 0); /* atomic_write */
376+
u16 interface = nfp_cpp_interface(cpp);
377+
int err;
378+
u32 tmp;
379+
380+
err = nfp_cpp_mutex_validate(interface, &target, address);
381+
if (err)
382+
return err;
383+
384+
/* Check lock */
385+
err = nfp_cpp_readl(cpp, mur, address, &tmp);
386+
if (err < 0)
387+
return err;
388+
389+
if (nfp_mutex_is_unlocked(tmp) || nfp_mutex_owner(tmp) != interface)
390+
return 0;
391+
392+
/* Bust the lock */
393+
err = nfp_cpp_writel(cpp, muw, address, nfp_mutex_unlocked(interface));
394+
if (err < 0)
395+
return err;
396+
397+
return 1;
398+
}

drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,3 +338,62 @@ u64 nfp_resource_size(struct nfp_resource *res)
338338
{
339339
return res->size;
340340
}
341+
342+
/**
343+
* nfp_resource_table_init() - Run initial checks on the resource table
344+
* @cpp: NFP CPP handle
345+
*
346+
* Start-of-day init procedure for resource table. Must be called before
347+
* any local resource table users may exist.
348+
*
349+
* Return: 0 on success, -errno on failure
350+
*/
351+
int nfp_resource_table_init(struct nfp_cpp *cpp)
352+
{
353+
struct nfp_cpp_mutex *dev_mutex;
354+
int i, err;
355+
356+
err = nfp_cpp_mutex_reclaim(cpp, NFP_RESOURCE_TBL_TARGET,
357+
NFP_RESOURCE_TBL_BASE);
358+
if (err < 0) {
359+
nfp_err(cpp, "Error: failed to reclaim resource table mutex\n");
360+
return err;
361+
}
362+
if (err)
363+
nfp_warn(cpp, "Warning: busted main resource table mutex\n");
364+
365+
dev_mutex = nfp_cpp_mutex_alloc(cpp, NFP_RESOURCE_TBL_TARGET,
366+
NFP_RESOURCE_TBL_BASE,
367+
NFP_RESOURCE_TBL_KEY);
368+
if (!dev_mutex)
369+
return -ENOMEM;
370+
371+
if (nfp_cpp_mutex_lock(dev_mutex)) {
372+
nfp_err(cpp, "Error: failed to claim resource table mutex\n");
373+
nfp_cpp_mutex_free(dev_mutex);
374+
return -EINVAL;
375+
}
376+
377+
/* Resource 0 is the dev_mutex, start from 1 */
378+
for (i = 1; i < NFP_RESOURCE_TBL_ENTRIES; i++) {
379+
u64 addr = NFP_RESOURCE_TBL_BASE +
380+
sizeof(struct nfp_resource_entry) * i;
381+
382+
err = nfp_cpp_mutex_reclaim(cpp, NFP_RESOURCE_TBL_TARGET, addr);
383+
if (err < 0) {
384+
nfp_err(cpp,
385+
"Error: failed to reclaim resource %d mutex\n",
386+
i);
387+
goto err_unlock;
388+
}
389+
if (err)
390+
nfp_warn(cpp, "Warning: busted resource %d mutex\n", i);
391+
}
392+
393+
err = 0;
394+
err_unlock:
395+
nfp_cpp_mutex_unlock(dev_mutex);
396+
nfp_cpp_mutex_free(dev_mutex);
397+
398+
return err;
399+
}

0 commit comments

Comments
 (0)