net/mlx5: FPGA, Add basic support for Innova

Mellanox Innova is a NIC with ConnectX and an FPGA on the same
board. The FPGA is a bump-on-the-wire and thus affects operation of
the mlx5_core driver on the ConnectX ASIC.

Add basic support for Innova in mlx5_core.

This allows using the Innova card as a regular NIC, by detecting
the FPGA capability bit, and verifying its load state before
initializing ConnectX interfaces.

Also detect FPGA fatal runtime failures and enter error state if
they ever happen.

All new FPGA-related logic is placed in its own subdirectory 'fpga',
which may be built by selecting CONFIG_MLX5_FPGA.
This prepares for further support of various Innova features in later
patchsets.
Additional details about hardware architecture will be provided as
more features get submitted.

Signed-off-by: Ilan Tayari <ilant@mellanox.com>
Reviewed-by: Boris Pismenny <borisp@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
This commit is contained in:
Ilan Tayari 2017-03-13 20:05:45 +02:00 committed by Saeed Mahameed
parent 0179720d6b
commit e29341fb3a
13 changed files with 640 additions and 3 deletions

View File

@ -8304,6 +8304,16 @@ W: http://www.mellanox.com
Q: http://patchwork.ozlabs.org/project/netdev/list/ Q: http://patchwork.ozlabs.org/project/netdev/list/
F: drivers/net/ethernet/mellanox/mlx5/core/en_* F: drivers/net/ethernet/mellanox/mlx5/core/en_*
MELLANOX ETHERNET INNOVA DRIVER
M: Ilan Tayari <ilant@mellanox.com>
R: Boris Pismenny <borisp@mellanox.com>
L: netdev@vger.kernel.org
S: Supported
W: http://www.mellanox.com
Q: http://patchwork.ozlabs.org/project/netdev/list/
F: drivers/net/ethernet/mellanox/mlx5/core/fpga/*
F: include/linux/mlx5/mlx5_ifc_fpga.h
MELLANOX ETHERNET SWITCH DRIVERS MELLANOX ETHERNET SWITCH DRIVERS
M: Jiri Pirko <jiri@mellanox.com> M: Jiri Pirko <jiri@mellanox.com>
M: Ido Schimmel <idosch@mellanox.com> M: Ido Schimmel <idosch@mellanox.com>

View File

@ -11,6 +11,16 @@ config MLX5_CORE
Core driver for low level functionality of the ConnectX-4 and Core driver for low level functionality of the ConnectX-4 and
Connect-IB cards by Mellanox Technologies. Connect-IB cards by Mellanox Technologies.
config MLX5_FPGA
bool "Mellanox Technologies Innova support"
depends on MLX5_CORE
---help---
Build support for the Innova family of network cards by Mellanox
Technologies. Innova network cards are comprised of a ConnectX chip
and an FPGA chip on one board. If you select this option, the
mlx5_core driver will include the Innova FPGA core and allow building
sandbox-specific client drivers.
config MLX5_CORE_EN config MLX5_CORE_EN
bool "Mellanox Technologies ConnectX-4 Ethernet support" bool "Mellanox Technologies ConnectX-4 Ethernet support"
depends on NETDEVICES && ETHERNET && PCI && MLX5_CORE depends on NETDEVICES && ETHERNET && PCI && MLX5_CORE

View File

@ -1,10 +1,13 @@
obj-$(CONFIG_MLX5_CORE) += mlx5_core.o obj-$(CONFIG_MLX5_CORE) += mlx5_core.o
subdir-ccflags-y += -I$(src)
mlx5_core-y := main.o cmd.o debugfs.o fw.o eq.o uar.o pagealloc.o \ mlx5_core-y := main.o cmd.o debugfs.o fw.o eq.o uar.o pagealloc.o \
health.o mcg.o cq.o srq.o alloc.o qp.o port.o mr.o pd.o \ health.o mcg.o cq.o srq.o alloc.o qp.o port.o mr.o pd.o \
mad.o transobj.o vport.o sriov.o fs_cmd.o fs_core.o \ mad.o transobj.o vport.o sriov.o fs_cmd.o fs_core.o \
fs_counters.o rl.o lag.o dev.o fs_counters.o rl.o lag.o dev.o
mlx5_core-$(CONFIG_MLX5_FPGA) += fpga/cmd.o fpga/core.o
mlx5_core-$(CONFIG_MLX5_CORE_EN) += wq.o eswitch.o eswitch_offloads.o \ mlx5_core-$(CONFIG_MLX5_CORE_EN) += wq.o eswitch.o eswitch_offloads.o \
en_main.o en_common.o en_fs.o en_ethtool.o en_tx.o \ en_main.o en_common.o en_fs.o en_ethtool.o en_tx.o \
en_rx.o en_rx_am.o en_txrx.o en_clock.o vxlan.o \ en_rx.o en_rx_am.o en_txrx.o en_clock.o vxlan.o \

View File

@ -35,6 +35,7 @@
#include <linux/mlx5/driver.h> #include <linux/mlx5/driver.h>
#include <linux/mlx5/cmd.h> #include <linux/mlx5/cmd.h>
#include "mlx5_core.h" #include "mlx5_core.h"
#include "fpga/core.h"
#ifdef CONFIG_MLX5_CORE_EN #ifdef CONFIG_MLX5_CORE_EN
#include "eswitch.h" #include "eswitch.h"
#endif #endif
@ -156,6 +157,8 @@ static const char *eqe_type_str(u8 type)
return "MLX5_EVENT_TYPE_PAGE_FAULT"; return "MLX5_EVENT_TYPE_PAGE_FAULT";
case MLX5_EVENT_TYPE_PPS_EVENT: case MLX5_EVENT_TYPE_PPS_EVENT:
return "MLX5_EVENT_TYPE_PPS_EVENT"; return "MLX5_EVENT_TYPE_PPS_EVENT";
case MLX5_EVENT_TYPE_FPGA_ERROR:
return "MLX5_EVENT_TYPE_FPGA_ERROR";
default: default:
return "Unrecognized event"; return "Unrecognized event";
} }
@ -476,6 +479,11 @@ static irqreturn_t mlx5_eq_int(int irq, void *eq_ptr)
if (dev->event) if (dev->event)
dev->event(dev, MLX5_DEV_EVENT_PPS, (unsigned long)eqe); dev->event(dev, MLX5_DEV_EVENT_PPS, (unsigned long)eqe);
break; break;
case MLX5_EVENT_TYPE_FPGA_ERROR:
mlx5_fpga_event(dev, eqe->type, &eqe->data.raw);
break;
default: default:
mlx5_core_warn(dev, "Unhandled event 0x%x on EQ 0x%x\n", mlx5_core_warn(dev, "Unhandled event 0x%x on EQ 0x%x\n",
eqe->type, eq->eqn); eqe->type, eq->eqn);
@ -693,6 +701,9 @@ int mlx5_start_eqs(struct mlx5_core_dev *dev)
if (MLX5_CAP_GEN(dev, pps)) if (MLX5_CAP_GEN(dev, pps))
async_event_mask |= (1ull << MLX5_EVENT_TYPE_PPS_EVENT); async_event_mask |= (1ull << MLX5_EVENT_TYPE_PPS_EVENT);
if (MLX5_CAP_GEN(dev, fpga))
async_event_mask |= (1ull << MLX5_EVENT_TYPE_FPGA_ERROR);
err = mlx5_create_map_eq(dev, &table->cmd_eq, MLX5_EQ_VEC_CMD, err = mlx5_create_map_eq(dev, &table->cmd_eq, MLX5_EQ_VEC_CMD,
MLX5_NUM_CMD_EQE, 1ull << MLX5_EVENT_TYPE_CMD, MLX5_NUM_CMD_EQE, 1ull << MLX5_EVENT_TYPE_CMD,
"mlx5_cmd_eq", MLX5_EQ_TYPE_ASYNC); "mlx5_cmd_eq", MLX5_EQ_TYPE_ASYNC);

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2017, Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - 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.
*/
#include <linux/etherdevice.h>
#include <linux/mlx5/cmd.h>
#include <linux/mlx5/driver.h>
#include "mlx5_core.h"
#include "fpga/cmd.h"
int mlx5_fpga_caps(struct mlx5_core_dev *dev, u32 *caps)
{
u32 in[MLX5_ST_SZ_DW(fpga_cap)] = {0};
return mlx5_core_access_reg(dev, in, sizeof(in), caps,
MLX5_ST_SZ_BYTES(fpga_cap),
MLX5_REG_FPGA_CAP, 0, 0);
}
int mlx5_fpga_query(struct mlx5_core_dev *dev, struct mlx5_fpga_query *query)
{
u32 in[MLX5_ST_SZ_DW(fpga_ctrl)] = {0};
u32 out[MLX5_ST_SZ_DW(fpga_ctrl)];
int err;
err = mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out),
MLX5_REG_FPGA_CTRL, 0, false);
if (err)
return err;
query->status = MLX5_GET(fpga_ctrl, out, status);
query->admin_image = MLX5_GET(fpga_ctrl, out, flash_select_admin);
query->oper_image = MLX5_GET(fpga_ctrl, out, flash_select_oper);
return 0;
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2017, Mellanox Technologies, Ltd. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - 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 __MLX5_FPGA_H__
#define __MLX5_FPGA_H__
#include <linux/mlx5/driver.h>
enum mlx5_fpga_image {
MLX5_FPGA_IMAGE_USER = 0,
MLX5_FPGA_IMAGE_FACTORY,
};
enum mlx5_fpga_status {
MLX5_FPGA_STATUS_SUCCESS = 0,
MLX5_FPGA_STATUS_FAILURE = 1,
MLX5_FPGA_STATUS_IN_PROGRESS = 2,
MLX5_FPGA_STATUS_NONE = 0xFFFF,
};
struct mlx5_fpga_query {
enum mlx5_fpga_image admin_image;
enum mlx5_fpga_image oper_image;
enum mlx5_fpga_status status;
};
int mlx5_fpga_caps(struct mlx5_core_dev *dev, u32 *caps);
int mlx5_fpga_query(struct mlx5_core_dev *dev, struct mlx5_fpga_query *query);
#endif /* __MLX5_FPGA_H__ */

