Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0c693323 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller
Browse files

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: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8f6196f6
Loading
Loading
Loading
Loading
+59 −0
Original line number Diff line number Diff line
/* 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
+108 −0
Original line number Diff line number Diff line
@@ -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);

+6 −0
Original line number Diff line number Diff line
@@ -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,