aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2017-09-13 16:29:13 -0400
committerDavid S. Miller <davem@davemloft.net>2017-09-13 16:29:13 -0400
commitd371465e81fc740cfa67ef47fbf692350c6b0113 (patch)
tree1db0fcbf574d3374f19777428d5cb5edad1661e0
parent255cd50f207ae8ec7b22663246c833407744e634 (diff)
parent7dbd5b7517376c4395a9ed0b26cf6b4db80d8415 (diff)
Merge branch 'nfp-card-init'
Jakub Kicinski says: ==================== nfp: wait more carefully for card init The first patch is a small fix for flower offload, we need a whitelist of supported matches, otherwise the unsupported ones will be ignored. The second and the third patch are adding wait/polling to the probe path. We had reports of driver failing probe because it couldn't find the control process (NSP) on the card. Turns out the NSP will only announce its existence after it's fully initialized. Until now we assumed it will be reachable, just not processing commands (hence we wait for a NOOP command to execute successfully). v2: - fix a bad merge which resulted in a build warning and retest. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/offload.c13
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_main.c47
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_main.c23
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfpcore/nfp.h2
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c45
5 files changed, 107 insertions, 23 deletions
diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c
index d396183108f7..a18b4d2b1d3e 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/offload.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c
@@ -44,6 +44,16 @@
44#include "../nfp_net.h" 44#include "../nfp_net.h"
45#include "../nfp_port.h" 45#include "../nfp_port.h"
46 46
47#define NFP_FLOWER_WHITELIST_DISSECTOR \
48 (BIT(FLOW_DISSECTOR_KEY_CONTROL) | \
49 BIT(FLOW_DISSECTOR_KEY_BASIC) | \
50 BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | \
51 BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | \
52 BIT(FLOW_DISSECTOR_KEY_PORTS) | \
53 BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | \
54 BIT(FLOW_DISSECTOR_KEY_VLAN) | \
55 BIT(FLOW_DISSECTOR_KEY_IP))
56
47static int 57static int
48nfp_flower_xmit_flow(struct net_device *netdev, 58nfp_flower_xmit_flow(struct net_device *netdev,
49 struct nfp_fl_payload *nfp_flow, u8 mtype) 59 struct nfp_fl_payload *nfp_flow, u8 mtype)
@@ -112,6 +122,9 @@ nfp_flower_calculate_key_layers(struct nfp_fl_key_ls *ret_key_ls,
112 u8 key_layer; 122 u8 key_layer;
113 int key_size; 123 int key_size;
114 124
125 if (flow->dissector->used_keys & ~NFP_FLOWER_WHITELIST_DISSECTOR)
126 return -EOPNOTSUPP;
127
115 if (dissector_uses_key(flow->dissector, 128 if (dissector_uses_key(flow->dissector,
116 FLOW_DISSECTOR_KEY_ENC_CONTROL)) { 129 FLOW_DISSECTOR_KEY_ENC_CONTROL)) {
117 struct flow_dissector_key_control *mask_enc_ctl = 130 struct flow_dissector_key_control *mask_enc_ctl =
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_main.c b/drivers/net/ethernet/netronome/nfp/nfp_main.c
index f055b1774d65..f8fa63b66739 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_main.c
@@ -74,6 +74,45 @@ static const struct pci_device_id nfp_pci_device_ids[] = {
74}; 74};
75MODULE_DEVICE_TABLE(pci, nfp_pci_device_ids); 75MODULE_DEVICE_TABLE(pci, nfp_pci_device_ids);
76 76
77static bool nfp_board_ready(struct nfp_pf *pf)
78{
79 const char *cp;
80 long state;
81 int err;
82
83 cp = nfp_hwinfo_lookup(pf->hwinfo, "board.state");
84 if (!cp)
85 return false;
86
87 err = kstrtol(cp, 0, &state);
88 if (err < 0)
89 return false;
90
91 return state == 15;
92}
93
94static int nfp_pf_board_state_wait(struct nfp_pf *pf)
95{
96 const unsigned long wait_until = jiffies + 10 * HZ;
97
98 while (!nfp_board_ready(pf)) {
99 if (time_is_before_eq_jiffies(wait_until)) {
100 nfp_err(pf->cpp, "NFP board initialization timeout\n");
101 return -EINVAL;
102 }
103
104 nfp_info(pf->cpp, "waiting for board initialization\n");
105 if (msleep_interruptible(500))
106 return -ERESTARTSYS;
107
108 /* Refresh cached information */
109 kfree(pf->hwinfo);
110 pf->hwinfo = nfp_hwinfo_read(pf->cpp);
111 }
112
113 return 0;
114}
115
77static int nfp_pcie_sriov_read_nfd_limit(struct nfp_pf *pf) 116static int nfp_pcie_sriov_read_nfd_limit(struct nfp_pf *pf)
78{ 117{
79 int err; 118 int err;
@@ -312,6 +351,10 @@ static int nfp_nsp_init(struct pci_dev *pdev, struct nfp_pf *pf)
312 struct nfp_nsp *nsp; 351 struct nfp_nsp *nsp;
313 int err; 352 int err;
314 353
354 err = nfp_resource_wait(pf->cpp, NFP_RESOURCE_NSP, 30);
355 if (err)
356 return err;
357
315 nsp = nfp_nsp_open(pf->cpp); 358 nsp = nfp_nsp_open(pf->cpp);
316 if (IS_ERR(nsp)) { 359 if (IS_ERR(nsp)) {
317 err = PTR_ERR(nsp); 360 err = PTR_ERR(nsp);
@@ -425,6 +468,10 @@ static int nfp_pci_probe(struct pci_dev *pdev,
425 nfp_hwinfo_lookup(pf->hwinfo, "assembly.revision"), 468 nfp_hwinfo_lookup(pf->hwinfo, "assembly.revision"),
426 nfp_hwinfo_lookup(pf->hwinfo, "cpld.version")); 469 nfp_hwinfo_lookup(pf->hwinfo, "cpld.version"));
427 470
471 err = nfp_pf_board_state_wait(pf);
472 if (err)
473 goto err_hwinfo_free;
474
428 err = devlink_register(devlink, &pdev->dev); 475 err = devlink_register(devlink, &pdev->dev);
429 if (err) 476 if (err)
430 goto err_hwinfo_free; 477 goto err_hwinfo_free;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
index 5abb9ba31e7d..ff373acd28f3 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
@@ -64,23 +64,6 @@
64 64
65#define NFP_PF_CSR_SLICE_SIZE (32 * 1024) 65#define NFP_PF_CSR_SLICE_SIZE (32 * 1024)
66 66
67static int nfp_is_ready(struct nfp_pf *pf)
68{
69 const char *cp;
70 long state;
71 int err;
72
73 cp = nfp_hwinfo_lookup(pf->hwinfo, "board.state");
74 if (!cp)
75 return 0;
76
77 err = kstrtol(cp, 0, &state);
78 if (err < 0)
79 return 0;
80
81 return state == 15;
82}
83
84/** 67/**
85 * nfp_net_get_mac_addr() - Get the MAC address. 68 * nfp_net_get_mac_addr() - Get the MAC address.
86 * @pf: NFP PF handle 69 * @pf: NFP PF handle
@@ -725,12 +708,6 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
725 708
726 INIT_WORK(&pf->port_refresh_work, nfp_net_refresh_vnics); 709 INIT_WORK(&pf->port_refresh_work, nfp_net_refresh_vnics);
727 710
728 /* Verify that the board has completed initialization */
729 if (!nfp_is_ready(pf)) {
730 nfp_err(pf->cpp, "NFP is not ready for NIC operation.\n");
731 return -EINVAL;
732 }
733
734 if (!pf->rtbl) { 711 if (!pf->rtbl) {
735 nfp_err(pf->cpp, "No %s, giving up.\n", 712 nfp_err(pf->cpp, "No %s, giving up.\n",
736 pf->fw_loaded ? "symbol table" : "firmware found"); 713 pf->fw_loaded ? "symbol table" : "firmware found");
diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp.h b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp.h
index 1a8d04a1e113..3ce51f03126f 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp.h
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp.h
@@ -97,6 +97,8 @@ nfp_resource_acquire(struct nfp_cpp *cpp, const char *name);
97 97
98void nfp_resource_release(struct nfp_resource *res); 98void nfp_resource_release(struct nfp_resource *res);
99 99
100int nfp_resource_wait(struct nfp_cpp *cpp, const char *name, unsigned int secs);
101
100u32 nfp_resource_cpp_id(struct nfp_resource *res); 102u32 nfp_resource_cpp_id(struct nfp_resource *res);
101 103
102const char *nfp_resource_name(struct nfp_resource *res); 104const char *nfp_resource_name(struct nfp_resource *res);
diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c
index 072612263dab..b1dd13ff282b 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c
@@ -250,6 +250,51 @@ void nfp_resource_release(struct nfp_resource *res)
250} 250}
251 251
252/** 252/**
253 * nfp_resource_wait() - Wait for resource to appear
254 * @cpp: NFP CPP handle
255 * @name: Name of the resource
256 * @secs: Number of seconds to wait
257 *
258 * Wait for resource to appear in the resource table, grab and release
259 * its lock. The wait is jiffies-based, don't expect fine granularity.
260 *
261 * Return: 0 on success, errno otherwise.
262 */
263int nfp_resource_wait(struct nfp_cpp *cpp, const char *name, unsigned int secs)
264{
265 unsigned long warn_at = jiffies + NFP_MUTEX_WAIT_FIRST_WARN * HZ;
266 unsigned long err_at = jiffies + secs * HZ;
267 struct nfp_resource *res;
268
269 while (true) {
270 res = nfp_resource_acquire(cpp, name);
271 if (!IS_ERR(res)) {
272 nfp_resource_release(res);
273 return 0;
274 }
275
276 if (PTR_ERR(res) != -ENOENT) {
277 nfp_err(cpp, "error waiting for resource %s: %ld\n",
278 name, PTR_ERR(res));
279 return PTR_ERR(res);
280 }
281 if (time_is_before_eq_jiffies(err_at)) {
282 nfp_err(cpp, "timeout waiting for resource %s\n", name);
283 return -ETIMEDOUT;
284 }
285 if (time_is_before_eq_jiffies(warn_at)) {
286 warn_at = jiffies + NFP_MUTEX_WAIT_NEXT_WARN * HZ;
287 nfp_info(cpp, "waiting for NFP resource %s\n", name);
288 }
289 if (msleep_interruptible(10)) {
290 nfp_err(cpp, "wait for resource %s interrupted\n",
291 name);
292 return -ERESTARTSYS;
293 }
294 }
295}
296
297/**
253 * nfp_resource_cpp_id() - Return the cpp_id of a resource handle 298 * nfp_resource_cpp_id() - Return the cpp_id of a resource handle
254 * @res: NFP Resource handle 299 * @res: NFP Resource handle
255 * 300 *