View File

@ -0,0 +1,202 @@
/*
* Copyright (c) 2017, Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - 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.
*/
#include <linux/module.h>
#include <linux/etherdevice.h>
#include <linux/mlx5/driver.h>
#include "mlx5_core.h"
#include "fpga/core.h"
static const char *const mlx5_fpga_error_strings[] = {
"Null Syndrome",
"Corrupted DDR",
"Flash Timeout",
"Internal Link Error",
"Watchdog HW Failure",
"I2C Failure",
"Image Changed",
"Temperature Critical",
};
static struct mlx5_fpga_device *mlx5_fpga_device_alloc(void)
{
struct mlx5_fpga_device *fdev = NULL;
fdev = kzalloc(sizeof(*fdev), GFP_KERNEL);
if (!fdev)
return NULL;
spin_lock_init(&fdev->state_lock);
fdev->state = MLX5_FPGA_STATUS_NONE;
return fdev;
}
static const char *mlx5_fpga_image_name(enum mlx5_fpga_image image)
{
switch (image) {
case MLX5_FPGA_IMAGE_USER:
return "user";
case MLX5_FPGA_IMAGE_FACTORY:
return "factory";
default:
return "unknown";
}
}
static int mlx5_fpga_device_load_check(struct mlx5_fpga_device *fdev)
{
struct mlx5_fpga_query query;
int err;
err = mlx5_fpga_query(fdev->mdev, &query);
if (err) {
mlx5_fpga_err(fdev, "Failed to query status: %d\n", err);
return err;
}
fdev->last_admin_image = query.admin_image;
fdev->last_oper_image = query.oper_image;
mlx5_fpga_dbg(fdev, "Status %u; Admin image %u; Oper image %u\n",
query.status, query.admin_image, query.oper_image);
if (query.status != MLX5_FPGA_STATUS_SUCCESS) {
mlx5_fpga_err(fdev, "%s image failed to load; status %u\n",
mlx5_fpga_image_name(fdev->last_oper_image),
query.status);
return -EIO;
}
return 0;
}
int mlx5_fpga_device_start(struct mlx5_core_dev *mdev)
{
struct mlx5_fpga_device *fdev = mdev->fpga;
unsigned long flags;
int err;
if (!fdev)
return 0;
err = mlx5_fpga_device_load_check(fdev);
if (err)
goto out;
err = mlx5_fpga_caps(fdev->mdev,
fdev->mdev->caps.hca_cur[MLX5_CAP_FPGA]);
if (err)
goto out;
mlx5_fpga_info(fdev, "device %u; %s image, version %u\n",
MLX5_CAP_FPGA(fdev->mdev, fpga_device),
mlx5_fpga_image_name(fdev->last_oper_image),
MLX5_CAP_FPGA(fdev->mdev, image_version));
out:
spin_lock_irqsave(&fdev->state_lock, flags);
fdev->state = err ? MLX5_FPGA_STATUS_FAILURE : MLX5_FPGA_STATUS_SUCCESS;
spin_unlock_irqrestore(&fdev->state_lock, flags);
return err;
}
int mlx5_fpga_device_init(struct mlx5_core_dev *mdev)
{
struct mlx5_fpga_device *fdev = NULL;
if (!MLX5_CAP_GEN(mdev, fpga)) {
mlx5_core_dbg(mdev, "FPGA capability not present\n");
return 0;
}
mlx5_core_dbg(mdev, "Initializing FPGA\n");
fdev = mlx5_fpga_device_alloc();
if (!fdev)
return -ENOMEM;
fdev->mdev = mdev;
mdev->fpga = fdev;
return 0;
}
void mlx5_fpga_device_cleanup(struct mlx5_core_dev *mdev)
{
kfree(mdev->fpga);
mdev->fpga = NULL;
}
static const char *mlx5_fpga_syndrome_to_string(u8 syndrome)
{
if (syndrome < ARRAY_SIZE(mlx5_fpga_error_strings))
return mlx5_fpga_error_strings[syndrome];
return "Unknown";
}
void mlx5_fpga_event(struct mlx5_core_dev *mdev, u8 event, void *data)
{
struct mlx5_fpga_device *fdev = mdev->fpga;
const char *event_name;
bool teardown = false;
unsigned long flags;
u8 syndrome;
if (event != MLX5_EVENT_TYPE_FPGA_ERROR) {
mlx5_fpga_warn_ratelimited(fdev, "Unexpected event %u\n",
event);
return;
}
syndrome = MLX5_GET(fpga_error_event, data, syndrome);
event_name = mlx5_fpga_syndrome_to_string(syndrome);
spin_lock_irqsave(&fdev->state_lock, flags);
switch (fdev->state) {
case MLX5_FPGA_STATUS_SUCCESS:
mlx5_fpga_warn(fdev, "Error %u: %s\n", syndrome, event_name);
teardown = true;
break;
default:
mlx5_fpga_warn_ratelimited(fdev, "Unexpected error event %u: %s\n",
syndrome, event_name);
}
spin_unlock_irqrestore(&fdev->state_lock, flags);
/* We tear-down the card's interfaces and functionality because
* the FPGA bump-on-the-wire is misbehaving and we lose ability
* to communicate with the network. User may still be able to
* recover by re-programming or debugging the FPGA
*/
if (teardown)
mlx5_trigger_health_work(fdev->mdev);
}

