@@ -849,7 +849,6 @@ struct qed_dev {
u32 rdma_max_srq_sge;
u16 tunn_feature_mask;
- struct devlink *dl;
bool iwarp_cmt;
};
@@ -5,6 +5,7 @@
*/
#include <linux/kernel.h>
+#include <linux/qed/qed_if.h>
#include "qed.h"
#include "qed_devlink.h"
@@ -13,17 +14,12 @@ enum qed_devlink_param_id {
QED_DEVLINK_PARAM_ID_IWARP_CMT,
};
-struct qed_devlink {
- struct qed_dev *cdev;
-};
-
static int qed_dl_param_get(struct devlink *dl, u32 id,
struct devlink_param_gset_ctx *ctx)
{
- struct qed_devlink *qed_dl;
+ struct qed_devlink *qed_dl = devlink_priv(dl);
struct qed_dev *cdev;
- qed_dl = devlink_priv(dl);
cdev = qed_dl->cdev;
ctx->val.vbool = cdev->iwarp_cmt;
@@ -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,
struct devlink_param_gset_ctx *ctx)
{
- struct qed_devlink *qed_dl;
+ struct qed_devlink *qed_dl = devlink_priv(dl);
struct qed_dev *cdev;
- qed_dl = devlink_priv(dl);
cdev = qed_dl->cdev;
cdev->iwarp_cmt = ctx->val.vbool;
@@ -52,21 +47,19 @@ static const struct devlink_param qed_devlink_params[] = {
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;
- struct qed_devlink *qed_dl;
+ struct qed_devlink *qdevlink;
struct devlink *dl;
int rc;
- dl = devlink_alloc(&qed_dl_ops, sizeof(*qed_dl));
+ dl = devlink_alloc(&qed_dl_ops, sizeof(struct qed_devlink));
if (!dl)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
- qed_dl = devlink_priv(dl);
-
- cdev->dl = dl;
- qed_dl->cdev = cdev;
+ qdevlink = devlink_priv(dl);
+ qdevlink->cdev = cdev;
rc = devlink_register(dl, &cdev->pdev->dev);
if (rc)
@@ -85,26 +78,25 @@ int qed_devlink_register(struct qed_dev *cdev)
devlink_params_publish(dl);
cdev->iwarp_cmt = false;
- return 0;
+ return dl;
err_unregister:
devlink_unregister(dl);
err_free:
- cdev->dl = NULL;
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;
- devlink_params_unregister(cdev->dl, qed_devlink_params,
+ devlink_params_unregister(devlink, qed_devlink_params,
ARRAY_SIZE(qed_devlink_params));
- devlink_unregister(cdev->dl);
- devlink_free(cdev->dl);
+ devlink_unregister(devlink);
+ devlink_free(devlink);
}
@@ -9,7 +9,7 @@
#include <linux/qed/qed_if.h>
#include <net/devlink.h>
-int qed_devlink_register(struct qed_dev *cdev);
-void qed_devlink_unregister(struct qed_dev *cdev);
+struct devlink *qed_devlink_register(struct qed_dev *cdev);
+void qed_devlink_unregister(struct devlink *devlink);
#endif
@@ -539,12 +539,6 @@ static struct qed_dev *qed_probe(struct pci_dev *pdev,
}
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);
if (rc) {
DP_ERR(cdev, "hw prepare failed\n");
@@ -574,8 +568,6 @@ static void qed_remove(struct qed_dev *cdev)
qed_set_power_state(cdev, PCI_D3hot);
- qed_devlink_unregister(cdev);
-
qed_free_cdev(cdev);
}
@@ -3012,6 +3004,8 @@ const struct qed_common_ops qed_common_ops_pass = {
.get_link = &qed_get_current_link,
.drain = &qed_drain,
.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_size = &qed_dbg_all_data_size,
.chain_alloc = &qed_chain_alloc,
@@ -172,6 +172,7 @@ struct qede_dev {
struct qed_dev *cdev;
struct net_device *ndev;
struct pci_dev *pdev;
+ struct devlink *devlink;
u32 dp_module;
u8 dp_level;
@@ -1172,10 +1172,23 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level,
rc = -ENOMEM;
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 {
struct net_device *ndev = pci_get_drvdata(pdev);
edev = netdev_priv(ndev);
+
+ if (edev && edev->devlink) {
+ struct qed_devlink *qdl = devlink_priv(edev->devlink);
+
+ qdl->cdev = cdev;
+ }
edev->cdev = cdev;
memset(&edev->stats, 0, sizeof(edev->stats));
memcpy(&edev->dev_info, &dev_info, sizeof(dev_info));
@@ -1298,6 +1311,11 @@ static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode)
qed_ops->common->slowpath_stop(cdev);
if (system_state == SYSTEM_POWER_OFF)
return;
+
+ if (mode != QEDE_REMOVE_RECOVERY && edev->devlink) {
+ qed_ops->common->devlink_unregister(edev->devlink);
+ edev->devlink = NULL;
+ }
qed_ops->common->remove(cdev);
edev->cdev = NULL;
@@ -21,6 +21,7 @@
#include <linux/qed/common_hsi.h>
#include <linux/qed/qed_chain.h>
#include <linux/io-64-nonatomic-lo-hi.h>
+#include <net/devlink.h>
enum dcbx_protocol_type {
DCBX_PROTOCOL_ISCSI,
@@ -779,6 +780,10 @@ enum qed_nvm_flash_cmd {
QED_NVM_FLASH_CMD_NVM_MAX,
};
+struct qed_devlink {
+ struct qed_dev *cdev;
+};
+
struct qed_common_cb_ops {
void (*arfs_filter_op)(void *dev, void *fltr, u8 fw_rc);
void (*link_update)(void *dev, struct qed_link_output *link);
@@ -1137,6 +1142,10 @@ struct qed_common_ops {
*
*/
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) \