Commit 755f982b authored by Igor Russkikh's avatar Igor Russkikh Committed by David S. Miller

qed/qede: make devlink survive recovery

Devlink instance lifecycle was linked to qed_dev object,
that caused devlink to be recreated on each recovery.

Changing it by making higher level driver (qede) responsible for its
life. This way devlink now survives recoveries.

qede now stores devlink structure pointer as a part of its device
object, devlink private data contains a linkage structure,
qed_devlink.
Signed-off-by: default avatarIgor Russkikh <irusskikh@marvell.com>
Signed-off-by: default avatarAlexander Lobakin <alobakin@marvell.com>
Signed-off-by: default avatarMichal Kalderon <michal.kalderon@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 52306dee
...@@ -849,7 +849,6 @@ struct qed_dev { ...@@ -849,7 +849,6 @@ struct qed_dev {
u32 rdma_max_srq_sge; u32 rdma_max_srq_sge;
u16 tunn_feature_mask; u16 tunn_feature_mask;
struct devlink *dl;
bool iwarp_cmt; bool iwarp_cmt;
}; };
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/qed/qed_if.h>
#include "qed.h" #include "qed.h"
#include "qed_devlink.h" #include "qed_devlink.h"
...@@ -13,17 +14,12 @@ enum qed_devlink_param_id { ...@@ -13,17 +14,12 @@ enum qed_devlink_param_id {
QED_DEVLINK_PARAM_ID_IWARP_CMT, QED_DEVLINK_PARAM_ID_IWARP_CMT,
}; };
struct qed_devlink {
struct qed_dev *cdev;
};
static int qed_dl_param_get(struct devlink *dl, u32 id, static int qed_dl_param_get(struct devlink *dl, u32 id,
struct devlink_param_gset_ctx *ctx) struct devlink_param_gset_ctx *ctx)
{ {
struct qed_devlink *qed_dl; struct qed_devlink *qed_dl = devlink_priv(dl);
struct qed_dev *cdev; struct qed_dev *cdev;
qed_dl = devlink_priv(dl);
cdev = qed_dl->cdev; cdev = qed_dl->cdev;
ctx->val.vbool = cdev->iwarp_cmt; ctx->val.vbool = cdev->iwarp_cmt;
...@@ -33,10 +29,9 @@ static int qed_dl_param_get(struct devlink *dl, u32 id, ...@@ -33,10 +29,9 @@ static int qed_dl_param_get(struct devlink *dl, u32 id,
static int qed_dl_param_set(struct devlink *dl, u32 id, static int qed_dl_param_set(struct devlink *dl, u32 id,
struct devlink_param_gset_ctx *ctx) struct devlink_param_gset_ctx *ctx)
{ {
struct qed_devlink *qed_dl; struct qed_devlink *qed_dl = devlink_priv(dl);
struct qed_dev *cdev; struct qed_dev *cdev;
qed_dl = devlink_priv(dl);
cdev = qed_dl->cdev; cdev = qed_dl->cdev;
cdev->iwarp_cmt = ctx->val.vbool; cdev->iwarp_cmt = ctx->val.vbool;
...@@ -52,21 +47,19 @@ static const struct devlink_param qed_devlink_params[] = { ...@@ -52,21 +47,19 @@ static const struct devlink_param qed_devlink_params[] = {
static const struct devlink_ops qed_dl_ops; static const struct devlink_ops qed_dl_ops;
int qed_devlink_register(struct qed_dev *cdev) struct devlink *qed_devlink_register(struct qed_dev *cdev)
{ {
union devlink_param_value value; union devlink_param_value value;
struct qed_devlink *qed_dl; struct qed_devlink *qdevlink;
struct devlink *dl; struct devlink *dl;
int rc; int rc;
dl = devlink_alloc(&qed_dl_ops, sizeof(*qed_dl)); dl = devlink_alloc(&qed_dl_ops, sizeof(struct qed_devlink));
if (!dl) if (!dl)
return -ENOMEM; return ERR_PTR(-ENOMEM);
qed_dl = devlink_priv(dl); qdevlink = devlink_priv(dl);
qdevlink->cdev = cdev;
cdev->dl = dl;
qed_dl->cdev = cdev;
rc = devlink_register(dl, &cdev->pdev->dev); rc = devlink_register(dl, &cdev->pdev->dev);
if (rc) if (rc)
...@@ -85,26 +78,25 @@ int qed_devlink_register(struct qed_dev *cdev) ...@@ -85,26 +78,25 @@ int qed_devlink_register(struct qed_dev *cdev)
devlink_params_publish(dl); devlink_params_publish(dl);
cdev->iwarp_cmt = false; cdev->iwarp_cmt = false;
return 0; return dl;
err_unregister: err_unregister:
devlink_unregister(dl); devlink_unregister(dl);
err_free: err_free:
cdev->dl = NULL;
devlink_free(dl); devlink_free(dl);
return rc; return ERR_PTR(rc);
} }
void qed_devlink_unregister(struct qed_dev *cdev) void qed_devlink_unregister(struct devlink *devlink)
{ {
if (!cdev->dl) if (!devlink)
return; return;
devlink_params_unregister(cdev->dl, qed_devlink_params, devlink_params_unregister(devlink, qed_devlink_params,
ARRAY_SIZE(qed_devlink_params)); ARRAY_SIZE(qed_devlink_params));
devlink_unregister(cdev->dl); devlink_unregister(devlink);
devlink_free(cdev->dl); devlink_free(devlink);
} }
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include <linux/qed/qed_if.h> #include <linux/qed/qed_if.h>
#include <net/devlink.h> #include <net/devlink.h>
int qed_devlink_register(struct qed_dev *cdev); struct devlink *qed_devlink_register(struct qed_dev *cdev);
void qed_devlink_unregister(struct qed_dev *cdev); void qed_devlink_unregister(struct devlink *devlink);
#endif #endif
...@@ -539,12 +539,6 @@ static struct qed_dev *qed_probe(struct pci_dev *pdev, ...@@ -539,12 +539,6 @@ static struct qed_dev *qed_probe(struct pci_dev *pdev,
} }
DP_INFO(cdev, "PCI init completed successfully\n"); DP_INFO(cdev, "PCI init completed successfully\n");
rc = qed_devlink_register(cdev);
if (rc) {
DP_INFO(cdev, "Failed to register devlink.\n");
goto err2;
}
rc = qed_hw_prepare(cdev, QED_PCI_DEFAULT); rc = qed_hw_prepare(cdev, QED_PCI_DEFAULT);
if (rc) { if (rc) {
DP_ERR(cdev, "hw prepare failed\n"); DP_ERR(cdev, "hw prepare failed\n");
...@@ -574,8 +568,6 @@ static void qed_remove(struct qed_dev *cdev) ...@@ -574,8 +568,6 @@ static void qed_remove(struct qed_dev *cdev)
qed_set_power_state(cdev, PCI_D3hot); qed_set_power_state(cdev, PCI_D3hot);
qed_devlink_unregister(cdev);
qed_free_cdev(cdev); qed_free_cdev(cdev);
} }
...@@ -3012,6 +3004,8 @@ const struct qed_common_ops qed_common_ops_pass = { ...@@ -3012,6 +3004,8 @@ const struct qed_common_ops qed_common_ops_pass = {
.get_link = &qed_get_current_link, .get_link = &qed_get_current_link,
.drain = &qed_drain, .drain = &qed_drain,
.update_msglvl = &qed_init_dp, .update_msglvl = &qed_init_dp,
.devlink_register = qed_devlink_register,
.devlink_unregister = qed_devlink_unregister,
.dbg_all_data = &qed_dbg_all_data, .dbg_all_data = &qed_dbg_all_data,
.dbg_all_data_size = &qed_dbg_all_data_size, .dbg_all_data_size = &qed_dbg_all_data_size,
.chain_alloc = &qed_chain_alloc, .chain_alloc = &qed_chain_alloc,
......
...@@ -172,6 +172,7 @@ struct qede_dev { ...@@ -172,6 +172,7 @@ struct qede_dev {
struct qed_dev *cdev; struct qed_dev *cdev;
struct net_device *ndev; struct net_device *ndev;
struct pci_dev *pdev; struct pci_dev *pdev;
struct devlink *devlink;
u32 dp_module; u32 dp_module;
u8 dp_level; u8 dp_level;
......
...@@ -1170,10 +1170,23 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level, ...@@ -1170,10 +1170,23 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level,
rc = -ENOMEM; rc = -ENOMEM;
goto err2; goto err2;
} }
edev->devlink = qed_ops->common->devlink_register(cdev);
if (IS_ERR(edev->devlink)) {
DP_NOTICE(edev, "Cannot register devlink\n");
edev->devlink = NULL;
/* Go on, we can live without devlink */
}
} else { } else {
struct net_device *ndev = pci_get_drvdata(pdev); struct net_device *ndev = pci_get_drvdata(pdev);
edev = netdev_priv(ndev); edev = netdev_priv(ndev);
if (edev->devlink) {
struct qed_devlink *qdl = devlink_priv(edev->devlink);
qdl->cdev = cdev;
}
edev->cdev = cdev; edev->cdev = cdev;
memset(&edev->stats, 0, sizeof(edev->stats)); memset(&edev->stats, 0, sizeof(edev->stats));
memcpy(&edev->dev_info, &dev_info, sizeof(dev_info)); memcpy(&edev->dev_info, &dev_info, sizeof(dev_info));
...@@ -1296,6 +1309,11 @@ static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode) ...@@ -1296,6 +1309,11 @@ static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode)
qed_ops->common->slowpath_stop(cdev); qed_ops->common->slowpath_stop(cdev);
if (system_state == SYSTEM_POWER_OFF) if (system_state == SYSTEM_POWER_OFF)
return; return;
if (mode != QEDE_REMOVE_RECOVERY && edev->devlink) {
qed_ops->common->devlink_unregister(edev->devlink);
edev->devlink = NULL;
}
qed_ops->common->remove(cdev); qed_ops->common->remove(cdev);
edev->cdev = NULL; edev->cdev = NULL;
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/qed/common_hsi.h> #include <linux/qed/common_hsi.h>
#include <linux/qed/qed_chain.h> #include <linux/qed/qed_chain.h>
#include <linux/io-64-nonatomic-lo-hi.h> #include <linux/io-64-nonatomic-lo-hi.h>
#include <net/devlink.h>
enum dcbx_protocol_type { enum dcbx_protocol_type {
DCBX_PROTOCOL_ISCSI, DCBX_PROTOCOL_ISCSI,
...@@ -779,6 +780,10 @@ enum qed_nvm_flash_cmd { ...@@ -779,6 +780,10 @@ enum qed_nvm_flash_cmd {
QED_NVM_FLASH_CMD_NVM_MAX, QED_NVM_FLASH_CMD_NVM_MAX,
}; };
struct qed_devlink {
struct qed_dev *cdev;
};
struct qed_common_cb_ops { struct qed_common_cb_ops {
void (*arfs_filter_op)(void *dev, void *fltr, u8 fw_rc); void (*arfs_filter_op)(void *dev, void *fltr, u8 fw_rc);
void (*link_update)(void *dev, struct qed_link_output *link); void (*link_update)(void *dev, struct qed_link_output *link);
...@@ -1137,6 +1142,10 @@ struct qed_common_ops { ...@@ -1137,6 +1142,10 @@ struct qed_common_ops {
* *
*/ */
int (*set_grc_config)(struct qed_dev *cdev, u32 cfg_id, u32 val); int (*set_grc_config)(struct qed_dev *cdev, u32 cfg_id, u32 val);
struct devlink* (*devlink_register)(struct qed_dev *cdev);
void (*devlink_unregister)(struct devlink *devlink);
}; };
#define MASK_FIELD(_name, _value) \ #define MASK_FIELD(_name, _value) \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment