nfp: add support for per-PCI PF mailbox
When working with devlink-related functionality for locking reasons it's easier to create a new mailbox per-PCI PF device than try to use one of the netdev/vNIC mailboxes. Define new mailbox structure and resolve its symbol during probe. For forward compatibility allow silent truncation of mailbox command data. Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
8f6196f63c
commit
0c693323a1
|
@ -0,0 +1,59 @@
|
|||
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */
|
||||
/*
|
||||
* Copyright (C) 2018 Netronome Systems, Inc.
|
||||
*
|
||||
* This software is dual licensed under the GNU General License Version 2,
|
||||
* June 1991 as shown in the file COPYING in the top-level directory of this
|
||||
* source tree or the BSD 2-Clause License provided below. You have the
|
||||
* option to license this software under the complete terms of either license.
|
||||
*
|
||||
* The BSD 2-Clause License:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __NFP_ABI__
|
||||
#define __NFP_ABI__ 1
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define NFP_MBOX_SYM_NAME "_abi_nfd_pf%u_mbox"
|
||||
#define NFP_MBOX_SYM_MIN_SIZE 16 /* When no data needed */
|
||||
|
||||
#define NFP_MBOX_CMD 0x00
|
||||
#define NFP_MBOX_RET 0x04
|
||||
#define NFP_MBOX_DATA_LEN 0x08
|
||||
#define NFP_MBOX_RESERVED 0x0c
|
||||
#define NFP_MBOX_DATA 0x10
|
||||
|
||||
/**
|
||||
* enum nfp_mbox_cmd - PF mailbox commands
|
||||
*
|
||||
* @NFP_MBOX_NO_CMD: null command
|
||||
* Used to indicate previous command has finished.
|
||||
*/
|
||||
enum nfp_mbox_cmd {
|
||||
NFP_MBOX_NO_CMD = 0x00,
|
||||
};
|
||||
|
||||
#endif
|
|
@ -55,6 +55,7 @@
|
|||
|
||||
#include "nfpcore/nfp6000_pcie.h"
|
||||
|
||||
#include "nfp_abi.h"
|
||||
#include "nfp_app.h"
|
||||
#include "nfp_main.h"
|
||||
#include "nfp_net.h"
|
||||
|
@ -107,6 +108,90 @@ nfp_pf_map_rtsym(struct nfp_pf *pf, const char *name, const char *sym_fmt,
|
|||
return nfp_rtsym_map(pf->rtbl, pf_symbol, name, min_size, area);
|
||||
}
|
||||
|
||||
/* Callers should hold the devlink instance lock */
|
||||
int nfp_mbox_cmd(struct nfp_pf *pf, u32 cmd, void *in_data, u64 in_length,
|
||||
void *out_data, u64 out_length)
|
||||
{
|
||||
unsigned long long addr;
|
||||
unsigned long err_at;
|
||||
u64 max_data_sz;
|
||||
u32 val = 0;
|
||||
u32 cpp_id;
|
||||
int n, err;
|
||||
|
||||
if (!pf->mbox)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
cpp_id = NFP_CPP_ISLAND_ID(pf->mbox->target, NFP_CPP_ACTION_RW, 0,
|
||||
pf->mbox->domain);
|
||||
addr = pf->mbox->addr;
|
||||
max_data_sz = pf->mbox->size - NFP_MBOX_SYM_MIN_SIZE;
|
||||
|
||||
/* Check if cmd field is clear */
|
||||
err = nfp_cpp_readl(pf->cpp, cpp_id, addr + NFP_MBOX_CMD, &val);
|
||||
if (err || val) {
|
||||
nfp_warn(pf->cpp, "failed to issue command (%u): %u, err: %d\n",
|
||||
cmd, val, err);
|
||||
return err ?: -EBUSY;
|
||||
}
|
||||
|
||||
in_length = min(in_length, max_data_sz);
|
||||
n = nfp_cpp_write(pf->cpp, cpp_id, addr + NFP_MBOX_DATA,
|
||||
in_data, in_length);
|
||||
if (n != in_length)
|
||||
return -EIO;
|
||||
/* Write data_len and wipe reserved */
|
||||
err = nfp_cpp_writeq(pf->cpp, cpp_id, addr + NFP_MBOX_DATA_LEN,
|
||||
in_length);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Read back for ordering */
|
||||
err = nfp_cpp_readl(pf->cpp, cpp_id, addr + NFP_MBOX_DATA_LEN, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Write cmd and wipe return value */
|
||||
err = nfp_cpp_writeq(pf->cpp, cpp_id, addr + NFP_MBOX_CMD, cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err_at = jiffies + 5 * HZ;
|
||||
while (true) {
|
||||
/* Wait for command to go to 0 (NFP_MBOX_NO_CMD) */
|
||||
err = nfp_cpp_readl(pf->cpp, cpp_id, addr + NFP_MBOX_CMD, &val);
|
||||
if (err)
|
||||
return err;
|
||||
if (!val)
|
||||
break;
|
||||
|
||||
if (time_is_before_eq_jiffies(err_at))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
msleep(5);
|
||||
}
|
||||
|
||||
/* Copy output if any (could be error info, do it before reading ret) */
|
||||
err = nfp_cpp_readl(pf->cpp, cpp_id, addr + NFP_MBOX_DATA_LEN, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
out_length = min_t(u32, val, min(out_length, max_data_sz));
|
||||
n = nfp_cpp_read(pf->cpp, cpp_id, addr + NFP_MBOX_DATA,
|
||||
out_data, out_length);
|
||||
if (n != out_length)
|
||||
return -EIO;
|
||||
|
||||
/* Check if there is an error */
|
||||
err = nfp_cpp_readl(pf->cpp, cpp_id, addr + NFP_MBOX_RET, &val);
|
||||
if (err)
|
||||
return err;
|
||||
if (val)
|
||||
return -val;
|
||||
|
||||
return out_length;
|
||||
}
|
||||
|
||||
static bool nfp_board_ready(struct nfp_pf *pf)
|
||||
{
|
||||
const char *cp;
|
||||
|
@ -468,6 +553,25 @@ static void nfp_fw_unload(struct nfp_pf *pf)
|
|||
nfp_nsp_close(nsp);
|
||||
}
|
||||
|
||||
static int nfp_pf_find_rtsyms(struct nfp_pf *pf)
|
||||
{
|
||||
char pf_symbol[256];
|
||||
unsigned int pf_id;
|
||||
|
||||
pf_id = nfp_cppcore_pcie_unit(pf->cpp);
|
||||
|
||||
/* Optional per-PCI PF mailbox */
|
||||
snprintf(pf_symbol, sizeof(pf_symbol), NFP_MBOX_SYM_NAME, pf_id);
|
||||
pf->mbox = nfp_rtsym_lookup(pf->rtbl, pf_symbol);
|
||||
if (pf->mbox && pf->mbox->size < NFP_MBOX_SYM_MIN_SIZE) {
|
||||
nfp_err(pf->cpp, "PF mailbox symbol too small: %llu < %d\n",
|
||||
pf->mbox->size, NFP_MBOX_SYM_MIN_SIZE);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nfp_pci_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *pci_id)
|
||||
{
|
||||
|
@ -542,6 +646,10 @@ static int nfp_pci_probe(struct pci_dev *pdev,
|
|||
pf->mip = nfp_mip_open(pf->cpp);
|
||||
pf->rtbl = __nfp_rtsym_table_read(pf->cpp, pf->mip);
|
||||
|
||||
err = nfp_pf_find_rtsyms(pf);
|
||||
if (err)
|
||||
goto err_fw_unload;
|
||||
|
||||
pf->dump_flag = NFP_DUMP_NSP_DIAG;
|
||||
pf->dumpspec = nfp_net_dump_load_dumpspec(pf->cpp, pf->rtbl);
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@ struct nfp_mip;
|
|||
struct nfp_net;
|
||||
struct nfp_nsp_identify;
|
||||
struct nfp_port;
|
||||
struct nfp_rtsym;
|
||||
struct nfp_rtsym_table;
|
||||
|
||||
/**
|
||||
|
@ -87,6 +88,7 @@ struct nfp_dumpspec {
|
|||
* @vf_cfg_mem: Pointer to mapped VF configuration area
|
||||
* @vfcfg_tbl2_area: Pointer to the CPP area for the VF config table
|
||||
* @vfcfg_tbl2: Pointer to mapped VF config table
|
||||
* @mbox: RTSym of per-PCI PF mailbox (under devlink lock)
|
||||
* @irq_entries: Array of MSI-X entries for all vNICs
|
||||
* @limit_vfs: Number of VFs supported by firmware (~0 for PCI limit)
|
||||
* @num_vfs: Number of SR-IOV VFs enabled
|
||||
|
@ -127,6 +129,8 @@ struct nfp_pf {
|
|||
struct nfp_cpp_area *vfcfg_tbl2_area;
|
||||
u8 __iomem *vfcfg_tbl2;
|
||||
|
||||
const struct nfp_rtsym *mbox;
|
||||
|
||||
struct msix_entry *irq_entries;
|
||||
|
||||
unsigned int limit_vfs;
|
||||
|
@ -182,6 +186,8 @@ int nfp_pf_rtsym_read_optional(struct nfp_pf *pf, const char *format,
|
|||
u8 __iomem *
|
||||
nfp_pf_map_rtsym(struct nfp_pf *pf, const char *name, const char *sym_fmt,
|
||||
unsigned int min_size, struct nfp_cpp_area **area);
|
||||
int nfp_mbox_cmd(struct nfp_pf *pf, u32 cmd, void *in_data, u64 in_length,
|
||||
void *out_data, u64 out_length);
|
||||
|
||||
enum nfp_dump_diag {
|
||||
NFP_DUMP_NSP_DIAG = 0,
|
||||
|
|
Loading…
Reference in New Issue