Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+107 -23
+13
drivers/net/ethernet/netronome/nfp/flower/offload.c
··· 44 44 #include "../nfp_net.h" 45 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 + 47 57 static int 48 58 nfp_flower_xmit_flow(struct net_device *netdev, 49 59 struct nfp_fl_payload *nfp_flow, u8 mtype) ··· 121 111 u32 key_layer_two; 122 112 u8 key_layer; 123 113 int key_size; 114 + 115 + if (flow->dissector->used_keys & ~NFP_FLOWER_WHITELIST_DISSECTOR) 116 + return -EOPNOTSUPP; 124 117 125 118 if (dissector_uses_key(flow->dissector, 126 119 FLOW_DISSECTOR_KEY_ENC_CONTROL)) {
+47
drivers/net/ethernet/netronome/nfp/nfp_main.c
··· 74 74 }; 75 75 MODULE_DEVICE_TABLE(pci, nfp_pci_device_ids); 76 76 77 + static 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 + 94 + static 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 + 77 116 static int nfp_pcie_sriov_read_nfd_limit(struct nfp_pf *pf) 78 117 { 79 118 int err; ··· 351 312 struct nfp_nsp *nsp; 352 313 int err; 353 314 315 + err = nfp_resource_wait(pf->cpp, NFP_RESOURCE_NSP, 30); 316 + if (err) 317 + return err; 318 + 354 319 nsp = nfp_nsp_open(pf->cpp); 355 320 if (IS_ERR(nsp)) { 356 321 err = PTR_ERR(nsp); ··· 467 424 nfp_hwinfo_lookup(pf->hwinfo, "assembly.serial"), 468 425 nfp_hwinfo_lookup(pf->hwinfo, "assembly.revision"), 469 426 nfp_hwinfo_lookup(pf->hwinfo, "cpld.version")); 427 + 428 + err = nfp_pf_board_state_wait(pf); 429 + if (err) 430 + goto err_hwinfo_free; 470 431 471 432 err = devlink_register(devlink, &pdev->dev); 472 433 if (err)
-23
drivers/net/ethernet/netronome/nfp/nfp_net_main.c
··· 64 64 65 65 #define NFP_PF_CSR_SLICE_SIZE (32 * 1024) 66 66 67 - static 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 68 * nfp_net_get_mac_addr() - Get the MAC address. 86 69 * @pf: NFP PF handle ··· 707 724 int err; 708 725 709 726 INIT_WORK(&pf->port_refresh_work, nfp_net_refresh_vnics); 710 - 711 - /* Verify that the board has completed initialization */ 712 - if (!nfp_is_ready(pf)) { 713 - nfp_err(pf->cpp, "NFP is not ready for NIC operation.\n"); 714 - return -EINVAL; 715 - } 716 727 717 728 if (!pf->rtbl) { 718 729 nfp_err(pf->cpp, "No %s, giving up.\n",
+2
drivers/net/ethernet/netronome/nfp/nfpcore/nfp.h
··· 97 97 98 98 void nfp_resource_release(struct nfp_resource *res); 99 99 100 + int nfp_resource_wait(struct nfp_cpp *cpp, const char *name, unsigned int secs); 101 + 100 102 u32 nfp_resource_cpp_id(struct nfp_resource *res); 101 103 102 104 const char *nfp_resource_name(struct nfp_resource *res);
+45
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c
··· 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 + */ 263 + int 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 298 * nfp_resource_cpp_id() - Return the cpp_id of a resource handle 254 299 * @res: NFP Resource handle 255 300 *