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>
This commit is contained in:
Коммит
d371465e81
|
@ -44,6 +44,16 @@
|
||||||
#include "../nfp_net.h"
|
#include "../nfp_net.h"
|
||||||
#include "../nfp_port.h"
|
#include "../nfp_port.h"
|
||||||
|
|
||||||
|
#define NFP_FLOWER_WHITELIST_DISSECTOR \
|
||||||
|
(BIT(FLOW_DISSECTOR_KEY_CONTROL) | \
|
||||||
|
BIT(FLOW_DISSECTOR_KEY_BASIC) | \
|
||||||
|
BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | \
|
||||||
|
BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | \
|
||||||
|
BIT(FLOW_DISSECTOR_KEY_PORTS) | \
|
||||||
|
BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | \
|
||||||
|
BIT(FLOW_DISSECTOR_KEY_VLAN) | \
|
||||||
|
BIT(FLOW_DISSECTOR_KEY_IP))
|
||||||
|
|
||||||
static int
|
static int
|
||||||
nfp_flower_xmit_flow(struct net_device *netdev,
|
nfp_flower_xmit_flow(struct net_device *netdev,
|
||||||
struct nfp_fl_payload *nfp_flow, u8 mtype)
|
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,
|
||||||
u8 key_layer;
|
u8 key_layer;
|
||||||
int key_size;
|
int key_size;
|
||||||
|
|
||||||
|
if (flow->dissector->used_keys & ~NFP_FLOWER_WHITELIST_DISSECTOR)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (dissector_uses_key(flow->dissector,
|
if (dissector_uses_key(flow->dissector,
|
||||||
FLOW_DISSECTOR_KEY_ENC_CONTROL)) {
|
FLOW_DISSECTOR_KEY_ENC_CONTROL)) {
|
||||||
struct flow_dissector_key_control *mask_enc_ctl =
|
struct flow_dissector_key_control *mask_enc_ctl =
|
||||||
|
|
|
@ -74,6 +74,45 @@ static const struct pci_device_id nfp_pci_device_ids[] = {
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(pci, nfp_pci_device_ids);
|
MODULE_DEVICE_TABLE(pci, nfp_pci_device_ids);
|
||||||
|
|
||||||
|
static bool nfp_board_ready(struct nfp_pf *pf)
|
||||||
|
{
|
||||||
|
const char *cp;
|
||||||
|
long state;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
cp = nfp_hwinfo_lookup(pf->hwinfo, "board.state");
|
||||||
|
if (!cp)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
err = kstrtol(cp, 0, &state);
|
||||||
|
if (err < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return state == 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nfp_pf_board_state_wait(struct nfp_pf *pf)
|
||||||
|
{
|
||||||
|
const unsigned long wait_until = jiffies + 10 * HZ;
|
||||||
|
|
||||||
|
while (!nfp_board_ready(pf)) {
|
||||||
|
if (time_is_before_eq_jiffies(wait_until)) {
|
||||||
|
nfp_err(pf->cpp, "NFP board initialization timeout\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
nfp_info(pf->cpp, "waiting for board initialization\n");
|
||||||
|
if (msleep_interruptible(500))
|
||||||
|
return -ERESTARTSYS;
|
||||||
|
|
||||||
|
/* Refresh cached information */
|
||||||
|
kfree(pf->hwinfo);
|
||||||
|
pf->hwinfo = nfp_hwinfo_read(pf->cpp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int nfp_pcie_sriov_read_nfd_limit(struct nfp_pf *pf)
|
static int nfp_pcie_sriov_read_nfd_limit(struct nfp_pf *pf)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
@ -312,6 +351,10 @@ static int nfp_nsp_init(struct pci_dev *pdev, struct nfp_pf *pf)
|
||||||
struct nfp_nsp *nsp;
|
struct nfp_nsp *nsp;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
err = nfp_resource_wait(pf->cpp, NFP_RESOURCE_NSP, 30);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
nsp = nfp_nsp_open(pf->cpp);
|
nsp = nfp_nsp_open(pf->cpp);
|
||||||
if (IS_ERR(nsp)) {
|
if (IS_ERR(nsp)) {
|
||||||
err = PTR_ERR(nsp);
|
err = PTR_ERR(nsp);
|
||||||
|
@ -425,6 +468,10 @@ static int nfp_pci_probe(struct pci_dev *pdev,
|
||||||
nfp_hwinfo_lookup(pf->hwinfo, "assembly.revision"),
|
nfp_hwinfo_lookup(pf->hwinfo, "assembly.revision"),
|
||||||
nfp_hwinfo_lookup(pf->hwinfo, "cpld.version"));
|
nfp_hwinfo_lookup(pf->hwinfo, "cpld.version"));
|
||||||
|
|
||||||
|
err = nfp_pf_board_state_wait(pf);
|
||||||
|
if (err)
|
||||||
|
goto err_hwinfo_free;
|
||||||
|
|
||||||
err = devlink_register(devlink, &pdev->dev);
|
err = devlink_register(devlink, &pdev->dev);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_hwinfo_free;
|
goto err_hwinfo_free;
|
||||||
|
|
|
@ -64,23 +64,6 @@
|
||||||
|
|
||||||
#define NFP_PF_CSR_SLICE_SIZE (32 * 1024)
|
#define NFP_PF_CSR_SLICE_SIZE (32 * 1024)
|
||||||
|
|
||||||
static int nfp_is_ready(struct nfp_pf *pf)
|
|
||||||
{
|
|
||||||
const char *cp;
|
|
||||||
long state;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
cp = nfp_hwinfo_lookup(pf->hwinfo, "board.state");
|
|
||||||
if (!cp)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
err = kstrtol(cp, 0, &state);
|
|
||||||
if (err < 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return state == 15;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nfp_net_get_mac_addr() - Get the MAC address.
|
* nfp_net_get_mac_addr() - Get the MAC address.
|
||||||
* @pf: NFP PF handle
|
* @pf: NFP PF handle
|
||||||
|
@ -725,12 +708,6 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
|
||||||
|
|
||||||
INIT_WORK(&pf->port_refresh_work, nfp_net_refresh_vnics);
|
INIT_WORK(&pf->port_refresh_work, nfp_net_refresh_vnics);
|
||||||
|
|
||||||
/* Verify that the board has completed initialization */
|
|
||||||
if (!nfp_is_ready(pf)) {
|
|
||||||
nfp_err(pf->cpp, "NFP is not ready for NIC operation.\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pf->rtbl) {
|
if (!pf->rtbl) {
|
||||||
nfp_err(pf->cpp, "No %s, giving up.\n",
|
nfp_err(pf->cpp, "No %s, giving up.\n",
|
||||||
pf->fw_loaded ? "symbol table" : "firmware found");
|
pf->fw_loaded ? "symbol table" : "firmware found");
|
||||||
|
|
|
@ -97,6 +97,8 @@ nfp_resource_acquire(struct nfp_cpp *cpp, const char *name);
|
||||||
|
|
||||||
void nfp_resource_release(struct nfp_resource *res);
|
void nfp_resource_release(struct nfp_resource *res);
|
||||||
|
|
||||||
|
int nfp_resource_wait(struct nfp_cpp *cpp, const char *name, unsigned int secs);
|
||||||
|
|
||||||
u32 nfp_resource_cpp_id(struct nfp_resource *res);
|
u32 nfp_resource_cpp_id(struct nfp_resource *res);
|
||||||
|
|
||||||
const char *nfp_resource_name(struct nfp_resource *res);
|
const char *nfp_resource_name(struct nfp_resource *res);
|
||||||
|
|
|
@ -249,6 +249,51 @@ void nfp_resource_release(struct nfp_resource *res)
|
||||||
kfree(res);
|
kfree(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfp_resource_wait() - Wait for resource to appear
|
||||||
|
* @cpp: NFP CPP handle
|
||||||
|
* @name: Name of the resource
|
||||||
|
* @secs: Number of seconds to wait
|
||||||
|
*
|
||||||
|
* Wait for resource to appear in the resource table, grab and release
|
||||||
|
* its lock. The wait is jiffies-based, don't expect fine granularity.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, errno otherwise.
|
||||||
|
*/
|
||||||
|
int nfp_resource_wait(struct nfp_cpp *cpp, const char *name, unsigned int secs)
|
||||||
|
{
|
||||||
|
unsigned long warn_at = jiffies + NFP_MUTEX_WAIT_FIRST_WARN * HZ;
|
||||||
|
unsigned long err_at = jiffies + secs * HZ;
|
||||||
|
struct nfp_resource *res;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
res = nfp_resource_acquire(cpp, name);
|
||||||
|
if (!IS_ERR(res)) {
|
||||||
|
nfp_resource_release(res);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PTR_ERR(res) != -ENOENT) {
|
||||||
|
nfp_err(cpp, "error waiting for resource %s: %ld\n",
|
||||||
|
name, PTR_ERR(res));
|
||||||
|
return PTR_ERR(res);
|
||||||
|
}
|
||||||
|
if (time_is_before_eq_jiffies(err_at)) {
|
||||||
|
nfp_err(cpp, "timeout waiting for resource %s\n", name);
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
if (time_is_before_eq_jiffies(warn_at)) {
|
||||||
|
warn_at = jiffies + NFP_MUTEX_WAIT_NEXT_WARN * HZ;
|
||||||
|
nfp_info(cpp, "waiting for NFP resource %s\n", name);
|
||||||
|
}
|
||||||
|
if (msleep_interruptible(10)) {
|
||||||
|
nfp_err(cpp, "wait for resource %s interrupted\n",
|
||||||
|
name);
|
||||||
|
return -ERESTARTSYS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nfp_resource_cpp_id() - Return the cpp_id of a resource handle
|
* nfp_resource_cpp_id() - Return the cpp_id of a resource handle
|
||||||
* @res: NFP Resource handle
|
* @res: NFP Resource handle
|
||||||
|
|
Загрузка…
Ссылка в новой задаче