View File

@ -0,0 +1,99 @@
/*
* Copyright (c) 2017, Mellanox Technologies, Ltd. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - 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 __MLX5_FPGA_CORE_H__
#define __MLX5_FPGA_CORE_H__
#ifdef CONFIG_MLX5_FPGA
#include "fpga/cmd.h"
/* Represents an Innova device */
struct mlx5_fpga_device {
struct mlx5_core_dev *mdev;
spinlock_t state_lock; /* Protects state transitions */
enum mlx5_fpga_status state;
enum mlx5_fpga_image last_admin_image;
enum mlx5_fpga_image last_oper_image;
};
#define mlx5_fpga_dbg(__adev, format, ...) \
dev_dbg(&(__adev)->mdev->pdev->dev, "FPGA: %s:%d:(pid %d): " format, \
__func__, __LINE__, current->pid, ##__VA_ARGS__)
#define mlx5_fpga_err(__adev, format, ...) \
dev_err(&(__adev)->mdev->pdev->dev, "FPGA: %s:%d:(pid %d): " format, \
__func__, __LINE__, current->pid, ##__VA_ARGS__)
#define mlx5_fpga_warn(__adev, format, ...) \
dev_warn(&(__adev)->mdev->pdev->dev, "FPGA: %s:%d:(pid %d): " format, \
__func__, __LINE__, current->pid, ##__VA_ARGS__)
#define mlx5_fpga_warn_ratelimited(__adev, format, ...) \
dev_warn_ratelimited(&(__adev)->mdev->pdev->dev, "FPGA: %s:%d: " \
format, __func__, __LINE__, ##__VA_ARGS__)
#define mlx5_fpga_notice(__adev, format, ...) \
dev_notice(&(__adev)->mdev->pdev->dev, "FPGA: " format, ##__VA_ARGS__)
#define mlx5_fpga_info(__adev, format, ...) \
dev_info(&(__adev)->mdev->pdev->dev, "FPGA: " format, ##__VA_ARGS__)
int mlx5_fpga_device_init(struct mlx5_core_dev *mdev);
void mlx5_fpga_device_cleanup(struct mlx5_core_dev *mdev);
int mlx5_fpga_device_start(struct mlx5_core_dev *mdev);
void mlx5_fpga_event(struct mlx5_core_dev *mdev, u8 event, void *data);
#else
static inline int mlx5_fpga_device_init(struct mlx5_core_dev *mdev)
{
return 0;
}
static inline void mlx5_fpga_device_cleanup(struct mlx5_core_dev *mdev)
{
}
static inline int mlx5_fpga_device_start(struct mlx5_core_dev *mdev)
{
return 0;
}
static inline void mlx5_fpga_event(struct mlx5_core_dev *mdev, u8 event,
void *data)
{
}
#endif
#endif /* __MLX5_FPGA_CORE_H__ */

View File

@ -56,6 +56,7 @@
#ifdef CONFIG_MLX5_CORE_EN #ifdef CONFIG_MLX5_CORE_EN
#include "eswitch.h" #include "eswitch.h"
#endif #endif
#include "fpga/core.h"
MODULE_AUTHOR("Eli Cohen <eli@mellanox.com>"); MODULE_AUTHOR("Eli Cohen <eli@mellanox.com>");
MODULE_DESCRIPTION("Mellanox Connect-IB, ConnectX-4 core driver"); MODULE_DESCRIPTION("Mellanox Connect-IB, ConnectX-4 core driver");
@ -1113,10 +1114,16 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
goto err_disable_msix; goto err_disable_msix;
} }
err = mlx5_fpga_device_init(dev);
if (err) {
dev_err(&pdev->dev, "fpga device init failed %d\n", err);
goto err_put_uars;
}
err = mlx5_start_eqs(dev); err = mlx5_start_eqs(dev);
if (err) { if (err) {
dev_err(&pdev->dev, "Failed to start pages and async EQs\n"); dev_err(&pdev->dev, "Failed to start pages and async EQs\n");
goto err_put_uars; goto err_fpga_init;
} }
err = alloc_comp_eqs(dev); err = alloc_comp_eqs(dev);
@ -1147,6 +1154,12 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
goto err_sriov; goto err_sriov;
} }
err = mlx5_fpga_device_start(dev);
if (err) {
dev_err(&pdev->dev, "fpga device start failed %d\n", err);
goto err_reg_dev;
}
if (mlx5_device_registered(dev)) { if (mlx5_device_registered(dev)) {
mlx5_attach_device(dev); mlx5_attach_device(dev);
} else { } else {
@ -1182,6 +1195,9 @@ err_affinity_hints:
err_stop_eqs: err_stop_eqs:
mlx5_stop_eqs(dev); mlx5_stop_eqs(dev);
err_fpga_init:
mlx5_fpga_device_cleanup(dev);
err_put_uars: err_put_uars:
mlx5_put_uars_page(dev, priv->uar); mlx5_put_uars_page(dev, priv->uar);
@ -1246,6 +1262,7 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
mlx5_irq_clear_affinity_hints(dev); mlx5_irq_clear_affinity_hints(dev);
free_comp_eqs(dev); free_comp_eqs(dev);
mlx5_stop_eqs(dev); mlx5_stop_eqs(dev);
mlx5_fpga_device_cleanup(dev);
mlx5_put_uars_page(dev, priv->uar); mlx5_put_uars_page(dev, priv->uar);
mlx5_disable_msix(dev); mlx5_disable_msix(dev);
if (cleanup) if (cleanup)

View File

@ -300,6 +300,8 @@ enum mlx5_event {
MLX5_EVENT_TYPE_PAGE_FAULT = 0xc, MLX5_EVENT_TYPE_PAGE_FAULT = 0xc,
MLX5_EVENT_TYPE_NIC_VPORT_CHANGE = 0xd, MLX5_EVENT_TYPE_NIC_VPORT_CHANGE = 0xd,
MLX5_EVENT_TYPE_FPGA_ERROR = 0x20,
}; };
enum { enum {
@ -967,6 +969,7 @@ enum mlx5_cap_type {
MLX5_CAP_RESERVED, MLX5_CAP_RESERVED,
MLX5_CAP_VECTOR_CALC, MLX5_CAP_VECTOR_CALC,
MLX5_CAP_QOS, MLX5_CAP_QOS,
MLX5_CAP_FPGA,
/* NUM OF CAP Types */ /* NUM OF CAP Types */
MLX5_CAP_NUM MLX5_CAP_NUM
}; };
@ -1088,6 +1091,9 @@ enum mlx5_mcam_feature_groups {
#define MLX5_CAP_MCAM_FEATURE(mdev, fld) \ #define MLX5_CAP_MCAM_FEATURE(mdev, fld) \
MLX5_GET(mcam_reg, (mdev)->caps.mcam, mng_feature_cap_mask.enhanced_features.fld) MLX5_GET(mcam_reg, (mdev)->caps.mcam, mng_feature_cap_mask.enhanced_features.fld)
#define MLX5_CAP_FPGA(mdev, cap) \
MLX5_GET(fpga_cap, (mdev)->caps.hca_cur[MLX5_CAP_FPGA], cap)
enum { enum {
MLX5_CMD_STAT_OK = 0x0, MLX5_CMD_STAT_OK = 0x0,
MLX5_CMD_STAT_INT_ERR = 0x1, MLX5_CMD_STAT_INT_ERR = 0x1,

View File

@ -108,6 +108,8 @@ enum {
MLX5_REG_QTCT = 0x400a, MLX5_REG_QTCT = 0x400a,
MLX5_REG_DCBX_PARAM = 0x4020, MLX5_REG_DCBX_PARAM = 0x4020,
MLX5_REG_DCBX_APP = 0x4021, MLX5_REG_DCBX_APP = 0x4021,
MLX5_REG_FPGA_CAP = 0x4022,
MLX5_REG_FPGA_CTRL = 0x4023,
MLX5_REG_PCAP = 0x5001, MLX5_REG_PCAP = 0x5001,
MLX5_REG_PMTU = 0x5003, MLX5_REG_PMTU = 0x5003,
MLX5_REG_PTYS = 0x5004, MLX5_REG_PTYS = 0x5004,
@ -761,6 +763,9 @@ struct mlx5_core_dev {
atomic_t num_qps; atomic_t num_qps;
u32 issi; u32 issi;
struct mlx5e_resources mlx5e_res; struct mlx5e_resources mlx5e_res;
#ifdef CONFIG_MLX5_FPGA
struct mlx5_fpga_device *fpga;
#endif
#ifdef CONFIG_RFS_ACCEL #ifdef CONFIG_RFS_ACCEL
struct cpu_rmap *rmap; struct cpu_rmap *rmap;
#endif #endif

View File

@ -32,6 +32,8 @@
#ifndef MLX5_IFC_H #ifndef MLX5_IFC_H
#define MLX5_IFC_H #define MLX5_IFC_H
#include "mlx5_ifc_fpga.h"
enum { enum {
MLX5_EVENT_TYPE_CODING_COMPLETION_EVENTS = 0x0, MLX5_EVENT_TYPE_CODING_COMPLETION_EVENTS = 0x0,
MLX5_EVENT_TYPE_CODING_PATH_MIGRATED_SUCCEEDED = 0x1, MLX5_EVENT_TYPE_CODING_PATH_MIGRATED_SUCCEEDED = 0x1,
@ -56,7 +58,8 @@ enum {
MLX5_EVENT_TYPE_CODING_STALL_VL_EVENT = 0x1b, MLX5_EVENT_TYPE_CODING_STALL_VL_EVENT = 0x1b,
MLX5_EVENT_TYPE_CODING_DROPPED_PACKET_LOGGED_EVENT = 0x1f, MLX5_EVENT_TYPE_CODING_DROPPED_PACKET_LOGGED_EVENT = 0x1f,
MLX5_EVENT_TYPE_CODING_COMMAND_INTERFACE_COMPLETION = 0xa, MLX5_EVENT_TYPE_CODING_COMMAND_INTERFACE_COMPLETION = 0xa,
MLX5_EVENT_TYPE_CODING_PAGE_REQUEST = 0xb MLX5_EVENT_TYPE_CODING_PAGE_REQUEST = 0xb,
MLX5_EVENT_TYPE_CODING_FPGA_ERROR = 0x20,
}; };
enum { enum {
@ -854,7 +857,8 @@ struct mlx5_ifc_cmd_hca_cap_bits {
u8 max_tc[0x4]; u8 max_tc[0x4];
u8 reserved_at_1d0[0x1]; u8 reserved_at_1d0[0x1];
u8 dcbx[0x1]; u8 dcbx[0x1];
u8 reserved_at_1d2[0x4]; u8 reserved_at_1d2[0x3];
u8 fpga[0x1];
u8 rol_s[0x1]; u8 rol_s[0x1];
u8 rol_g[0x1]; u8 rol_g[0x1];
u8 reserved_at_1d8[0x1]; u8 reserved_at_1d8[0x1];
@ -2186,6 +2190,7 @@ union mlx5_ifc_hca_cap_union_bits {
struct mlx5_ifc_e_switch_cap_bits e_switch_cap; struct mlx5_ifc_e_switch_cap_bits e_switch_cap;
struct mlx5_ifc_vector_calc_cap_bits vector_calc_cap; struct mlx5_ifc_vector_calc_cap_bits vector_calc_cap;
struct mlx5_ifc_qos_cap_bits qos_cap; struct mlx5_ifc_qos_cap_bits qos_cap;
struct mlx5_ifc_fpga_cap_bits fpga_cap;
u8 reserved_at_0[0x8000]; u8 reserved_at_0[0x8000];
}; };
@ -8182,6 +8187,8 @@ union mlx5_ifc_ports_control_registers_document_bits {
struct mlx5_ifc_sltp_reg_bits sltp_reg; struct mlx5_ifc_sltp_reg_bits sltp_reg;
struct mlx5_ifc_mtpps_reg_bits mtpps_reg; struct mlx5_ifc_mtpps_reg_bits mtpps_reg;
struct mlx5_ifc_mtppse_reg_bits mtppse_reg; struct mlx5_ifc_mtppse_reg_bits mtppse_reg;
struct mlx5_ifc_fpga_ctrl_bits fpga_ctrl_bits;
struct mlx5_ifc_fpga_cap_bits fpga_cap_bits;
u8 reserved_at_0[0x60e0]; u8 reserved_at_0[0x60e0];
}; };

View File

@ -0,0 +1,144 @@
/*
* Copyright (c) 2017, Mellanox Technologies, Ltd. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - 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 MLX5_IFC_FPGA_H
#define MLX5_IFC_FPGA_H
struct mlx5_ifc_fpga_shell_caps_bits {
u8 max_num_qps[0x10];
u8 reserved_at_10[0x8];
u8 total_rcv_credits[0x8];
u8 reserved_at_20[0xe];
u8 qp_type[0x2];
u8 reserved_at_30[0x5];
u8 rae[0x1];
u8 rwe[0x1];
u8 rre[0x1];
u8 reserved_at_38[0x4];
u8 dc[0x1];
u8 ud[0x1];
u8 uc[0x1];
u8 rc[0x1];
u8 reserved_at_40[0x1a];
u8 log_ddr_size[0x6];
u8 max_fpga_qp_msg_size[0x20];
u8 reserved_at_80[0x180];
};
struct mlx5_ifc_fpga_cap_bits {
u8 fpga_id[0x8];
u8 fpga_device[0x18];
u8 register_file_ver[0x20];
u8 fpga_ctrl_modify[0x1];
u8 reserved_at_41[0x5];
u8 access_reg_query_mode[0x2];
u8 reserved_at_48[0x6];
u8 access_reg_modify_mode[0x2];
u8 reserved_at_50[0x10];
u8 reserved_at_60[0x20];
u8 image_version[0x20];
u8 image_date[0x20];
u8 image_time[0x20];
u8 shell_version[0x20];
u8 reserved_at_100[0x80];
struct mlx5_ifc_fpga_shell_caps_bits shell_caps;
u8 reserved_at_380[0x8];
u8 ieee_vendor_id[0x18];
u8 sandbox_product_version[0x10];
u8 sandbox_product_id[0x10];
u8 sandbox_basic_caps[0x20];
u8 reserved_at_3e0[0x10];
u8 sandbox_extended_caps_len[0x10];
u8 sandbox_extended_caps_addr[0x40];
u8 fpga_ddr_start_addr[0x40];
u8 fpga_cr_space_start_addr[0x40];
u8 fpga_ddr_size[0x20];
u8 fpga_cr_space_size[0x20];
u8 reserved_at_500[0x300];
};
struct mlx5_ifc_fpga_ctrl_bits {
u8 reserved_at_0[0x8];
u8 operation[0x8];
u8 reserved_at_10[0x8];
u8 status[0x8];
u8 reserved_at_20[0x8];
u8 flash_select_admin[0x8];
u8 reserved_at_30[0x8];
u8 flash_select_oper[0x8];
u8 reserved_at_40[0x40];
};
enum {
MLX5_FPGA_ERROR_EVENT_SYNDROME_CORRUPTED_DDR = 0x1,
MLX5_FPGA_ERROR_EVENT_SYNDROME_FLASH_TIMEOUT = 0x2,
MLX5_FPGA_ERROR_EVENT_SYNDROME_INTERNAL_LINK_ERROR = 0x3,
MLX5_FPGA_ERROR_EVENT_SYNDROME_WATCHDOG_FAILURE = 0x4,
MLX5_FPGA_ERROR_EVENT_SYNDROME_I2C_FAILURE = 0x5,
MLX5_FPGA_ERROR_EVENT_SYNDROME_IMAGE_CHANGED = 0x6,
MLX5_FPGA_ERROR_EVENT_SYNDROME_TEMPERATURE_CRITICAL = 0x7,
};
struct mlx5_ifc_fpga_error_event_bits {
u8 reserved_at_0[0x40];
u8 reserved_at_40[0x18];
u8 syndrome[0x8];
u8 reserved_at_60[0x80];
};
#endif /* MLX5_IFC_FPGA_H */