mirror of
https://github.com/torvalds/linux.git
synced 2024-12-15 07:33:56 +00:00
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
59
drivers/net/ethernet/netronome/nfp/nfp_abi.h
Normal file
59
drivers/net/ethernet/netronome/nfp/nfp_abi.h
Normal file
@ -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 "nfpcore/nfp6000_pcie.h"
|
||||||
|
|
||||||
|
#include "nfp_abi.h"
|
||||||
#include "nfp_app.h"
|
#include "nfp_app.h"
|
||||||
#include "nfp_main.h"
|
#include "nfp_main.h"
|
||||||
#include "nfp_net.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);
|
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)
|
static bool nfp_board_ready(struct nfp_pf *pf)
|
||||||
{
|
{
|
||||||
const char *cp;
|
const char *cp;
|
||||||
@ -468,6 +553,25 @@ static void nfp_fw_unload(struct nfp_pf *pf)
|
|||||||
nfp_nsp_close(nsp);
|
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,
|
static int nfp_pci_probe(struct pci_dev *pdev,
|
||||||
const struct pci_device_id *pci_id)
|
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->mip = nfp_mip_open(pf->cpp);
|
||||||
pf->rtbl = __nfp_rtsym_table_read(pf->cpp, pf->mip);
|
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->dump_flag = NFP_DUMP_NSP_DIAG;
|
||||||
pf->dumpspec = nfp_net_dump_load_dumpspec(pf->cpp, pf->rtbl);
|
pf->dumpspec = nfp_net_dump_load_dumpspec(pf->cpp, pf->rtbl);
|
||||||
|
|
||||||
|
@ -60,6 +60,7 @@ struct nfp_mip;
|
|||||||
struct nfp_net;
|
struct nfp_net;
|
||||||
struct nfp_nsp_identify;
|
struct nfp_nsp_identify;
|
||||||
struct nfp_port;
|
struct nfp_port;
|
||||||
|
struct nfp_rtsym;
|
||||||
struct nfp_rtsym_table;
|
struct nfp_rtsym_table;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -87,6 +88,7 @@ struct nfp_dumpspec {
|
|||||||
* @vf_cfg_mem: Pointer to mapped VF configuration area
|
* @vf_cfg_mem: Pointer to mapped VF configuration area
|
||||||
* @vfcfg_tbl2_area: Pointer to the CPP area for the VF config table
|
* @vfcfg_tbl2_area: Pointer to the CPP area for the VF config table
|
||||||
* @vfcfg_tbl2: Pointer to mapped 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
|
* @irq_entries: Array of MSI-X entries for all vNICs
|
||||||
* @limit_vfs: Number of VFs supported by firmware (~0 for PCI limit)
|
* @limit_vfs: Number of VFs supported by firmware (~0 for PCI limit)
|
||||||
* @num_vfs: Number of SR-IOV VFs enabled
|
* @num_vfs: Number of SR-IOV VFs enabled
|
||||||
@ -127,6 +129,8 @@ struct nfp_pf {
|
|||||||
struct nfp_cpp_area *vfcfg_tbl2_area;
|
struct nfp_cpp_area *vfcfg_tbl2_area;
|
||||||
u8 __iomem *vfcfg_tbl2;
|
u8 __iomem *vfcfg_tbl2;
|
||||||
|
|
||||||
|
const struct nfp_rtsym *mbox;
|
||||||
|
|
||||||
struct msix_entry *irq_entries;
|
struct msix_entry *irq_entries;
|
||||||
|
|
||||||
unsigned int limit_vfs;
|
unsigned int limit_vfs;
|
||||||
@ -182,6 +186,8 @@ int nfp_pf_rtsym_read_optional(struct nfp_pf *pf, const char *format,
|
|||||||
u8 __iomem *
|
u8 __iomem *
|
||||||
nfp_pf_map_rtsym(struct nfp_pf *pf, const char *name, const char *sym_fmt,
|
nfp_pf_map_rtsym(struct nfp_pf *pf, const char *name, const char *sym_fmt,
|
||||||
unsigned int min_size, struct nfp_cpp_area **area);
|
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 {
|
enum nfp_dump_diag {
|
||||||
NFP_DUMP_NSP_DIAG = 0,
|
NFP_DUMP_NSP_DIAG = 0,
|
||||||
|
Loading…
Reference in New Issue
Block a user