diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h index b2a7b53ee7602209559812d89a7f0bfa4bef2be7..b6ce1488abcc61595ad0b8d4e124cf7323683123 100644 --- a/drivers/net/ethernet/qlogic/qed/qed.h +++ b/drivers/net/ethernet/qlogic/qed/qed.h @@ -849,7 +849,6 @@ struct qed_dev { u32 rdma_max_srq_sge; u16 tunn_feature_mask; - struct devlink *dl; bool iwarp_cmt; }; diff --git a/drivers/net/ethernet/qlogic/qed/qed_devlink.c b/drivers/net/ethernet/qlogic/qed/qed_devlink.c index eb693787c99e9a307d0b0f8d2a1ee0cbb2457d9d..a62c47c61edf5b056a60eb8dbd4696f4d8c87d6f 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_devlink.c +++ b/drivers/net/ethernet/qlogic/qed/qed_devlink.c @@ -5,6 +5,7 @@ */ #include +#include #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); } diff --git a/drivers/net/ethernet/qlogic/qed/qed_devlink.h b/drivers/net/ethernet/qlogic/qed/qed_devlink.h index b94c40e9b7c1d8b4536239d90b73b1270847da69..c79dc6bfa194251a8494130d2105f7137c5c94b7 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_devlink.h +++ b/drivers/net/ethernet/qlogic/qed/qed_devlink.h @@ -9,7 +9,7 @@ #include #include -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 diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index 8751355d9ef7f4084b3e8ca7b25e40151d6d35bb..d6f76421379b260b91f4904a3303cc22f138fdbe 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -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, diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h index 803c1fcca8ad1cb7864cb68cd4f280d193c001a4..1f0e7505a9738af35ad9efe9a5eaacde4dcbada5 100644 --- a/drivers/net/ethernet/qlogic/qede/qede.h +++ b/drivers/net/ethernet/qlogic/qede/qede.h @@ -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; diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index 140a392a81bbd6aeb1564d027bc27d79ad914834..4cd8412e5ed02beef28ed8c4bfca12cf60285adc 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -1170,10 +1170,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->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)); @@ -1296,6 +1309,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; diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h index cd6a5c7e56ebaa918bc6854f2ba3469374c03164..d8368e1770dfe232238d01bb62ac4aa22127f5cb 100644 --- a/include/linux/qed/qed_if.h +++ b/include/linux/qed/qed_if.h @@ -21,6 +21,7 @@ #include #include #include +#include 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) \